summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am3
-rw-r--r--TODO14
-rw-r--r--hwdb/60-keyboard.hwdb4
-rw-r--r--hwdb/70-mouse.hwdb3
-rw-r--r--man/tmpfiles.d.xml5
-rw-r--r--shell-completion/bash/systemd-run2
-rw-r--r--src/basic/btrfs-util.c63
-rw-r--r--src/basic/btrfs-util.h3
-rw-r--r--src/basic/missing.h8
-rw-r--r--src/basic/util.c5
-rw-r--r--src/basic/util.h2
-rw-r--r--src/bus-proxyd/bus-proxyd.c17
-rw-r--r--src/bus-proxyd/bus-xml-policy.c8
-rw-r--r--src/bus-proxyd/proxy.c38
-rw-r--r--src/core/dbus-execute.c18
-rw-r--r--src/core/dbus.c2
-rw-r--r--src/core/execute.c7
-rw-r--r--src/core/unit.c19
-rw-r--r--src/core/unit.h2
-rw-r--r--src/libsystemd/sd-bus/bus-kernel.c12
-rw-r--r--src/libsystemd/sd-event/sd-event.c4
-rw-r--r--src/libsystemd/sd-netlink/netlink-internal.h6
-rw-r--r--src/libsystemd/sd-netlink/netlink-socket.c155
-rw-r--r--src/libsystemd/sd-netlink/sd-netlink.c56
-rw-r--r--src/shared/bus-util.c15
-rw-r--r--units/tmp.mount (renamed from units/tmp.mount.m4)4
26 files changed, 389 insertions, 86 deletions
diff --git a/Makefile.am b/Makefile.am
index 1d2651a765..e210d8a2da 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -616,8 +616,7 @@ EXTRA_DIST += \
units/initrd-udevadm-cleanup-db.service.in \
units/initrd-switch-root.service.in \
units/systemd-nspawn@.service.in \
- units/systemd-update-done.service.in \
- units/tmp.mount.m4
+ units/systemd-update-done.service.in
if HAVE_SYSV_COMPAT
nodist_systemunit_DATA += \
diff --git a/TODO b/TODO
index d399ae9477..ba9ee160ff 100644
--- a/TODO
+++ b/TODO
@@ -176,14 +176,12 @@ Features:
* networkd/udev: implement SR_IOV configuration in .link files:
http://lists.freedesktop.org/archives/systemd-devel/2015-January/027451.html
-* When RLIMIT_NPROC is set from a unit file it currently always is set
- for root, not for the user set in User=, which makes it
- useless. After fixing this, set RLIMIT_NPROC for
- systemd-journal-xyz, and all other of our services that run under
- their own user ids, and use User= (but only in a world where userns
- is ubiquitous since otherwise we cannot invoke those daemons on the
- host AND in a container anymore). Also, if LimitNPROC= is used
- without User= we should warn and refuse operation.
+* Set RLIMIT_NPROC for systemd-journal-xyz, and all other of our
+ services that run under their own user ids, and use User= (but only
+ in a world where userns is ubiquitous since otherwise we cannot
+ invoke those daemons on the host AND in a container anymore). Also,
+ if LimitNPROC= is used without User= we should warn and refuse
+ operation.
* logind: maybe allow configuration of the StopTimeout for session scopes
diff --git a/hwdb/60-keyboard.hwdb b/hwdb/60-keyboard.hwdb
index 3e49449ae9..94906abcbf 100644
--- a/hwdb/60-keyboard.hwdb
+++ b/hwdb/60-keyboard.hwdb
@@ -495,6 +495,10 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPProBook445G1NotebookPC:pvr
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPProBook450G0:pvr*
KEYBOARD_KEY_81=f20 # Fn+F8; Microphone mute button, should be micmute
+# HP ProBook 6555b
+evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard:pnHPProBook6555b:*
+ KEYBOARD_KEY_b2=www # Earth
+
###########################################################
# IBM
###########################################################
diff --git a/hwdb/70-mouse.hwdb b/hwdb/70-mouse.hwdb
index 55e68a9138..2383d586a3 100644
--- a/hwdb/70-mouse.hwdb
+++ b/hwdb/70-mouse.hwdb
@@ -311,6 +311,9 @@ mouse:usb:v046dpc05a:name:Logitech USB Optical Mouse:
mouse:usb:v046dpc065:name:Logitech USB Laser Mouse:
# Logitech V500 Cordless Notebook Mouse
mouse:usb:v046dpc510:name:Logitech USB Receiver:
+# Logitech M560 Wireless Mouse
+mouse:usb:v046dp402d:name:Logitech M560:
+mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:402d:
MOUSE_DPI=1000@125
# Logitech V220 Cordless Optical Mouse
diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml
index 8d3ed37ae3..3cee0fff59 100644
--- a/man/tmpfiles.d.xml
+++ b/man/tmpfiles.d.xml
@@ -506,8 +506,9 @@
<para>The age field only applies to lines
starting with <varname>d</varname>,
- <varname>D</varname>, and
- <varname>x</varname>. If omitted or set to
+ <varname>D</varname>, <varname>v</varname>,
+ <varname>C</varname>, <varname>x</varname> and
+ <varname>X</varname>. If omitted or set to
<literal>-</literal>, no automatic clean-up is
done.</para>
diff --git a/shell-completion/bash/systemd-run b/shell-completion/bash/systemd-run
index 518812e040..ea59a42407 100644
--- a/shell-completion/bash/systemd-run
+++ b/shell-completion/bash/systemd-run
@@ -84,7 +84,7 @@ _systemd_run() {
LimitNICE= LimitRTPRIO= LimitRTTIME= PrivateTmp= PrivateDevices=
PrivateNetwork= NoNewPrivileges= WorkingDirectory= RootDirectory=
TTYPath= SyslogIdentifier= SyslogLevelPrefix= SyslogLevel=
- SyslogFacility= TimerSlackNSec='
+ SyslogFacility= TimerSlackNSec= OOMScoreAdjust='
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
return 0
diff --git a/src/basic/btrfs-util.c b/src/basic/btrfs-util.c
index 074deeccda..ec7e00986b 100644
--- a/src/basic/btrfs-util.c
+++ b/src/basic/btrfs-util.c
@@ -799,6 +799,45 @@ int btrfs_resize_loopback(const char *p, uint64_t new_size, bool grow_only) {
return btrfs_resize_loopback_fd(fd, new_size, grow_only);
}
+static int make_qgroup_id(uint64_t level, uint64_t id, uint64_t *ret) {
+ assert(ret);
+
+ if (level >= (UINT64_C(1) << (64 - BTRFS_QGROUP_LEVEL_SHIFT)))
+ return -EINVAL;
+
+ if (id >= (UINT64_C(1) << BTRFS_QGROUP_LEVEL_SHIFT))
+ return -EINVAL;
+
+ *ret = (level << BTRFS_QGROUP_LEVEL_SHIFT) | id;
+ return 0;
+}
+
+static int qgroup_create_or_destroy(int fd, bool b, uint64_t level, uint64_t id) {
+
+ struct btrfs_ioctl_qgroup_create_args args = {
+ .create = b,
+ };
+
+ int r;
+
+ r = make_qgroup_id(level, id, (uint64_t*) &args.qgroupid);
+ if (r < 0)
+ return r;
+
+ if (ioctl(fd, BTRFS_IOC_QGROUP_CREATE, &args) < 0)
+ return -errno;
+
+ return 0;
+}
+
+int btrfs_qgroup_create(int fd, uint64_t level, uint64_t id) {
+ return qgroup_create_or_destroy(fd, true, level, id);
+}
+
+int btrfs_qgroup_destroy(int fd, uint64_t level, uint64_t id) {
+ return qgroup_create_or_destroy(fd, false, level, id);
+}
+
static int subvol_remove_children(int fd, const char *subvolume, uint64_t subvol_id, bool recursive) {
struct btrfs_ioctl_search_args args = {
.key.tree_id = BTRFS_ROOT_TREE_OBJECTID,
@@ -828,16 +867,6 @@ static int subvol_remove_children(int fd, const char *subvolume, uint64_t subvol
if (!S_ISDIR(st.st_mode))
return -EINVAL;
- /* First, try to remove the subvolume. If it happens to be
- * already empty, this will just work. */
- strncpy(vol_args.name, subvolume, sizeof(vol_args.name)-1);
- if (ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &vol_args) >= 0)
- return 0;
- if (!recursive || errno != ENOTEMPTY)
- return -errno;
-
- /* OK, the subvolume is not empty, let's look for child
- * subvolumes, and remove them, first */
subvol_fd = openat(fd, subvolume, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
if (subvol_fd < 0)
return -errno;
@@ -848,6 +877,19 @@ static int subvol_remove_children(int fd, const char *subvolume, uint64_t subvol
return r;
}
+ /* First, try to remove the subvolume. If it happens to be
+ * already empty, this will just work. */
+ strncpy(vol_args.name, subvolume, sizeof(vol_args.name)-1);
+ if (ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &vol_args) >= 0) {
+ (void) btrfs_qgroup_destroy(fd, 0, subvol_id);
+ return 0;
+ }
+ if (!recursive || errno != ENOTEMPTY)
+ return -errno;
+
+ /* OK, the subvolume is not empty, let's look for child
+ * subvolumes, and remove them, first */
+
args.key.min_offset = args.key.max_offset = subvol_id;
while (btrfs_ioctl_search_args_compare(&args) <= 0) {
@@ -925,6 +967,7 @@ static int subvol_remove_children(int fd, const char *subvolume, uint64_t subvol
if (ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &vol_args) < 0)
return -errno;
+ (void) btrfs_qgroup_destroy(fd, 0, subvol_id);
return 0;
}
diff --git a/src/basic/btrfs-util.h b/src/basic/btrfs-util.h
index 8632c3638c..ad7c7009ab 100644
--- a/src/basic/btrfs-util.h
+++ b/src/basic/btrfs-util.h
@@ -86,3 +86,6 @@ int btrfs_resize_loopback(const char *path, uint64_t size, bool grow_only);
int btrfs_subvol_remove(const char *path, bool recursive);
int btrfs_subvol_remove_fd(int fd, const char *subvolume, bool recursive);
+
+int btrfs_qgroup_create(int fd, uint64_t level, uint64_t id);
+int btrfs_qgroup_destroy(int fd, uint64_t level, uint64_t id);
diff --git a/src/basic/missing.h b/src/basic/missing.h
index 59e835a466..70d6c8308e 100644
--- a/src/basic/missing.h
+++ b/src/basic/missing.h
@@ -126,6 +126,10 @@
#define SOL_NETLINK 270
#endif
+#ifndef NETLINK_LIST_MEMBERSHIPS
+#define NETLINK_LIST_MEMBERSHIPS 9
+#endif
+
#if !HAVE_DECL_PIVOT_ROOT
static inline int pivot_root(const char *new_root, const char *put_old) {
return syscall(SYS_pivot_root, new_root, put_old);
@@ -248,6 +252,10 @@ static inline int getrandom(void *buffer, size_t count, unsigned flags) {
#define BTRFS_SEARCH_ARGS_BUFSIZE (4096 - sizeof(struct btrfs_ioctl_search_key))
#endif
+#ifndef BTRFS_QGROUP_LEVEL_SHIFT
+#define BTRFS_QGROUP_LEVEL_SHIFT 48
+#endif
+
#ifndef HAVE_LINUX_BTRFS_H
struct btrfs_ioctl_vol_args {
int64_t fd;
diff --git a/src/basic/util.c b/src/basic/util.c
index 8b896a2df3..2565b0f547 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -29,6 +29,7 @@
#include <libintl.h>
#include <limits.h>
#include <linux/magic.h>
+#include <linux/oom.h>
#include <linux/sched.h>
#include <locale.h>
#include <netinet/ip.h>
@@ -6800,3 +6801,7 @@ bool fdname_is_valid(const char *s) {
return p - s < 256;
}
+
+bool oom_score_adjust_is_valid(int oa) {
+ return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX;
+}
diff --git a/src/basic/util.h b/src/basic/util.h
index 2544ad0830..6c63bc221f 100644
--- a/src/basic/util.h
+++ b/src/basic/util.h
@@ -941,3 +941,5 @@ void nop_signal_handler(int sig);
int version(void);
bool fdname_is_valid(const char *s);
+
+bool oom_score_adjust_is_valid(int oa);
diff --git a/src/bus-proxyd/bus-proxyd.c b/src/bus-proxyd/bus-proxyd.c
index 2bc265d9b4..64d1c5231f 100644
--- a/src/bus-proxyd/bus-proxyd.c
+++ b/src/bus-proxyd/bus-proxyd.c
@@ -85,11 +85,11 @@ static void *run_client(void *userdata) {
int r;
r = proxy_new(&p, c->fd, c->fd, arg_address);
+ c->fd = -1;
+
if (r < 0)
goto exit;
- c->fd = -1;
-
/* set comm to "p$PIDu$UID" and suffix with '*' if truncated */
r = snprintf(comm, sizeof(comm), "p" PID_FMT "u" UID_FMT, p->local_creds.pid, p->local_creds.uid);
if (r >= (ssize_t)sizeof(comm))
@@ -116,13 +116,12 @@ static int loop_clients(int accept_fd, uid_t bus_uid) {
int r;
r = pthread_attr_init(&attr);
- if (r < 0) {
- return log_error_errno(errno, "Cannot initialize pthread attributes: %m");
- }
+ if (r != 0)
+ return log_error_errno(r, "Cannot initialize pthread attributes: %m");
r = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- if (r < 0) {
- r = log_error_errno(errno, "Cannot mark pthread attributes as detached: %m");
+ if (r != 0) {
+ r = log_error_errno(r, "Cannot mark pthread attributes as detached: %m");
goto finish;
}
@@ -156,8 +155,8 @@ static int loop_clients(int accept_fd, uid_t bus_uid) {
c->bus_uid = bus_uid;
r = pthread_create(&tid, &attr, run_client, c);
- if (r < 0) {
- log_error("Cannot spawn thread: %m");
+ if (r != 0) {
+ log_warning_errno(r, "Cannot spawn thread, ignoring: %m");
client_context_free(c);
continue;
}
diff --git a/src/bus-proxyd/bus-xml-policy.c b/src/bus-proxyd/bus-xml-policy.c
index 9a3b451c56..91717653c2 100644
--- a/src/bus-proxyd/bus-xml-policy.c
+++ b/src/bus-proxyd/bus-xml-policy.c
@@ -1186,14 +1186,14 @@ int shared_policy_new(SharedPolicy **out) {
return log_oom();
r = pthread_mutex_init(&sp->lock, NULL);
- if (r < 0) {
- log_error_errno(r, "Cannot initialize shared policy mutex: %m");
+ if (r != 0) {
+ r = log_error_errno(r, "Cannot initialize shared policy mutex: %m");
goto exit_free;
}
r = pthread_rwlock_init(&sp->rwlock, NULL);
- if (r < 0) {
- log_error_errno(r, "Cannot initialize shared policy rwlock: %m");
+ if (r != 0) {
+ r = log_error_errno(r, "Cannot initialize shared policy rwlock: %m");
goto exit_mutex;
}
diff --git a/src/bus-proxyd/proxy.c b/src/bus-proxyd/proxy.c
index 88800f5e7f..bc8516f5c6 100644
--- a/src/bus-proxyd/proxy.c
+++ b/src/bus-proxyd/proxy.c
@@ -100,18 +100,24 @@ static int proxy_create_destination(Proxy *p, const char *destination, const cha
return 0;
}
-static int proxy_create_local(Proxy *p, int in_fd, int out_fd, bool negotiate_fds) {
- _cleanup_bus_flush_close_unref_ sd_bus *b = NULL;
+static int proxy_create_local(Proxy *p, bool negotiate_fds) {
sd_id128_t server_id;
+ sd_bus *b;
int r;
r = sd_bus_new(&b);
if (r < 0)
return log_error_errno(r, "Failed to allocate bus: %m");
- r = sd_bus_set_fd(b, in_fd, out_fd);
- if (r < 0)
+ r = sd_bus_set_fd(b, p->local_in, p->local_out);
+ if (r < 0) {
+ sd_bus_unref(b);
return log_error_errno(r, "Failed to set fds: %m");
+ }
+
+ /* The fds are now owned by the bus, and we indicate that by
+ * storing the bus object in the proxy object. */
+ p->local_bus = b;
r = sd_bus_get_bus_id(p->destination_bus, &server_id);
if (r < 0)
@@ -139,8 +145,6 @@ static int proxy_create_local(Proxy *p, int in_fd, int out_fd, bool negotiate_fd
if (r < 0)
return log_error_errno(r, "Failed to start bus client: %m");
- p->local_bus = b;
- b = NULL;
return 0;
}
@@ -224,9 +228,17 @@ int proxy_new(Proxy **out, int in_fd, int out_fd, const char *destination) {
bool is_unix;
int r;
+ /* This takes possession/destroys the file descriptors passed
+ * in even on failure. The caller should hence forget about
+ * the fds in all cases after calling this function and not
+ * close them. */
+
p = new0(Proxy, 1);
- if (!p)
+ if (!p) {
+ safe_close(in_fd);
+ safe_close(out_fd);
return log_oom();
+ }
p->local_in = in_fd;
p->local_out = out_fd;
@@ -247,7 +259,7 @@ int proxy_new(Proxy **out, int in_fd, int out_fd, const char *destination) {
if (r < 0)
return r;
- r = proxy_create_local(p, in_fd, out_fd, is_unix);
+ r = proxy_create_local(p, is_unix);
if (r < 0)
return r;
@@ -257,6 +269,7 @@ int proxy_new(Proxy **out, int in_fd, int out_fd, const char *destination) {
*out = p;
p = NULL;
+
return 0;
}
@@ -273,7 +286,14 @@ Proxy *proxy_free(Proxy *p) {
free(activation);
}
- sd_bus_flush_close_unref(p->local_bus);
+ if (p->local_bus)
+ sd_bus_flush_close_unref(p->local_bus);
+ else {
+ safe_close(p->local_in);
+ if (p->local_out != p->local_in)
+ safe_close(p->local_out);
+ }
+
sd_bus_flush_close_unref(p->destination_bus);
set_free_free(p->owned_names);
free(p);
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
index 436229330e..2662b07525 100644
--- a/src/core/dbus-execute.c
+++ b/src/core/dbus-execute.c
@@ -1186,6 +1186,24 @@ int bus_exec_context_set_transient_property(
return 1;
+ } else if (streq(name, "OOMScoreAdjust")) {
+ int oa;
+
+ r = sd_bus_message_read(message, "i", &oa);
+ if (r < 0)
+ return r;
+
+ if (!oom_score_adjust_is_valid(oa))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "OOM score adjust value out of range");
+
+ if (mode != UNIT_CHECK) {
+ c->oom_score_adjust = oa;
+ c->oom_score_adjust_set = true;
+ unit_write_drop_in_private_format(u, mode, name, "OOMScoreAdjust=%i\n", oa);
+ }
+
+ return 1;
+
} else if (rlimit_from_string(name) >= 0) {
uint64_t rl;
rlim_t x;
diff --git a/src/core/dbus.c b/src/core/dbus.c
index 2d6a1ff836..d8891d49d8 100644
--- a/src/core/dbus.c
+++ b/src/core/dbus.c
@@ -777,7 +777,7 @@ static int bus_setup_api(Manager *m, sd_bus *bus) {
return r;
HASHMAP_FOREACH_KEY(u, name, m->watch_bus, i) {
- r = unit_install_bus_match(bus, u, name);
+ r = unit_install_bus_match(u, bus, name);
if (r < 0)
log_error_errno(r, "Failed to subscribe to NameOwnerChanged signal: %m");
}
diff --git a/src/core/execute.c b/src/core/execute.c
index d6217840c0..51efb7c215 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -2314,7 +2314,7 @@ static void strv_fprintf(FILE *f, char **l) {
}
void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
- char **e;
+ char **e, **d;
unsigned i;
assert(c);
@@ -2350,6 +2350,11 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
STRV_FOREACH(e, c->environment_files)
fprintf(f, "%sEnvironmentFile: %s\n", prefix, *e);
+ fprintf(f, "%sRuntimeDirectoryMode: %04o\n", prefix, c->runtime_directory_mode);
+
+ STRV_FOREACH(d, c->runtime_directory)
+ fprintf(f, "%sRuntimeDirectory: %s\n", prefix, *d);
+
if (c->nice_set)
fprintf(f,
"%sNice: %i\n",
diff --git a/src/core/unit.c b/src/core/unit.c
index 39cd89f1e3..d8f0eb8111 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -2508,26 +2508,23 @@ static int signal_name_owner_changed(sd_bus_message *message, void *userdata, sd
return 0;
}
-int unit_install_bus_match(sd_bus *bus, Unit *u, const char *name) {
- _cleanup_free_ char *match = NULL;
- Manager *m = u->manager;
+int unit_install_bus_match(Unit *u, sd_bus *bus, const char *name) {
+ const char *match;
- assert(m);
+ assert(u);
+ assert(bus);
+ assert(name);
if (u->match_bus_slot)
return -EBUSY;
- match = strjoin("type='signal',"
+ match = strjoina("type='signal',"
"sender='org.freedesktop.DBus',"
"path='/org/freedesktop/DBus',"
"interface='org.freedesktop.DBus',"
"member='NameOwnerChanged',"
- "arg0='",
- name,
- "'",
+ "arg0='", name, "'",
NULL);
- if (!match)
- return -ENOMEM;
return sd_bus_add_match(bus, &u->match_bus_slot, match, signal_name_owner_changed, u);
}
@@ -2544,7 +2541,7 @@ int unit_watch_bus_name(Unit *u, const char *name) {
if (u->manager->api_bus) {
/* If the bus is already available, install the match directly.
* Otherwise, just put the name in the list. bus_setup_api() will take care later. */
- r = unit_install_bus_match(u->manager->api_bus, u, name);
+ r = unit_install_bus_match(u, u->manager->api_bus, name);
if (r < 0)
return log_warning_errno(r, "Failed to subscribe to NameOwnerChanged signal: %m");
}
diff --git a/src/core/unit.h b/src/core/unit.h
index a4a1b011fc..9f8518c720 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -520,7 +520,7 @@ void unit_unwatch_all_pids(Unit *u);
void unit_tidy_watch_pids(Unit *u, pid_t except1, pid_t except2);
-int unit_install_bus_match(sd_bus *bus, Unit *u, const char *name);
+int unit_install_bus_match(Unit *u, sd_bus *bus, const char *name);
int unit_watch_bus_name(Unit *u, const char *name);
void unit_unwatch_bus_name(Unit *u, const char *name);
diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c
index 577a8b44c3..570d35c7ad 100644
--- a/src/libsystemd/sd-bus/bus-kernel.c
+++ b/src/libsystemd/sd-bus/bus-kernel.c
@@ -1433,12 +1433,12 @@ int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *al
if (!bus || !bus->is_kernel)
return -EOPNOTSUPP;
- assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
+ assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) == 0);
if (bus->n_memfd_cache <= 0) {
int r;
- assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
+ assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0);
r = memfd_new(bus->description);
if (r < 0)
@@ -1460,7 +1460,7 @@ int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *al
*allocated = c->allocated;
fd = c->fd;
- assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
+ assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0);
return fd;
}
@@ -1484,10 +1484,10 @@ void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t mapped, si
return;
}
- assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) >= 0);
+ assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) == 0);
if (bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
- assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
+ assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0);
close_and_munmap(fd, address, mapped);
return;
@@ -1507,7 +1507,7 @@ void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t mapped, si
c->allocated = allocated;
}
- assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) >= 0);
+ assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0);
}
void bus_kernel_flush_memfd(sd_bus *b) {
diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
index 1a82c4c940..1905ebfc73 100644
--- a/src/libsystemd/sd-event/sd-event.c
+++ b/src/libsystemd/sd-event/sd-event.c
@@ -1123,8 +1123,8 @@ _public_ int sd_event_add_signal(
callback = signal_exit_callback;
r = pthread_sigmask(SIG_SETMASK, NULL, &ss);
- if (r < 0)
- return -errno;
+ if (r != 0)
+ return -r;
if (!sigismember(&ss, sig))
return -EBUSY;
diff --git a/src/libsystemd/sd-netlink/netlink-internal.h b/src/libsystemd/sd-netlink/netlink-internal.h
index 4026e2c341..b9cb80668d 100644
--- a/src/libsystemd/sd-netlink/netlink-internal.h
+++ b/src/libsystemd/sd-netlink/netlink-internal.h
@@ -64,6 +64,9 @@ struct sd_netlink {
struct sockaddr_nl nl;
} sockaddr;
+ Hashmap *broadcast_group_refs;
+ bool broadcast_group_dont_leave:1; /* until we can rely on 4.2 */
+
sd_netlink_message **rqueue;
unsigned rqueue_size;
size_t rqueue_allocated;
@@ -124,7 +127,8 @@ int message_new_empty(sd_netlink *rtnl, sd_netlink_message **ret);
int socket_open(int family);
int socket_bind(sd_netlink *nl);
-int socket_join_broadcast_group(sd_netlink *nl, unsigned group);
+int socket_broadcast_group_ref(sd_netlink *nl, unsigned group);
+int socket_broadcast_group_unref(sd_netlink *nl, unsigned group);
int socket_write_message(sd_netlink *nl, sd_netlink_message *m);
int socket_read_message(sd_netlink *nl);
diff --git a/src/libsystemd/sd-netlink/netlink-socket.c b/src/libsystemd/sd-netlink/netlink-socket.c
index 84ff7c38c9..e1b14c3ed2 100644
--- a/src/libsystemd/sd-netlink/netlink-socket.c
+++ b/src/libsystemd/sd-netlink/netlink-socket.c
@@ -44,6 +44,65 @@ int socket_open(int family) {
return fd;
}
+static int broadcast_groups_get(sd_netlink *nl) {
+ _cleanup_free_ uint32_t *groups = NULL;
+ socklen_t len = 0, old_len;
+ unsigned i, j;
+ int r;
+
+ assert(nl);
+ assert(nl->fd > 0);
+
+ r = getsockopt(nl->fd, SOL_NETLINK, NETLINK_LIST_MEMBERSHIPS, NULL, &len);
+ if (r < 0) {
+ if (errno == ENOPROTOOPT) {
+ nl->broadcast_group_dont_leave = true;
+ return 0;
+ } else
+ return -errno;
+ }
+
+ if (len == 0)
+ return 0;
+
+ groups = new0(uint32_t, len);
+ if (!groups)
+ return -ENOMEM;
+
+ old_len = len;
+
+ r = getsockopt(nl->fd, SOL_NETLINK, NETLINK_LIST_MEMBERSHIPS, groups, &len);
+ if (r < 0)
+ return -errno;
+
+ if (old_len != len)
+ return -EIO;
+
+ r = hashmap_ensure_allocated(&nl->broadcast_group_refs, NULL);
+ if (r < 0)
+ return r;
+
+ for (i = 0; i < len; i++) {
+ for (j = 0; j < sizeof(uint32_t) * 8; j ++) {
+ uint32_t offset;
+ unsigned group;
+
+ offset = 1U << j;
+
+ if (!(groups[i] & offset))
+ continue;
+
+ group = i * sizeof(uint32_t) * 8 + j + 1;
+
+ r = hashmap_put(nl->broadcast_group_refs, UINT_TO_PTR(group), UINT_TO_PTR(1));
+ if (r < 0)
+ return r;
+ }
+ }
+
+ return 0;
+}
+
int socket_bind(sd_netlink *nl) {
socklen_t addrlen;
int r, one = 1;
@@ -63,11 +122,32 @@ int socket_bind(sd_netlink *nl) {
if (r < 0)
return -errno;
+ r = broadcast_groups_get(nl);
+ if (r < 0)
+ return r;
+
return 0;
}
+static unsigned broadcast_group_get_ref(sd_netlink *nl, unsigned group) {
+ assert(nl);
+
+ return PTR_TO_UINT(hashmap_get(nl->broadcast_group_refs, UINT_TO_PTR(group)));
+}
-int socket_join_broadcast_group(sd_netlink *nl, unsigned group) {
+static int broadcast_group_set_ref(sd_netlink *nl, unsigned group, unsigned n_ref) {
+ int r;
+
+ assert(nl);
+
+ r = hashmap_replace(nl->broadcast_group_refs, UINT_TO_PTR(group), UINT_TO_PTR(n_ref));
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static int broadcast_group_join(sd_netlink *nl, unsigned group) {
int r;
assert(nl);
@@ -81,6 +161,79 @@ int socket_join_broadcast_group(sd_netlink *nl, unsigned group) {
return 0;
}
+int socket_broadcast_group_ref(sd_netlink *nl, unsigned group) {
+ unsigned n_ref;
+ int r;
+
+ assert(nl);
+
+ n_ref = broadcast_group_get_ref(nl, group);
+
+ n_ref ++;
+
+ r = hashmap_ensure_allocated(&nl->broadcast_group_refs, NULL);
+ if (r < 0)
+ return r;
+
+ r = broadcast_group_set_ref(nl, group, n_ref);
+ if (r < 0)
+ return r;
+
+ if (n_ref > 1)
+ /* not yet in the group */
+ return 0;
+
+ r = broadcast_group_join(nl, group);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static int broadcast_group_leave(sd_netlink *nl, unsigned group) {
+ int r;
+
+ assert(nl);
+ assert(nl->fd >= 0);
+ assert(group > 0);
+
+ if (nl->broadcast_group_dont_leave)
+ return 0;
+
+ r = setsockopt(nl->fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP, &group, sizeof(group));
+ if (r < 0)
+ return -errno;
+
+ return 0;
+}
+
+int socket_broadcast_group_unref(sd_netlink *nl, unsigned group) {
+ unsigned n_ref;
+ int r;
+
+ assert(nl);
+
+ n_ref = broadcast_group_get_ref(nl, group);
+
+ assert(n_ref > 0);
+
+ n_ref --;
+
+ r = broadcast_group_set_ref(nl, group, n_ref);
+ if (r < 0)
+ return r;
+
+ if (n_ref > 0)
+ /* still refs left */
+ return 0;
+
+ r = broadcast_group_leave(nl, group);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
/* returns the number of bytes sent, or a negative error code */
int socket_write_message(sd_netlink *nl, sd_netlink_message *m) {
union {
diff --git a/src/libsystemd/sd-netlink/sd-netlink.c b/src/libsystemd/sd-netlink/sd-netlink.c
index f4a0a358a9..5af28600ba 100644
--- a/src/libsystemd/sd-netlink/sd-netlink.c
+++ b/src/libsystemd/sd-netlink/sd-netlink.c
@@ -183,10 +183,11 @@ sd_netlink *sd_netlink_unref(sd_netlink *rtnl) {
sd_event_unref(rtnl->event);
while ((f = rtnl->match_callbacks)) {
- LIST_REMOVE(match_callbacks, rtnl->match_callbacks, f);
- free(f);
+ sd_netlink_remove_match(rtnl, f->type, f->callback, f->userdata);
}
+ hashmap_free(rtnl->broadcast_group_refs);
+
safe_close(rtnl->fd);
free(rtnl);
}
@@ -857,29 +858,29 @@ int sd_netlink_add_match(sd_netlink *rtnl,
switch (type) {
case RTM_NEWLINK:
case RTM_DELLINK:
- r = socket_join_broadcast_group(rtnl, RTNLGRP_LINK);
+ r = socket_broadcast_group_ref(rtnl, RTNLGRP_LINK);
if (r < 0)
return r;
break;
case RTM_NEWADDR:
case RTM_DELADDR:
- r = socket_join_broadcast_group(rtnl, RTNLGRP_IPV4_IFADDR);
+ r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV4_IFADDR);
if (r < 0)
return r;
- r = socket_join_broadcast_group(rtnl, RTNLGRP_IPV6_IFADDR);
+ r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV6_IFADDR);
if (r < 0)
return r;
break;
case RTM_NEWROUTE:
case RTM_DELROUTE:
- r = socket_join_broadcast_group(rtnl, RTNLGRP_IPV4_ROUTE);
+ r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV4_ROUTE);
if (r < 0)
return r;
- r = socket_join_broadcast_group(rtnl, RTNLGRP_IPV6_ROUTE);
+ r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV6_ROUTE);
if (r < 0)
return r;
break;
@@ -899,23 +900,50 @@ int sd_netlink_remove_match(sd_netlink *rtnl,
sd_netlink_message_handler_t callback,
void *userdata) {
struct match_callback *c;
+ int r;
assert_return(rtnl, -EINVAL);
assert_return(callback, -EINVAL);
assert_return(!rtnl_pid_changed(rtnl), -ECHILD);
- /* we should unsubscribe from the broadcast groups at this point, but it is not so
- trivial for a few reasons: the refcounting is a bit of a mess and not obvious
- how it will look like after we add genetlink support, and it is also not possible
- to query what broadcast groups were subscribed to when we inherit the socket to get
- the initial refcount. The latter could indeed be done for the first 32 broadcast
- groups (which incidentally is all we currently support in .socket units anyway),
- but we better not rely on only ever using 32 groups. */
LIST_FOREACH(match_callbacks, c, rtnl->match_callbacks)
if (c->callback == callback && c->type == type && c->userdata == userdata) {
LIST_REMOVE(match_callbacks, rtnl->match_callbacks, c);
free(c);
+ switch (type) {
+ case RTM_NEWLINK:
+ case RTM_DELLINK:
+ r = socket_broadcast_group_unref(rtnl, RTNLGRP_LINK);
+ if (r < 0)
+ return r;
+
+ break;
+ case RTM_NEWADDR:
+ case RTM_DELADDR:
+ r = socket_broadcast_group_unref(rtnl, RTNLGRP_IPV4_IFADDR);
+ if (r < 0)
+ return r;
+
+ r = socket_broadcast_group_unref(rtnl, RTNLGRP_IPV6_IFADDR);
+ if (r < 0)
+ return r;
+
+ break;
+ case RTM_NEWROUTE:
+ case RTM_DELROUTE:
+ r = socket_broadcast_group_unref(rtnl, RTNLGRP_IPV4_ROUTE);
+ if (r < 0)
+ return r;
+
+ r = socket_broadcast_group_unref(rtnl, RTNLGRP_IPV6_ROUTE);
+ if (r < 0)
+ return r;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
return 1;
}
diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c
index a5d6edbba9..78d6b0eb27 100644
--- a/src/shared/bus-util.c
+++ b/src/shared/bus-util.c
@@ -1665,6 +1665,21 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
}
r = sd_bus_message_append(m, "v", "t", n);
+ } else if (streq(field, "OOMScoreAdjust")) {
+ int oa;
+
+ r = safe_atoi(eq, &oa);
+ if (r < 0) {
+ log_error("Failed to parse %s value %s", field, eq);
+ return -EINVAL;
+ }
+
+ if (!oom_score_adjust_is_valid(oa)) {
+ log_error("OOM score adjust value out of range");
+ return -EINVAL;
+ }
+
+ r = sd_bus_message_append(m, "v", "i", oa);
} else {
log_error("Unknown assignment %s.", assignment);
return -EINVAL;
diff --git a/units/tmp.mount.m4 b/units/tmp.mount
index d537746dbf..00a0d28722 100644
--- a/units/tmp.mount.m4
+++ b/units/tmp.mount
@@ -18,6 +18,4 @@ Before=local-fs.target umount.target
What=tmpfs
Where=/tmp
Type=tmpfs
-m4_ifdef(`HAVE_SMACK',
-`Options=mode=1777,strictatime,smackfsroot=*',
-`Options=mode=1777,strictatime')
+Options=mode=1777,strictatime