summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIvana Hutarova Varekova <varekova@redhat.com>2009-10-09 11:40:04 +0200
committerDhaval Giani <dhaval@linux.vnet.ibm.com>2009-10-09 15:45:26 +0530
commit9c012385dbd80003ba5fe920e644f944ae8eceb3 (patch)
tree267e2ad7941f746988fb84c1ff997201af6d2514
parent9d8f0ae5c3b3df6bef2f12738f62397623481090 (diff)
downloadlibcg-9c012385dbd80003ba5fe920e644f944ae8eceb3.tar.gz
libcg-9c012385dbd80003ba5fe920e644f944ae8eceb3.tar.xz
libcg-9c012385dbd80003ba5fe920e644f944ae8eceb3.zip
adds lscgroup tool
Description: create tool which shows cgroups which are on system: Usage: lscgroup [<controllers>:<path>] [...] list all cgroups Changes since V1(the previous versions was not enumerated): * fix the format of comments which have more than 1 line * printf of help -> fprintf(stdout,... * change the sequence of processing of cgroups on input (now first) and internal controller list(first in the previous version), now the cgroups are output in order in which they are put to input * fix return values/error messages - now if the controller is not mount the tool return error - it returns 0 otherwise Changes since V2 * fix problem with slash characters ( $ lscgroup cpu:/1/2 cpu:/1/2/ cpu:/1/2/1 $ lscgroup cpu:1/2 cpu:/2/ cpu:/2/1 ) Changes since V3 * rename the variables (dp1 -> cgroup_dir_path, dp2 -> input_dir_path) * improve the coding style Examples: $ lscgroup devices:/ devices:/sysdefault cpuset,cpuacct:/ cpuset,cpuacct:/sysdefault cpuset,cpuacct:/daemons cpuset,cpuacct:/daemons/ftp $ lscgroup cpuset:/ cpuset,cpuacct:/ cpuset,cpuacct:/sysdefault cpuset,cpuacct:/daemons cpuset,cpuacct:/daemons/ftp $ lscgroup cpuset:/daemons cpuset,cpuacct:/daemons/ cpuset,cpuacct:/daemons/ftp Signed-off-by: Ivana Hutarova Varekova <varekova@redhat.com> Signed-off-by: Dhaval Giani <dhaval@linux.vnet.ibm.com>
-rw-r--r--src/tools/Makefile.am4
-rw-r--r--src/tools/lscgroup.c295
2 files changed, 298 insertions, 1 deletions
diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am
index e2338bd..d541445 100644
--- a/src/tools/Makefile.am
+++ b/src/tools/Makefile.am
@@ -3,7 +3,7 @@ LDADD = $(top_srcdir)/src/.libs/libcgroup.la
if WITH_TOOLS
-bin_PROGRAMS = cgexec cgclassify cgcreate cgset cgdelete lssubsys
+bin_PROGRAMS = cgexec cgclassify cgcreate cgset cgdelete lssubsys lscgroup
sbin_PROGRAMS = cgconfigparser cgclear
@@ -23,6 +23,8 @@ cgdelete_SOURCES = cgdelete.c tools-common.c tools-common.h
lssubsys_SOURCES = lssubsys.c
+lscgroup_SOURCES = tools-common.c lscgroup.c
+
install-exec-hook:
chmod u+s $(DESTDIR)$(bindir)/cgexec
diff --git a/src/tools/lscgroup.c b/src/tools/lscgroup.c
new file mode 100644
index 0000000..5e3e80b
--- /dev/null
+++ b/src/tools/lscgroup.c
@@ -0,0 +1,295 @@
+/* Copyright (C) 2009 Red Hat, Inc. All Rights Reserved.
+ * Written by Ivana Hutarova Varekova <varekova@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2.1 of the GNU Lesser General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+
+#include <libcgroup.h>
+#include <libcgroup-internal.h>
+#include "tools-common.h"
+
+enum flag{
+ /*
+ * the flag set if there is a cgroup on output
+ * if there is no one we want to display all cgroups
+ */
+ FL_LIST = 1
+};
+
+void usage(int status, char *program_name)
+{
+ if (status != 0) {
+ fprintf(stderr, "Wrong input parameters,"
+ " try %s -h' for more information.\n",
+ program_name);
+ } else {
+ fprintf(stdout, "Usage: %s [<controllers>:<path>] [...]\n",
+ program_name);
+ fprintf(stdout, "list all cgroups\n");
+ }
+}
+
+/*
+ * if the info about controller "name" should be printed,
+ * then the function returns nonzero value
+ */
+int is_ctlr_on_list(struct cgroup_group_spec *cgroup_list,
+ char name[FILENAME_MAX])
+{
+ int j;
+
+ for (j = 0; cgroup_list->controllers[j] != NULL; j++)
+ if (strcmp(cgroup_list->controllers[j], name) == 0)
+ return 1;
+
+ return 0;
+}
+
+void print_info(struct cgroup_file_info *info, char *name, int pref)
+{
+ if (info->type == CGROUP_FILE_TYPE_DIR) {
+ if (info->full_path[pref] == '/')
+ printf("%s:%s\n", name, &info->full_path[pref]);
+ else
+ printf("%s:/%s\n", name, &info->full_path[pref]);
+ }
+}
+
+/* display controller:/input_path cgroups */
+int display_controller_data(char *input_path, char *controller, char *name)
+{
+ int ret;
+ void *handle;
+ struct cgroup_file_info info;
+ char cgroup_dir_path[FILENAME_MAX];
+ char input_dir_path[FILENAME_MAX];
+ char *end;
+ int lvl;
+ int len;
+
+ ret = cgroup_walk_tree_begin(controller, input_path, 0,
+ &handle, &info, &lvl);
+ if (ret != 0)
+ return ret;
+
+ strncpy(cgroup_dir_path, info.full_path, FILENAME_MAX);
+ /* remove problematic '/' characters from cgroup directory path*/
+ len = strlen(cgroup_dir_path)-1;
+ while (cgroup_dir_path[len] == '/')
+ len--;
+
+ cgroup_dir_path[len+1] = '\0';
+
+ strncpy(input_dir_path, input_path, FILENAME_MAX);
+ /* remove problematic '/' characters from input path*/
+ len = strlen(input_dir_path)-1;
+ while (input_dir_path[len] == '/')
+ len--;
+
+ input_dir_path[len+1] = '\0';
+
+ len = strlen(cgroup_dir_path) - strlen(input_dir_path);
+
+ print_info(&info, name, len);
+ while ((ret = cgroup_walk_tree_next(0, &handle, &info, lvl)) == 0)
+ print_info(&info, name, len);
+
+ cgroup_walk_tree_end(&handle);
+ if (ret == ECGEOF)
+ ret = 0;
+
+ return ret;
+}
+
+/*
+ * print data about input cgroup_list cgroups
+ * if FL_LIST flag is set then if the function does not find
+ * the cgroup it returns ECGEOF
+ */
+
+int print_cgroup(struct cgroup_group_spec *cgroup_spec, int flags)
+{
+ int ret = 0;
+ void *handle;
+ struct cgroup_mount_point controller;
+ char path[FILENAME_MAX];
+ char con_name[FILENAME_MAX];
+ char all_conts[FILENAME_MAX];
+ int output = 0;
+
+ path[0] = '\0';
+ con_name[0] = '\0';
+ all_conts[0] = '\0';
+
+ ret = cgroup_get_controller_begin(&handle, &controller);
+
+ /* go through the list of controllers/mount point pairs */
+ while (ret == 0) {
+ if (strcmp(path, controller.path) == 0) {
+ /* if it is still the same mount point */
+ strncat(all_conts, ",",
+ FILENAME_MAX-strlen(all_conts)-1);
+ strncat(all_conts, controller.name,
+ FILENAME_MAX-strlen(all_conts)-1);
+ } else {
+ /* we got new mount point, print it if needed */
+ if (output) {
+ ret = display_controller_data(
+ cgroup_spec->path,
+ con_name, all_conts);
+ if (ret)
+ return ret;
+ if ((flags & FL_LIST) != 0) {
+ /* we succesfully finish printing */
+ output = 0;
+ break;
+ }
+ }
+
+ output = 0;
+ strncpy(all_conts, controller.name, FILENAME_MAX);
+ all_conts[FILENAME_MAX-1] = '\0';
+ strncpy(con_name, controller.name, FILENAME_MAX);
+ con_name[FILENAME_MAX-1] = '\0';
+ strncpy(path, controller.path, FILENAME_MAX);
+ path[FILENAME_MAX-1] = '\0';
+ }
+
+ /* set output flag */
+ if ((output == 0) && (!(flags & FL_LIST) ||
+ (is_ctlr_on_list(cgroup_spec, controller.name))))
+ output = 1;
+
+ /* the actual controller should not be printed */
+ ret = cgroup_get_controller_next(&handle, &controller);
+ }
+
+ cgroup_get_controller_end(&handle);
+ if (ret != ECGEOF)
+ return ret;
+
+ if (output) {
+ ret = display_controller_data(
+ cgroup_spec->path,
+ con_name, all_conts);
+ }
+
+ return ret;
+}
+
+
+int cgroup_list_cgroups(char *tname,
+ struct cgroup_group_spec *cgroup_list[],
+ int flags)
+{
+ int ret = 0;
+ int final_ret = 0;
+ int i = 0;
+
+ /* initialize libcgroup */
+ ret = cgroup_init();
+ if (ret) {
+ fprintf(stderr, "cgroups can't be listed: %s\n",
+ cgroup_strerror(ret));
+ return ret;
+ }
+
+ if ((flags & FL_LIST) == 0) {
+ struct cgroup_group_spec *cgroup_spec;
+ cgroup_spec = calloc(1, sizeof(struct cgroup_group_spec));
+ /* we have to print all cgroups */
+ ret = print_cgroup(cgroup_spec, flags);
+ free(cgroup_spec);
+ if (ret == 0) {
+ final_ret = 0;
+ } else {
+ final_ret = ret;
+ fprintf(stderr, "cgroups can't be listed: %s\n",
+ cgroup_strerror(ret));
+ }
+ } else {
+ /* we have he list of controllers which should be print */
+ while ((cgroup_list[i] != NULL)
+ && ((ret == ECGEOF) || (ret == 0))) {
+ ret = print_cgroup(cgroup_list[i], flags);
+ if (ret != 0) {
+ if (ret == ECGEOF) {
+ /* controller was not found */
+ final_ret = ECGFAIL;
+ } else {
+ /* other problem */
+ final_ret = ret;
+ }
+ fprintf(stderr,
+ "%s: cannot find group %s..:%s: %s\n",
+ tname, cgroup_list[i]->controllers[0],
+ cgroup_list[i]->path,
+ cgroup_strerror(final_ret));
+ }
+ i++;
+ }
+ }
+ return final_ret;
+}
+
+int main(int argc, char *argv[])
+{
+
+ int ret = 0;
+ int c;
+
+ int flags = 0;
+
+ struct cgroup_group_spec *cgroup_list[CG_HIER_MAX];
+
+ static struct option options[] = {
+ {"help", 0, 0, 'h'},
+ {0, 0, 0, 0}
+ };
+
+ /* parse arguments */
+ while ((c = getopt_long(argc, argv, "h", options, NULL)) > 0) {
+ switch (c) {
+ case 'h':
+ usage(0, argv[0]);
+ return 0;
+ default:
+ usage(1, argv[0]);
+ return -1;
+ }
+ }
+
+ memset(cgroup_list, 0, sizeof(cgroup_list));
+
+ /* no cgroup on input */
+ if (optind < argc)
+ flags |= FL_LIST;
+
+ /* read the list of controllers */
+ while (optind < argc) {
+ if (parse_cgroup_spec(cgroup_list, argv[optind])) {
+ fprintf(stderr, "%s: cgroup controller"
+ " and path parsing failed (%s)\n",
+ argv[0], argv[optind]);
+ return -1;
+ }
+ optind++;
+ }
+
+ /* print the information, based on list of input cgroups and flags */
+ ret = cgroup_list_cgroups(argv[0], cgroup_list, flags);
+
+ return ret;
+}