diff options
Diffstat (limited to 'src/basic')
-rw-r--r-- | src/basic/cgroup-util.c | 83 | ||||
-rw-r--r-- | src/basic/cgroup-util.h | 20 | ||||
-rw-r--r-- | src/basic/fileio.c | 3 | ||||
-rw-r--r-- | src/basic/missing.h | 4 | ||||
-rw-r--r-- | src/basic/missing_syscall.h | 2 | ||||
-rw-r--r-- | src/basic/mount-util.c | 33 | ||||
-rw-r--r-- | src/basic/nss-util.h | 2 | ||||
-rw-r--r-- | src/basic/process-util.c | 6 | ||||
-rw-r--r-- | src/basic/util.c | 96 | ||||
-rw-r--r-- | src/basic/util.h | 5 |
10 files changed, 168 insertions, 86 deletions
diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 7cdc97ee3c..302b958d0d 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -134,6 +134,20 @@ int cg_read_event(const char *controller, const char *path, const char *event, return -ENOENT; } +bool cg_ns_supported(void) { + static thread_local int enabled = -1; + + if (enabled >= 0) + return enabled; + + if (access("/proc/self/ns/cgroup", F_OK) == 0) + enabled = 1; + else + enabled = 0; + + return enabled; +} + int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d) { _cleanup_free_ char *fs = NULL; int r; @@ -197,7 +211,15 @@ int cg_rmdir(const char *controller, const char *path) { return 0; } -int cg_kill(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, Set *s) { +int cg_kill( + const char *controller, + const char *path, + int sig, + CGroupFlags flags, + Set *s, + cg_kill_log_func_t log_kill, + void *userdata) { + _cleanup_set_free_ Set *allocated_set = NULL; bool done = false; int r, ret = 0; @@ -205,6 +227,11 @@ int cg_kill(const char *controller, const char *path, int sig, bool sigcont, boo assert(sig >= 0); + /* Don't send SIGCONT twice. Also, SIGKILL always works even when process is suspended, hence don't send + * SIGCONT on SIGKILL. */ + if (IN_SET(sig, SIGCONT, SIGKILL)) + flags &= ~CGROUP_SIGCONT; + /* This goes through the tasks list and kills them all. This * is repeated until no further processes are added to the * tasks list, to properly handle forking processes */ @@ -232,19 +259,22 @@ int cg_kill(const char *controller, const char *path, int sig, bool sigcont, boo while ((r = cg_read_pid(f, &pid)) > 0) { - if (ignore_self && pid == my_pid) + if ((flags & CGROUP_IGNORE_SELF) && pid == my_pid) continue; if (set_get(s, PID_TO_PTR(pid)) == PID_TO_PTR(pid)) continue; + if (log_kill) + log_kill(pid, sig, userdata); + /* If we haven't killed this process yet, kill * it */ if (kill(pid, sig) < 0) { if (ret >= 0 && errno != ESRCH) ret = -errno; } else { - if (sigcont && sig != SIGKILL) + if (flags & CGROUP_SIGCONT) (void) kill(pid, SIGCONT); if (ret == 0) @@ -278,7 +308,15 @@ int cg_kill(const char *controller, const char *path, int sig, bool sigcont, boo return ret; } -int cg_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool rem, Set *s) { +int cg_kill_recursive( + const char *controller, + const char *path, + int sig, + CGroupFlags flags, + Set *s, + cg_kill_log_func_t log_kill, + void *userdata) { + _cleanup_set_free_ Set *allocated_set = NULL; _cleanup_closedir_ DIR *d = NULL; int r, ret; @@ -293,7 +331,7 @@ int cg_kill_recursive(const char *controller, const char *path, int sig, bool si return -ENOMEM; } - ret = cg_kill(controller, path, sig, sigcont, ignore_self, s); + ret = cg_kill(controller, path, sig, flags, s, log_kill, userdata); r = cg_enumerate_subgroups(controller, path, &d); if (r < 0) { @@ -311,15 +349,14 @@ int cg_kill_recursive(const char *controller, const char *path, int sig, bool si if (!p) return -ENOMEM; - r = cg_kill_recursive(controller, p, sig, sigcont, ignore_self, rem, s); + r = cg_kill_recursive(controller, p, sig, flags, s, log_kill, userdata); if (r != 0 && ret >= 0) ret = r; } - if (ret >= 0 && r < 0) ret = r; - if (rem) { + if (flags & CGROUP_REMOVE) { r = cg_rmdir(controller, path); if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY) return r; @@ -328,7 +365,13 @@ int cg_kill_recursive(const char *controller, const char *path, int sig, bool si return ret; } -int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self) { +int cg_migrate( + const char *cfrom, + const char *pfrom, + const char *cto, + const char *pto, + CGroupFlags flags) { + bool done = false; _cleanup_set_free_ Set *s = NULL; int r, ret = 0; @@ -363,7 +406,7 @@ int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char /* This might do weird stuff if we aren't a * single-threaded program. However, we * luckily know we are not */ - if (ignore_self && pid == my_pid) + if ((flags & CGROUP_IGNORE_SELF) && pid == my_pid) continue; if (set_get(s, PID_TO_PTR(pid)) == PID_TO_PTR(pid)) @@ -411,8 +454,7 @@ int cg_migrate_recursive( const char *pfrom, const char *cto, const char *pto, - bool ignore_self, - bool rem) { + CGroupFlags flags) { _cleanup_closedir_ DIR *d = NULL; int r, ret = 0; @@ -423,7 +465,7 @@ int cg_migrate_recursive( assert(cto); assert(pto); - ret = cg_migrate(cfrom, pfrom, cto, pto, ignore_self); + ret = cg_migrate(cfrom, pfrom, cto, pto, flags); r = cg_enumerate_subgroups(cfrom, pfrom, &d); if (r < 0) { @@ -441,7 +483,7 @@ int cg_migrate_recursive( if (!p) return -ENOMEM; - r = cg_migrate_recursive(cfrom, p, cto, pto, ignore_self, rem); + r = cg_migrate_recursive(cfrom, p, cto, pto, flags); if (r != 0 && ret >= 0) ret = r; } @@ -449,7 +491,7 @@ int cg_migrate_recursive( if (r < 0 && ret >= 0) ret = r; - if (rem) { + if (flags & CGROUP_REMOVE) { r = cg_rmdir(cfrom, pfrom); if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY) return r; @@ -463,8 +505,7 @@ int cg_migrate_recursive_fallback( const char *pfrom, const char *cto, const char *pto, - bool ignore_self, - bool rem) { + CGroupFlags flags) { int r; @@ -473,7 +514,7 @@ int cg_migrate_recursive_fallback( assert(cto); assert(pto); - r = cg_migrate_recursive(cfrom, pfrom, cto, pto, ignore_self, rem); + r = cg_migrate_recursive(cfrom, pfrom, cto, pto, flags); if (r < 0) { char prefix[strlen(pto) + 1]; @@ -482,7 +523,7 @@ int cg_migrate_recursive_fallback( PATH_FOREACH_PREFIX(prefix, pto) { int q; - q = cg_migrate_recursive(cfrom, pfrom, cto, prefix, ignore_self, rem); + q = cg_migrate_recursive(cfrom, pfrom, cto, prefix, flags); if (q >= 0) return q; } @@ -1955,7 +1996,7 @@ int cg_migrate_everywhere(CGroupMask supported, const char *from, const char *to int r = 0, unified; if (!path_equal(from, to)) { - r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, from, SYSTEMD_CGROUP_CONTROLLER, to, false, true); + r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, from, SYSTEMD_CGROUP_CONTROLLER, to, CGROUP_REMOVE); if (r < 0) return r; } @@ -1979,7 +2020,7 @@ int cg_migrate_everywhere(CGroupMask supported, const char *from, const char *to if (!p) p = to; - (void) cg_migrate_recursive_fallback(SYSTEMD_CGROUP_CONTROLLER, to, cgroup_controller_to_string(c), p, false, false); + (void) cg_migrate_recursive_fallback(SYSTEMD_CGROUP_CONTROLLER, to, cgroup_controller_to_string(c), p, 0); } return 0; diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index 4bb5291296..ec5c715987 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -135,12 +135,20 @@ int cg_read_event(const char *controller, const char *path, const char *event, int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d); int cg_read_subgroup(DIR *d, char **fn); -int cg_kill(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, Set *s); -int cg_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool remove, Set *s); +typedef enum CGroupFlags { + CGROUP_SIGCONT = 1, + CGROUP_IGNORE_SELF = 2, + CGROUP_REMOVE = 4, +} CGroupFlags; -int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self); -int cg_migrate_recursive(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self, bool remove); -int cg_migrate_recursive_fallback(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self, bool rem); +typedef void (*cg_kill_log_func_t)(pid_t pid, int sig, void *userdata); + +int cg_kill(const char *controller, const char *path, int sig, CGroupFlags flags, Set *s, cg_kill_log_func_t kill_log, void *userdata); +int cg_kill_recursive(const char *controller, const char *path, int sig, CGroupFlags flags, Set *s, cg_kill_log_func_t kill_log, void *userdata); + +int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, CGroupFlags flags); +int cg_migrate_recursive(const char *cfrom, const char *pfrom, const char *cto, const char *pto, CGroupFlags flags); +int cg_migrate_recursive_fallback(const char *cfrom, const char *pfrom, const char *cto, const char *pto, CGroupFlags flags); int cg_split_spec(const char *spec, char **controller, char **path); int cg_mangle_path(const char *path, char **result); @@ -214,6 +222,8 @@ int cg_mask_supported(CGroupMask *ret); int cg_kernel_controllers(Set *controllers); +bool cg_ns_supported(void); + int cg_unified(void); void cg_unified_flush(void); diff --git a/src/basic/fileio.c b/src/basic/fileio.c index 47ccfc39d8..f183de4999 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -1259,7 +1259,8 @@ int open_tmpfile_unlinkable(const char *directory, int flags) { char *p; int fd; - assert(directory); + if (!directory) + directory = "/tmp"; /* Returns an unlinked temporary file that cannot be linked into the file system anymore */ diff --git a/src/basic/missing.h b/src/basic/missing.h index b1272f8799..f8e096605e 100644 --- a/src/basic/missing.h +++ b/src/basic/missing.h @@ -445,6 +445,10 @@ struct btrfs_ioctl_quota_ctl_args { #define CGROUP2_SUPER_MAGIC 0x63677270 #endif +#ifndef CLONE_NEWCGROUP +#define CLONE_NEWCGROUP 0x02000000 +#endif + #ifndef TMPFS_MAGIC #define TMPFS_MAGIC 0x01021994 #endif diff --git a/src/basic/missing_syscall.h b/src/basic/missing_syscall.h index e102083684..e6fd67cb9d 100644 --- a/src/basic/missing_syscall.h +++ b/src/basic/missing_syscall.h @@ -279,6 +279,8 @@ static inline key_serial_t request_key(const char *type, const char *description # define __NR_copy_file_range 391 # elif defined __aarch64__ # define __NR_copy_file_range 285 +# elif defined __powerpc__ +# define __NR_copy_file_range 379 # else # warning "__NR_copy_file_range not defined for your architecture" # endif diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c index 63dff3dd5c..28dc778969 100644 --- a/src/basic/mount-util.c +++ b/src/basic/mount-util.c @@ -448,21 +448,21 @@ int bind_remount_recursive(const char *prefix, bool ro) { if (r < 0) return r; - /* Try to reuse the original flag set, but - * don't care for errors, in case of - * obstructed mounts */ + /* Deal with mount points that are obstructed by a + * later mount */ + r = path_is_mount_point(x, 0); + if (r == -ENOENT || r == 0) + continue; + if (r < 0) + return r; + + /* Try to reuse the original flag set */ orig_flags = 0; (void) get_mount_flags(x, &orig_flags); orig_flags &= ~MS_RDONLY; - if (mount(NULL, x, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0) { - - /* Deal with mount points that are - * obstructed by a later mount */ - - if (errno != ENOENT) - return -errno; - } + if (mount(NULL, x, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0) + return -errno; } } @@ -534,15 +534,22 @@ int repeat_unmount(const char *path, int flags) { } const char* mode_to_inaccessible_node(mode_t mode) { + /* This function maps a node type to the correspondent inaccessible node type. + * Character and block inaccessible devices may not be created (because major=0 and minor=0), + * in such case we map character and block devices to the inaccessible node type socket. */ switch(mode & S_IFMT) { case S_IFREG: return "/run/systemd/inaccessible/reg"; case S_IFDIR: return "/run/systemd/inaccessible/dir"; case S_IFCHR: - return "/run/systemd/inaccessible/chr"; + if (access("/run/systemd/inaccessible/chr", F_OK) == 0) + return "/run/systemd/inaccessible/chr"; + return "/run/systemd/inaccessible/sock"; case S_IFBLK: - return "/run/systemd/inaccessible/blk"; + if (access("/run/systemd/inaccessible/blk", F_OK) == 0) + return "/run/systemd/inaccessible/blk"; + return "/run/systemd/inaccessible/sock"; case S_IFIFO: return "/run/systemd/inaccessible/fifo"; case S_IFSOCK: diff --git a/src/basic/nss-util.h b/src/basic/nss-util.h index bf7c4854fc..e7844fff96 100644 --- a/src/basic/nss-util.h +++ b/src/basic/nss-util.h @@ -137,7 +137,7 @@ enum nss_status _nss_##module##_getpwnam_r( \ struct passwd *pwd, \ char *buffer, size_t buflen, \ int *errnop) _public_; \ -enum nss_status _nss_mymachines_getpwuid_r( \ +enum nss_status _nss_##module##_getpwuid_r( \ uid_t uid, \ struct passwd *pwd, \ char *buffer, size_t buflen, \ diff --git a/src/basic/process-util.c b/src/basic/process-util.c index e38b67405e..54b644ad56 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -625,8 +625,10 @@ int kill_and_sigcont(pid_t pid, int sig) { r = kill(pid, sig) < 0 ? -errno : 0; - if (r >= 0) - kill(pid, SIGCONT); + /* If this worked, also send SIGCONT, unless we already just sent a SIGCONT, or SIGKILL was sent which isn't + * affected by a process being suspended anyway. */ + if (r >= 0 && !IN_SET(SIGCONT, SIGKILL)) + (void) kill(pid, SIGCONT); return r; } diff --git a/src/basic/util.c b/src/basic/util.c index 09d16697b7..9d66d28eb7 100644 --- a/src/basic/util.c +++ b/src/basic/util.c @@ -581,47 +581,6 @@ int on_ac_power(void) { return found_online || !found_offline; } -bool id128_is_valid(const char *s) { - size_t i, l; - - l = strlen(s); - if (l == 32) { - - /* Simple formatted 128bit hex string */ - - for (i = 0; i < l; i++) { - char c = s[i]; - - if (!(c >= '0' && c <= '9') && - !(c >= 'a' && c <= 'z') && - !(c >= 'A' && c <= 'Z')) - return false; - } - - } else if (l == 36) { - - /* Formatted UUID */ - - for (i = 0; i < l; i++) { - char c = s[i]; - - if ((i == 8 || i == 13 || i == 18 || i == 23)) { - if (c != '-') - return false; - } else { - if (!(c >= '0' && c <= '9') && - !(c >= 'a' && c <= 'z') && - !(c >= 'A' && c <= 'Z')) - return false; - } - } - - } else - return false; - - return true; -} - int container_get_leader(const char *machine, pid_t *pid) { _cleanup_free_ char *s = NULL, *class = NULL; const char *p; @@ -832,6 +791,61 @@ uint64_t physical_memory_scale(uint64_t v, uint64_t max) { return r; } +uint64_t system_tasks_max(void) { + +#if SIZEOF_PID_T == 4 +#define TASKS_MAX ((uint64_t) (INT32_MAX-1)) +#elif SIZEOF_PID_T == 2 +#define TASKS_MAX ((uint64_t) (INT16_MAX-1)) +#else +#error "Unknown pid_t size" +#endif + + _cleanup_free_ char *value = NULL, *root = NULL; + uint64_t a = TASKS_MAX, b = TASKS_MAX; + + /* Determine the maximum number of tasks that may run on this system. We check three sources to determine this + * limit: + * + * a) the maximum value for the pid_t type + * b) the cgroups pids_max attribute for the system + * c) the kernel's configure maximum PID value + * + * And then pick the smallest of the three */ + + if (read_one_line_file("/proc/sys/kernel/pid_max", &value) >= 0) + (void) safe_atou64(value, &a); + + if (cg_get_root_path(&root) >= 0) { + value = mfree(value); + + if (cg_get_attribute("pids", root, "pids.max", &value) >= 0) + (void) safe_atou64(value, &b); + } + + return MIN3(TASKS_MAX, + a <= 0 ? TASKS_MAX : a, + b <= 0 ? TASKS_MAX : b); +} + +uint64_t system_tasks_max_scale(uint64_t v, uint64_t max) { + uint64_t t, m; + + assert(max > 0); + + /* Multiply the system's task value by the fraction v/max. Hence, if max==100 this calculates percentages + * relative to the system's maximum number of tasks. Returns UINT64_MAX on overflow. */ + + t = system_tasks_max(); + assert(t > 0); + + m = t * v; + if (m / t != v) /* overflow? */ + return UINT64_MAX; + + return m / max; +} + int update_reboot_parameter_and_warn(const char *param) { int r; diff --git a/src/basic/util.h b/src/basic/util.h index db105197e8..44497dcd78 100644 --- a/src/basic/util.h +++ b/src/basic/util.h @@ -176,8 +176,6 @@ static inline unsigned log2u_round_up(unsigned x) { return log2u(x - 1) + 1; } -bool id128_is_valid(const char *s) _pure_; - int container_get_leader(const char *machine, pid_t *pid); int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd); @@ -186,6 +184,9 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int uint64_t physical_memory(void); uint64_t physical_memory_scale(uint64_t v, uint64_t max); +uint64_t system_tasks_max(void); +uint64_t system_tasks_max_scale(uint64_t v, uint64_t max); + int update_reboot_parameter_and_warn(const char *param); int version(void); |