Extend the argument syntax of struct/union/* commands to recognize percpu specifiers. Note that percpu addresses are not valid kernel virtual addresses, so they must be parsed separately. Signed-off-by: Petr Tesarik <ptesarik@xxxxxxx>
[PATCH 11/11] Add percpu handling to struct/union/* commands Extend the argument syntax of struct/union/* commands to recognize percpu specifiers. Note that percpu addresses are not valid kernel virtual addresses, so they must be parsed separately. Signed-off-by: Petr Tesarik <ptesarik@xxxxxxx> --- help.c | 18 ++++++++++++++---- symbols.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 5 deletions(-) --- a/help.c +++ b/help.c @@ -4104,8 +4104,8 @@ NULL char *help_struct[] = { "struct", "structure contents", -"struct_name[.member[,member]][-o][-l offset][-rfuxdp][address | symbol]\n" -" [count | -c count]", +"struct_name[.member[,member]][-o][-l offset][-rfuxdp]\n" +" [address | symbol][:cpuspec] [count | -c count]", " This command displays either a structure definition, or a formatted display", " of the contents of a structure at a specified address. When no address is", " specified, the structure definition is shown along with the structure size.", @@ -4139,6 +4139,11 @@ char *help_struct[] = { " to an embedded list_head structure contained within the", " target data structure, then the \"-l\" option must be used.", " symbol symbolic reference to the address of a structure.", +" cpuspec CPU specification for per-cpu variables:", +" : CPU of the currently selected task.", +" :a[ll] all CPUs.", +" :#[-#][,...] CPU list(s), e.g. \"1,3,5\", \"1-3\",", +" or \"1,3,5-7,10\".", " count count of structures to dump from an array of structures;", " if used, this must be the last argument entered.", " -c count \"-c\" is only required if \"count\" is not the last argument", @@ -4394,8 +4399,8 @@ NULL char *help_union[] = { "union", "union contents", -"union_name[.member[,member]] [-o][-l offset][-rfuxdp] [address | symbol]\n" -" [count | -c count]", +"union_name[.member[,member]] [-o][-l offset][-rfuxdp]\n" +" [address | symbol][:cpuspec] [count | -c count]", " This command displays either a union definition, or a formatted display", " of the contents of a union at a specified address. When no address is", " specified, the union definition is shown along with the union size.", @@ -4430,6 +4435,11 @@ char *help_union[] = { " to an embedded list_head structure contained within the", " target union structure, then the \"-l\" option must be used.", " symbol symbolic reference to the address of a union.", +" cpuspec CPU specification for per-cpu variables:", +" : CPU of the currently selected task.", +" :a[ll] all CPUs.", +" :#[-#][,...] CPU list(s), e.g. \"1,3,5\", \"1-3\",", +" or \"1,3,5-7,10\".", " count count of unions to dump from an array of unions; if used,", " this must be the last argument entered.", " -c count \"-c\" is only required if \"count\" is not the last argument", --- a/symbols.c +++ b/symbols.c @@ -5712,6 +5712,8 @@ cmd_datatype_common(ulong flags) { int c; ulong addr, aflag; + char *cpuspec; + ulong *cpus; struct syment *sp; ulong list_head_offset; int count; @@ -5730,6 +5732,8 @@ cmd_datatype_common(ulong flags) argc_members = 0; radix = restore_radix = 0; separator = members = NULL; + cpuspec = NULL; + cpus = NULL; while ((c = getopt(argcnt, args, "pxdhfuc:rvol:")) != EOF) { switch (c) @@ -5818,11 +5822,22 @@ cmd_datatype_common(ulong flags) if (aflag && (count != 0xdeadbeef)) error(FATAL, "too many arguments!\n"); + if (!aflag) { + cpuspec = strchr(args[optind], ':'); + if (cpuspec) + *cpuspec++ = NULLCHAR; + } + if (clean_arg() && IS_A_NUMBER(args[optind])) { if (aflag) count = stol(args[optind], FAULT_ON_ERROR, NULL); - else { + else if (cpuspec) { + if (pc->curcmd_flags & MEMTYPE_FILEADDR) + error(FATAL, "percpu cannot be used with dumpfile offsets\n"); + addr = htol(args[optind], FAULT_ON_ERROR, NULL); + aflag++; + } else { if (pc->curcmd_flags & MEMTYPE_FILEADDR) pc->curcmd_private = stoll(args[optind], FAULT_ON_ERROR, NULL); @@ -5837,6 +5852,12 @@ cmd_datatype_common(ulong flags) aflag++; } } else if ((sp = symbol_search(args[optind]))) { + if (cpuspec && !is_percpu_symbol(sp)) { + error(WARNING, + "%s is not percpu; cpuspec ignored.\n", + sp->name); + cpuspec = NULL; + } addr = sp->value; aflag++; } else { @@ -5848,6 +5869,15 @@ cmd_datatype_common(ulong flags) } } + if (cpuspec) { + cpus = get_cpumask_buf(); + if (STREQ(cpuspec, "")) { + SET_BIT(cpus, CURRENT_CONTEXT()->processor); + } else { + make_cpumask(cpuspec, cpus, FAULT_ON_ERROR, NULL); + } + } + optind = optind_save; if (count == 0xdeadbeef) @@ -5914,6 +5944,18 @@ cmd_datatype_common(ulong flags) error(FATAL, "invalid data structure reference: %s.%s\n", dm->name, memberlist[0]); do_datatype_declaration(dm, flags | (dm->flags & TYPEDEF)); + } else if (cpus) { + for (c = 0; c < kt->cpus; c++) { + ulong cpuaddr; + + if (!NUM_IN_BITMAP(cpus, c)) + continue; + + cpuaddr = addr + kt->__per_cpu_offset[c]; + fprintf(fp, " [%d]: %lx\n", c, cpuaddr); + do_datatype_addr(dm, cpuaddr , count, + flags, memberlist, argc_members); + } } else do_datatype_addr(dm, addr, count, flags, memberlist, argc_members); @@ -5925,6 +5967,9 @@ freebuf: FREEBUF(structname); FREEBUF(members); } + + if (cpus) + FREEBUF(cpus); } static void
-- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility