From c60d32aa37fc0b10451b0d392d90b3b96eb88ebc Mon Sep 17 00:00:00 2001 From: Sven Eden Date: Wed, 14 Jun 2017 17:44:53 +0200 Subject: [PATCH] Prep v231: Apply missing fixes from upstream (1/6) src/basic --- src/basic/cgroup-util.c | 5 +- src/basic/cgroup-util.h | 2 +- src/basic/fileio.c | 41 ++++++++ src/basic/fileio.h | 2 + src/basic/fs-util.c | 28 ++++++ src/basic/fs-util.h | 2 + src/basic/hashmap.c | 25 +++++ src/basic/missing.h | 3 + src/basic/missing_syscall.h | 12 --- src/basic/mkdir.c | 4 +- src/basic/mount-util.c | 25 +++++ src/basic/process-util.c | 2 +- src/basic/raw-clone.h | 8 +- src/basic/set.h | 1 + src/basic/strv.c | 29 +++++- src/basic/terminal-util.c | 17 +++- src/basic/terminal-util.h | 2 + src/basic/time-util.c | 74 +++++++++++++++ src/basic/time-util.h | 27 +++++- src/basic/umask-util.h | 2 - src/basic/util.c | 180 +++++++++++++++++++++++++----------- src/basic/util.h | 7 +- 22 files changed, 409 insertions(+), 89 deletions(-) diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index c98c1c400..73134caa5 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -376,7 +376,8 @@ int cg_migrate( log_debug_elogind("Migrating \"%s\"/\"%s\" to \"%s\"/\"%s\" (%s)", cfrom, pfrom, cto, pto, - ignore_self ? "ignoring self" : "watching self"); + (flags & CGROUP_IGNORE_SELF) + ? "ignoring self" : "watching self"); do { _cleanup_fclose_ FILE *f = NULL; pid_t pid = 0; @@ -1925,7 +1926,6 @@ int cg_set_attribute(const char *controller, const char *path, const char *attri return write_string_file(p, value, 0); } -#if 0 /// UNNEEDED by elogind int cg_get_attribute(const char *controller, const char *path, const char *attribute, char **ret) { _cleanup_free_ char *p = NULL; int r; @@ -1937,6 +1937,7 @@ int cg_get_attribute(const char *controller, const char *path, const char *attri return read_one_line_file(p, ret); } +#if 0 /// UNNEEDED by elogind int cg_create_everywhere(CGroupMask supported, CGroupMask mask, const char *path) { CGroupController c; int r, unified; diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index 58f0eafdc..56598d22b 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -170,9 +170,9 @@ int cg_attach_fallback(const char *controller, const char *path, pid_t pid); int cg_create_and_attach(const char *controller, const char *path, pid_t pid); int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value); -#if 0 /// UNNEEDED by elogind int cg_get_attribute(const char *controller, const char *path, const char *attribute, char **ret); +#if 0 /// UNNEEDED by elogind int cg_set_group_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid); int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid); #endif // 0 diff --git a/src/basic/fileio.c b/src/basic/fileio.c index 42de50dcf..df432eaee 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -1361,3 +1361,44 @@ int link_tmpfile(int fd, const char *path, const char *target) { return 0; } #endif // 0 + +int read_nul_string(FILE *f, char **ret) { + _cleanup_free_ char *x = NULL; + size_t allocated = 0, n = 0; + + assert(f); + assert(ret); + + /* Reads a NUL-terminated string from the specified file. */ + + for (;;) { + int c; + + if (!GREEDY_REALLOC(x, allocated, n+2)) + return -ENOMEM; + + c = fgetc(f); + if (c == 0) /* Terminate at NUL byte */ + break; + if (c == EOF) { + if (ferror(f)) + return -errno; + break; /* Terminate at EOF */ + } + + x[n++] = (char) c; + } + + if (x) + x[n] = 0; + else { + x = new0(char, 1); + if (!x) + return -ENOMEM; + } + + *ret = x; + x = NULL; + + return 0; +} diff --git a/src/basic/fileio.h b/src/basic/fileio.h index 3c7b9c85b..2469b4ca4 100644 --- a/src/basic/fileio.h +++ b/src/basic/fileio.h @@ -92,3 +92,5 @@ int open_tmpfile_linkable(const char *target, int flags, char **ret_path); int link_tmpfile(int fd, const char *path, const char *target); #endif // 0 + +int read_nul_string(FILE *f, char **ret); diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index 426ad9761..d2d7bb566 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -501,6 +501,34 @@ int get_files_in_directory(const char *path, char ***list) { } #if 0 /// UNNEEDED by elogind +int var_tmp(char **ret) { + const char *tmp_dir = NULL; + const char *env_tmp_dir = NULL; + char *c = NULL; + int r; + + assert(ret); + + env_tmp_dir = getenv("TMPDIR"); + if (env_tmp_dir != NULL) { + r = is_dir(env_tmp_dir, true); + if (r < 0 && r != -ENOENT) + return r; + if (r > 0) + tmp_dir = env_tmp_dir; + } + + if (!tmp_dir) + tmp_dir = "/var/tmp"; + + c = strdup(tmp_dir); + if (!c) + return -ENOMEM; + *ret = c; + + return 0; +} + int inotify_add_watch_fd(int fd, int what, uint32_t mask) { char path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1]; int r; diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h index 2c5a65026..ab31f061e 100644 --- a/src/basic/fs-util.h +++ b/src/basic/fs-util.h @@ -73,6 +73,8 @@ int mkfifo_atomic(const char *path, mode_t mode); int get_files_in_directory(const char *path, char ***list); #if 0 /// UNNEEDED by elogind +int var_tmp(char **ret); + #define INOTIFY_EVENT_MAX (sizeof(struct inotify_event) + NAME_MAX + 1) #define FOREACH_INOTIFY_EVENT(e, buffer, sz) \ diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c index c89630f04..250fed534 100644 --- a/src/basic/hashmap.c +++ b/src/basic/hashmap.c @@ -1768,6 +1768,9 @@ void *ordered_hashmap_next(OrderedHashmap *h, const void *key) { int set_consume(Set *s, void *value) { int r; + assert(s); + assert(value); + r = set_put(s, value); if (r <= 0) free(value); @@ -1796,6 +1799,8 @@ int set_put_strdupv(Set *s, char **l) { int n = 0, r; char **i; + assert(s); + STRV_FOREACH(i, l) { r = set_put_strdup(s, *i); if (r < 0) @@ -1806,4 +1811,24 @@ int set_put_strdupv(Set *s, char **l) { return n; } + +int set_put_strsplit(Set *s, const char *v, const char *separators, ExtractFlags flags) { + const char *p = v; + int r; + + assert(s); + assert(v); + + for (;;) { + char *word; + + r = extract_first_word(&p, &word, separators, flags); + if (r <= 0) + return r; + + r = set_consume(s, word); + if (r < 0) + return r; + } +} #endif // 0 diff --git a/src/basic/missing.h b/src/basic/missing.h index 4a3b5ecb5..322cb5695 100644 --- a/src/basic/missing.h +++ b/src/basic/missing.h @@ -38,6 +38,7 @@ #include #include +/// Additional includes needed by elogind #include "musl_missing.h" #ifdef HAVE_AUDIT @@ -990,11 +991,13 @@ struct btrfs_ioctl_quota_ctl_args { #ifndef INPUT_PROP_ACCELEROMETER #define INPUT_PROP_ACCELEROMETER 0x06 #endif +#endif // 0 #ifndef HAVE_KEY_SERIAL_T typedef int32_t key_serial_t; #endif +#if 0 /// UNNEEDED by elogind #ifndef KEYCTL_READ #define KEYCTL_READ 11 #endif diff --git a/src/basic/missing_syscall.h b/src/basic/missing_syscall.h index 8a1c24cc5..84598c05b 100644 --- a/src/basic/missing_syscall.h +++ b/src/basic/missing_syscall.h @@ -181,18 +181,6 @@ static inline int setns(int fd, int nstype) { /* ======================================================================= */ #if 0 /// UNNEEDED by elogind -static inline int raw_clone(unsigned long flags, void *child_stack) { -#if defined(__s390__) || defined(__CRIS__) - /* On s390 and cris the order of the first and second arguments - * of the raw clone() system call is reversed. */ - return (int) syscall(__NR_clone, child_stack, flags); -#else - return (int) syscall(__NR_clone, flags, child_stack); -#endif -} - -/* ======================================================================= */ - static inline pid_t raw_getpid(void) { #if defined(__alpha__) return (pid_t) syscall(__NR_getxpid); diff --git a/src/basic/mkdir.c b/src/basic/mkdir.c index 62e9b082e..db1e83291 100644 --- a/src/basic/mkdir.c +++ b/src/basic/mkdir.c @@ -24,12 +24,14 @@ #include "fs-util.h" #include "macro.h" -#include "missing.h" #include "mkdir.h" #include "path-util.h" #include "stat-util.h" #include "user-util.h" +/// Additional includes needed by elogind +#include "missing.h" + int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, mkdir_func_t _mkdir) { struct stat st; diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c index d04a49e2f..121619eed 100644 --- a/src/basic/mount-util.c +++ b/src/basic/mount-util.c @@ -534,3 +534,28 @@ int repeat_unmount(const char *path, int flags) { } } #endif // 0 + +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: + if (access("/run/systemd/inaccessible/chr", F_OK) == 0) + return "/run/systemd/inaccessible/chr"; + return "/run/systemd/inaccessible/sock"; + case S_IFBLK: + 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: + return "/run/systemd/inaccessible/sock"; + } + return NULL; +} diff --git a/src/basic/process-util.c b/src/basic/process-util.c index c976f1f68..cd9c0f7e5 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -814,7 +814,7 @@ void valgrind_summary_hack(void) { #ifdef HAVE_VALGRIND_VALGRIND_H if (getpid() == 1 && RUNNING_ON_VALGRIND) { pid_t pid; - pid = raw_clone(SIGCHLD, NULL); + pid = raw_clone(SIGCHLD); if (pid < 0) log_emergency_errno(errno, "Failed to fork off valgrind helper: %m"); else if (pid == 0) diff --git a/src/basic/raw-clone.h b/src/basic/raw-clone.h index 1bef6f2da..d47382899 100644 --- a/src/basic/raw-clone.h +++ b/src/basic/raw-clone.h @@ -1,22 +1,22 @@ #pragma once /*** - This file is part of elogind. + This file is part of systemd. Copyright 2010 Lennart Poettering Copyright 2016 Michael Karcher - elogind is free software; you can redistribute it and/or modify it + systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - elogind is distributed in the hope that it will be useful, but + systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License - along with elogind; If not, see . + along with systemd; If not, see . ***/ #include diff --git a/src/basic/set.h b/src/basic/set.h index 170f0c446..5a5c8edb4 100644 --- a/src/basic/set.h +++ b/src/basic/set.h @@ -125,6 +125,7 @@ int set_consume(Set *s, void *value); int set_put_strdup(Set *s, const char *p); #if 0 /// UNNEEDED by elogind int set_put_strdupv(Set *s, char **l); +int set_put_strsplit(Set *s, const char *v, const char *separators, ExtractFlags flags); #endif // 0 #define SET_FOREACH(e, s, i) \ diff --git a/src/basic/strv.c b/src/basic/strv.c index 251031e01..baaa72e67 100644 --- a/src/basic/strv.c +++ b/src/basic/strv.c @@ -648,6 +648,17 @@ char **strv_remove(char **l, const char *s) { } char **strv_parse_nulstr(const char *s, size_t l) { + /* l is the length of the input data, which will be split at NULs into + * elements of the resulting strv. Hence, the number of items in the resulting strv + * will be equal to one plus the number of NUL bytes in the l bytes starting at s, + * unless s[l-1] is NUL, in which case the final empty string is not stored in + * the resulting strv, and length is equal to the number of NUL bytes. + * + * Note that contrary to a normal nulstr which cannot contain empty strings, because + * the input data is terminated by any two consequent NUL bytes, this parser accepts + * empty strings in s. + */ + const char *p; unsigned c = 0, i = 0; char **v; @@ -711,6 +722,13 @@ char **strv_split_nulstr(const char *s) { #if 0 /// UNNEEDED by elogind int strv_make_nulstr(char **l, char **p, size_t *q) { + /* A valid nulstr with two NULs at the end will be created, but + * q will be the length without the two trailing NULs. Thus the output + * string is a valid nulstr and can be iterated over using NULSTR_FOREACH, + * and can also be parsed by strv_parse_nulstr as long as the length + * is provided separately. + */ + size_t n_allocated = 0, n = 0; _cleanup_free_ char *m = NULL; char **i; @@ -723,7 +741,7 @@ int strv_make_nulstr(char **l, char **p, size_t *q) { z = strlen(*i); - if (!GREEDY_REALLOC(m, n_allocated, n + z + 1)) + if (!GREEDY_REALLOC(m, n_allocated, n + z + 2)) return -ENOMEM; memcpy(m + n, *i, z + 1); @@ -734,11 +752,14 @@ int strv_make_nulstr(char **l, char **p, size_t *q) { m = new0(char, 1); if (!m) return -ENOMEM; - n = 0; - } + n = 1; + } else + /* make sure there is a second extra NUL at the end of resulting nulstr */ + m[n] = '\0'; + assert(n > 0); *p = m; - *q = n; + *q = n - 1; m = NULL; diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index 40e3c400f..465326cfc 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -1203,6 +1203,19 @@ int open_terminal_in_namespace(pid_t pid, const char *name, int mode) { } #endif // 0 +bool terminal_is_dumb(void) { + const char *e; + + if (!on_tty()) + return true; + + e = getenv("TERM"); + if (!e) + return true; + + return streq(e, "dumb"); +} + bool colors_enabled(void) { static int enabled = -1; @@ -1212,10 +1225,8 @@ bool colors_enabled(void) { colors = getenv("SYSTEMD_COLORS"); if (colors) enabled = parse_boolean(colors) != 0; - else if (streq_ptr(getenv("TERM"), "dumb")) - enabled = false; else - enabled = on_tty(); + enabled = !terminal_is_dumb(); } return enabled; diff --git a/src/basic/terminal-util.h b/src/basic/terminal-util.h index 38f91514d..561045871 100644 --- a/src/basic/terminal-util.h +++ b/src/basic/terminal-util.h @@ -68,6 +68,7 @@ int vt_disallocate(const char *name); char *resolve_dev_console(char **active); #endif // 0 +int get_kernel_consoles(char ***consoles); bool tty_is_vc(const char *tty); #if 0 /// UNNEEDED by elogind bool tty_is_vc_resolve(const char *tty); @@ -93,6 +94,7 @@ void columns_lines_cache_reset(int _unused_ signum); #endif // 0 bool on_tty(void); +bool terminal_is_dumb(void); bool colors_enabled(void); static inline const char *ansi_underline(void) { diff --git a/src/basic/time-util.c b/src/basic/time-util.c index 97db1e2cc..1c4999aae 100644 --- a/src/basic/time-util.c +++ b/src/basic/time-util.c @@ -91,6 +91,16 @@ dual_timestamp* dual_timestamp_get(dual_timestamp *ts) { return ts; } +triple_timestamp* triple_timestamp_get(triple_timestamp *ts) { + assert(ts); + + ts->realtime = now(CLOCK_REALTIME); + ts->monotonic = now(CLOCK_MONOTONIC); + ts->boottime = clock_boottime_supported() ? now(CLOCK_BOOTTIME) : USEC_INFINITY; + + return ts; +} + dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u) { int64_t delta; assert(ts); @@ -109,6 +119,24 @@ dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u) { } #if 0 /// UNNEEDED by elogind +triple_timestamp* triple_timestamp_from_realtime(triple_timestamp *ts, usec_t u) { + int64_t delta; + + assert(ts); + + if (u == USEC_INFINITY || u <= 0) { + ts->realtime = ts->monotonic = ts->boottime = u; + return ts; + } + + ts->realtime = u; + delta = (int64_t) now(CLOCK_REALTIME) - (int64_t) u; + ts->monotonic = usec_sub(now(CLOCK_MONOTONIC), delta); + ts->boottime = clock_boottime_supported() ? usec_sub(now(CLOCK_BOOTTIME), delta) : USEC_INFINITY; + + return ts; +} + dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp *ts, usec_t u) { int64_t delta; assert(ts); @@ -142,6 +170,26 @@ dual_timestamp* dual_timestamp_from_boottime_or_monotonic(dual_timestamp *ts, us } #endif // 0 +usec_t triple_timestamp_by_clock(triple_timestamp *ts, clockid_t clock) { + + switch (clock) { + + case CLOCK_REALTIME: + case CLOCK_REALTIME_ALARM: + return ts->realtime; + + case CLOCK_MONOTONIC: + return ts->monotonic; + + case CLOCK_BOOTTIME: + case CLOCK_BOOTTIME_ALARM: + return ts->boottime; + + default: + return USEC_INFINITY; + } +} + usec_t timespec_load(const struct timespec *ts) { assert(ts); @@ -1125,7 +1173,33 @@ clockid_t clock_boottime_or_monotonic(void) { else return CLOCK_MONOTONIC; } +#endif // 0 + +bool clock_supported(clockid_t clock) { + struct timespec ts; + switch (clock) { + + case CLOCK_MONOTONIC: + case CLOCK_REALTIME: + return true; + + case CLOCK_BOOTTIME: + return clock_boottime_supported(); + + case CLOCK_BOOTTIME_ALARM: + if (!clock_boottime_supported()) + return false; + + /* fall through, after checking the cached value for CLOCK_BOOTTIME. */ + + default: + /* For everything else, check properly */ + return clock_gettime(clock, &ts) >= 0; + } +} + +#if 0 /// UNNEEDED by elogind int get_timezone(char **tz) { _cleanup_free_ char *t = NULL; const char *e; diff --git a/src/basic/time-util.h b/src/basic/time-util.h index 6feb75cc7..f80b6594f 100644 --- a/src/basic/time-util.h +++ b/src/basic/time-util.h @@ -39,6 +39,12 @@ typedef struct dual_timestamp { usec_t monotonic; } dual_timestamp; +typedef struct triple_timestamp { + usec_t realtime; + usec_t monotonic; + usec_t boottime; +} triple_timestamp; + #define USEC_INFINITY ((usec_t) -1) #define NSEC_INFINITY ((nsec_t) -1) @@ -69,7 +75,8 @@ typedef struct dual_timestamp { #define TIME_T_MAX (time_t)((UINTMAX_C(1) << ((sizeof(time_t) << 3) - 1)) - 1) -#define DUAL_TIMESTAMP_NULL ((struct dual_timestamp) { 0ULL, 0ULL }) +#define DUAL_TIMESTAMP_NULL ((struct dual_timestamp) {}) +#define TRIPLE_TIMESTAMP_NULL ((struct triple_timestamp) {}) usec_t now(clockid_t clock); #if 0 /// UNNEEDED by elogind @@ -83,11 +90,28 @@ dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp *ts, usec_t u); dual_timestamp* dual_timestamp_from_boottime_or_monotonic(dual_timestamp *ts, usec_t u); #endif // 0 +triple_timestamp* triple_timestamp_get(triple_timestamp *ts); +triple_timestamp* triple_timestamp_from_realtime(triple_timestamp *ts, usec_t u); + +#define DUAL_TIMESTAMP_HAS_CLOCK(clock) \ + IN_SET(clock, CLOCK_REALTIME, CLOCK_REALTIME_ALARM, CLOCK_MONOTONIC) + +#define TRIPLE_TIMESTAMP_HAS_CLOCK(clock) \ + IN_SET(clock, CLOCK_REALTIME, CLOCK_REALTIME_ALARM, CLOCK_MONOTONIC, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM) + static inline bool dual_timestamp_is_set(dual_timestamp *ts) { return ((ts->realtime > 0 && ts->realtime != USEC_INFINITY) || (ts->monotonic > 0 && ts->monotonic != USEC_INFINITY)); } +static inline bool triple_timestamp_is_set(triple_timestamp *ts) { + return ((ts->realtime > 0 && ts->realtime != USEC_INFINITY) || + (ts->monotonic > 0 && ts->monotonic != USEC_INFINITY) || + (ts->boottime > 0 && ts->boottime != USEC_INFINITY)); +} + +usec_t triple_timestamp_by_clock(triple_timestamp *ts, clockid_t clock); + usec_t timespec_load(const struct timespec *ts) _pure_; struct timespec *timespec_store(struct timespec *ts, usec_t u); @@ -127,6 +151,7 @@ bool timezone_is_valid(const char *name); #endif // 0 bool clock_boottime_supported(void); +bool clock_supported(clockid_t clock); #if 0 /// UNNEEDED by elogind clockid_t clock_boottime_or_monotonic(void); #endif // 0 diff --git a/src/basic/umask-util.h b/src/basic/umask-util.h index be90d5a3c..359d87d27 100644 --- a/src/basic/umask-util.h +++ b/src/basic/umask-util.h @@ -31,7 +31,6 @@ static inline void umaskp(mode_t *u) { #define _cleanup_umask_ _cleanup_(umaskp) -#if 0 /// UNNEEDED by elogind struct _umask_struct_ { mode_t mask; bool quit; @@ -45,4 +44,3 @@ static inline void _reset_umask_(struct _umask_struct_ *s) { for (_cleanup_(_reset_umask_) struct _umask_struct_ _saved_umask_ = { umask(mask), false }; \ !_saved_umask_.quit ; \ _saved_umask_.quit = true) -#endif // 0 diff --git a/src/basic/util.c b/src/basic/util.c index 12f7e1b05..f14dba9d9 100644 --- a/src/basic/util.c +++ b/src/basic/util.c @@ -36,6 +36,7 @@ #include "alloc-util.h" #include "build.h" +#include "cgroup-util.h" //#include "def.h" #include "dirent-util.h" #include "fd-util.h" @@ -64,6 +65,7 @@ assert_cc(EAGAIN == EWOULDBLOCK); int saved_argc = 0; char **saved_argv = NULL; +static int saved_in_initrd = -1; size_t page_size(void) { static thread_local size_t pgsz = 0; @@ -413,10 +415,10 @@ int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *pa /* Detach from stdout/stderr. and reopen * /dev/tty for them. This is important to - * ensure that when loginctl is started via + * ensure that when systemctl is started via * popen() or a similar call that expects to * read EOF we actually do generate EOF and - * not delay this indefinitely because we + * not delay this indefinitely by because we * keep an unused copy of stdin around. */ fd = open("/dev/tty", O_WRONLY); if (fd < 0) { @@ -458,11 +460,10 @@ int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *pa } bool in_initrd(void) { - static int saved = -1; struct statfs s; - if (saved >= 0) - return saved; + if (saved_in_initrd >= 0) + return saved_in_initrd; /* We make two checks here: * @@ -474,11 +475,15 @@ bool in_initrd(void) { * emptying when transititioning to the main systemd. */ - saved = access("/etc/initrd-release", F_OK) >= 0 && - statfs("/", &s) >= 0 && - is_temporary_fs(&s); + saved_in_initrd = access("/etc/initrd-release", F_OK) >= 0 && + statfs("/", &s) >= 0 && + is_temporary_fs(&s); - return saved; + return saved_in_initrd; +} + +void in_initrd_force(bool value) { + saved_in_initrd = value; } #if 0 /// UNNEEDED by elogind @@ -581,48 +586,7 @@ 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; -} #endif // 0 - int container_get_leader(const char *machine, pid_t *pid) { _cleanup_free_ char *s = NULL, *class = NULL; const char *p; @@ -773,15 +737,119 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int } uint64_t physical_memory(void) { - long mem; + _cleanup_free_ char *root = NULL, *value = NULL; + uint64_t mem, lim; + size_t ps; + long sc; + + /* We return this as uint64_t in case we are running as 32bit process on a 64bit kernel with huge amounts of + * memory. + * + * In order to support containers nicely that have a configured memory limit we'll take the minimum of the + * physically reported amount of memory and the limit configured for the root cgroup, if there is any. */ + + sc = sysconf(_SC_PHYS_PAGES); + assert(sc > 0); + + ps = page_size(); + mem = (uint64_t) sc * (uint64_t) ps; + + if (cg_get_root_path(&root) < 0) + return mem; + + if (cg_get_attribute("memory", root, "memory.limit_in_bytes", &value)) + return mem; + + if (safe_atou64(value, &lim) < 0) + return mem; + + /* Make sure the limit is a multiple of our own page size */ + lim /= ps; + lim *= ps; + + return MIN(mem, lim); +} + +uint64_t physical_memory_scale(uint64_t v, uint64_t max) { + uint64_t p, m, ps, r; + + assert(max > 0); + + /* Returns the physical memory size, multiplied by v divided by max. Returns UINT64_MAX on overflow. On success + * the result is a multiple of the page size (rounds down). */ + + ps = page_size(); + assert(ps > 0); + + p = physical_memory() / ps; + assert(p > 0); + + m = p * v; + if (m / p != v) + return UINT64_MAX; + + m /= max; + + r = m * ps; + if (r / ps != m) + return UINT64_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. */ - /* We return this as uint64_t in case we are running as 32bit - * process on a 64bit kernel with huge amounts of memory */ + t = system_tasks_max(); + assert(t > 0); - mem = sysconf(_SC_PHYS_PAGES); - assert(mem > 0); + m = t * v; + if (m / t != v) /* overflow? */ + return UINT64_MAX; - return (uint64_t) mem * (uint64_t) page_size(); + return m / max; } #if 0 /// UNNEEDED by elogind diff --git a/src/basic/util.h b/src/basic/util.h index af5a4fc9e..346221ca0 100644 --- a/src/basic/util.h +++ b/src/basic/util.h @@ -92,6 +92,7 @@ int prot_from_flags(int flags) _const_; int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...); bool in_initrd(void); +void in_initrd_force(bool value); #if 0 /// UNNEEDED by elogind void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size, @@ -186,15 +187,17 @@ static inline unsigned log2u_round_up(unsigned x) { } #if 0 /// UNNEEDED by elogind -bool id128_is_valid(const char *s) _pure_; #endif // 0 - 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); int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd); 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); #if 0 /// UNNEEDED by elogind #endif // 0 -- 2.30.2