From 049cb73b360d4551a82cb8f0e46fc9c24226a793 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Wed, 1 Feb 2017 13:25:27 -0500 Subject: cgls: make function to query cgroup root public No functional change. --- src/cgls/cgls.c | 48 ++---------------------------------------- src/shared/cgroup-show.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++ src/shared/cgroup-show.h | 4 ++++ 3 files changed, 61 insertions(+), 46 deletions(-) diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c index b55aa86a40..e6ec9640a8 100644 --- a/src/cgls/cgls.c +++ b/src/cgls/cgls.c @@ -120,50 +120,6 @@ static int parse_argv(int argc, char *argv[]) { return 1; } -static int get_cgroup_root(char **ret) { - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; - _cleanup_free_ char *unit = NULL, *path = NULL; - const char *m; - int r; - - if (!arg_machine) { - r = cg_get_root_path(ret); - if (r == -ENOMEDIUM) - return log_error_errno(r, "Failed to get root control group path: No cgroup filesystem mounted on /sys/fs/cgroup"); - else if (r < 0) - return log_error_errno(r, "Failed to get root control group path: %m"); - - return 0; - } - - m = strjoina("/run/systemd/machines/", arg_machine); - r = parse_env_file(m, NEWLINE, "SCOPE", &unit, NULL); - if (r < 0) - return log_error_errno(r, "Failed to load machine data: %m"); - - path = unit_dbus_path_from_name(unit); - if (!path) - return log_oom(); - - r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, false, &bus); - if (r < 0) - return log_error_errno(r, "Failed to create bus connection: %m"); - - r = sd_bus_get_property_string( - bus, - "org.freedesktop.systemd1", - path, - unit_dbus_interface_from_name(unit), - "ControlGroup", - &error, - ret); - if (r < 0) - return log_error_errno(r, "Failed to query unit control group path: %s", bus_error_message(&error, r)); - - return 0; -} - static void show_cg_info(const char *controller, const char *path) { if (cg_all_unified() <= 0 && controller && !streq(controller, SYSTEMD_CGROUP_CONTROLLER)) @@ -198,7 +154,7 @@ int main(int argc, char *argv[]) { _cleanup_free_ char *root = NULL; int i; - r = get_cgroup_root(&root); + r = show_cgroup_get_root_and_warn(arg_machine, &root); if (r < 0) goto finish; @@ -267,7 +223,7 @@ int main(int argc, char *argv[]) { if (!done) { _cleanup_free_ char *root = NULL; - r = get_cgroup_root(&root); + r = show_cgroup_get_root_and_warn(arg_machine, &root); if (r < 0) goto finish; diff --git a/src/shared/cgroup-show.c b/src/shared/cgroup-show.c index f5bb0603c3..105710436e 100644 --- a/src/shared/cgroup-show.c +++ b/src/shared/cgroup-show.c @@ -24,10 +24,15 @@ #include #include +#include + #include "alloc-util.h" +#include "bus-error.h" +#include "bus-util.h" #include "cgroup-show.h" #include "cgroup-util.h" #include "fd-util.h" +#include "fileio.h" #include "format-util.h" #include "locale-util.h" #include "macro.h" @@ -36,6 +41,7 @@ #include "process-util.h" #include "string-util.h" #include "terminal-util.h" +#include "unit-name.h" static void show_pid_array( pid_t pids[], @@ -310,3 +316,52 @@ int show_cgroup_and_extra_by_spec( return show_cgroup_and_extra(controller, path, prefix, n_columns, extra_pids, n_extra_pids, flags); } + +int show_cgroup_get_root_and_warn( + const char *machine, + char **ret) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_free_ char *unit = NULL, *path = NULL; + const char *m; + int r; + + if (!machine) { + r = cg_get_root_path(ret); + if (r == -ENOMEDIUM) + return log_error_errno(r, "Failed to get root control group path.\n" + "No cgroup filesystem mounted on /sys/fs/cgroup"); + else if (r < 0) + return log_error_errno(r, "Failed to get root control group path: %m"); + + return 0; + } + + m = strjoina("/run/systemd/machines/", machine); + r = parse_env_file(m, NEWLINE, "SCOPE", &unit, NULL); + if (r < 0) + return log_error_errno(r, "Failed to load machine data: %m"); + + path = unit_dbus_path_from_name(unit); + if (!path) + return log_oom(); + + r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, false, &bus); + if (r < 0) + return log_error_errno(r, "Failed to create bus connection: %m"); + + r = sd_bus_get_property_string( + bus, + "org.freedesktop.systemd1", + path, + unit_dbus_interface_from_name(unit), + "ControlGroup", + &error, + ret); + if (r < 0) + return log_error_errno(r, "Failed to query unit control group path: %s", + bus_error_message(&error, r)); + + return 0; +} diff --git a/src/shared/cgroup-show.h b/src/shared/cgroup-show.h index 5c1d6e6d98..0574f40552 100644 --- a/src/shared/cgroup-show.h +++ b/src/shared/cgroup-show.h @@ -30,3 +30,7 @@ int show_cgroup(const char *controller, const char *path, const char *prefix, un int show_cgroup_and_extra_by_spec(const char *spec, const char *prefix, unsigned n_columns, const pid_t extra_pids[], unsigned n_extra_pids, OutputFlags flags); int show_cgroup_and_extra(const char *controller, const char *path, const char *prefix, unsigned n_columns, const pid_t extra_pids[], unsigned n_extra_pids, OutputFlags flags); + +int show_cgroup_get_root_and_warn( + const char *machine, + char **ret); -- cgit v1.2.3-54-g00ecf From d3e8277d5004163c725a895778c3a9dce9ca091e Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Wed, 1 Feb 2017 20:26:58 -0500 Subject: cgtop: use common function to query cgroup root show_cgroup_get_root_and_warn is renamed to show_cgroup_get_path_and_warn because it now optionally allows querying a non-root path. This removes duplicated code and teaches cgtop to combine -M with a root prefix: $ systemd-cgtop -M myprecious /system.slice ... --- src/cgls/cgls.c | 4 +-- src/cgtop/cgtop.c | 67 ++++-------------------------------------- src/shared/cgroup-show.c | 76 ++++++++++++++++++++++++++++-------------------- src/shared/cgroup-show.h | 3 +- 4 files changed, 55 insertions(+), 95 deletions(-) diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c index e6ec9640a8..1d21c1c20c 100644 --- a/src/cgls/cgls.c +++ b/src/cgls/cgls.c @@ -154,7 +154,7 @@ int main(int argc, char *argv[]) { _cleanup_free_ char *root = NULL; int i; - r = show_cgroup_get_root_and_warn(arg_machine, &root); + r = show_cgroup_get_path_and_warn(arg_machine, NULL, &root); if (r < 0) goto finish; @@ -223,7 +223,7 @@ int main(int argc, char *argv[]) { if (!done) { _cleanup_free_ char *root = NULL; - r = show_cgroup_get_root_and_warn(arg_machine, &root); + r = show_cgroup_get_path_and_warn(arg_machine, NULL, &root); if (r < 0) goto finish; diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c index af5c3d8695..50ac6a58b0 100644 --- a/src/cgtop/cgtop.c +++ b/src/cgtop/cgtop.c @@ -31,6 +31,7 @@ #include "alloc-util.h" #include "bus-error.h" #include "bus-util.h" +#include "cgroup-show.h" #include "cgroup-util.h" #include "fd-util.h" #include "fileio.h" @@ -862,13 +863,9 @@ static int parse_argv(int argc, char *argv[]) { assert_not_reached("Unhandled option"); } - if (optind == argc-1) { - if (arg_machine) { - log_error("Specifying a control group path together with the -M option is not allowed"); - return -EINVAL; - } + if (optind == argc - 1) arg_root = argv[optind]; - } else if (optind < argc) { + else if (optind < argc) { log_error("Too many arguments."); return -EINVAL; } @@ -890,59 +887,6 @@ static const char* counting_what(void) { return "userspace processes (excl. kernel)"; } -static int get_cgroup_root(char **ret) { - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; - _cleanup_free_ char *unit = NULL, *path = NULL; - const char *m; - int r; - - if (arg_root) { - char *aux; - - aux = strdup(arg_root); - if (!aux) - return log_oom(); - - *ret = aux; - return 0; - } - - if (!arg_machine) { - r = cg_get_root_path(ret); - if (r < 0) - return log_error_errno(r, "Failed to get root control group path: %m"); - - return 0; - } - - m = strjoina("/run/systemd/machines/", arg_machine); - r = parse_env_file(m, NEWLINE, "SCOPE", &unit, NULL); - if (r < 0) - return log_error_errno(r, "Failed to load machine data: %m"); - - path = unit_dbus_path_from_name(unit); - if (!path) - return log_oom(); - - r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, false, &bus); - if (r < 0) - return log_error_errno(r, "Failed to create bus connection: %m"); - - r = sd_bus_get_property_string( - bus, - "org.freedesktop.systemd1", - path, - unit_dbus_interface_from_name(unit), - "ControlGroup", - &error, - ret); - if (r < 0) - return log_error_errno(r, "Failed to query unit control group path: %s", bus_error_message(&error, r)); - - return 0; -} - int main(int argc, char *argv[]) { int r; Hashmap *a = NULL, *b = NULL; @@ -967,11 +911,12 @@ int main(int argc, char *argv[]) { if (r <= 0) goto finish; - r = get_cgroup_root(&root); + r = show_cgroup_get_path_and_warn(arg_machine, arg_root, &root); if (r < 0) { log_error_errno(r, "Failed to get root control group path: %m"); goto finish; - } + } else + log_debug("Cgroup path: %s", root); a = hashmap_new(&string_hash_ops); b = hashmap_new(&string_hash_ops); diff --git a/src/shared/cgroup-show.c b/src/shared/cgroup-show.c index 105710436e..c9815f22ac 100644 --- a/src/shared/cgroup-show.c +++ b/src/shared/cgroup-show.c @@ -317,51 +317,65 @@ int show_cgroup_and_extra_by_spec( return show_cgroup_and_extra(controller, path, prefix, n_columns, extra_pids, n_extra_pids, flags); } -int show_cgroup_get_root_and_warn( +int show_cgroup_get_path_and_warn( const char *machine, + const char *prefix, char **ret) { - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; - _cleanup_free_ char *unit = NULL, *path = NULL; - const char *m; int r; + _cleanup_free_ char *root = NULL; + + if (machine) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_free_ char *unit = NULL, *path = NULL; + const char *m; + + m = strjoina("/run/systemd/machines/", machine); + r = parse_env_file(m, NEWLINE, "SCOPE", &unit, NULL); + if (r < 0) + return log_error_errno(r, "Failed to load machine data: %m"); - if (!machine) { - r = cg_get_root_path(ret); + path = unit_dbus_path_from_name(unit); + if (!path) + return log_oom(); + + r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, false, &bus); + if (r < 0) + return log_error_errno(r, "Failed to create bus connection: %m"); + + r = sd_bus_get_property_string( + bus, + "org.freedesktop.systemd1", + path, + unit_dbus_interface_from_name(unit), + "ControlGroup", + &error, + &root); + if (r < 0) + return log_error_errno(r, "Failed to query unit control group path: %s", + bus_error_message(&error, r)); + } else { + r = cg_get_root_path(&root); if (r == -ENOMEDIUM) return log_error_errno(r, "Failed to get root control group path.\n" "No cgroup filesystem mounted on /sys/fs/cgroup"); else if (r < 0) return log_error_errno(r, "Failed to get root control group path: %m"); - - return 0; } - m = strjoina("/run/systemd/machines/", machine); - r = parse_env_file(m, NEWLINE, "SCOPE", &unit, NULL); - if (r < 0) - return log_error_errno(r, "Failed to load machine data: %m"); + if (prefix) { + char *t; - path = unit_dbus_path_from_name(unit); - if (!path) - return log_oom(); + t = strjoin(root, prefix); + if (!t) + return log_oom(); - r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, false, &bus); - if (r < 0) - return log_error_errno(r, "Failed to create bus connection: %m"); - - r = sd_bus_get_property_string( - bus, - "org.freedesktop.systemd1", - path, - unit_dbus_interface_from_name(unit), - "ControlGroup", - &error, - ret); - if (r < 0) - return log_error_errno(r, "Failed to query unit control group path: %s", - bus_error_message(&error, r)); + *ret = t; + } else { + *ret = root; + root = NULL; + } return 0; } diff --git a/src/shared/cgroup-show.h b/src/shared/cgroup-show.h index 0574f40552..1445c05f1f 100644 --- a/src/shared/cgroup-show.h +++ b/src/shared/cgroup-show.h @@ -31,6 +31,7 @@ int show_cgroup(const char *controller, const char *path, const char *prefix, un int show_cgroup_and_extra_by_spec(const char *spec, const char *prefix, unsigned n_columns, const pid_t extra_pids[], unsigned n_extra_pids, OutputFlags flags); int show_cgroup_and_extra(const char *controller, const char *path, const char *prefix, unsigned n_columns, const pid_t extra_pids[], unsigned n_extra_pids, OutputFlags flags); -int show_cgroup_get_root_and_warn( +int show_cgroup_get_path_and_warn( const char *machine, + const char *prefix, char **ret); -- cgit v1.2.3-54-g00ecf From bc06be753346784e19151814b5b9c01c624317f2 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Wed, 1 Feb 2017 14:30:57 -0500 Subject: shared/cgroup-show: extract funtion to query unit cgroup path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …and use it where possible. --- src/cgls/cgls.c | 1 - src/login/loginctl.c | 25 +++---------------------- src/machine/machinectl.c | 24 +++--------------------- src/shared/cgroup-show.c | 47 +++++++++++++++++++++++++++++++---------------- src/shared/cgroup-show.h | 6 ++++++ 5 files changed, 43 insertions(+), 60 deletions(-) diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c index 1d21c1c20c..b8af4680f9 100644 --- a/src/cgls/cgls.c +++ b/src/cgls/cgls.c @@ -26,7 +26,6 @@ #include "sd-bus.h" #include "alloc-util.h" -#include "bus-error.h" #include "bus-util.h" #include "cgroup-show.h" #include "cgroup-util.h" diff --git a/src/login/loginctl.c b/src/login/loginctl.c index 4c618ed19e..1aac7ae979 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -240,7 +240,6 @@ static int list_seats(int argc, char *argv[], void *userdata) { sd_bus *bus = userdata; unsigned k = 0; int r; - assert(bus); assert(argv); @@ -280,35 +279,17 @@ static int list_seats(int argc, char *argv[], void *userdata) { } static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit, pid_t leader) { + _cleanup_free_ char *cgroup = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - _cleanup_free_ char *path = NULL; - const char *cgroup; unsigned c; int r; assert(bus); assert(unit); - path = unit_dbus_path_from_name(unit); - if (!path) - return log_oom(); - - r = sd_bus_get_property( - bus, - "org.freedesktop.systemd1", - path, - interface, - "ControlGroup", - &error, - &reply, - "s"); - if (r < 0) - return log_error_errno(r, "Failed to query ControlGroup: %s", bus_error_message(&error, r)); - - r = sd_bus_message_read(reply, "s", &cgroup); + r = show_cgroup_get_unit_path_and_warn(bus, unit, &cgroup); if (r < 0) - return bus_log_parse_error(r); + return r; if (isempty(cgroup)) return 0; diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index 31a40d47c3..4f5f659c7c 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -477,35 +477,17 @@ static int list_images(int argc, char *argv[], void *userdata) { } static int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) { + _cleanup_free_ char *cgroup = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - _cleanup_free_ char *path = NULL; - const char *cgroup; int r; unsigned c; assert(bus); assert(unit); - path = unit_dbus_path_from_name(unit); - if (!path) - return log_oom(); - - r = sd_bus_get_property( - bus, - "org.freedesktop.systemd1", - path, - unit_dbus_interface_from_name(unit), - "ControlGroup", - &error, - &reply, - "s"); - if (r < 0) - return log_error_errno(r, "Failed to query ControlGroup: %s", bus_error_message(&error, r)); - - r = sd_bus_message_read(reply, "s", &cgroup); + r = show_cgroup_get_unit_path_and_warn(bus, unit, &cgroup); if (r < 0) - return bus_log_parse_error(r); + return r; if (isempty(cgroup)) return 0; diff --git a/src/shared/cgroup-show.c b/src/shared/cgroup-show.c index c9815f22ac..8765cf2f49 100644 --- a/src/shared/cgroup-show.c +++ b/src/shared/cgroup-show.c @@ -317,6 +317,34 @@ int show_cgroup_and_extra_by_spec( return show_cgroup_and_extra(controller, path, prefix, n_columns, extra_pids, n_extra_pids, flags); } +int show_cgroup_get_unit_path_and_warn( + sd_bus *bus, + const char *unit, + char **ret) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *path = NULL; + int r; + + path = unit_dbus_path_from_name(unit); + if (!path) + return log_oom(); + + r = sd_bus_get_property_string( + bus, + "org.freedesktop.systemd1", + path, + unit_dbus_interface_from_name(unit), + "ControlGroup", + &error, + ret); + if (r < 0) + return log_error_errno(r, "Failed to query unit control group path: %s", + bus_error_message(&error, r)); + + return 0; +} + int show_cgroup_get_path_and_warn( const char *machine, const char *prefix, @@ -326,9 +354,8 @@ int show_cgroup_get_path_and_warn( _cleanup_free_ char *root = NULL; if (machine) { - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; - _cleanup_free_ char *unit = NULL, *path = NULL; + _cleanup_free_ char *unit = NULL; const char *m; m = strjoina("/run/systemd/machines/", machine); @@ -336,25 +363,13 @@ int show_cgroup_get_path_and_warn( if (r < 0) return log_error_errno(r, "Failed to load machine data: %m"); - path = unit_dbus_path_from_name(unit); - if (!path) - return log_oom(); - r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, false, &bus); if (r < 0) return log_error_errno(r, "Failed to create bus connection: %m"); - r = sd_bus_get_property_string( - bus, - "org.freedesktop.systemd1", - path, - unit_dbus_interface_from_name(unit), - "ControlGroup", - &error, - &root); + r = show_cgroup_get_unit_path_and_warn(bus, unit, &root); if (r < 0) - return log_error_errno(r, "Failed to query unit control group path: %s", - bus_error_message(&error, r)); + return r; } else { r = cg_get_root_path(&root); if (r == -ENOMEDIUM) diff --git a/src/shared/cgroup-show.h b/src/shared/cgroup-show.h index 1445c05f1f..736f0f34c8 100644 --- a/src/shared/cgroup-show.h +++ b/src/shared/cgroup-show.h @@ -22,6 +22,8 @@ #include #include +#include + #include "logs-show.h" #include "output-mode.h" @@ -31,6 +33,10 @@ int show_cgroup(const char *controller, const char *path, const char *prefix, un int show_cgroup_and_extra_by_spec(const char *spec, const char *prefix, unsigned n_columns, const pid_t extra_pids[], unsigned n_extra_pids, OutputFlags flags); int show_cgroup_and_extra(const char *controller, const char *path, const char *prefix, unsigned n_columns, const pid_t extra_pids[], unsigned n_extra_pids, OutputFlags flags); +int show_cgroup_get_unit_path_and_warn( + sd_bus *bus, + const char *unit, + char **ret); int show_cgroup_get_path_and_warn( const char *machine, const char *prefix, -- cgit v1.2.3-54-g00ecf From d9855d87eb18ed6f5161904c38fc19c075a7d89a Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Wed, 1 Feb 2017 14:52:46 -0500 Subject: cgls: add --unit to show units $ systemd-cgls -u systemd-journald.service machine.slice I opted for a "global" switch, instead of modifying the behaviour of just one argument. It seem to be a more useful setting, since usually one will want to query one or more units, and not mix unit names with paths. Closes #5156. --- man/systemd-cgls.xml | 14 ++++++++++++ src/cgls/cgls.c | 61 +++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 67 insertions(+), 8 deletions(-) diff --git a/man/systemd-cgls.xml b/man/systemd-cgls.xml index e8f0368f48..91d0c0b1bb 100644 --- a/man/systemd-cgls.xml +++ b/man/systemd-cgls.xml @@ -54,6 +54,12 @@ OPTIONS CGROUP + + systemd-cgls + OPTIONS + + UNIT + @@ -95,6 +101,14 @@ + + + + + Show cgroup subtrees for the specified units. + + + diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c index b8af4680f9..83e47170d8 100644 --- a/src/cgls/cgls.c +++ b/src/cgls/cgls.c @@ -40,6 +40,7 @@ static bool arg_no_pager = false; static bool arg_kernel_threads = false; static bool arg_all = false; +static bool arg_unit = false; static int arg_full = -1; static char* arg_machine = NULL; @@ -50,6 +51,7 @@ static void help(void) { " --version Show package version\n" " --no-pager Do not pipe output into a pager\n" " -a --all Show all groups, including empty\n" + " -u --unit Show the subtrees of specifified units\n" " -l --full Do not ellipsize output\n" " -k Include kernel threads in output\n" " -M --machine= Show container\n" @@ -70,6 +72,7 @@ static int parse_argv(int argc, char *argv[]) { { "all", no_argument, NULL, 'a' }, { "full", no_argument, NULL, 'l' }, { "machine", required_argument, NULL, 'M' }, + { "unit", no_argument, NULL, 'u' }, {} }; @@ -78,7 +81,7 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 1); assert(argv); - while ((c = getopt_long(argc, argv, "hkalM:", options, NULL)) >= 0) + while ((c = getopt_long(argc, argv, "hkalM:u", options, NULL)) >= 0) switch (c) { @@ -97,6 +100,10 @@ static int parse_argv(int argc, char *argv[]) { arg_all = true; break; + case 'u': + arg_unit = true; + break; + case 'l': arg_full = true; break; @@ -116,6 +123,11 @@ static int parse_argv(int argc, char *argv[]) { assert_not_reached("Unhandled option"); } + if (arg_machine && arg_unit) { + log_error("Cannot combine --unit with --machine."); + return -EINVAL; + } + return 1; } @@ -150,17 +162,42 @@ int main(int argc, char *argv[]) { arg_kernel_threads * OUTPUT_KERNEL_THREADS; if (optind < argc) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; _cleanup_free_ char *root = NULL; int i; - r = show_cgroup_get_path_and_warn(arg_machine, NULL, &root); - if (r < 0) - goto finish; - for (i = optind; i < argc; i++) { int q; - if (path_startswith(argv[i], "/sys/fs/cgroup")) { + if (arg_unit) { + /* Command line arguments are unit names */ + _cleanup_free_ char *cgroup = NULL; + + if (!bus) { + /* Connect to the bus only if necessary */ + r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, false, &bus); + if (r < 0) { + log_error_errno(r, "Failed to create bus connection: %m"); + goto finish; + } + } + + q = show_cgroup_get_unit_path_and_warn(bus, argv[i], &cgroup); + if (q < 0) + goto failed; + + if (isempty(cgroup)) { + log_warning("Unit %s not found.", argv[i]); + q = -ENOENT; + goto failed; + } + + printf("Unit %s (%s):\n", argv[i], cgroup); + fflush(stdout); + + q = show_cgroup_by_path(cgroup, NULL, 0, output_flags); + + } else if (path_startswith(argv[i], "/sys/fs/cgroup")) { printf("Directory %s:\n", argv[i]); fflush(stdout); @@ -170,10 +207,17 @@ int main(int argc, char *argv[]) { _cleanup_free_ char *c = NULL, *p = NULL, *j = NULL; const char *controller, *path; + if (!root) { + /* Query root only if needed, treat error as fatal */ + r = show_cgroup_get_path_and_warn(arg_machine, NULL, &root); + if (r < 0) + goto finish; + } + r = cg_split_spec(argv[i], &c, &p); if (r < 0) { log_error_errno(r, "Failed to split argument %s: %m", argv[i]); - goto finish; + goto failed; } controller = c ?: SYSTEMD_CGROUP_CONTROLLER; @@ -194,7 +238,8 @@ int main(int argc, char *argv[]) { q = show_cgroup(controller, path, NULL, 0, output_flags); } - if (q < 0) + failed: + if (q < 0 && r >= 0) r = q; } -- cgit v1.2.3-54-g00ecf From e7aa3f5014d601b91c7bf8f3a20d5b5c1a0a5908 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Wed, 1 Feb 2017 15:20:46 -0500 Subject: cgls: add --user-unit to show user units --- man/systemd-cgls.xml | 9 ++++++++- src/cgls/cgls.c | 43 +++++++++++++++++++++++++++++-------------- 2 files changed, 37 insertions(+), 15 deletions(-) diff --git a/man/systemd-cgls.xml b/man/systemd-cgls.xml index 91d0c0b1bb..219514b183 100644 --- a/man/systemd-cgls.xml +++ b/man/systemd-cgls.xml @@ -57,7 +57,7 @@ systemd-cgls OPTIONS - + | UNIT @@ -109,6 +109,13 @@ + + + + Show cgroup subtrees for the specified user units. + + + diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c index 83e47170d8..b64a0df542 100644 --- a/src/cgls/cgls.c +++ b/src/cgls/cgls.c @@ -40,7 +40,13 @@ static bool arg_no_pager = false; static bool arg_kernel_threads = false; static bool arg_all = false; -static bool arg_unit = false; + +static enum { + SHOW_UNIT_NONE, + SHOW_UNIT_SYSTEM, + SHOW_UNIT_USER, +} arg_show_unit = SHOW_UNIT_NONE; + static int arg_full = -1; static char* arg_machine = NULL; @@ -51,7 +57,8 @@ static void help(void) { " --version Show package version\n" " --no-pager Do not pipe output into a pager\n" " -a --all Show all groups, including empty\n" - " -u --unit Show the subtrees of specifified units\n" + " -u --unit Show the subtrees of specifified system units\n" + " --user-unit Show the subtrees of specifified user units\n" " -l --full Do not ellipsize output\n" " -k Include kernel threads in output\n" " -M --machine= Show container\n" @@ -63,16 +70,18 @@ static int parse_argv(int argc, char *argv[]) { enum { ARG_NO_PAGER = 0x100, ARG_VERSION, + ARG_USER_UNIT, }; static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "no-pager", no_argument, NULL, ARG_NO_PAGER }, - { "all", no_argument, NULL, 'a' }, - { "full", no_argument, NULL, 'l' }, - { "machine", required_argument, NULL, 'M' }, - { "unit", no_argument, NULL, 'u' }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "all", no_argument, NULL, 'a' }, + { "full", no_argument, NULL, 'l' }, + { "machine", required_argument, NULL, 'M' }, + { "unit", no_argument, NULL, 'u' }, + { "user-unit", no_argument, NULL, ARG_USER_UNIT }, {} }; @@ -101,7 +110,11 @@ static int parse_argv(int argc, char *argv[]) { break; case 'u': - arg_unit = true; + arg_show_unit = SHOW_UNIT_SYSTEM; + break; + + case ARG_USER_UNIT: + arg_show_unit = SHOW_UNIT_USER; break; case 'l': @@ -123,8 +136,8 @@ static int parse_argv(int argc, char *argv[]) { assert_not_reached("Unhandled option"); } - if (arg_machine && arg_unit) { - log_error("Cannot combine --unit with --machine."); + if (arg_machine && arg_show_unit != SHOW_UNIT_NONE) { + log_error("Cannot combine --unit or --user-unit with --machine."); return -EINVAL; } @@ -169,13 +182,15 @@ int main(int argc, char *argv[]) { for (i = optind; i < argc; i++) { int q; - if (arg_unit) { + if (arg_show_unit != SHOW_UNIT_NONE) { /* Command line arguments are unit names */ _cleanup_free_ char *cgroup = NULL; if (!bus) { /* Connect to the bus only if necessary */ - r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, false, &bus); + r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, + arg_show_unit == SHOW_UNIT_USER, + &bus); if (r < 0) { log_error_errno(r, "Failed to create bus connection: %m"); goto finish; -- cgit v1.2.3-54-g00ecf From 256c1eba6b9eb31e2e9aa5cf82ed38eb441a6a51 Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Wed, 1 Feb 2017 22:24:41 -0500 Subject: cgls: allow --unit, --user-unit to take optional argument The following are all equivalent: --unit foo.service bar.service --unit=foo.service bar.service --unit=foo.service --unit=bar.service foo.service bar.service --unit Similarly for --user-unit. The only case that doesn't work well is when --unit and --user-unit are mixed: --unit=foo.service --user-unit=bar.service We'll treat both names as user units. I think this is OK. --- src/cgls/cgls.c | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c index b64a0df542..82b4d9ccb3 100644 --- a/src/cgls/cgls.c +++ b/src/cgls/cgls.c @@ -34,6 +34,7 @@ #include "output-mode.h" #include "pager.h" #include "path-util.h" +#include "strv.h" #include "unit-name.h" #include "util.h" @@ -46,6 +47,7 @@ static enum { SHOW_UNIT_SYSTEM, SHOW_UNIT_USER, } arg_show_unit = SHOW_UNIT_NONE; +static char **arg_names = NULL; static int arg_full = -1; static char* arg_machine = NULL; @@ -80,8 +82,8 @@ static int parse_argv(int argc, char *argv[]) { { "all", no_argument, NULL, 'a' }, { "full", no_argument, NULL, 'l' }, { "machine", required_argument, NULL, 'M' }, - { "unit", no_argument, NULL, 'u' }, - { "user-unit", no_argument, NULL, ARG_USER_UNIT }, + { "unit", optional_argument, NULL, 'u' }, + { "user-unit", optional_argument, NULL, ARG_USER_UNIT }, {} }; @@ -90,7 +92,7 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 1); assert(argv); - while ((c = getopt_long(argc, argv, "hkalM:u", options, NULL)) >= 0) + while ((c = getopt_long(argc, argv, "-hkalM:u::", options, NULL)) >= 0) switch (c) { @@ -111,10 +113,20 @@ static int parse_argv(int argc, char *argv[]) { case 'u': arg_show_unit = SHOW_UNIT_SYSTEM; + if (strv_push(&arg_names, optarg) < 0) /* push optarg if not empty */ + return log_oom(); break; case ARG_USER_UNIT: arg_show_unit = SHOW_UNIT_USER; + if (strv_push(&arg_names, optarg) < 0) /* push optarg if not empty */ + return log_oom(); + break; + + case 1: + /* positional argument */ + if (strv_push(&arg_names, optarg) < 0) + return log_oom(); break; case 'l': @@ -174,12 +186,12 @@ int main(int argc, char *argv[]) { (arg_full > 0) * OUTPUT_FULL_WIDTH | arg_kernel_threads * OUTPUT_KERNEL_THREADS; - if (optind < argc) { + if (arg_names) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; _cleanup_free_ char *root = NULL; - int i; + char **name; - for (i = optind; i < argc; i++) { + STRV_FOREACH(name, arg_names) { int q; if (arg_show_unit != SHOW_UNIT_NONE) { @@ -197,27 +209,27 @@ int main(int argc, char *argv[]) { } } - q = show_cgroup_get_unit_path_and_warn(bus, argv[i], &cgroup); + q = show_cgroup_get_unit_path_and_warn(bus, *name, &cgroup); if (q < 0) goto failed; if (isempty(cgroup)) { - log_warning("Unit %s not found.", argv[i]); + log_warning("Unit %s not found.", *name); q = -ENOENT; goto failed; } - printf("Unit %s (%s):\n", argv[i], cgroup); + printf("Unit %s (%s):\n", *name, cgroup); fflush(stdout); q = show_cgroup_by_path(cgroup, NULL, 0, output_flags); - } else if (path_startswith(argv[i], "/sys/fs/cgroup")) { + } else if (path_startswith(*name, "/sys/fs/cgroup")) { - printf("Directory %s:\n", argv[i]); + printf("Directory %s:\n", *name); fflush(stdout); - q = show_cgroup_by_path(argv[i], NULL, 0, output_flags); + q = show_cgroup_by_path(*name, NULL, 0, output_flags); } else { _cleanup_free_ char *c = NULL, *p = NULL, *j = NULL; const char *controller, *path; @@ -229,9 +241,9 @@ int main(int argc, char *argv[]) { goto finish; } - r = cg_split_spec(argv[i], &c, &p); + r = cg_split_spec(*name, &c, &p); if (r < 0) { - log_error_errno(r, "Failed to split argument %s: %m", argv[i]); + log_error_errno(r, "Failed to split argument %s: %m", *name); goto failed; } @@ -298,6 +310,7 @@ int main(int argc, char *argv[]) { finish: pager_close(); + free(arg_names); /* don't free the strings */ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } -- cgit v1.2.3-54-g00ecf