diff options
Diffstat (limited to 'src')
52 files changed, 646 insertions, 330 deletions
diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 94a25585b2..6099dc8721 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -2018,9 +2018,10 @@ int cg_mask_supported(CGroupMask *ret) { mask |= CGROUP_CONTROLLER_TO_MASK(v); } - /* Currently, we only support the memory controller in - * the unified hierarchy, mask everything else off. */ - mask &= CGROUP_MASK_MEMORY; + /* Currently, we only support the memory and pids + * controller in the unified hierarchy, mask + * everything else off. */ + mask &= CGROUP_MASK_MEMORY | CGROUP_MASK_PIDS; } else { CGroupController c; @@ -2212,6 +2213,7 @@ static const char *cgroup_controller_table[_CGROUP_CONTROLLER_MAX] = { [CGROUP_CONTROLLER_BLKIO] = "blkio", [CGROUP_CONTROLLER_MEMORY] = "memory", [CGROUP_CONTROLLER_DEVICES] = "devices", + [CGROUP_CONTROLLER_PIDS] = "pids", }; DEFINE_STRING_TABLE_LOOKUP(cgroup_controller, CGroupController); diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index 16d439fd9d..7e1b4f9c72 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -35,6 +35,7 @@ typedef enum CGroupController { CGROUP_CONTROLLER_BLKIO, CGROUP_CONTROLLER_MEMORY, CGROUP_CONTROLLER_DEVICES, + CGROUP_CONTROLLER_PIDS, _CGROUP_CONTROLLER_MAX, _CGROUP_CONTROLLER_INVALID = -1, } CGroupController; @@ -48,6 +49,7 @@ typedef enum CGroupMask { CGROUP_MASK_BLKIO = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_BLKIO), CGROUP_MASK_MEMORY = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_MEMORY), CGROUP_MASK_DEVICES = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_DEVICES), + CGROUP_MASK_PIDS = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_PIDS), _CGROUP_MASK_ALL = CGROUP_CONTROLLER_TO_MASK(_CGROUP_CONTROLLER_MAX) - 1 } CGroupMask; diff --git a/src/basic/copy.c b/src/basic/copy.c index cc5faa80a1..b8cbe644d4 100644 --- a/src/basic/copy.c +++ b/src/basic/copy.c @@ -29,7 +29,7 @@ #define COPY_BUFFER_SIZE (16*1024) -int copy_bytes(int fdf, int fdt, off_t max_bytes, bool try_reflink) { +int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) { bool try_sendfile = true, try_splice = true; int r; @@ -37,7 +37,7 @@ int copy_bytes(int fdf, int fdt, off_t max_bytes, bool try_reflink) { assert(fdt >= 0); /* Try btrfs reflinks first. */ - if (try_reflink && max_bytes == (off_t) -1) { + if (try_reflink && max_bytes == (uint64_t) -1) { r = btrfs_reflink(fdf, fdt); if (r >= 0) return r; @@ -47,12 +47,12 @@ int copy_bytes(int fdf, int fdt, off_t max_bytes, bool try_reflink) { size_t m = COPY_BUFFER_SIZE; ssize_t n; - if (max_bytes != (off_t) -1) { + if (max_bytes != (uint64_t) -1) { if (max_bytes <= 0) return -EFBIG; - if ((off_t) m > max_bytes) + if ((uint64_t) m > max_bytes) m = (size_t) max_bytes; } @@ -105,8 +105,8 @@ int copy_bytes(int fdf, int fdt, off_t max_bytes, bool try_reflink) { } next: - if (max_bytes != (off_t) -1) { - assert(max_bytes >= n); + if (max_bytes != (uint64_t) -1) { + assert(max_bytes >= (uint64_t) n); max_bytes -= n; } } @@ -152,7 +152,7 @@ static int fd_copy_regular(int df, const char *from, const struct stat *st, int if (fdt < 0) return -errno; - r = copy_bytes(fdf, fdt, (off_t) -1, true); + r = copy_bytes(fdf, fdt, (uint64_t) -1, true); if (r < 0) { unlinkat(dt, to, 0); return r; @@ -371,7 +371,7 @@ int copy_file_fd(const char *from, int fdt, bool try_reflink) { if (fdf < 0) return -errno; - r = copy_bytes(fdf, fdt, (off_t) -1, try_reflink); + r = copy_bytes(fdf, fdt, (uint64_t) -1, try_reflink); (void) copy_times(fdf, fdt); (void) copy_xattr(fdf, fdt); diff --git a/src/basic/copy.h b/src/basic/copy.h index 8de0cfba32..ba0890b442 100644 --- a/src/basic/copy.h +++ b/src/basic/copy.h @@ -21,6 +21,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include <inttypes.h> #include <stdbool.h> #include <sys/types.h> @@ -30,6 +31,6 @@ int copy_file_atomic(const char *from, const char *to, mode_t mode, bool replace int copy_tree(const char *from, const char *to, bool merge); int copy_tree_at(int fdf, const char *from, int fdt, const char *to, bool merge); int copy_directory_fd(int dirfd, const char *to, bool merge); -int copy_bytes(int fdf, int fdt, off_t max_bytes, bool try_reflink); +int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink); int copy_times(int fdf, int fdt); int copy_xattr(int fdf, int fdt); diff --git a/src/basic/util.c b/src/basic/util.c index f7b2edf88c..e3b2af8e02 100644 --- a/src/basic/util.c +++ b/src/basic/util.c @@ -2214,7 +2214,7 @@ int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) { return 0; } -int parse_size(const char *t, off_t base, off_t *size) { +int parse_size(const char *t, uint64_t base, uint64_t *size) { /* Soo, sometimes we want to parse IEC binary suffixes, and * sometimes SI decimal suffixes. This function can parse @@ -2242,8 +2242,8 @@ int parse_size(const char *t, off_t base, off_t *size) { { "G", 1024ULL*1024ULL*1024ULL }, { "M", 1024ULL*1024ULL }, { "K", 1024ULL }, - { "B", 1 }, - { "", 1 }, + { "B", 1ULL }, + { "", 1ULL }, }; static const struct table si[] = { @@ -2253,8 +2253,8 @@ int parse_size(const char *t, off_t base, off_t *size) { { "G", 1000ULL*1000ULL*1000ULL }, { "M", 1000ULL*1000ULL }, { "K", 1000ULL }, - { "B", 1 }, - { "", 1 }, + { "B", 1ULL }, + { "", 1ULL }, }; const struct table *table; @@ -2276,33 +2276,32 @@ int parse_size(const char *t, off_t base, off_t *size) { p = t; do { - long long l; - unsigned long long l2; + unsigned long long l, tmp; double frac = 0; char *e; unsigned i; - errno = 0; - l = strtoll(p, &e, 10); + p += strspn(p, WHITESPACE); + if (*p == '-') + return -ERANGE; + errno = 0; + l = strtoull(p, &e, 10); if (errno > 0) return -errno; - - if (l < 0) - return -ERANGE; - if (e == p) return -EINVAL; if (*e == '.') { e++; + + /* strtoull() itself would accept space/+/- */ if (*e >= '0' && *e <= '9') { + unsigned long long l2; char *e2; - /* strotoull itself would accept space/+/- */ l2 = strtoull(e, &e2, 10); - - if (errno == ERANGE) + if (errno > 0) return -errno; /* Ignore failure. E.g. 10.M is valid */ @@ -2315,27 +2314,27 @@ int parse_size(const char *t, off_t base, off_t *size) { e += strspn(e, WHITESPACE); for (i = start_pos; i < n_entries; i++) - if (startswith(e, table[i].suffix)) { - unsigned long long tmp; - if ((unsigned long long) l + (frac > 0) > ULLONG_MAX / table[i].factor) - return -ERANGE; - tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor); - if (tmp > ULLONG_MAX - r) - return -ERANGE; - - r += tmp; - if ((unsigned long long) (off_t) r != r) - return -ERANGE; - - p = e + strlen(table[i].suffix); - - start_pos = i + 1; + if (startswith(e, table[i].suffix)) break; - } if (i >= n_entries) return -EINVAL; + if (l + (frac > 0) > ULLONG_MAX / table[i].factor) + return -ERANGE; + + tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor); + if (tmp > ULLONG_MAX - r) + return -ERANGE; + + r += tmp; + if ((unsigned long long) (uint64_t) r != r) + return -ERANGE; + + p = e + strlen(table[i].suffix); + + start_pos = i + 1; + } while (*p); *size = r; @@ -3785,38 +3784,38 @@ int prot_from_flags(int flags) { } } -char *format_bytes(char *buf, size_t l, off_t t) { +char *format_bytes(char *buf, size_t l, uint64_t t) { unsigned i; static const struct { const char *suffix; - off_t factor; + uint64_t factor; } table[] = { - { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL }, - { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL }, - { "T", 1024ULL*1024ULL*1024ULL*1024ULL }, - { "G", 1024ULL*1024ULL*1024ULL }, - { "M", 1024ULL*1024ULL }, - { "K", 1024ULL }, + { "E", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) }, + { "P", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) }, + { "T", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) }, + { "G", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) }, + { "M", UINT64_C(1024)*UINT64_C(1024) }, + { "K", UINT64_C(1024) }, }; - if (t == (off_t) -1) + if (t == (uint64_t) -1) return NULL; for (i = 0; i < ELEMENTSOF(table); i++) { if (t >= table[i].factor) { snprintf(buf, l, - "%llu.%llu%s", - (unsigned long long) (t / table[i].factor), - (unsigned long long) (((t*10ULL) / table[i].factor) % 10ULL), + "%" PRIu64 ".%" PRIu64 "%s", + t / table[i].factor, + ((t*UINT64_C(10)) / table[i].factor) % UINT64_C(10), table[i].suffix); goto finish; } } - snprintf(buf, l, "%lluB", (unsigned long long) t); + snprintf(buf, l, "%" PRIu64 "B", t); finish: buf[l-1] = 0; diff --git a/src/basic/util.h b/src/basic/util.h index 5fa44b5cf3..c7dff9a86d 100644 --- a/src/basic/util.h +++ b/src/basic/util.h @@ -152,7 +152,7 @@ void close_many(const int fds[], unsigned n_fd); int fclose_nointr(FILE *f); FILE* safe_fclose(FILE *f); -int parse_size(const char *t, off_t base, off_t *size); +int parse_size(const char *t, uint64_t base, uint64_t *size); int parse_boolean(const char *v) _pure_; int parse_pid(const char *s, pid_t* ret_pid); @@ -478,7 +478,7 @@ bool kexec_loaded(void); int prot_from_flags(int flags) _const_; -char *format_bytes(char *buf, size_t l, off_t t); +char *format_bytes(char *buf, size_t l, uint64_t t); int fd_wait_for_event(int fd, int event, usec_t timeout); diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c index 1c94bea31a..4786a155da 100644 --- a/src/cgtop/cgtop.c +++ b/src/cgtop/cgtop.c @@ -45,7 +45,7 @@ typedef struct Group { bool memory_valid:1; bool io_valid:1; - unsigned n_tasks; + uint64_t n_tasks; unsigned cpu_iteration; nsec_t cpu_usage; @@ -65,7 +65,12 @@ static unsigned arg_iterations = (unsigned) -1; static bool arg_batch = false; static bool arg_raw = false; static usec_t arg_delay = 1*USEC_PER_SEC; -static bool arg_kernel_threads = false; + +enum { + COUNT_PIDS, + COUNT_USERSPACE_PROCESSES, + COUNT_ALL_PROCESSES, +} arg_count = COUNT_PIDS; static bool arg_recursive = true; static enum { @@ -73,7 +78,7 @@ static enum { ORDER_TASKS, ORDER_CPU, ORDER_MEMORY, - ORDER_IO + ORDER_IO, } arg_order = ORDER_CPU; static enum { @@ -100,7 +105,7 @@ static void group_hashmap_free(Hashmap *h) { hashmap_free(h); } -static const char *maybe_format_bytes(char *buf, size_t l, bool is_valid, off_t t) { +static const char *maybe_format_bytes(char *buf, size_t l, bool is_valid, uint64_t t) { if (!is_valid) return "-"; if (arg_raw) { @@ -153,7 +158,7 @@ static int process( } } - if (streq(controller, SYSTEMD_CGROUP_CONTROLLER)) { + if (streq(controller, SYSTEMD_CGROUP_CONTROLLER) && IN_SET(arg_count, COUNT_ALL_PROCESSES, COUNT_USERSPACE_PROCESSES)) { _cleanup_fclose_ FILE *f = NULL; pid_t pid; @@ -166,7 +171,7 @@ static int process( g->n_tasks = 0; while (cg_read_pid(f, &pid) > 0) { - if (!arg_kernel_threads && is_kernel_thread(pid) > 0) + if (arg_count == COUNT_USERSPACE_PROCESSES && is_kernel_thread(pid) > 0) continue; g->n_tasks++; @@ -175,6 +180,26 @@ static int process( if (g->n_tasks > 0) g->n_tasks_valid = true; + } else if (streq(controller, "pids") && arg_count == COUNT_PIDS) { + _cleanup_free_ char *p = NULL, *v = NULL; + + r = cg_get_path(controller, path, "pids.current", &p); + if (r < 0) + return r; + + r = read_one_line_file(p, &v); + if (r == -ENOENT) + return 0; + if (r < 0) + return r; + + r = safe_atou64(v, &g->n_tasks); + if (r < 0) + return r; + + if (g->n_tasks > 0) + g->n_tasks_valid = true; + } else if (streq(controller, "cpuacct") && cg_unified() <= 0) { _cleanup_free_ char *p = NULL, *v = NULL; uint64_t new_usage; @@ -371,6 +396,7 @@ static int refresh_one( return r; if (arg_recursive && + IN_SET(arg_count, COUNT_ALL_PROCESSES, COUNT_USERSPACE_PROCESSES) && child && child->n_tasks_valid && streq(controller, SYSTEMD_CGROUP_CONTROLLER)) { @@ -409,6 +435,9 @@ static int refresh(const char *root, Hashmap *a, Hashmap *b, unsigned iteration) r = refresh_one("blkio", root, a, b, iteration, 0, NULL); if (r < 0) return r; + r = refresh_one("pids", root, a, b, iteration, 0, NULL); + if (r < 0) + return r; return 0; } @@ -549,7 +578,7 @@ static void display(Hashmap *a) { printf("%s%-*s%s %s%7s%s %s%s%s %s%8s%s %s%8s%s %s%8s%s\n\n", arg_order == ORDER_PATH ? ON : "", path_columns, "Control Group", arg_order == ORDER_PATH ? OFF : "", - arg_order == ORDER_TASKS ? ON : "", "Tasks", + arg_order == ORDER_TASKS ? ON : "", arg_count == COUNT_PIDS ? "Tasks" : arg_count == COUNT_USERSPACE_PROCESSES ? "Procs" : "Proc+", arg_order == ORDER_TASKS ? OFF : "", arg_order == ORDER_CPU ? ON : "", buffer, arg_order == ORDER_CPU ? OFF : "", @@ -576,7 +605,7 @@ static void display(Hashmap *a) { printf("%-*s", path_columns, ellipsized ?: path); if (g->n_tasks_valid) - printf(" %7u", g->n_tasks); + printf(" %7" PRIu64, g->n_tasks); else fputs(" -", stdout); @@ -602,15 +631,16 @@ static void help(void) { " -h --help Show this help\n" " --version Show package version\n" " -p --order=path Order by path\n" - " -t --order=tasks Order by number of tasks\n" + " -t --order=tasks Order by number of tasks/processes\n" " -c --order=cpu Order by CPU load (default)\n" " -m --order=memory Order by memory load\n" " -i --order=io Order by IO load\n" " -r --raw Provide raw (not human-readable) numbers\n" " --cpu=percentage Show CPU usage as percentage (default)\n" " --cpu=time Show CPU usage as time\n" - " -k Include kernel threads in task count\n" - " --recursive=BOOL Sum up task count recursively\n" + " -P Count userspace processes instead of tasks (excl. kernel)\n" + " -k Count all processes instead of tasks (incl. kernel)\n" + " --recursive=BOOL Sum up process count recursively\n" " -d --delay=DELAY Delay between updates\n" " -n --iterations=N Run for N iterations before exiting\n" " -b --batch Run in batch mode, accepting no input\n" @@ -642,12 +672,13 @@ static int parse_argv(int argc, char *argv[]) { {} }; + bool recursive_unset = false; int c, r; assert(argc >= 1); assert(argv); - while ((c = getopt_long(argc, argv, "hptcmin:brd:k", options, NULL)) >= 0) + while ((c = getopt_long(argc, argv, "hptcmin:brd:kP", options, NULL)) >= 0) switch (c) { @@ -748,7 +779,11 @@ static int parse_argv(int argc, char *argv[]) { break; case 'k': - arg_kernel_threads = true; + arg_count = COUNT_ALL_PROCESSES; + break; + + case 'P': + arg_count = COUNT_USERSPACE_PROCESSES; break; case ARG_RECURSIVE: @@ -759,6 +794,7 @@ static int parse_argv(int argc, char *argv[]) { } arg_recursive = r; + recursive_unset = r == 0; break; case '?': @@ -773,9 +809,23 @@ static int parse_argv(int argc, char *argv[]) { return -EINVAL; } + if (recursive_unset && arg_count == COUNT_PIDS) { + log_error("Non-recursive counting is only supported when counting processes, not tasks. Use -P or -k."); + return -EINVAL; + } + return 1; } +static const char* counting_what(void) { + if (arg_count == COUNT_PIDS) + return "tasks"; + else if (arg_count == COUNT_ALL_PROCESSES) + return "all processes (incl. kernel)"; + else + return "userspace processes (excl. kernel)"; +} + int main(int argc, char *argv[]) { int r; Hashmap *a = NULL, *b = NULL; @@ -783,10 +833,19 @@ int main(int argc, char *argv[]) { usec_t last_refresh = 0; bool quit = false, immediate_refresh = false; _cleanup_free_ char *root = NULL; + CGroupMask mask; log_parse_environment(); log_open(); + r = cg_mask_supported(&mask); + if (r < 0) { + log_error_errno(r, "Failed to determine supported controllers: %m"); + goto finish; + } + + arg_count = (mask & CGROUP_MASK_PIDS) ? COUNT_PIDS : COUNT_USERSPACE_PROCESSES; + r = parse_argv(argc, argv); if (r <= 0) goto finish; @@ -899,15 +958,26 @@ int main(int argc, char *argv[]) { break; case 'k': - arg_kernel_threads = !arg_kernel_threads; - fprintf(stdout, "\nCounting kernel threads: %s.", yes_no(arg_kernel_threads)); + arg_count = arg_count != COUNT_ALL_PROCESSES ? COUNT_ALL_PROCESSES : COUNT_PIDS; + fprintf(stdout, "\nCounting: %s.", counting_what()); + fflush(stdout); + sleep(1); + break; + + case 'P': + arg_count = arg_count != COUNT_USERSPACE_PROCESSES ? COUNT_USERSPACE_PROCESSES : COUNT_PIDS; + fprintf(stdout, "\nCounting: %s.", counting_what()); fflush(stdout); sleep(1); break; case 'r': - arg_recursive = !arg_recursive; - fprintf(stdout, "\nRecursive task counting: %s", yes_no(arg_recursive)); + if (arg_count == COUNT_PIDS) + fprintf(stdout, "\n\aCannot toggle recursive counting, not available in task counting mode."); + else { + arg_recursive = !arg_recursive; + fprintf(stdout, "\nRecursive process counting: %s", yes_no(arg_recursive)); + } fflush(stdout); sleep(1); break; @@ -939,9 +1009,10 @@ int main(int argc, char *argv[]) { case '?': case 'h': fprintf(stdout, - "\t<" ON "p" OFF "> By path; <" ON "t" OFF "> By tasks; <" ON "c" OFF "> By CPU; <" ON "m" OFF "> By memory; <" ON "i" OFF "> By I/O\n" + "\t<" ON "p" OFF "> By path; <" ON "t" OFF "> By tasks/procs; <" ON "c" OFF "> By CPU; <" ON "m" OFF "> By memory; <" ON "i" OFF "> By I/O\n" "\t<" ON "+" OFF "> Inc. delay; <" ON "-" OFF "> Dec. delay; <" ON "%%" OFF "> Toggle time; <" ON "SPACE" OFF "> Refresh\n" - "\t<" ON "k" OFF "> Count kernel threads; <" ON "r" OFF "> Count recursively; <" ON "q" OFF "> Quit"); + "\t<" ON "P" OFF "> Toggle count userspace processes; <" ON "k" OFF "> Toggle count all processes\n" + "\t<" ON "r" OFF "> Count processes recursively; <" ON "q" OFF "> Quit"); fflush(stdout); sleep(3); break; diff --git a/src/core/automount.c b/src/core/automount.c index 5bb61b95d3..c88e3311bc 100644 --- a/src/core/automount.c +++ b/src/core/automount.c @@ -129,10 +129,8 @@ static void automount_done(Unit *u) { a->where = mfree(a->where); - set_free(a->tokens); - a->tokens = NULL; - set_free(a->expire_tokens); - a->expire_tokens = NULL; + a->tokens = set_free(a->tokens); + a->expire_tokens = set_free(a->expire_tokens); a->expire_event_source = sd_event_source_unref(a->expire_event_source); } diff --git a/src/core/cgroup.c b/src/core/cgroup.c index baa7cc5488..48000d4e6e 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -22,10 +22,11 @@ #include <fcntl.h> #include <fnmatch.h> -#include "process-util.h" +#include "cgroup-util.h" #include "path-util.h" +#include "process-util.h" #include "special.h" -#include "cgroup-util.h" + #include "cgroup.h" #define CGROUP_CPU_QUOTA_PERIOD_USEC ((usec_t) 100 * USEC_PER_MSEC) @@ -41,6 +42,7 @@ void cgroup_context_init(CGroupContext *c) { c->memory_limit = (uint64_t) -1; c->blockio_weight = (unsigned long) -1; c->startup_blockio_weight = (unsigned long) -1; + c->tasks_max = (uint64_t) -1; c->cpu_quota_per_sec_usec = USEC_INFINITY; } @@ -106,6 +108,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) { "%sBlockIOWeight=%lu\n" "%sStartupBlockIOWeight=%lu\n" "%sMemoryLimit=%" PRIu64 "\n" + "%sTasksMax=%" PRIu64 "\n" "%sDevicePolicy=%s\n" "%sDelegate=%s\n", prefix, yes_no(c->cpu_accounting), @@ -117,6 +120,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) { prefix, c->blockio_weight, prefix, c->startup_blockio_weight, prefix, c->memory_limit, + prefix, c->tasks_max, prefix, cgroup_device_policy_to_string(c->device_policy), prefix, yes_no(c->delegate)); @@ -466,6 +470,21 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, M log_debug("Ignoring device %s while writing cgroup attribute.", a->path); } } + + if ((mask & CGROUP_MASK_PIDS) && !is_root) { + + if (c->tasks_max != (uint64_t) -1) { + char buf[DECIMAL_STR_MAX(uint64_t) + 2]; + + sprintf(buf, "%" PRIu64 "\n", c->tasks_max); + r = cg_set_attribute("pids", path, "pids.max", buf); + } else + r = cg_set_attribute("pids", path, "pids.max", "max"); + + if (r < 0) + log_full_errno(IN_SET(r, -ENOENT, -EROFS) ? LOG_DEBUG : LOG_WARNING, r, + "Failed to set pids.max on %s: %m", path); + } } CGroupMask cgroup_context_get_mask(CGroupContext *c) { @@ -494,6 +513,10 @@ CGroupMask cgroup_context_get_mask(CGroupContext *c) { c->device_policy != CGROUP_AUTO) mask |= CGROUP_MASK_DEVICES; + if (c->tasks_accounting || + c->tasks_max != (uint64_t) -1) + mask |= CGROUP_MASK_PIDS; + return mask; } @@ -1459,6 +1482,28 @@ int unit_get_memory_current(Unit *u, uint64_t *ret) { return safe_atou64(v, ret); } +int unit_get_tasks_current(Unit *u, uint64_t *ret) { + _cleanup_free_ char *v = NULL; + int r; + + assert(u); + assert(ret); + + if (!u->cgroup_path) + return -ENODATA; + + if ((u->cgroup_realized_mask & CGROUP_MASK_PIDS) == 0) + return -ENODATA; + + r = cg_get_attribute("pids", u->cgroup_path, "pids.current", &v); + if (r == -ENOENT) + return -ENODATA; + if (r < 0) + return r; + + return safe_atou64(v, ret); +} + static int unit_get_cpu_usage_raw(Unit *u, nsec_t *ret) { _cleanup_free_ char *v = NULL; uint64_t ns; diff --git a/src/core/cgroup.h b/src/core/cgroup.h index 438f5bf50f..3ba09d56a4 100644 --- a/src/core/cgroup.h +++ b/src/core/cgroup.h @@ -72,6 +72,7 @@ struct CGroupContext { bool cpu_accounting; bool blockio_accounting; bool memory_accounting; + bool tasks_accounting; unsigned long cpu_shares; unsigned long startup_cpu_shares; @@ -88,6 +89,8 @@ struct CGroupContext { LIST_HEAD(CGroupDeviceAllow, device_allow); bool delegate; + + uint64_t tasks_max; }; #include "unit.h" @@ -137,6 +140,7 @@ int unit_search_main_pid(Unit *u, pid_t *ret); int unit_watch_all_pids(Unit *u); int unit_get_memory_current(Unit *u, uint64_t *ret); +int unit_get_tasks_current(Unit *u, uint64_t *ret); int unit_get_cpu_usage(Unit *u, nsec_t *ret); int unit_reset_cpu_usage(Unit *u); diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c index ba2f4e53b9..94de92c3dd 100644 --- a/src/core/dbus-cgroup.c +++ b/src/core/dbus-cgroup.c @@ -168,6 +168,8 @@ const sd_bus_vtable bus_cgroup_vtable[] = { SD_BUS_PROPERTY("MemoryLimit", "t", NULL, offsetof(CGroupContext, memory_limit), 0), SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy, offsetof(CGroupContext, device_policy), 0), SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow, 0, 0), + SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, tasks_accounting), 0), + SD_BUS_PROPERTY("TasksMax", "t", NULL, offsetof(CGroupContext, tasks_max), 0), SD_BUS_VTABLE_END }; @@ -551,7 +553,11 @@ int bus_cgroup_set_property( if (mode != UNIT_CHECK) { c->memory_limit = limit; u->cgroup_realized_mask &= ~CGROUP_MASK_MEMORY; - unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64, name, limit); + + if (limit == (uint64_t) -1) + unit_write_drop_in_private(u, mode, name, "MemoryLimit=infinity"); + else + unit_write_drop_in_private_format(u, mode, name, "MemoryLimit=%" PRIu64, limit); } return 1; @@ -667,6 +673,39 @@ int bus_cgroup_set_property( return 1; + } else if (streq(name, "TasksAccounting")) { + int b; + + r = sd_bus_message_read(message, "b", &b); + if (r < 0) + return r; + + if (mode != UNIT_CHECK) { + c->tasks_accounting = b; + u->cgroup_realized_mask &= ~CGROUP_MASK_PIDS; + unit_write_drop_in_private(u, mode, name, b ? "TasksAccounting=yes" : "TasksAccounting=no"); + } + + return 1; + + } else if (streq(name, "TasksMax")) { + uint64_t limit; + + r = sd_bus_message_read(message, "t", &limit); + if (r < 0) + return r; + + if (mode != UNIT_CHECK) { + c->tasks_max = limit; + u->cgroup_realized_mask &= ~CGROUP_MASK_PIDS; + + if (limit == (uint64_t) -1) + unit_write_drop_in_private(u, mode, name, "TasksMax=infinity"); + else + unit_write_drop_in_private_format(u, mode, name, "TasksMax=%" PRIu64, limit); + } + + return 1; } if (u->transient && u->load_state == UNIT_STUB) { diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index f9275ed935..f7e9795928 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -736,6 +736,30 @@ static int property_get_current_memory( return sd_bus_message_append(reply, "t", sz); } +static int property_get_current_tasks( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + uint64_t cn = (uint64_t) -1; + Unit *u = userdata; + int r; + + assert(bus); + assert(reply); + assert(u); + + r = unit_get_tasks_current(u, &cn); + if (r < 0 && r != -ENODATA) + log_unit_warning_errno(u, r, "Failed to get pids.current attribute: %m"); + + return sd_bus_message_append(reply, "t", cn); +} + static int property_get_cpu_usage( sd_bus *bus, const char *path, @@ -796,6 +820,7 @@ const sd_bus_vtable bus_unit_cgroup_vtable[] = { SD_BUS_PROPERTY("ControlGroup", "s", property_get_cgroup, 0, 0), SD_BUS_PROPERTY("MemoryCurrent", "t", property_get_current_memory, 0, 0), SD_BUS_PROPERTY("CPUUsageNSec", "t", property_get_cpu_usage, 0, 0), + SD_BUS_PROPERTY("TasksCurrent", "t", property_get_current_tasks, 0, 0), SD_BUS_VTABLE_END }; diff --git a/src/core/dbus.c b/src/core/dbus.c index 0a2180c6a7..2d6a1ff836 100644 --- a/src/core/dbus.c +++ b/src/core/dbus.c @@ -1055,12 +1055,10 @@ void bus_done(Manager *m) { while ((b = set_steal_first(m->private_buses))) destroy_bus(m, &b); - set_free(m->private_buses); - m->private_buses = NULL; + m->private_buses = set_free(m->private_buses); m->subscribed = sd_bus_track_unref(m->subscribed); - strv_free(m->deserialized_subscribed); - m->deserialized_subscribed = NULL; + m->deserialized_subscribed = strv_free(m->deserialized_subscribed); if (m->private_listen_event_source) m->private_listen_event_source = sd_event_source_unref(m->private_listen_event_source); @@ -1191,8 +1189,7 @@ int bus_track_coldplug(Manager *m, sd_bus_track **t, char ***l) { } } - strv_free(*l); - *l = NULL; + *l = strv_free(*l); return r; } diff --git a/src/core/device.c b/src/core/device.c index 7fdfacfddf..0b54518691 100644 --- a/src/core/device.c +++ b/src/core/device.c @@ -594,8 +594,7 @@ static void device_shutdown(Manager *m) { m->udev_monitor = NULL; } - hashmap_free(m->devices_by_sysfs); - m->devices_by_sysfs = NULL; + m->devices_by_sysfs = hashmap_free(m->devices_by_sysfs); } static int device_enumerate(Manager *m) { diff --git a/src/core/execute.c b/src/core/execute.c index 6abb0a5d5d..d1acda6682 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1992,11 +1992,8 @@ void exec_context_done(ExecContext *c) { assert(c); - strv_free(c->environment); - c->environment = NULL; - - strv_free(c->environment_files); - c->environment_files = NULL; + c->environment = strv_free(c->environment); + c->environment_files = strv_free(c->environment_files); for (l = 0; l < ELEMENTSOF(c->rlimit); l++) c->rlimit[l] = mfree(c->rlimit[l]); @@ -2008,8 +2005,7 @@ void exec_context_done(ExecContext *c) { c->user = mfree(c->user); c->group = mfree(c->group); - strv_free(c->supplementary_groups); - c->supplementary_groups = NULL; + c->supplementary_groups = strv_free(c->supplementary_groups); c->pam_name = mfree(c->pam_name); @@ -2018,14 +2014,9 @@ void exec_context_done(ExecContext *c) { c->capabilities = NULL; } - strv_free(c->read_only_dirs); - c->read_only_dirs = NULL; - - strv_free(c->read_write_dirs); - c->read_write_dirs = NULL; - - strv_free(c->inaccessible_dirs); - c->inaccessible_dirs = NULL; + c->read_only_dirs = strv_free(c->read_only_dirs); + c->read_write_dirs = strv_free(c->read_write_dirs); + c->inaccessible_dirs = strv_free(c->inaccessible_dirs); if (c->cpuset) CPU_FREE(c->cpuset); @@ -2034,17 +2025,11 @@ void exec_context_done(ExecContext *c) { c->selinux_context = mfree(c->selinux_context); c->apparmor_profile = mfree(c->apparmor_profile); - set_free(c->syscall_filter); - c->syscall_filter = NULL; + c->syscall_filter = set_free(c->syscall_filter); + c->syscall_archs = set_free(c->syscall_archs); + c->address_families = set_free(c->address_families); - set_free(c->syscall_archs); - c->syscall_archs = NULL; - - set_free(c->address_families); - c->address_families = NULL; - - strv_free(c->runtime_directory); - c->runtime_directory = NULL; + c->runtime_directory = strv_free(c->runtime_directory); bus_endpoint_free(c->bus_endpoint); c->bus_endpoint = NULL; @@ -2079,8 +2064,7 @@ void exec_command_done(ExecCommand *c) { c->path = mfree(c->path); - strv_free(c->argv); - c->argv = NULL; + c->argv = strv_free(c->argv); } void exec_command_done_array(ExecCommand *c, unsigned n) { diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index edd55b9e45..e056fd863c 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -124,6 +124,8 @@ $1.StartupBlockIOWeight, config_parse_blockio_weight, 0, $1.BlockIODeviceWeight, config_parse_blockio_device_weight, 0, offsetof($1, cgroup_context) $1.BlockIOReadBandwidth, config_parse_blockio_bandwidth, 0, offsetof($1, cgroup_context) $1.BlockIOWriteBandwidth, config_parse_blockio_bandwidth, 0, offsetof($1, cgroup_context) +$1.TasksAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.tasks_accounting) +$1.TasksMax, config_parse_tasks_max, 0, offsetof($1, cgroup_context) $1.Delegate, config_parse_bool, 0, offsetof($1, cgroup_context.delegate)' )m4_dnl Unit.Description, config_parse_unit_string_printf, 0, offsetof(Unit, description) diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index b695c57da8..f7a8539910 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -1888,8 +1888,7 @@ int config_parse_unit_env_file(const char *unit, if (isempty(rvalue)) { /* Empty assignment frees the list */ - strv_free(*env); - *env = NULL; + *env = strv_free(*env); return 0; } @@ -1937,8 +1936,7 @@ int config_parse_environ(const char *unit, if (isempty(rvalue)) { /* Empty assignment resets the list */ - strv_free(*env); - *env = NULL; + *env = strv_free(*env); return 0; } @@ -2245,8 +2243,7 @@ int config_parse_documentation(const char *unit, if (isempty(rvalue)) { /* Empty assignment resets the list */ - strv_free(u->documentation); - u->documentation = NULL; + u->documentation = strv_free(u->documentation); return 0; } @@ -2305,8 +2302,7 @@ int config_parse_syscall_filter( if (isempty(rvalue)) { /* Empty assignment resets the list */ - set_free(c->syscall_filter); - c->syscall_filter = NULL; + c->syscall_filter = set_free(c->syscall_filter); c->syscall_whitelist = false; return 0; } @@ -2404,8 +2400,7 @@ int config_parse_syscall_archs( int r; if (isempty(rvalue)) { - set_free(*archs); - *archs = NULL; + *archs = set_free(*archs); return 0; } @@ -2501,8 +2496,7 @@ int config_parse_address_families( if (isempty(rvalue)) { /* Empty assignment resets the list */ - set_free(c->address_families); - c->address_families = NULL; + c->address_families = set_free(c->address_families); c->address_families_whitelist = false; return 0; } @@ -2689,24 +2683,51 @@ int config_parse_memory_limit( void *userdata) { CGroupContext *c = data; - off_t bytes; + uint64_t bytes; int r; - if (isempty(rvalue)) { + if (isempty(rvalue) || streq(rvalue, "infinity")) { c->memory_limit = (uint64_t) -1; return 0; } - assert_cc(sizeof(uint64_t) == sizeof(off_t)); - r = parse_size(rvalue, 1024, &bytes); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "Memory limit '%s' invalid. Ignoring.", rvalue); + if (r < 0 || bytes < 1) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Memory limit '%s' invalid. Ignoring.", rvalue); + return 0; + } + + c->memory_limit = bytes; + return 0; +} + +int config_parse_tasks_max( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + CGroupContext *c = data; + uint64_t u; + int r; + + if (isempty(rvalue) || streq(rvalue, "infinity")) { + c->tasks_max = (uint64_t) -1; + return 0; + } + + r = safe_atou64(rvalue, &u); + if (r < 0 || u < 1) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Maximum tasks value '%s' invalid. Ignoring.", rvalue); return 0; } - c->memory_limit = (uint64_t) bytes; return 0; } @@ -2893,7 +2914,7 @@ int config_parse_blockio_bandwidth( CGroupBlockIODeviceBandwidth *b; CGroupContext *c = data; const char *bandwidth; - off_t bytes; + uint64_t bytes; bool read; size_t n; int r; @@ -2947,7 +2968,7 @@ int config_parse_blockio_bandwidth( b->path = path; path = NULL; - b->bandwidth = (uint64_t) bytes; + b->bandwidth = bytes; b->read = read; LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, b); @@ -3011,8 +3032,7 @@ int config_parse_runtime_directory( if (isempty(rvalue)) { /* Empty assignment resets the list */ - strv_free(*rt); - *rt = NULL; + *rt = strv_free(*rt); return 0; } @@ -3140,8 +3160,7 @@ int config_parse_namespace_path_strv( if (isempty(rvalue)) { /* Empty assignment resets the list */ - strv_free(*sv); - *sv = NULL; + *sv = strv_free(*sv); return 0; } @@ -3622,7 +3641,7 @@ void unit_dump_config_items(FILE *f) { { config_parse_int, "INTEGER" }, { config_parse_unsigned, "UNSIGNED" }, { config_parse_iec_size, "SIZE" }, - { config_parse_iec_off, "SIZE" }, + { config_parse_iec_uint64, "SIZE" }, { config_parse_si_size, "SIZE" }, { config_parse_bool, "BOOLEAN" }, { config_parse_string, "STRING" }, diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h index 1d128716c4..638b343a6e 100644 --- a/src/core/load-fragment.h +++ b/src/core/load-fragment.h @@ -84,6 +84,7 @@ int config_parse_environ(const char *unit, const char *filename, unsigned line, int config_parse_unit_slice(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_cpu_shares(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_memory_limit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_tasks_max(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_device_policy(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_device_allow(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_blockio_weight(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); diff --git a/src/core/main.c b/src/core/main.c index be95dc68b2..200fe740da 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -114,6 +114,7 @@ static FILE* arg_serialization = NULL; static bool arg_default_cpu_accounting = false; static bool arg_default_blockio_accounting = false; static bool arg_default_memory_accounting = false; +static bool arg_default_tasks_accounting = false; static void nop_handler(int sig) {} @@ -676,6 +677,7 @@ static int parse_config_file(void) { { "Manager", "DefaultCPUAccounting", config_parse_bool, 0, &arg_default_cpu_accounting }, { "Manager", "DefaultBlockIOAccounting", config_parse_bool, 0, &arg_default_blockio_accounting }, { "Manager", "DefaultMemoryAccounting", config_parse_bool, 0, &arg_default_memory_accounting }, + { "Manager", "DefaultTasksAccounting", config_parse_bool, 0, &arg_default_tasks_accounting }, {} }; @@ -704,6 +706,7 @@ static void manager_set_defaults(Manager *m) { m->default_cpu_accounting = arg_default_cpu_accounting; m->default_blockio_accounting = arg_default_blockio_accounting; m->default_memory_accounting = arg_default_memory_accounting; + m->default_tasks_accounting = arg_default_tasks_accounting; manager_set_default_rlimits(m, arg_default_rlimit); manager_environment_add(m, NULL, arg_default_environment); @@ -1846,8 +1849,7 @@ finish: arg_default_environment = strv_free(arg_default_environment); - set_free(arg_syscall_archs); - arg_syscall_archs = NULL; + arg_syscall_archs = set_free(arg_syscall_archs); mac_selinux_finish(); diff --git a/src/core/manager.h b/src/core/manager.h index 9956cb7700..78a0e50a33 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -256,6 +256,7 @@ struct Manager { bool default_cpu_accounting; bool default_memory_accounting; bool default_blockio_accounting; + bool default_tasks_accounting; usec_t default_timer_accuracy_usec; diff --git a/src/core/swap.c b/src/core/swap.c index 311ce7ee04..bef457069f 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -1254,8 +1254,7 @@ static void swap_shutdown(Manager *m) { m->proc_swaps = safe_fclose(m->proc_swaps); - hashmap_free(m->swaps_by_devnode); - m->swaps_by_devnode = NULL; + m->swaps_by_devnode = hashmap_free(m->swaps_by_devnode); } static int swap_enumerate(Manager *m) { diff --git a/src/core/unit.c b/src/core/unit.c index 24a6747b10..2ebfb09a7a 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -125,6 +125,7 @@ static void unit_init(Unit *u) { cc->cpu_accounting = u->manager->default_cpu_accounting; cc->blockio_accounting = u->manager->default_blockio_accounting; cc->memory_accounting = u->manager->default_memory_accounting; + cc->tasks_accounting = u->manager->default_tasks_accounting; } ec = unit_get_exec_context(u); @@ -445,8 +446,7 @@ static void unit_free_requires_mounts_for(Unit *u) { } } - strv_free(u->requires_mounts_for); - u->requires_mounts_for = NULL; + u->requires_mounts_for = strv_free(u->requires_mounts_for); } static void unit_done(Unit *u) { @@ -674,8 +674,7 @@ static void merge_dependencies(Unit *u, Unit *other, const char *other_id, UnitD /* The move cannot fail. The caller must have performed a reservation. */ assert_se(complete_move(&u->dependencies[d], &other->dependencies[d]) == 0); - set_free(other->dependencies[d]); - other->dependencies[d] = NULL; + other->dependencies[d] = set_free(other->dependencies[d]); } int unit_merge(Unit *u, Unit *other) { diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c index 6fad8ad80c..ab91afec4d 100644 --- a/src/cryptsetup/cryptsetup-generator.c +++ b/src/cryptsetup/cryptsetup-generator.c @@ -330,7 +330,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value) { free(d->keyfile); d->keyfile = uuid_value; uuid_value = NULL; - } else if (free_and_strdup(&arg_default_keyfile, value)) + } else if (free_and_strdup(&arg_default_keyfile, value) < 0) return log_oom(); } else if (STR_IN_SET(key, "luks.name", "rd.luks.name") && value) { diff --git a/src/import/pull-raw.c b/src/import/pull-raw.c index 44e029ef98..0e77197e34 100644 --- a/src/import/pull-raw.c +++ b/src/import/pull-raw.c @@ -314,7 +314,7 @@ static int raw_pull_make_local_copy(RawPull *i) { if (r < 0) log_warning_errno(errno, "Failed to set file attributes on %s: %m", tp); - r = copy_bytes(i->raw_job->disk_fd, dfd, (off_t) -1, true); + r = copy_bytes(i->raw_job->disk_fd, dfd, (uint64_t) -1, true); if (r < 0) { unlink(tp); return log_error_errno(r, "Failed to make writable copy of image: %m"); diff --git a/src/journal/compress.c b/src/journal/compress.c index 383f6a6e96..c66043e503 100644 --- a/src/journal/compress.c +++ b/src/journal/compress.c @@ -342,11 +342,10 @@ int decompress_startswith(int compression, return -EBADMSG; } -int compress_stream_xz(int fdf, int fdt, off_t max_bytes) { +int compress_stream_xz(int fdf, int fdt, uint64_t max_bytes) { #ifdef HAVE_XZ _cleanup_(lzma_end) lzma_stream s = LZMA_STREAM_INIT; lzma_ret ret; - uint8_t buf[BUFSIZ], out[BUFSIZ]; lzma_action action = LZMA_RUN; @@ -364,8 +363,8 @@ int compress_stream_xz(int fdf, int fdt, off_t max_bytes) { size_t m = sizeof(buf); ssize_t n; - if (max_bytes != -1 && m > (size_t) max_bytes) - m = max_bytes; + if (max_bytes != (uint64_t) -1 && (uint64_t) m > max_bytes) + m = (size_t) max_bytes; n = read(fdf, buf, m); if (n < 0) @@ -376,8 +375,8 @@ int compress_stream_xz(int fdf, int fdt, off_t max_bytes) { s.next_in = buf; s.avail_in = n; - if (max_bytes != -1) { - assert(max_bytes >= n); + if (max_bytes != (uint64_t) -1) { + assert(max_bytes >= (uint64_t) n); max_bytes -= n; } } @@ -419,7 +418,7 @@ int compress_stream_xz(int fdf, int fdt, off_t max_bytes) { #define LZ4_BUFSIZE (512*1024) -int compress_stream_lz4(int fdf, int fdt, off_t max_bytes) { +int compress_stream_lz4(int fdf, int fdt, uint64_t max_bytes) { #ifdef HAVE_LZ4 @@ -445,8 +444,8 @@ int compress_stream_lz4(int fdf, int fdt, off_t max_bytes) { int r; m = LZ4_BUFSIZE; - if (max_bytes != -1 && m > (size_t) max_bytes - total_in) - m = max_bytes - total_in; + if (max_bytes != (uint64_t) -1 && (uint64_t) m > (max_bytes - total_in)) + m = (size_t) (max_bytes - total_in); n = read(fdf, buf, m); if (n < 0) @@ -497,7 +496,7 @@ int compress_stream_lz4(int fdf, int fdt, off_t max_bytes) { #endif } -int decompress_stream_xz(int fdf, int fdt, off_t max_bytes) { +int decompress_stream_xz(int fdf, int fdt, uint64_t max_bytes) { #ifdef HAVE_XZ _cleanup_(lzma_end) lzma_stream s = LZMA_STREAM_INIT; @@ -546,8 +545,8 @@ int decompress_stream_xz(int fdf, int fdt, off_t max_bytes) { n = sizeof(out) - s.avail_out; - if (max_bytes != -1) { - if (max_bytes < n) + if (max_bytes != (uint64_t) -1) { + if (max_bytes < (uint64_t) n) return -EFBIG; max_bytes -= n; @@ -572,7 +571,7 @@ int decompress_stream_xz(int fdf, int fdt, off_t max_bytes) { #endif } -int decompress_stream_lz4(int fdf, int fdt, off_t max_bytes) { +int decompress_stream_lz4(int fdf, int fdt, uint64_t max_bytes) { #ifdef HAVE_LZ4 _cleanup_free_ char *buf = NULL, *out = NULL; @@ -626,8 +625,8 @@ int decompress_stream_lz4(int fdf, int fdt, off_t max_bytes) { total_out += r; - if (max_bytes != -1 && total_out > (size_t) max_bytes) { - log_debug("Decompressed stream longer than %zd bytes", max_bytes); + if (max_bytes != (uint64_t) -1 && (uint64_t) total_out > max_bytes) { + log_debug("Decompressed stream longer than %" PRIu64 " bytes", max_bytes); return -EFBIG; } @@ -647,7 +646,7 @@ int decompress_stream_lz4(int fdf, int fdt, off_t max_bytes) { #endif } -int decompress_stream(const char *filename, int fdf, int fdt, off_t max_bytes) { +int decompress_stream(const char *filename, int fdf, int fdt, uint64_t max_bytes) { if (endswith(filename, ".lz4")) return decompress_stream_lz4(fdf, fdt, max_bytes); diff --git a/src/journal/compress.h b/src/journal/compress.h index 6294f16faa..9a065eb763 100644 --- a/src/journal/compress.h +++ b/src/journal/compress.h @@ -67,11 +67,11 @@ int decompress_startswith(int compression, const void *prefix, size_t prefix_len, uint8_t extra); -int compress_stream_xz(int fdf, int fdt, off_t max_bytes); -int compress_stream_lz4(int fdf, int fdt, off_t max_bytes); +int compress_stream_xz(int fdf, int fdt, uint64_t max_bytes); +int compress_stream_lz4(int fdf, int fdt, uint64_t max_bytes); -int decompress_stream_xz(int fdf, int fdt, off_t max_size); -int decompress_stream_lz4(int fdf, int fdt, off_t max_size); +int decompress_stream_xz(int fdf, int fdt, uint64_t max_size); +int decompress_stream_lz4(int fdf, int fdt, uint64_t max_size); #ifdef HAVE_LZ4 # define compress_stream compress_stream_lz4 @@ -81,4 +81,4 @@ int decompress_stream_lz4(int fdf, int fdt, off_t max_size); # define COMPRESSED_EXT ".xz" #endif -int decompress_stream(const char *filename, int fdf, int fdt, off_t max_bytes); +int decompress_stream(const char *filename, int fdf, int fdt, uint64_t max_bytes); diff --git a/src/journal/coredump-vacuum.c b/src/journal/coredump-vacuum.c index c0347ef569..efe418615a 100644 --- a/src/journal/coredump-vacuum.c +++ b/src/journal/coredump-vacuum.c @@ -28,10 +28,10 @@ #include "coredump-vacuum.h" -#define DEFAULT_MAX_USE_LOWER (off_t) (1ULL*1024ULL*1024ULL) /* 1 MiB */ -#define DEFAULT_MAX_USE_UPPER (off_t) (4ULL*1024ULL*1024ULL*1024ULL) /* 4 GiB */ -#define DEFAULT_KEEP_FREE_UPPER (off_t) (4ULL*1024ULL*1024ULL*1024ULL) /* 4 GiB */ -#define DEFAULT_KEEP_FREE (off_t) (1024ULL*1024ULL) /* 1 MB */ +#define DEFAULT_MAX_USE_LOWER (uint64_t) (1ULL*1024ULL*1024ULL) /* 1 MiB */ +#define DEFAULT_MAX_USE_UPPER (uint64_t) (4ULL*1024ULL*1024ULL*1024ULL) /* 4 GiB */ +#define DEFAULT_KEEP_FREE_UPPER (uint64_t) (4ULL*1024ULL*1024ULL*1024ULL) /* 4 GiB */ +#define DEFAULT_KEEP_FREE (uint64_t) (1024ULL*1024ULL) /* 1 MB */ struct vacuum_candidate { unsigned n_files; @@ -82,8 +82,8 @@ static int uid_from_file_name(const char *filename, uid_t *uid) { return parse_uid(u, uid); } -static bool vacuum_necessary(int fd, off_t sum, off_t keep_free, off_t max_use) { - off_t fs_size = 0, fs_free = (off_t) -1; +static bool vacuum_necessary(int fd, uint64_t sum, uint64_t keep_free, uint64_t max_use) { + uint64_t fs_size = 0, fs_free = (uint64_t) -1; struct statvfs sv; assert(fd >= 0); @@ -93,7 +93,7 @@ static bool vacuum_necessary(int fd, off_t sum, off_t keep_free, off_t max_use) fs_free = sv.f_frsize * sv.f_bfree; } - if (max_use == (off_t) -1) { + if (max_use == (uint64_t) -1) { if (fs_size > 0) { max_use = PAGE_ALIGN(fs_size / 10); /* 10% */ @@ -111,7 +111,7 @@ static bool vacuum_necessary(int fd, off_t sum, off_t keep_free, off_t max_use) if (max_use > 0 && sum > max_use) return true; - if (keep_free == (off_t) -1) { + if (keep_free == (uint64_t) -1) { if (fs_size > 0) { keep_free = PAGE_ALIGN((fs_size * 3) / 20); /* 15% */ @@ -129,7 +129,7 @@ static bool vacuum_necessary(int fd, off_t sum, off_t keep_free, off_t max_use) return false; } -int coredump_vacuum(int exclude_fd, off_t keep_free, off_t max_use) { +int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use) { _cleanup_closedir_ DIR *d = NULL; struct stat exclude_st; int r; @@ -161,7 +161,7 @@ int coredump_vacuum(int exclude_fd, off_t keep_free, off_t max_use) { _cleanup_(vacuum_candidate_hasmap_freep) Hashmap *h = NULL; struct vacuum_candidate *worst = NULL; struct dirent *de; - off_t sum = 0; + uint64_t sum = 0; rewinddir(d); diff --git a/src/journal/coredump-vacuum.h b/src/journal/coredump-vacuum.h index 7ad4399305..7779c97574 100644 --- a/src/journal/coredump-vacuum.h +++ b/src/journal/coredump-vacuum.h @@ -21,6 +21,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include <inttypes.h> #include <sys/types.h> -int coredump_vacuum(int exclude_fd, off_t keep_free, off_t max_use); +int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use); diff --git a/src/journal/coredump.c b/src/journal/coredump.c index 7d94b145c9..e1e66b9826 100644 --- a/src/journal/coredump.c +++ b/src/journal/coredump.c @@ -51,7 +51,7 @@ #include "process-util.h" /* The maximum size up to which we process coredumps */ -#define PROCESS_SIZE_MAX ((off_t) (2LLU*1024LLU*1024LLU*1024LLU)) +#define PROCESS_SIZE_MAX ((uint64_t) (2LLU*1024LLU*1024LLU*1024LLU)) /* The maximum size up to which we leave the coredump around on * disk */ @@ -97,21 +97,21 @@ static DEFINE_CONFIG_PARSE_ENUM(config_parse_coredump_storage, coredump_storage, static CoredumpStorage arg_storage = COREDUMP_STORAGE_EXTERNAL; static bool arg_compress = true; -static off_t arg_process_size_max = PROCESS_SIZE_MAX; -static off_t arg_external_size_max = EXTERNAL_SIZE_MAX; +static uint64_t arg_process_size_max = PROCESS_SIZE_MAX; +static uint64_t arg_external_size_max = EXTERNAL_SIZE_MAX; static size_t arg_journal_size_max = JOURNAL_SIZE_MAX; -static off_t arg_keep_free = (off_t) -1; -static off_t arg_max_use = (off_t) -1; +static uint64_t arg_keep_free = (uint64_t) -1; +static uint64_t arg_max_use = (uint64_t) -1; static int parse_config(void) { static const ConfigTableItem items[] = { { "Coredump", "Storage", config_parse_coredump_storage, 0, &arg_storage }, { "Coredump", "Compress", config_parse_bool, 0, &arg_compress }, - { "Coredump", "ProcessSizeMax", config_parse_iec_off, 0, &arg_process_size_max }, - { "Coredump", "ExternalSizeMax", config_parse_iec_off, 0, &arg_external_size_max }, + { "Coredump", "ProcessSizeMax", config_parse_iec_uint64, 0, &arg_process_size_max }, + { "Coredump", "ExternalSizeMax", config_parse_iec_uint64, 0, &arg_external_size_max }, { "Coredump", "JournalSizeMax", config_parse_iec_size, 0, &arg_journal_size_max }, - { "Coredump", "KeepFree", config_parse_iec_off, 0, &arg_keep_free }, - { "Coredump", "MaxUse", config_parse_iec_off, 0, &arg_max_use }, + { "Coredump", "KeepFree", config_parse_iec_uint64, 0, &arg_keep_free }, + { "Coredump", "MaxUse", config_parse_iec_uint64, 0, &arg_max_use }, {} }; @@ -224,7 +224,7 @@ static int fix_permissions( return 0; } -static int maybe_remove_external_coredump(const char *filename, off_t size) { +static int maybe_remove_external_coredump(const char *filename, uint64_t size) { /* Returns 1 if might remove, 0 if will not remove, < 0 on error. */ @@ -285,7 +285,7 @@ static int save_external_coredump( uid_t uid, char **ret_filename, int *ret_fd, - off_t *ret_size) { + uint64_t *ret_size) { _cleanup_free_ char *fn = NULL, *tmp = NULL; _cleanup_close_ int fd = -1; @@ -372,9 +372,9 @@ static int save_external_coredump( /* OK, this worked, we can get rid of the uncompressed version now */ unlink_noerrno(tmp); - *ret_filename = fn_compressed; /* compressed */ - *ret_fd = fd; /* uncompressed */ - *ret_size = st.st_size; /* uncompressed */ + *ret_filename = fn_compressed; /* compressed */ + *ret_fd = fd; /* uncompressed */ + *ret_size = (uint64_t) st.st_size; /* uncompressed */ fn_compressed = NULL; fd = -1; @@ -393,7 +393,7 @@ uncompressed: *ret_filename = fn; *ret_fd = fd; - *ret_size = st.st_size; + *ret_size = (uint64_t) st.st_size; fn = NULL; fd = -1; @@ -544,7 +544,7 @@ int main(int argc, char* argv[]) { _cleanup_close_ int coredump_fd = -1; struct iovec iovec[26]; - off_t coredump_size; + uint64_t coredump_size; int r, j = 0; uid_t uid, owner_uid; gid_t gid; @@ -840,7 +840,7 @@ log: /* Optionally store the entire coredump in the journal */ if (IN_SET(arg_storage, COREDUMP_STORAGE_JOURNAL, COREDUMP_STORAGE_BOTH) && - coredump_size <= (off_t) arg_journal_size_max) { + coredump_size <= arg_journal_size_max) { size_t sz = 0; /* Store the coredump itself in the journal */ diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 4f94799ce7..73d3a4bb9d 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -2542,7 +2542,7 @@ void journal_file_print_header(JournalFile *f) { le64toh(f->header->n_entry_arrays)); if (fstat(f->fd, &st) >= 0) - printf("Disk usage: %s\n", format_bytes(bytes, sizeof(bytes), (off_t) st.st_blocks * 512ULL)); + printf("Disk usage: %s\n", format_bytes(bytes, sizeof(bytes), (uint64_t) st.st_blocks * 512ULL)); } static int journal_file_warn_btrfs(JournalFile *f) { diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 576e4e4d03..9b483413e7 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -107,7 +107,7 @@ static bool arg_reverse = false; static int arg_journal_type = 0; static const char *arg_root = NULL; static const char *arg_machine = NULL; -static off_t arg_vacuum_size = (off_t) -1; +static uint64_t arg_vacuum_size = (uint64_t) -1; static usec_t arg_vacuum_time = USEC_INFINITY; static enum { diff --git a/src/journal/journald-gperf.gperf b/src/journal/journald-gperf.gperf index 74554c1c34..bf7c773009 100644 --- a/src/journal/journald-gperf.gperf +++ b/src/journal/journald-gperf.gperf @@ -21,12 +21,12 @@ Journal.Seal, config_parse_bool, 0, offsetof(Server, seal) Journal.SyncIntervalSec, config_parse_sec, 0, offsetof(Server, sync_interval_usec) Journal.RateLimitInterval, config_parse_sec, 0, offsetof(Server, rate_limit_interval) Journal.RateLimitBurst, config_parse_unsigned, 0, offsetof(Server, rate_limit_burst) -Journal.SystemMaxUse, config_parse_iec_off, 0, offsetof(Server, system_metrics.max_use) -Journal.SystemMaxFileSize, config_parse_iec_off, 0, offsetof(Server, system_metrics.max_size) -Journal.SystemKeepFree, config_parse_iec_off, 0, offsetof(Server, system_metrics.keep_free) -Journal.RuntimeMaxUse, config_parse_iec_off, 0, offsetof(Server, runtime_metrics.max_use) -Journal.RuntimeMaxFileSize, config_parse_iec_off, 0, offsetof(Server, runtime_metrics.max_size) -Journal.RuntimeKeepFree, config_parse_iec_off, 0, offsetof(Server, runtime_metrics.keep_free) +Journal.SystemMaxUse, config_parse_iec_uint64, 0, offsetof(Server, system_metrics.max_use) +Journal.SystemMaxFileSize, config_parse_iec_uint64, 0, offsetof(Server, system_metrics.max_size) +Journal.SystemKeepFree, config_parse_iec_uint64, 0, offsetof(Server, system_metrics.keep_free) +Journal.RuntimeMaxUse, config_parse_iec_uint64, 0, offsetof(Server, runtime_metrics.max_use) +Journal.RuntimeMaxFileSize, config_parse_iec_uint64, 0, offsetof(Server, runtime_metrics.max_size) +Journal.RuntimeKeepFree, config_parse_iec_uint64, 0, offsetof(Server, runtime_metrics.keep_free) Journal.MaxRetentionSec, config_parse_sec, 0, offsetof(Server, max_retention_usec) Journal.MaxFileSec, config_parse_sec, 0, offsetof(Server, max_file_usec) Journal.ForwardToSyslog, config_parse_bool, 0, offsetof(Server, forward_to_syslog) diff --git a/src/journal/test-compress.c b/src/journal/test-compress.c index 41a566d714..f17c00e60d 100644 --- a/src/journal/test-compress.c +++ b/src/journal/test-compress.c @@ -44,8 +44,8 @@ typedef int (decompress_sw_t)(const void *src, uint64_t src_size, const void *prefix, size_t prefix_len, uint8_t extra); -typedef int (compress_stream_t)(int fdf, int fdt, off_t max_bytes); -typedef int (decompress_stream_t)(int fdf, int fdt, off_t max_size); +typedef int (compress_stream_t)(int fdf, int fdt, uint64_t max_bytes); +typedef int (decompress_stream_t)(int fdf, int fdt, uint64_t max_size); static void test_compress_decompress(int compression, compress_blob_t compress, diff --git a/src/journal/test-coredump-vacuum.c b/src/journal/test-coredump-vacuum.c index a4dd00125d..514dadc1dc 100644 --- a/src/journal/test-coredump-vacuum.c +++ b/src/journal/test-coredump-vacuum.c @@ -25,7 +25,7 @@ int main(int argc, char *argv[]) { - if (coredump_vacuum(-1, (off_t) -1, 70 * 1024) < 0) + if (coredump_vacuum(-1, (uint64_t) -1, 70 * 1024) < 0) return EXIT_FAILURE; return EXIT_SUCCESS; diff --git a/src/libsystemd/sd-bus/bus-creds.c b/src/libsystemd/sd-bus/bus-creds.c index 6826e21665..3e8cb0b7d0 100644 --- a/src/libsystemd/sd-bus/bus-creds.c +++ b/src/libsystemd/sd-bus/bus-creds.c @@ -109,8 +109,7 @@ _public_ sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c) { c->supplementary_gids = mfree(c->supplementary_gids); - strv_free(c->well_known_names); - c->well_known_names = NULL; + c->well_known_names = strv_free(c->well_known_names); bus_creds_done(c); diff --git a/src/libsystemd/sd-bus/busctl.c b/src/libsystemd/sd-bus/busctl.c index a1f0f30d6c..9a6d338231 100644 --- a/src/libsystemd/sd-bus/busctl.c +++ b/src/libsystemd/sd-bus/busctl.c @@ -1823,20 +1823,20 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_SIZE: { - off_t o; + uint64_t sz; - r = parse_size(optarg, 1024, &o); + r = parse_size(optarg, 1024, &sz); if (r < 0) { log_error("Failed to parse size: %s", optarg); return r; } - if ((off_t) (size_t) o != o) { + if ((uint64_t) (size_t) sz != sz) { log_error("Size out of range."); return -E2BIG; } - arg_snaplen = (size_t) o; + arg_snaplen = (size_t) sz; break; } diff --git a/src/login/logind-user.c b/src/login/logind-user.c index f2c89e3653..47669afdef 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -879,15 +879,15 @@ int config_parse_tmpfs_size( *sz = PAGE_ALIGN((size_t) ((physical_memory() * (uint64_t) ul) / (uint64_t) 100)); } else { - off_t o; + uint64_t k; - r = parse_size(rvalue, 1024, &o); - if (r < 0 || (off_t) (size_t) o != o) { - log_syntax(unit, LOG_ERR, filename, line, r < 0 ? -r : ERANGE, "Failed to parse size value, ignoring: %s", rvalue); + r = parse_size(rvalue, 1024, &k); + if (r < 0 || (uint64_t) (size_t) k != k) { + log_syntax(unit, LOG_ERR, filename, line, r < 0 ? r : ERANGE, "Failed to parse size value, ignoring: %s", rvalue); return 0; } - *sz = PAGE_ALIGN((size_t) o); + *sz = PAGE_ALIGN((size_t) k); } return 0; diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c index cc38116704..6aaaa8aa31 100644 --- a/src/machine/machine-dbus.c +++ b/src/machine/machine-dbus.c @@ -423,7 +423,7 @@ int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, s _exit(EXIT_FAILURE); } - r = copy_bytes(fd, pair[1], (off_t) -1, false); + r = copy_bytes(fd, pair[1], (uint64_t) -1, false); if (r < 0) _exit(EXIT_FAILURE); diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index 7b8f6d1fab..ab113efb28 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -2385,13 +2385,9 @@ static int set_limit(int argc, char *argv[], void *userdata) { if (streq(argv[argc-1], "-")) limit = (uint64_t) -1; else { - off_t off; - - r = parse_size(argv[argc-1], 1024, &off); + r = parse_size(argv[argc-1], 1024, &limit); if (r < 0) return log_error("Failed to parse size: %s", argv[argc-1]); - - limit = (uint64_t) off; } if (argc > 2) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 33943a4b2f..5702df8ab4 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -3601,7 +3601,7 @@ finish: /* Try to flush whatever is still queued in the pty */ if (master >= 0) - (void) copy_bytes(master, STDOUT_FILENO, (off_t) -1, false); + (void) copy_bytes(master, STDOUT_FILENO, (uint64_t) -1, false); loop_remove(loop_nr, &image_fd); diff --git a/src/resolve/resolved-dns-zone.c b/src/resolve/resolved-dns-zone.c index 674bb6af28..8a59bd1c3c 100644 --- a/src/resolve/resolved-dns-zone.c +++ b/src/resolve/resolved-dns-zone.c @@ -90,11 +90,8 @@ void dns_zone_flush(DnsZone *z) { assert(hashmap_size(z->by_key) == 0); assert(hashmap_size(z->by_name) == 0); - hashmap_free(z->by_key); - z->by_key = NULL; - - hashmap_free(z->by_name); - z->by_name = NULL; + z->by_key = hashmap_free(z->by_key); + z->by_name = hashmap_free(z->by_name); } static DnsZoneItem* dns_zone_get(DnsZone *z, DnsResourceRecord *rr) { diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c index 47f461a37d..b9fd8e3dbc 100644 --- a/src/resolve/resolved-link.c +++ b/src/resolve/resolved-link.c @@ -238,8 +238,7 @@ static int link_update_domains(Link *l) { if (!l->unicast_scope) return 0; - strv_free(l->unicast_scope->domains); - l->unicast_scope->domains = NULL; + l->unicast_scope->domains = strv_free(l->unicast_scope->domains); r = sd_network_link_get_domains(l->ifindex, &l->unicast_scope->domains); diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index 36c44227c5..4dc4ca581d 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -1421,7 +1421,7 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen return bus_log_create_error(r); if (STR_IN_SET(field, - "CPUAccounting", "MemoryAccounting", "BlockIOAccounting", + "CPUAccounting", "MemoryAccounting", "BlockIOAccounting", "TasksAccounting", "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies", "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit")) { @@ -1434,15 +1434,34 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen r = sd_bus_message_append(m, "v", "b", r); } else if (streq(field, "MemoryLimit")) { - off_t bytes; + uint64_t bytes; - r = parse_size(eq, 1024, &bytes); - if (r < 0) { - log_error("Failed to parse bytes specification %s", assignment); - return -EINVAL; + if (isempty(eq) || streq(eq, "infinity")) + bytes = (uint64_t) -1; + else { + r = parse_size(eq, 1024, &bytes); + if (r < 0) { + log_error("Failed to parse bytes specification %s", assignment); + return -EINVAL; + } + } + + r = sd_bus_message_append(m, "v", "t", bytes); + + } else if (streq(field, "TasksMax")) { + uint64_t n; + + if (isempty(eq) || streq(eq, "infinity")) + n = (uint64_t) -1; + else { + r = safe_atou64(eq, &n); + if (r < 0) { + log_error("Failed to parse maximum tasks specification %s", assignment); + return -EINVAL; + } } - r = sd_bus_message_append(m, "v", "t", (uint64_t) bytes); + r = sd_bus_message_append(m, "v", "t", n); } else if (STR_IN_SET(field, "CPUShares", "BlockIOWeight")) { uint64_t u; @@ -1492,7 +1511,7 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen r = sd_bus_message_append(m, "v", "a(st)", 0); else { const char *path, *bandwidth, *e; - off_t bytes; + uint64_t bytes; e = strchr(eq, ' '); if (e) { @@ -1514,7 +1533,7 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen return -EINVAL; } - r = sd_bus_message_append(m, "v", "a(st)", 1, path, (uint64_t) bytes); + r = sd_bus_message_append(m, "v", "a(st)", 1, path, bytes); } } else if (streq(field, "BlockIODeviceWeight")) { diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index 23512f0d35..946eac6823 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -469,7 +469,7 @@ int config_parse_iec_size(const char* unit, void *userdata) { size_t *sz = data; - off_t o; + uint64_t v; int r; assert(filename); @@ -477,13 +477,13 @@ int config_parse_iec_size(const char* unit, assert(rvalue); assert(data); - r = parse_size(rvalue, 1024, &o); - if (r < 0 || (off_t) (size_t) o != o) { - log_syntax(unit, LOG_ERR, filename, line, r < 0 ? -r : ERANGE, "Failed to parse size value, ignoring: %s", rvalue); + r = parse_size(rvalue, 1024, &v); + if (r < 0 || (uint64_t) (size_t) v != v) { + log_syntax(unit, LOG_ERR, filename, line, r < 0 ? r : ERANGE, "Failed to parse size value, ignoring: %s", rvalue); return 0; } - *sz = (size_t) o; + *sz = (size_t) v; return 0; } @@ -499,7 +499,7 @@ int config_parse_si_size(const char* unit, void *userdata) { size_t *sz = data; - off_t o; + uint64_t v; int r; assert(filename); @@ -507,17 +507,17 @@ int config_parse_si_size(const char* unit, assert(rvalue); assert(data); - r = parse_size(rvalue, 1000, &o); - if (r < 0 || (off_t) (size_t) o != o) { - log_syntax(unit, LOG_ERR, filename, line, r < 0 ? -r : ERANGE, "Failed to parse size value, ignoring: %s", rvalue); + r = parse_size(rvalue, 1000, &v); + if (r < 0 || (uint64_t) (size_t) v != v) { + log_syntax(unit, LOG_ERR, filename, line, r < 0 ? r : ERANGE, "Failed to parse size value, ignoring: %s", rvalue); return 0; } - *sz = (size_t) o; + *sz = (size_t) v; return 0; } -int config_parse_iec_off(const char* unit, +int config_parse_iec_uint64(const char* unit, const char *filename, unsigned line, const char *section, @@ -528,7 +528,7 @@ int config_parse_iec_off(const char* unit, void *data, void *userdata) { - off_t *bytes = data; + uint64_t *bytes = data; int r; assert(filename); @@ -536,11 +536,9 @@ int config_parse_iec_off(const char* unit, assert(rvalue); assert(data); - assert_cc(sizeof(off_t) == sizeof(uint64_t)); - r = parse_size(rvalue, 1024, bytes); if (r < 0) - log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to parse size value, ignoring: %s", rvalue); + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value, ignoring: %s", rvalue); return 0; } diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h index 34e3815782..4efed138c9 100644 --- a/src/shared/conf-parser.h +++ b/src/shared/conf-parser.h @@ -109,7 +109,7 @@ int config_parse_uint64(const char *unit, const char *filename, unsigned line, c int config_parse_double(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_iec_size(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_si_size(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); -int config_parse_iec_off(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_iec_uint64(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_bool(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_tristate(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_string(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c index 70220bdd14..9c1e4d5e13 100644 --- a/src/shared/machine-image.c +++ b/src/shared/machine-image.c @@ -19,16 +19,18 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <sys/statfs.h> -#include <linux/fs.h> #include <fcntl.h> +#include <linux/fs.h> +#include <sys/statfs.h> -#include "utf8.h" #include "btrfs-util.h" -#include "path-util.h" #include "copy.h" #include "mkdir.h" +#include "path-util.h" #include "rm-rf.h" +#include "strv.h" +#include "utf8.h" + #include "machine-image.h" static const char image_search_path[] = @@ -47,6 +49,38 @@ Image *image_unref(Image *i) { return NULL; } +static char **image_settings_path(Image *image) { + _cleanup_strv_free_ char **l = NULL; + char **ret; + const char *fn, *s; + unsigned i = 0; + + assert(image); + + l = new0(char*, 4); + if (!l) + return NULL; + + fn = strjoina(image->name, ".nspawn"); + + FOREACH_STRING(s, "/etc/systemd/nspawn/", "/run/systemd/nspawn/") { + l[i] = strappend(s, fn); + if (!l[i]) + return NULL; + + i++; + } + + l[i] = file_in_same_dir(image->path, fn); + if (!l[i]) + return NULL; + + ret = l; + l = NULL; + + return ret; +} + static int image_new( ImageType t, const char *pretty, @@ -341,6 +375,8 @@ void image_hashmap_free(Hashmap *map) { int image_remove(Image *i) { _cleanup_release_lock_file_ LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT; + _cleanup_strv_free_ char **settings = NULL; + char **j; int r; assert(i); @@ -349,6 +385,10 @@ int image_remove(Image *i) { path_startswith(i->path, "/usr")) return -EROFS; + settings = image_settings_path(i); + if (!settings) + return -ENOMEM; + /* Make sure we don't interfere with a running nspawn */ r = image_path_lock(i->path, LOCK_EX|LOCK_NB, &global_lock, &local_lock); if (r < 0) @@ -357,28 +397,56 @@ int image_remove(Image *i) { switch (i->type) { case IMAGE_SUBVOLUME: - return btrfs_subvol_remove(i->path, true); + r = btrfs_subvol_remove(i->path, true); + if (r < 0) + return r; + break; case IMAGE_DIRECTORY: /* Allow deletion of read-only directories */ (void) chattr_path(i->path, false, FS_IMMUTABLE_FL); - return rm_rf(i->path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME); + r = rm_rf(i->path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME); + if (r < 0) + return r; + + break; case IMAGE_RAW: if (unlink(i->path) < 0) return -errno; - - return 0; + break; default: return -EOPNOTSUPP; } + + STRV_FOREACH(j, settings) { + if (unlink(*j) < 0 && errno != ENOENT) + log_debug_errno(errno, "Failed to unlink %s, ignoring: %m", *j); + } + + return 0; +} + +static int rename_settings_file(const char *path, const char *new_name) { + _cleanup_free_ char *rs = NULL; + const char *fn; + + fn = strjoina(new_name, ".nspawn"); + + rs = file_in_same_dir(path, fn); + if (!rs) + return -ENOMEM; + + return rename_noreplace(AT_FDCWD, path, AT_FDCWD, rs); } int image_rename(Image *i, const char *new_name) { _cleanup_release_lock_file_ LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT, name_lock = LOCK_FILE_INIT; _cleanup_free_ char *new_path = NULL, *nn = NULL; + _cleanup_strv_free_ char **settings = NULL; unsigned file_attr = 0; + char **j; int r; assert(i); @@ -390,6 +458,10 @@ int image_rename(Image *i, const char *new_name) { path_startswith(i->path, "/usr")) return -EROFS; + settings = image_settings_path(i); + if (!settings) + return -ENOMEM; + /* Make sure we don't interfere with a running nspawn */ r = image_path_lock(i->path, LOCK_EX|LOCK_NB, &global_lock, &local_lock); if (r < 0) @@ -458,12 +530,33 @@ int image_rename(Image *i, const char *new_name) { i->name = nn; nn = NULL; + STRV_FOREACH(j, settings) { + r = rename_settings_file(*j, new_name); + if (r < 0 && r != -ENOENT) + log_debug_errno(r, "Failed to rename settings file %s, ignoring: %m", *j); + } + return 0; } +static int clone_settings_file(const char *path, const char *new_name) { + _cleanup_free_ char *rs = NULL; + const char *fn; + + fn = strjoina(new_name, ".nspawn"); + + rs = file_in_same_dir(path, fn); + if (!rs) + return -ENOMEM; + + return copy_file_atomic(path, rs, 0664, false, 0); +} + int image_clone(Image *i, const char *new_name, bool read_only) { _cleanup_release_lock_file_ LockFile name_lock = LOCK_FILE_INIT; + _cleanup_strv_free_ char **settings = NULL; const char *new_path; + char **j; int r; assert(i); @@ -471,6 +564,10 @@ int image_clone(Image *i, const char *new_name, bool read_only) { if (!image_name_is_valid(new_name)) return -EINVAL; + settings = image_settings_path(i); + if (!settings) + return -ENOMEM; + /* Make sure nobody takes the new name, between the time we * checked it is currently unused in all search paths, and the * time we take possesion of it */ @@ -506,6 +603,12 @@ int image_clone(Image *i, const char *new_name, bool read_only) { if (r < 0) return r; + STRV_FOREACH(j, settings) { + r = clone_settings_file(*j, new_name); + if (r < 0 && r != -ENOENT) + log_debug_errno(r, "Failed to clone settings %s, ignoring: %m", *j); + } + return 0; } diff --git a/src/shared/pager.c b/src/shared/pager.c index 479a9d5e8d..41da820938 100644 --- a/src/shared/pager.c +++ b/src/shared/pager.c @@ -38,7 +38,7 @@ static pid_t pager_pid = 0; noreturn static void pager_fallback(void) { int r; - r = copy_bytes(STDIN_FILENO, STDOUT_FILENO, (off_t) -1, false); + r = copy_bytes(STDIN_FILENO, STDOUT_FILENO, (uint64_t) -1, false); if (r < 0) { log_error_errno(r, "Internal pager failed: %m"); _exit(EXIT_FAILURE); diff --git a/src/shared/path-lookup.c b/src/shared/path-lookup.c index f6a127174c..d803bbe07e 100644 --- a/src/shared/path-lookup.c +++ b/src/shared/path-lookup.c @@ -333,8 +333,7 @@ int lookup_paths_init( log_debug("Looking for unit files in (higher priority first):\n\t%s", t); } else { log_debug("Ignoring unit files."); - strv_free(p->unit_path); - p->unit_path = NULL; + p->unit_path = strv_free(p->unit_path); } if (running_as == MANAGER_SYSTEM) { @@ -390,8 +389,7 @@ int lookup_paths_init( log_debug("Looking for SysV init scripts in:\n\t%s", t); } else { log_debug("Ignoring SysV init scripts."); - strv_free(p->sysvinit_path); - p->sysvinit_path = NULL; + p->sysvinit_path = strv_free(p->sysvinit_path); } if (!strv_isempty(p->sysvrcnd_path)) { @@ -403,8 +401,7 @@ int lookup_paths_init( log_debug("Looking for SysV rcN.d links in:\n\t%s", t); } else { log_debug("Ignoring SysV rcN.d links."); - strv_free(p->sysvrcnd_path); - p->sysvrcnd_path = NULL; + p->sysvrcnd_path = strv_free(p->sysvrcnd_path); } #else log_debug("SysV init scripts and rcN.d links support disabled"); @@ -417,8 +414,7 @@ int lookup_paths_init( void lookup_paths_free(LookupPaths *p) { assert(p); - strv_free(p->unit_path); - p->unit_path = NULL; + p->unit_path = strv_free(p->unit_path); #ifdef HAVE_SYSV_COMPAT strv_free(p->sysvinit_path); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 20ded4dc0a..d21ba9a566 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -20,59 +20,60 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <sys/reboot.h> -#include <linux/reboot.h> -#include <stdio.h> +#include <errno.h> +#include <fcntl.h> #include <getopt.h> +#include <linux/reboot.h> #include <locale.h> #include <stdbool.h> +#include <stddef.h> +#include <stdio.h> #include <string.h> -#include <errno.h> -#include <unistd.h> -#include <fcntl.h> +#include <sys/reboot.h> #include <sys/socket.h> -#include <stddef.h> +#include <unistd.h> +#include "sd-bus.h" #include "sd-daemon.h" #include "sd-login.h" -#include "sd-bus.h" -#include "log.h" -#include "util.h" -#include "macro.h" -#include "set.h" -#include "utmp-wtmp.h" -#include "special.h" -#include "initreq.h" -#include "path-util.h" -#include "strv.h" + +#include "build.h" +#include "bus-common-errors.h" +#include "bus-error.h" +#include "bus-message.h" +#include "bus-util.h" #include "cgroup-show.h" #include "cgroup-util.h" -#include "list.h" -#include "path-lookup.h" -#include "exit-status.h" -#include "build.h" -#include "unit-name.h" -#include "pager.h" -#include "spawn-ask-password-agent.h" -#include "spawn-polkit-agent.h" -#include "install.h" -#include "logs-show.h" -#include "socket-util.h" -#include "fileio.h" #include "copy.h" -#include "env-util.h" -#include "bus-util.h" -#include "bus-message.h" -#include "bus-error.h" -#include "bus-common-errors.h" -#include "mkdir.h" #include "dropin.h" #include "efivars.h" +#include "env-util.h" +#include "exit-status.h" +#include "fileio.h" #include "formats-util.h" -#include "process-util.h" -#include "terminal-util.h" #include "hostname-util.h" +#include "initreq.h" +#include "install.h" +#include "list.h" +#include "log.h" +#include "logs-show.h" +#include "macro.h" +#include "mkdir.h" +#include "pager.h" +#include "path-lookup.h" +#include "path-util.h" +#include "process-util.h" +#include "set.h" #include "signal-util.h" +#include "socket-util.h" +#include "spawn-ask-password-agent.h" +#include "spawn-polkit-agent.h" +#include "special.h" +#include "strv.h" +#include "terminal-util.h" +#include "unit-name.h" +#include "util.h" +#include "utmp-wtmp.h" static char **arg_types = NULL; static char **arg_states = NULL; @@ -1477,6 +1478,8 @@ static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, cha "BindsTo\0", [DEPENDENCY_REVERSE] = "RequiredBy\0" "RequiredByOverridable\0" + "RequisiteOf\0" + "RequisiteOfOverridable\0" "WantedBy\0" "PartOf\0" "BoundBy\0", @@ -3297,6 +3300,8 @@ typedef struct UnitStatusInfo { uint64_t memory_current; uint64_t memory_limit; uint64_t cpu_usage_nsec; + uint64_t tasks_current; + uint64_t tasks_max; LIST_HEAD(ExecStatusInfo, exec); } UnitStatusInfo; @@ -3555,6 +3560,15 @@ static void print_status_info( if (i->status_errno > 0) printf(" Error: %i (%s)\n", i->status_errno, strerror(i->status_errno)); + if (i->tasks_current != (uint64_t) -1) { + printf(" Tasks: %" PRIu64, i->tasks_current); + + if (i->tasks_max != (uint64_t) -1) + printf(" (limit: %" PRIi64 ")\n", i->tasks_max); + else + printf("\n"); + } + if (i->memory_current != (uint64_t) -1) { char buf[FORMAT_BYTES_MAX]; @@ -3790,6 +3804,10 @@ static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo * i->memory_current = u; else if (streq(name, "MemoryLimit")) i->memory_limit = u; + else if (streq(name, "TasksCurrent")) + i->tasks_current = u; + else if (streq(name, "TasksMax")) + i->tasks_max = u; else if (streq(name, "CPUUsageNSec")) i->cpu_usage_nsec = u; @@ -4266,6 +4284,8 @@ static int show_one( .memory_current = (uint64_t) -1, .memory_limit = (uint64_t) -1, .cpu_usage_nsec = (uint64_t) -1, + .tasks_current = (uint64_t) -1, + .tasks_max = (uint64_t) -1, }; ExecStatusInfo *p; int r; @@ -4641,7 +4661,7 @@ static int cat_file(const char *filename, bool newline) { ansi_highlight_off()); fflush(stdout); - return copy_bytes(fd, STDOUT_FILENO, (off_t) -1, false); + return copy_bytes(fd, STDOUT_FILENO, (uint64_t) -1, false); } static int cat(sd_bus *bus, char **args) { diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index b5e09cad26..aaa33354f4 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -207,7 +207,7 @@ static int make_backup(const char *target, const char *x) { if (r < 0) return r; - r = copy_bytes(src, fileno(dst), (off_t) -1, true); + r = copy_bytes(src, fileno(dst), (uint64_t) -1, true); if (r < 0) goto fail; diff --git a/src/test/test-copy.c b/src/test/test-copy.c index b73c958ec5..a03a68bd43 100644 --- a/src/test/test-copy.c +++ b/src/test/test-copy.c @@ -146,7 +146,7 @@ static void test_copy_bytes(void) { assert_se(pipe2(pipefd, O_CLOEXEC) == 0); - r = copy_bytes(infd, pipefd[1], (off_t) -1, false); + r = copy_bytes(infd, pipefd[1], (uint64_t) -1, false); assert_se(r == 0); r = read(pipefd[0], buf, sizeof(buf)); diff --git a/src/test/test-util.c b/src/test/test-util.c index 8ceb71f22a..7935442dbb 100644 --- a/src/test/test-util.c +++ b/src/test/test-util.c @@ -893,7 +893,7 @@ static void test_protect_errno(void) { } static void test_parse_size(void) { - off_t bytes; + uint64_t bytes; assert_se(parse_size("111", 1024, &bytes) == 0); assert_se(bytes == 111); @@ -960,12 +960,12 @@ static void test_parse_size(void) { assert_se(parse_size("-10B 20K", 1024, &bytes) == -ERANGE); } -static void test_config_parse_iec_off(void) { - off_t offset = 0; - assert_se(config_parse_iec_off(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4M", &offset, NULL) == 0); +static void test_config_parse_iec_uint64(void) { + uint64_t offset = 0; + assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4M", &offset, NULL) == 0); assert_se(offset == 4 * 1024 * 1024); - assert_se(config_parse_iec_off(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4.5M", &offset, NULL) == 0); + assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4.5M", &offset, NULL) == 0); } static void test_strextend(void) { @@ -2250,7 +2250,7 @@ int main(int argc, char *argv[]) { test_u64log2(); test_protect_errno(); test_parse_size(); - test_config_parse_iec_off(); + test_config_parse_iec_uint64(); test_strextend(); test_strrep(); test_split_pair(); |