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: zhangxh@xxxxxxxxxxxxxx --------------------------------------------------
--- 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 Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility