Hello Dave,
This patch allows cgget to display one or some parameters of a
controller of cgroup and fix some bugs.
One will find it more efficient when he just focus on some
parameters instead of the whole controller.
Here are examples:
1.
crash> cgget -r cpuset.mems /
/:
cpuset.mems: 0
2.
crash> cgget -r memory.usage /
/:
memory.memsw.max_usage_in_bytes: 0
memory.memsw.usage_in_bytes: 1368694784
memory.max_usage_in_bytes: 0
memory.usage_in_bytes: 1368694784
To apply this patch, enter to crash-<version> directory and run
the commands as follows:
$ cp cgget.pacth ./
$ patch -p0 -i cgget.patch
For more information, please refer to the attachment.
Thanks.
--
Zhang Xiaohe
Regards
--------------------------------------------------
Development Dept.I
Nanjing Fujitsu Nanda Software Tech. Co., Ltd.(FNST)
No. 6 Wenzhu Road, Nanjing, 210012, China
TEL: +86+25-86630566-8552
FAX: +86+25-83317685
MAIL: [email protected]
--------------------------------------------------
--- extensions/cgget.c 2012-12-07 18:04:32.095275457 +0800
+++ ../crash/extensions/cgget.c 2012-12-28 15:35:03.816830712 +0800
@@ -369,11 +369,6 @@
BLKCG_POLICY_PROP,
};
-//enum blkcg_plid {
-// BLKCG_POLICY_THROTL = 0, /* Id of throtl is 0 from version 3.5 */
-// BLKCG_POLICY_PROP,
-//};
-
/* blkio attributes owned by proportional weight policy */
enum blkcg_file_name_prop {
BLKIO_PROP_weight = 1,
@@ -472,6 +467,9 @@
static struct cgroup_subsys_table cgroup_subsys_table[CGROUP_SUBSYS_MAX];
static int cgroup_subsys_num = 0;
static int is_cgroup_supported = 0;
+static uint variable_flag = 0;
+static int var_num[CGROUP_SUBSYS_MAX] = {0};
+static char *variable_str[CGROUP_SUBSYS_MAX][30] = {{0}};
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
@@ -576,12 +574,14 @@
static ulong get_subsys_parent(ulong, int);
static inline char *get_dentry_path(ulong, char *, int);
static void format_path_str(const char *, char *);
+static void filter_str(char **, int *);
static int make_cgroup_spec(struct cgroup_spec **, char **,
- char **, int, int);
+ char **, int *, int*);
static int make_all_cgroup_spec(struct cgroup_spec **, char **,
- char **, int, int);
+ char **, int *, int *);
static void cgroup_subsys_table_init();
-static int parse_cgroup_spec(struct cgroup_spec **, char *, int, int);
+static int parse_variable_spec(char *, char **, int *);
+static void print_specified_param(int);
static void print_cgroup_list(char *, struct cgroup_spec **, int, int);
static ulong retrieve_path(ulong, ulong, ulong *, const char *);
static ulong get_css_addr(struct cgroup_spec *, int, ulong);
@@ -602,15 +602,18 @@
char *help_cgget[] = {
"cgget", /* command name */
"display parameters of cgroup.",
- "cgget [-g <controller>] [-a] <path> ...\n"
+ "[-a] [-r <name>] [-g <controller>] <path> ...\n"
" or\n"
- " cgget -g <controller>:<path> ...",
+ " cgget [-a] [-r <name>] -g <controller>:<path> ...",
"Displays the parameter(s) of input cgroup(s).\n"
"If no controller is specified, the values of "
"all possible variables are printed.\n"
"Either command line style is OK, but these can not be mixed.\n",
"-a, --all",
"print the variables for all controllers which consist in the given path.\n",
+ "-r <name>",
+ "defines parameter to display.",
+ "This option can be used multiple times.\n",
"-g <controller>",
"defines controllers whose values should be displayed.",
"This option can be used multiple times.\n",
@@ -620,8 +623,8 @@
"-h, --help",
"display this message.\n",
"EXAMPLES",
- "display the controller 'cpu' in path '/'",
- " crash>cgget -g cpu:/",
+ "1. display the controller 'cpu' in path '/'",
+ " crash> cgget -g cpu:/",
" /:",
" cpu.rt_period_us: 1000000",
" cpu.rt_runtime_us: 950000",
@@ -632,7 +635,24 @@
" cpu.cfs_quota_us: 0",
" cpu.shares: 1024",
" or",
- " crash>cgget -g cpu /",
+ " crash> cgget -g cpu /",
+ " /:",
+ " cpu.rt_period_us: 1000000",
+ " cpu.rt_runtime_us: 950000",
+ " cpu.stat: nr_periods 0",
+ " \tnr_throttled 0",
+ " \tthrottled_time 0",
+ " cpu.cfs_period_us: 0",
+ " cpu.cfs_quota_us: 0",
+ " cpu.shares: 1024",
+ "2. display the parameter 'cpuset.mems' in path '/libvirt'",
+ " crash> cgget -r cpuset.mems /libvirt",
+ " /libvirt:",
+ " cpuset.mems: 0",
+ "3. display the controller 'cpu' and paramter 'cpuset.mems' at same time",
+ " crash> cgget -r cpuset.mems -g cpu /",
+ " /:",
+ " cpuset.mems: 0",
" /:",
" cpu.rt_period_us: 1000000",
" cpu.rt_runtime_us: 950000",
@@ -1564,7 +1584,7 @@
int val = 0;
if (is_root_mem_cgroup(subsys_addr)) {
- if (symbol_value("vm_swappiness") == -1)
+ if (symbol_exists("vm_swappiness") == -1)
return;
readmem(symbol_value("vm_swappiness"), KVADDR, &val,
sizeof(int), "vm_swappiness", FAULT_ON_ERROR);
@@ -2535,36 +2555,42 @@
{
int c;
int ret = 0;
- int i = 0, j = 0, k = 0;
- int dis_all_param = 0, group_flag = 0;
+ int idx, i = 0, j = 0, k = 0;
+ int dis_all_param = 0, group_flag = 0, var_flag = 0;
struct cgroup_spec *group_list[CGROUP_HIER_MAX] = {NULL};
- char *subsys_str[CGROUP_HIER_MAX], *path[CGROUP_HIER_MAX];
-
+ char *subsys_str[CGROUP_HIER_MAX], *path[CGROUP_HIER_MAX],
+ *gctrlptr, *pathptr;
if (!is_cgroup_supported) {
command_not_supported();
return;
}
- while ((c = getopt_long(argcnt, args, "hg:a",
+ while ((c = getopt_long(argcnt, args, "hg:r:a",
long_options, NULL)) != EOF) {
switch(c)
{
case 'g':
if (strchr(optarg, ':') != NULL) {
group_flag |= MODE_COMBINE_PATH;
- ret = parse_cgroup_spec(&group_list[i], optarg, i,
- CGROUP_HIER_MAX);
- if (ret != 0) {
+ gctrlptr = strtok(optarg, ":");
+ pathptr = strtok(NULL, ":");
+ if (gctrlptr == NULL || pathptr == NULL) {
argerrs++;
goto err;
}
- i++;
+ subsys_str[j++] = strdup(gctrlptr);
+ path[k++] = strdup(pathptr);
} else {
group_flag |= MODE_SEPARATE_PATH;
- subsys_str[j] = strdup(optarg);
- j++;
+ subsys_str[j++] = strdup(optarg);
}
break;
+ case 'r':
+ var_flag = 1;
+ ret = parse_variable_spec(optarg, subsys_str, &j);
+ if (ret == -1)
+ goto err;
+ break;
case 'a':
dis_all_param = 1;
break;
@@ -2576,8 +2602,7 @@
}
if (((group_flag & MODE_COMBINE_PATH) && args[optind]) ||
- (!(group_flag & MODE_COMBINE_PATH) && !args[optind]) ||
- ((group_flag & MODE_COMBINE_PATH) && dis_all_param)) {
+ (!(group_flag & MODE_COMBINE_PATH) && !args[optind])) {
argerrs++;
goto err;
}
@@ -2588,25 +2613,34 @@
argerrs++;
goto err;
}
- path[k] = strdup(args[optind]);
- k++;
- optind++;
+ path[k++] = strdup(args[optind++]);
+ }
+
+ if (var_flag && (path[0] == NULL)) {
+ argerrs++;
+ goto err;
}
/* if only PATH is specified, treat it as -a is specified. */
- if (!group_flag)
+ if (!group_flag && !var_flag)
dis_all_param = 1;
- if (group_flag & MODE_SEPARATE_PATH)
- i = make_cgroup_spec(group_list, subsys_str, path, j, k);
if (dis_all_param)
- i = make_all_cgroup_spec(group_list, subsys_str, path, j, k);
+ i = make_all_cgroup_spec(group_list, subsys_str, path, &j, &k);
+ else
+ i = make_cgroup_spec(group_list, subsys_str, path, &j, &k);
if (i < 1)
goto err;
print_cgroup_list(args[0], group_list, i, dis_all_param);
err:
+ for (idx = 0; idx < CGROUP_SUBSYS_MAX; idx++) {
+ while (--var_num[idx] >= 0)
+ free(variable_str[idx][var_num[idx]]);
+ var_num[idx] = 0;
+ }
+ variable_flag = 0;
while (--i >= 0)
free(group_list[i]);
while (--j >= 0)
@@ -2615,17 +2649,51 @@
free(path[k]);
if (argerrs)
cmd_usage(pc->curcmd, SYNOPSIS);
+}
+/* strip off the same string */
+static void
+filter_str(char *str[], int *str_num)
+{
+ char *work_str[CGROUP_HIER_MAX];
+ int i, j, k = 0;
+
+ /* Organize the filtered strings in the temp string array */
+ for (i = 0; i < *str_num; i++) {
+ for (j = i + 1; j < *str_num; j++) {
+ if (strcmp(str[i], str[j]) == 0)
+ break;
+ }
+ if (j == *str_num)
+ work_str[k++] = strdup(str[i]);
+ free(str[i]);
+ }
+ /* Assign the temp buffer to original string array */
+ for(i = 0; i < k; i++)
+ str[i] = work_str[i];
+ *str_num = k;
}
static int
make_cgroup_spec(struct cgroup_spec **group_list, char *subsys_str[],
- char *path[], int str_num, int path_num)
+ char *path[], int *str_num, int *path_num)
{
int j, k, i = 0;
- for (j = 0; j < str_num; j++) {
- for (k = 0; k < path_num; k++) {
+ filter_str(subsys_str, str_num);
+ filter_str(path, path_num);
+ for (j = 0; j < CGROUP_SUBSYS_MAX; j++)
+ filter_str(variable_str[j], &var_num[j]);
+
+ for (j = 0; j < *str_num; j++) {
+ for (k = 0; k < *path_num; k++) {
+ while (group_list[i] != NULL)
+ i++;
+ if (i > CGROUP_HIER_MAX) {
+ fprintf(stderr, "Max allowed hierarchies %d"
+ " reached.\n", CGROUP_HIER_MAX);
+ return -1;
+ }
group_list[i] = calloc(1, sizeof(struct cgroup_spec));
if (!group_list[i]) {
fprintf(stderr, "calloc error.\n");
@@ -2644,12 +2712,12 @@
static int
make_all_cgroup_spec(struct cgroup_spec **group_list, char *subsys_str[],
- char *path[], int str_num, int path_num)
+ char *path[], int *str_num, int *path_num)
{
- int i, j, k = 0;
+ int i, j, k;
for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
- for (j = 0; j < str_num; j++) {
+ for (j = 0; j < *str_num; j++) {
/* if matched string is found, it must be
* specified by user, jump out. */
if (0 == strcmp(cgroup_subsys_table[i].subsys_str,
@@ -2658,12 +2726,12 @@
}
/* "j == str_num" means no matched string is found,
* so add it to subsys_str. */
- if (j == str_num &&
+ if (j == *str_num &&
cgroup_subsys_table[i].subsys_str != NULL &&
*cgroup_subsys_table[i].subsys_str != '\0' &&
*cgroup_subsys_table[i].subsys_str != ' ') {
- subsys_str[str_num] = strdup(cgroup_subsys_table[i].subsys_str);
- str_num++;
+ subsys_str[*str_num] = strdup(cgroup_subsys_table[i].subsys_str);
+ (*str_num)++;
}
}
@@ -2714,34 +2782,81 @@
}
static int
-parse_cgroup_spec(struct cgroup_spec **group_list, char *optarg, int index, int capacity)
+parse_variable_spec(char *optarg, char **subsys_str, int *j)
{
- char *gctrlptr, *pathptr;
+ char *cg, *var;
+ int i;
- if (!(index < capacity)) {
- fprintf(stderr, "Max allowed hierarchies %d reached.\n", capacity);
+ cg = strtok(optarg, ".");
+ var = strtok(NULL, ".");
+ if (cg == NULL || var == NULL)
return -1;
+
+ for (i = 0; i < CGROUP_SUBSYS_MAX; i++) {
+ if (strcmp(subsys_name[i], cg) == 0) {
+ subsys_str[*j] = strdup(cg);
+ variable_str[i][var_num[i]] = strdup(var);
+ variable_flag |= NUM_TO_BIT(i);
+ (*j)++;
+ var_num[i]++;
+ break;
+ }
}
- *group_list = calloc(1, sizeof(struct cgroup_spec));
- if (!(*group_list)) {
- fprintf(stderr, "calloc error.\n");
+ if (i == CGROUP_SUBSYS_MAX) {
+ fprintf(fp, "No subsys '%s' is found.\n", cg);
return -1;
}
-
- gctrlptr = strtok(optarg, ":");
- pathptr = strtok(NULL, ":");
- if ( gctrlptr == NULL || pathptr == NULL)
- goto failed;
- strncpy((*group_list)->subsys_str, gctrlptr, strlen(gctrlptr));
- strncpy((*group_list)->path, pathptr, strlen(pathptr));
-
return 0;
+}
-failed:
- if (*group_list)
- free(*group_list);
- return -1;
+static void
+print_specified_param(int subsys_id)
+{
+ char *linebuf = NULL;
+ int i, flag = 0, found = 0;
+ size_t length;
+ int st_idx = strlen(subsys_name[subsys_id]);
+
+ /* reset the file discriptor */
+ rewind(fp);
+ while (-1 != getline(&linebuf, &length, fp)) {
+ /*
+ * If flag == 1, this means the param was matched.
+ * Since we don't know if the next line belongs to
+ * this param or not, we check it. If YES, print
+ * it, too.
+ */
+ if (flag == 1) {
+ if (!strstr(linebuf, subsys_name[subsys_id])) {
+ fprintf(pc->saved_fp, "%s", linebuf);
+ continue;
+ }
+ flag = 0;
+ }
+ for (i = 0; i < var_num[subsys_id]; i++) {
+ /*
+ * compare the param string after
+ * name of subsys at beginning.
+ */
+ if (variable_str[subsys_id][i] != NULL &&
+ strstr(&linebuf[st_idx], variable_str[subsys_id][i])) {
+ found |= NUM_TO_BIT(i);
+ flag = 1;
+ fprintf(pc->saved_fp, "%s", linebuf);
+ }
+ }
+ }
+
+ for (i = 0; i < var_num[subsys_id]; i++) {
+ if (!test_bit(i, found))
+ fprintf(pc->saved_fp, "Can not find param '%s'.\n",
+ variable_str[subsys_id][i]);
+ }
+ if (linebuf) {
+ free(linebuf);
+ linebuf = NULL;
+ }
}
static ulong
@@ -2831,15 +2946,21 @@
return;
/* if only "/" or "." */
- if ((0 == strcmp("/", str_in)) || (0 == strcmp(".", str_in))) {
+ if ((0 == strcmp("/", str_in)) || (0 == strcmp(".", str_in)))
strcpy(str_out, "/");
- return;
- }
+ else if ('.' == str_in[0] && '/' == str_in[1])
+ /* if "./" is specified at the beginning */
+ strcpy(str_out, &str_in[1]);
+ else if ('/' != str_in[0]) {
+ /* if no '/' is specified at the beginning */
+ str_out[0] = '/';
+ strcpy(&str_out[1], str_in);
+ } else
+ strcpy(str_out, str_in);
/* strip the '/' character at the last position */
- strcpy(str_out, str_in);
- if ('/' == str_out[len - 1])
- str_out[len - 1] = '\0';
+ if ('/' == str_out[strlen(str_out) - 1])
+ str_out[strlen(str_out) - 1] = '\0';
}
static ulong
@@ -2961,6 +3082,10 @@
fprintf(fp, "%s:\n", group_list->path);
+ /* if some param is specified, first output all into a tmpfile. */
+ if (test_bit(cpuset_subsys_id, variable_flag))
+ open_tmpfile();
+
for (i = CS_CPU_EXCLUSIVE; i <= CS_CPUS; i++) {
if (cpuset_offset_table.cpuset_shed_relax_domain_level == -1 &&
i == CS_SHED_RELAX_DOMAIN_LEVEL)
@@ -3031,6 +3156,12 @@
break;
}
}
+
+ /* second, output the needed param */
+ if (test_bit(cpuset_subsys_id, variable_flag)) {
+ print_specified_param(cpuset_subsys_id);
+ close_tmpfile();
+ }
}
static void
@@ -3043,6 +3174,10 @@
fprintf(fp, "%s:\n", group_list->path);
+ /* if some param is specified, first output all into a tmpfile. */
+ if (test_bit(cpu_cgroup_subsys_id, variable_flag))
+ open_tmpfile();
+
rt_bandwidth_addr = subsys_addr + tg_offset_table.tg_rt_bandwidth;
cfs_bandwidth_addr = subsys_addr + tg_offset_table.tg_cfs_bandwidth;
@@ -3101,6 +3236,12 @@
break;
}
}
+
+ /* second, output the needed param */
+ if (test_bit(cpu_cgroup_subsys_id, variable_flag)) {
+ print_specified_param(cpu_cgroup_subsys_id);
+ close_tmpfile();
+ }
}
static void
@@ -3112,6 +3253,9 @@
fprintf(fp, "%s:\n", group_list->path);
+ /* if some param is specified, first output all into a tmpfile. */
+ if (test_bit(cpuacct_subsys_id, variable_flag))
+ open_tmpfile();
for (i = CPUACCT_STAT; i < CPUACCT_NR_PARAMS; i++) {
if (cpuacct_offset_table.cpuacct_cpustat == -1 &&
@@ -3136,6 +3280,12 @@
break;
}
}
+
+ /* second, output the needed param */
+ if (test_bit(cpuacct_subsys_id, variable_flag)) {
+ print_specified_param(cpuacct_subsys_id);
+ close_tmpfile();
+ }
}
static void
@@ -3148,6 +3298,10 @@
fprintf(fp, "%s:\n", group_list->path);
+ /* if some param is specified, first output all into a tmpfile. */
+ if (test_bit(hugetlb_subsys_id, variable_flag))
+ open_tmpfile();
+
hugepage_addr = subsys_addr + hugetlb_offset_table.hugetlb_hugepage;
readmem(symbol_value("hstates") + MEMBER_OFFSET("hstate", "order"), KVADDR,
@@ -3169,6 +3323,12 @@
"limit"), NULL);
fprintf(fp, "%s.%s.limit_in_bytes: %lu\n",
group_list->subsys_str, buf, val);
+
+ /* second, output the needed param */
+ if (test_bit(hugetlb_subsys_id, variable_flag)) {
+ print_specified_param(hugetlb_subsys_id);
+ close_tmpfile();
+ }
}
static void
@@ -3182,6 +3342,10 @@
fprintf(fp, "%s:\n", group_list->path);
+ /* if some param is specified, first output all into a tmpfile. */
+ if (test_bit(mem_cgroup_subsys_id, variable_flag))
+ open_tmpfile();
+
/* check if do swap account */
if (symbol_exists("do_swap_account"))
readmem(symbol_value("do_swap_account"), KVADDR, &do_swap_account,
@@ -3337,6 +3501,12 @@
break;
}
}
+
+ /* second, output the needed param */
+ if (test_bit(mem_cgroup_subsys_id, variable_flag)) {
+ print_specified_param(mem_cgroup_subsys_id);
+ close_tmpfile();
+ }
}
static void
@@ -3346,6 +3516,10 @@
fprintf(fp, "%s:\n", group_list->path);
+ /* if some param is specified, first output all into a tmpfile. */
+ if (test_bit(devices_subsys_id, variable_flag))
+ open_tmpfile();
+
list_head = subsys_addr + devices_offset_table.devices_whitelist;
whitelist_addr = (ulong)list_next((void *)list_head, NULL,
MEMBER_OFFSET("dev_whitelist_item", "list"));
@@ -3360,6 +3534,12 @@
MEMBER_OFFSET("dev_whitelist_item", "list"));
} while (list_head != whitelist_addr +
MEMBER_OFFSET("dev_whitelist_item", "list"));
+
+ /* second, output the needed param */
+ if (test_bit(devices_subsys_id, variable_flag)) {
+ print_specified_param(devices_subsys_id);
+ close_tmpfile();
+ }
}
static void
@@ -3373,6 +3553,11 @@
return;
fprintf(fp, "%s:\n", group_list->path);
+
+ /* if some param is specified, first output all into a tmpfile. */
+ if (test_bit(freezer_subsys_id, variable_flag))
+ open_tmpfile();
+
readmem(subsys_addr + freezer_offset_table.freezer_state , KVADDR,
&state, sizeof(enum freezer_state), "freezer_state",
FAULT_ON_ERROR);
@@ -3390,6 +3575,12 @@
return;
}
fprintf(fp, "%s\n", buf);
+
+ /* second, output the needed param */
+ if (test_bit(freezer_subsys_id, variable_flag)) {
+ print_specified_param(freezer_subsys_id);
+ close_tmpfile();
+ }
}
static void
@@ -3399,10 +3590,20 @@
fprintf(fp, "%s:\n", group_list->path);
+ /* if some param is specified, first output all into a tmpfile. */
+ if (test_bit(net_cls_subsys_id, variable_flag))
+ open_tmpfile();
+
readmem(subsys_addr + cls_offset_table.cls_classid , KVADDR,
&classid, sizeof(uint32_t), "cls_classid",
FAULT_ON_ERROR);
fprintf(fp, "%s.classid: %d\n", group_list->subsys_str, classid);
+
+ /* second, output the needed param */
+ if (test_bit(net_cls_subsys_id, variable_flag)) {
+ print_specified_param(net_cls_subsys_id);
+ close_tmpfile();
+ }
}
static void
@@ -3412,10 +3613,20 @@
fprintf(fp, "%s:\n", group_list->path);
+ /* if some param is specified, first output all into a tmpfile. */
+ if (test_bit(net_prio_subsys_id, variable_flag))
+ open_tmpfile();
+
readmem(subsys_addr + netprio_offset_table.netprio_prioidx , KVADDR,
&prioidx, sizeof(uint32_t), "netprio_prioidx",
FAULT_ON_ERROR);
fprintf(fp, "%s.prioidx: %d\n", group_list->subsys_str, prioidx);
+
+ /* second, output the needed param */
+ if (test_bit(net_prio_subsys_id, variable_flag)) {
+ print_specified_param(net_prio_subsys_id);
+ close_tmpfile();
+ }
}
static void
@@ -3425,6 +3636,10 @@
fprintf(fp, "%s:\n", group_list->path);
+ /* if some param is specified, first output all into a tmpfile. */
+ if (test_bit(blkio_subsys_id, variable_flag))
+ open_tmpfile();
+
if (STRUCT_EXISTS("blkcg")) {
for (plid = BLKCG_POLICY_THROTL; plid <= BLKCG_POLICY_PROP; plid++) {
if (plid == BLKCG_POLICY_PROP)
@@ -3465,6 +3680,12 @@
}
/* there should be nothing to be displayed for reset_stats */
fprintf(fp, "%s.reset_stats: \n", group_list->subsys_str);
+
+ /* second, output the needed param */
+ if (test_bit(blkio_subsys_id, variable_flag)) {
+ print_specified_param(blkio_subsys_id);
+ close_tmpfile();
+ }
}
static void
--
Crash-utility mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility