Re: [Crash-utility] [PATCH v2] Handle blk_mq_ctx member changes for kernels v5.16-rc1~75^2~44
by HAGIO KAZUHITO(萩尾 一仁)
-----Original Message-----
> Admittedly, I haven't looked into the details, but those simple numbers for
> pending IO have been very valuable for me, when analyzing dumps with
> dm-multipath over (FC-attached) SCSI disks. Aren't those pending IO numbers
> available elsewhere in the kernel? Maybe not in debugfs anymore, but I suppose
> the (mq) block layer does keep track of them?
AFAIK, unfortunately there is no simple counter, crash needs to parse sbitmap
structures to count them. (please let us know if there is a simpler solution.)
Currently Sergey has worked on adding sbitmap function [1], and we plan to make
use of it after merging the patch. It may take some time, so Lianbo's patch is
a temporary workaround for the error.
Maybe it was better to write the status on the commit log..
[1] https://listman.redhat.com/archives/crash-utility/2021-December/msg00062....
Thanks,
Kazu
2 years, 9 months
[PATCH] Add new macros USELZO|USESNAPPY|USEZSTD|USEVALGRIND to improve crash build
by Lianbo Jiang
Currently, crash has multiple targets such as warn, Warn, nowarn,
lzo, snappy, zstd and valgrind in the top Makefile, and they will
always execute "make gdb_merge", if users use multiple targets to
build crash such as "make warn lzo zstd", it indicates that the
build process will run three times for "make gdb_merge", it was
not a problem in the past because the compilation process was not
concurrent.
But for now, crash has supported the "make -j jobs" option, the
compilation process is concurrent, if users still compile crash
as before with the "make -j jobs" option, it may fail with the
following errors, for example:
$ make -j24 warn lzo
...
mv: cannot stat 'Makefile.new': No such file or directory
Makefile: cannot create new Makefile
please copy Makefile.new to Makefile
make: *** [Makefile:321: lzo] Error 1
make: *** Waiting for unfinished jobs....
TARGET: X86_64
CRASH: 8.0.0++
GDB: 10.2
...
To avoid the current issue, need to do a minor improvement for
building crash, therefore, add several macros USELZO, USESANPPY,
USEZSTD and USEVALGRIND in the top Makefile. Also update the
documentation accordingly.
Signed-off-by: Lianbo Jiang <lijiang(a)redhat.com>
Signed-off-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
---
Makefile | 35 +++++++++++++++++++----------------
README | 7 ++++---
help.c | 7 ++++---
3 files changed, 27 insertions(+), 22 deletions(-)
diff --git a/Makefile b/Makefile
index ede87a1029c8..f578fd8366dd 100644
--- a/Makefile
+++ b/Makefile
@@ -223,6 +223,25 @@ ifneq ($(target),)
CONF_TARGET_FLAG="-t$(target)"
endif
+
+# To build crash with any or all of those libraries, need add these macroes
+# to the make commandline, for example:
+# make USELZO=on USESNAPPY=on USEZSTD=on
+# otherwise crash will lack support for these features
+# make
+ifeq ($(USELZO),on)
+CONF_TARGET_FLAG+=-x lzo
+endif
+ifeq ($(USESNAPPY),on)
+CONF_TARGET_FLAG+=-x snappy
+endif
+ifeq ($(USEZSTD),on)
+CONF_TARGET_FLAG+=-x zstd
+endif
+ifeq ($(USEVALGRIND),on)
+CONF_TARGET_FLAG+=-x valgrind
+endif
+
# To build the extensions library by default, uncomment the third command
# line below. Otherwise they can be built by entering "make extensions".
@@ -317,22 +336,6 @@ nowarn: make_configure
@./configure ${CONF_TARGET_FLAG} -n -b
@$(MAKE) gdb_merge
-lzo: make_configure
- @./configure -x lzo ${CONF_TARGET_FLAG} -w -b
- @$(MAKE) gdb_merge
-
-snappy: make_configure
- @./configure -x snappy ${CONF_TARGET_FLAG} -w -b
- @$(MAKE) gdb_merge
-
-zstd: make_configure
- @./configure -x zstd ${CONF_TARGET_FLAG} -w -b
- @$(MAKE) gdb_merge
-
-valgrind: make_configure
- @./configure -x valgrind ${CONF_TARGET_FLAG} -w -b
- @$(MAKE) gdb_merge
-
main.o: ${GENERIC_HFILES} main.c
${CC} -c ${CRASH_CFLAGS} main.c ${WARNING_OPTIONS} ${WARNING_ERROR}
diff --git a/README b/README
index 02aef58fa28c..ddc1e7d20bd2 100644
--- a/README
+++ b/README
@@ -103,11 +103,12 @@
the libz compression library is used, and by default the crash utility
only supports libz. Recently makedumpfile has been enhanced to optionally
use the LZO, snappy or zstd compression libraries. To build crash with any
- or all of those libraries, type "make lzo", "make snappy" or "make zstd".
+ or all of those libraries, type "make USELZO=on", "make USESNAPPY=on" or
+ "make USEZSTD=on".
crash supports valgrind Memcheck tool on the crash's custom memory allocator.
- To build crash with this feature enabled, type "make valgrind" and then run
- crash with valgrind as "valgrind crash vmlinux vmcore".
+ To build crash with this feature enabled, type "make USEVALGRIND=on" and
+ then run crash with valgrind as "valgrind crash vmlinux vmcore".
All of the alternate build commands above are "sticky" in that the
special "make" targets only have to be entered one time; all subsequent
diff --git a/help.c b/help.c
index e57ed72f51d9..b33f090b2f21 100644
--- a/help.c
+++ b/help.c
@@ -9441,11 +9441,12 @@ README_ENTER_DIRECTORY,
" the libz compression library is used, and by default the crash utility",
" only supports libz. Recently makedumpfile has been enhanced to optionally",
" use the LZO, snappy or zstd compression libraries. To build crash with any",
-" or all of those libraries, type \"make lzo\", \"make snappy\" or \"make zstd\".",
+" or all of those libraries, type \"make USELZO=on\", \"make USESNAPPY=on\" or",
+" \"make USEZSTD=on\".",
"",
" crash supports valgrind Memcheck tool on the crash's custom memory allocator.",
-" To build crash with this feature enabled, type \"make valgrind\" and then run",
-" crash with valgrind as \"valgrind crash vmlinux vmcore\".",
+" To build crash with this feature enabled, type \"make USEVALGRIND=on\" and",
+" then run, crash with valgrind as \"valgrind crash vmlinux vmcore\".",
"",
" All of the alternate build commands above are \"sticky\" in that the",
" special \"make\" targets only have to be entered one time; all subsequent",
--
2.20.1
2 years, 9 months
there is a stack problem which is not in accordance with x86_64 stack layout
by hellothedreamer
Hello, I found some confusing things during the usage of analysing the stack data.
Summury:
with the same demo named oops.ko and the same architecure(x86_64), there are two different stack layout
the demo make a crash with hungtask.
1) kernel version
[root@localhost ~]# uname -r
3.10.0-693.el7.x86_64
gcc version 4.8.5 20150623 (Red Hat 4.8.5-16) (GCC)
crash version:
[root@localhost ~]# crash --version
crash 7.1.9-2.el7
[root@localhost ~]# gdb -v
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-100.el7\
bt -f pid
1--the callback address for create_oops function
2--the rbp register value for stack frame 5, point to the address ffff8800a637fd69.
this layout in accordance with the x86_64 stack principle
2) kernel version
[root@kylinv10 ~]# uname -r
4.19.90-24.4.v2101.ky10.x86_64
gcc version:
[root@kylinv10 ~]# gcc --version
gcc (GCC) 7.3.0
[root@kylinv10 ~]# gdb -v
GNU gdb (GDB) EulerOS 9.2-1.ky10
crash version:
[root@kylinv10 ~]# crash --version
crash 7.2.9-2.p02.ky10
bt -f pid
1/2/3--there should be the value for the next stack frame's(in higher address) rbp register value, should be the valid address in this stack.
but, they are invalid address "0000000000000001" "ffff8adb5424ccc0" and "ffffffffc096b000"
I don't know the reason.4.19kernel, has this kernel param value like:
kernel.randomize_va_space=0
thank you.
--
Jane
2 years, 9 months
Re: [Crash-utility] [PATCH v3 0/7] log: output logs of printk safe buffers
by lijiang
Thank you for the patch, Shogo.
On Thu, Feb 10, 2022 at 4:25 PM <crash-utility-request(a)redhat.com> wrote:
> Date: Thu, 10 Feb 2022 06:38:32 +0000
> From: HAGIO KAZUHITO(?????) <k-hagio-ab(a)nec.com>
> To: "shogo.matsumoto(a)fujitsu.com" <shogo.matsumoto(a)fujitsu.com>
> Cc: "Discussion list for crash utility usage, maintenance and
> development" <crash-utility(a)redhat.com>
> Subject: Re: [Crash-utility] [PATCH v3 0/7] log: output logs of printk
> safe buffers
> Message-ID:
> <
> TYYPR01MB6777FE775F5CD6438FC2E448DD2F9(a)TYYPR01MB6777.jpnprd01.prod.outlook.com
> >
>
> Content-Type: text/plain; charset="iso-2022-jp"
>
>
> -----Original Message-----
> > This patch set introduces -s option for log builtin command to display
> > printk safe buffers (safe_print_seq/nmi_print_seq) as follows:
> >
> > ===
> > crash> log -s
> > PRINTK_SAFE_SEQ_BUF: nmi_print_seq
> > CPU: 0 ADDR: ffff969d7bc19ce0 LEN: 150 MESSAGE_LOST: 0
> > Uhhuh. NMI received for unknown reason 20 on CPU 0.
> > Do you have a strange power saving mode enabled?
> > Dazed and confused, but trying to continue
> > ...
> > ===
> >
> > The printk safe buffers are also displayed at the bottom of
> > 'log' output so as not to overlook them.
> >
> > ===
> > crash> log
> > ...
> > [nmi_print_seq] Uhhuh. NMI received for unknown reason 20 on CPU 0.
> > [nmi_print_seq] Do you have a strange power saving mode enabled?
> > [nmi_print_seq] Dazed and confused, but trying to continue
> > ===
> >
> > -m and -t options are also supported.
> >
> > Note that the safe buffer (struct printk_safe_seq_buf) was introduced
> > in kernel-4.11 (Merge commit 7d91de74436a69c2b78a7a72f1e7f97f8b4396fa)
> > and removed in kernel-5.15 (93d102f094be9beab28e5afb656c188b16a3793b).
> >
> > Changes since v2:
> > - Add support new options -s, -t, -m (Kazu)
> > - Add help text (Kazu)
>
> Thank you for the update.
>
> Maybe I will join the patches into two or three and the following warning
> is emitted, so I will adjust a little when merging, but otherwise the
>
I would recommend packing them into two patches as below:
[PATCH v3 1/7] log: introduce -s option
[PATCH v3 2/7] log: adjust indent and line breaks for log -s
[PATCH v3 3/7] log: append printk safe buffer output to 'log'
[PATCH v3 6/7] symbols: add support 'help -o' for printk safe buffers
[PATCH v3 7/7] log: add help text for printk safe buffers
Another one:
[PATCH v3 4/7] log: add support -t option for output of printk safe buffers
[PATCH v3 5/7] log: add support -m for output of printk safe buffers
BTW: If there is a better way, you could rearrange them when merging.
Thanks.
And with the warning fix, otherwise:
Acked-by: Lianbo Jiang <lijiang(a)redhat.com>
> patchset and the output of the commands look nice to me!
>
> Acked-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
>
>
> $ make clean ; make warn
> ...
> cc -c -g -DX86_64 -DLZO -DSNAPPY -DGDB_10_2 kernel.c -Wall -O2
> -Wstrict-prototypes -Wmissing-prototypes -fstack-protector
> -Wformat-security
> kernel.c: In function ?__dump_printk_safe_seq_buf?:
> kernel.c:11623:7: warning: format not a string literal and no format
> arguments [-Wformat-security]
> fprintf(fp, space(PRINTK_SAFE_SEQ_BUF_INDENT));
> ^~~~~~~
>
> Will add "%s".
>
> Thanks,
> Kazu
>
> >
> > [v1]:
> https://listman.redhat.com/archives/crash-utility/2021-December/msg00031....
> > [v2]:
> https://listman.redhat.com/archives/crash-utility/2022-January/msg00004.html
> >
> > Test program is attached in the above v2 patch e-mail.
> >
> > Shogo Matsumoto (7):
> > log: introduce -s option
> > log: adjust indent and line breaks for log -s
> > log: append printk safe buffer output to 'log'
> > log: add support -t option for output of printk safe buffers
> > log: add support -m for output of printk safe buffers
> > symbols: add support 'help -o' for printk safe buffers
> > log: add help text for printk safe buffers
> >
> > defs.h | 5 ++
> > help.c | 25 ++++++++-
> > kernel.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
> > symbols.c | 5 ++
> > 4 files changed, 192 insertions(+), 2 deletions(-)
> >
> > --
> > 2.29.2
> >
> >
> > --
> > Crash-utility mailing list
> > Crash-utility(a)redhat.com
> > https://listman.redhat.com/mailman/listinfo/crash-utility
>
>
>
>
> ------------------------------
>
> Message: 2
> Date: Thu, 10 Feb 2022 08:21:52 +0000
> From: HAGIO KAZUHITO(?????) <k-hagio-ab(a)nec.com>
> To: "Discussion list for crash utility usage, maintenance and
> development" <crash-utility(a)redhat.com>
> Cc: "zwang(a)amperecomputing.com" <zwang(a)amperecomputing.com>,
> "patches(a)amperecomputing.com" <patches(a)amperecomputing.com>,
> "lijiang(a)redhat.com" <lijiang(a)redhat.com>,
> "darren(a)os.amperecomputing.com" <darren(a)os.amperecomputing.com>
> Subject: Re: [Crash-utility] [PATCH] arm64: Use CONFIG_ARM64_VA_BITS
> to initialize VA_BITS_ACTUAL
> Message-ID:
> <
> TYYPR01MB6777479D629CD1F2A18A7A6DDD2F9(a)TYYPR01MB6777.jpnprd01.prod.outlook.com
> >
>
> Content-Type: text/plain; charset="iso-2022-jp"
>
> Hi Huang,
>
> thanks for the patch.
>
> -----Original Message-----
> > For DISKDUMP case, we can get VA_BITS_ACTUAL from CONFIG_ARM64_VA_BITS.
>
> I could not understand this, there is a case where CONFIG_ARM64_VA_BITS
> is different from VA_BITS_ACTUAL and why is this only for DISKDUMP case?
>
> If the patch intends to guess the value of VA_BITS_ACTUAL to be the same as
> CONFIG_ARM64_VA_BITS when no NUMBER(TCR_EL1_T1SZ), I think that DISKDUMP
> check is not needed and it would be better to write such a commit log and
> a comment e.g. "/* guess */" on the else if block.
>
> Thanks,
> Kazu
>
> > Without this patch, we may have to use "--machdep vabits_actual=48" to
> > set the VA_BITS_ACTUAL.
> >
> > Signed-off-by: Huang Shijie <shijie(a)os.amperecomputing.com>
> > ---
> > arm64.c | 6 ++++++
> > 1 file changed, 6 insertions(+)
> >
> > diff --git a/arm64.c b/arm64.c
> > index 4f2c2b5..2b3ec02 100644
> > --- a/arm64.c
> > +++ b/arm64.c
> > @@ -4170,6 +4170,12 @@ arm64_calc_VA_BITS(void)
> > } else if (machdep->machspec->VA_BITS_ACTUAL) {
> > machdep->machspec->VA_BITS =
> machdep->machspec->VA_BITS_ACTUAL;
> > machdep->machspec->VA_START =
> _VA_START(machdep->machspec->VA_BITS_ACTUAL);
> > + } else if (pc->flags & DISKDUMP) {
> > + if
> (machdep->machspec->CONFIG_ARM64_VA_BITS) {
> > + machdep->machspec->VA_BITS_ACTUAL =
> > machdep->machspec->CONFIG_ARM64_VA_BITS;
> > + machdep->machspec->VA_BITS =
> > machdep->machspec->CONFIG_ARM64_VA_BITS;
> > + machdep->machspec->VA_START =
> > _VA_START(machdep->machspec->VA_BITS_ACTUAL);
> > + }
> > } else
> > error(FATAL, "cannot determine
> VA_BITS_ACTUAL\n");
> > }
> > --
> > 2.30.2
> >
> >
> > --
> > Crash-utility mailing list
> > Crash-utility(a)redhat.com
> > https://listman.redhat.com/mailman/listinfo/crash-utility
>
>
>
>
> ------------------------------
>
> --
> Crash-utility mailing list
> Crash-utility(a)redhat.com
> https://listman.redhat.com/mailman/listinfo/crash-utility
>
> End of Crash-utility Digest, Vol 197, Issue 7
> *********************************************
>
>
2 years, 9 months
[PATCH] Flush the build data generated by configure into build_data.c
by Lianbo Jiang
The build_data.c is dynamically generated by configure, sometimes the
data may not be synchronized to the file build_data.c, as a result,
it will break the compilation process with the following error:
$ for i in {1..50} ; do make clean ; rm -rf gdb-10.2/ ; make warn ;\
[ $? -ne 0 ] && echo "TRY $i" && break ; done
...
ar: creating crashlib.a
CXXLD gdb
/usr/bin/ld: ../../crashlib.a(main.o): in function `dump_build_data':
/home/crash/main.c:1829: undefined reference to `build_command'
/usr/bin/ld: /home/crash/main.c:1830: undefined reference to `build_data'
collect2: error: ld returned 1 exit status
make[4]: *** [Makefile:1872: gdb] Error 1
make[3]: *** [Makefile:10072: all-gdb] Error 2
make[2]: *** [Makefile:860: all] Error 2
crash build failed
The fflush() will help flush the data into the build_data.c.
Signed-off-by: Lianbo Jiang <lijiang(a)redhat.com>
Signed-off-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
---
configure.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/configure.c b/configure.c
index 51888519c18c..41d096bc56ca 100644
--- a/configure.c
+++ b/configure.c
@@ -1337,6 +1337,7 @@ make_build_data(char *target)
pclose(fp1);
pclose(fp2);
pclose(fp3);
+ fflush(fp4);
fclose(fp4);
}
--
2.20.1
2 years, 9 months
[PATCH] Doc: update man page for the option "--src directory"
by Lianbo Jiang
The "--src directory" option information is missing from the man page of
crash utility. Originally it was added by commit <9254c7f206d5> ("Added
a new "--src <directory>"...), lets sync this option information to the
man page.
Signed-off-by: Lianbo Jiang <lijiang(a)redhat.com>
---
crash.8 | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/crash.8 b/crash.8
index 5020ce12d16c..1f3657b11e4c 100644
--- a/crash.8
+++ b/crash.8
@@ -486,6 +486,10 @@ command, search for their object files in
.I directory
instead of in the standard location.
.TP
+.BI --src \ directory
+Search for the kernel source code in directory instead of in the
+standard location that is compiled into the debuginfo data.
+.TP
.BI --kaslr \ offset | auto
If an x86_64 kernel was configured with
.B CONFIG_RANDOMIZE_BASE,
--
2.20.1
2 years, 9 months
[PATCH v2] Fix for "bpf -m|-M" options to appropriately display MEMLOCK and UID
by Lianbo Jiang
Kernel commit 80ee81e0403c ("bpf: Eliminate rlimit-based memory
accounting infra for bpf maps") removed the struct bpf_map_memory
member from struct bpf_map. Without the patch, the "bpf -m|-M" options
will print "(unknown)" for MEMLOCK and UID:
crash> bpf -m 1
ID BPF_MAP BPF_MAP_TYPE MAP_FLAGS
1 ffff96ba41804400 ARRAY 00000000
KEY_SIZE: 4 VALUE_SIZE: 8 MAX_ENTRIES: 64 MEMLOCK: (unknown)
NAME: "dist" UID: (unknown)
Signed-off-by: Lianbo Jiang <lijiang(a)redhat.com>
Signed-off-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
---
bpf.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 66 insertions(+), 4 deletions(-)
diff --git a/bpf.c b/bpf.c
index cb6b0ed385f9..466b244e0c3a 100644
--- a/bpf.c
+++ b/bpf.c
@@ -63,6 +63,64 @@ static int do_old_idr(int, ulong, struct list_pair *);
#define PROG_VERBOSE (0x40)
#define MAP_VERBOSE (0x80)
+static int map_is_per_cpu(int type)
+{
+
+/* See the definition of bpf_map_type: include/uapi/linux/bpf.h */
+#define BPF_MAP_TYPE_PERCPU_HASH (5UL)
+#define BPF_MAP_TYPE_PERCPU_ARRAY (6UL)
+#define BPF_MAP_TYPE_LRU_PERCPU_HASH (10UL)
+#define BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE (21UL)
+
+ return type == BPF_MAP_TYPE_PERCPU_HASH ||
+ type == BPF_MAP_TYPE_PERCPU_ARRAY ||
+ type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
+ type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE;
+}
+
+static int map_is_fd_map(int type)
+{
+
+/* See the definition of bpf_map_type: include/uapi/linux/bpf.h */
+#define BPF_MAP_TYPE_PROG_ARRAY (3UL)
+#define BPF_MAP_TYPE_PERF_EVENT_ARRAY (4UL)
+#define BPF_MAP_TYPE_CGROUP_ARRAY (8UL)
+#define BPF_MAP_TYPE_ARRAY_OF_MAPS (12UL)
+#define BPF_MAP_TYPE_HASH_OF_MAPS (13UL)
+
+ return type == BPF_MAP_TYPE_PROG_ARRAY ||
+ type == BPF_MAP_TYPE_PERF_EVENT_ARRAY ||
+ type == BPF_MAP_TYPE_CGROUP_ARRAY ||
+ type == BPF_MAP_TYPE_ARRAY_OF_MAPS ||
+ type == BPF_MAP_TYPE_HASH_OF_MAPS;
+
+}
+
+static ulong bpf_map_memory_size(int map_type, uint value_size,
+ uint key_size, uint max_entries)
+{
+ ulong size;
+ uint valsize;
+ int cpus = 0;
+
+ if (map_is_per_cpu(map_type)) {
+ cpus = get_cpus_possible();
+ if (!cpus) {
+ error(WARNING, "cpu_possible_map does not exist, possible cpus: %d\n", cpus);
+ return 0;
+ }
+
+ valsize = roundup(value_size, 8) * cpus;
+ } else if (map_is_fd_map(map_type))
+ valsize = sizeof(uint);
+ else
+ valsize = value_size;
+
+ size = roundup((key_size + valsize), 8);
+
+ return roundup((max_entries * size), PAGESIZE());
+}
+
void
cmd_bpf(void)
{
@@ -332,7 +390,7 @@ do_bpf(ulong flags, ulong prog_id, ulong map_id, int radix)
{
struct bpf_info *bpf;
int i, c, found, entries, type;
- uint uid, map_pages, key_size, value_size, max_entries;
+ uint uid, map_pages, key_size = 0, value_size = 0, max_entries = 0;
ulong bpf_prog_aux, bpf_func, end_func, addr, insnsi, user;
ulong do_progs, do_maps;
ulonglong load_time;
@@ -572,6 +630,8 @@ do_map_only:
fprintf(fp, "\n");
if (flags & (MAP_ID|MAP_VERBOSE)) {
+ ulong msize = 0;
+
fprintf(fp, " KEY_SIZE: ");
if (VALID_MEMBER(bpf_map_key_size)) {
key_size = UINT(bpf->bpf_map_buf + OFFSET(bpf_map_key_size));
@@ -602,8 +662,10 @@ do_map_only:
} else if (VALID_MEMBER(bpf_map_pages)) {
map_pages = UINT(bpf->bpf_map_buf + OFFSET(bpf_map_pages));
fprintf(fp, "%d\n", map_pages * PAGESIZE());
- } else
- fprintf(fp, "(unknown)\n");
+ } else if ((msize = bpf_map_memory_size(type, value_size, key_size, max_entries)))
+ fprintf(fp, "%ld\n", msize);
+ else
+ fprintf(fp, "(unknown)");
fprintf(fp, " NAME: ");
if (VALID_MEMBER(bpf_map_name)) {
@@ -632,7 +694,7 @@ do_map_only:
else
fprintf(fp, "(unknown)\n");
} else
- fprintf(fp, "(unknown)\n");
+ fprintf(fp, "(unused)\n");
}
if (flags & DUMP_STRUCT) {
--
2.30.2
2 years, 9 months
[v2] sbitmapq command
by Sergey Samoylenko
Patch adds new 'sbitmapq' command. This command dumps
the contents of the sbitmap_queue structure and the used
bits in the bitmap. Also, it shows the dump of a structure
array associated with the sbitmap_queue.
v1 -> v2:
- Update the help page (Lianbo)
- Use crash interfaces (offset_table, size_table, GETBUF()
and etc.) for reduce the number of readmem() (Kazu)
Signed-off-by: Sergey Samoylenko <s.samoylenko(a)yadro.com>
---
Makefile | 7 +-
defs.h | 59 +++++
global_data.c | 1 +
help.c | 108 ++++++++
sbitmap.c | 664 ++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 837 insertions(+), 2 deletions(-)
create mode 100644 sbitmap.c
diff --git a/Makefile b/Makefile
index 4fd8b78..a381c5f 100644
--- a/Makefile
+++ b/Makefile
@@ -72,7 +72,7 @@ CFILES=main.c tools.c global_data.c memory.c filesys.c help.c task.c \
xen_hyper.c xen_hyper_command.c xen_hyper_global_data.c \
xen_hyper_dump_tables.c kvmdump.c qemu.c qemu-load.c sadump.c ipcs.c \
ramdump.c vmware_vmss.c vmware_guestdump.c \
- xen_dom0.c kaslr_helper.c
+ xen_dom0.c kaslr_helper.c sbitmap.c
SOURCE_FILES=${CFILES} ${GENERIC_HFILES} ${MCORE_HFILES} \
${REDHAT_CFILES} ${REDHAT_HFILES} ${UNWIND_HFILES} \
@@ -92,7 +92,7 @@ OBJECT_FILES=main.o tools.o global_data.o memory.o filesys.o help.o task.o \
xen_hyper.o xen_hyper_command.o xen_hyper_global_data.o \
xen_hyper_dump_tables.o kvmdump.o qemu.o qemu-load.o sadump.o ipcs.o \
ramdump.o vmware_vmss.o vmware_guestdump.o \
- xen_dom0.o kaslr_helper.o
+ xen_dom0.o kaslr_helper.o sbitmap.o
MEMORY_DRIVER_FILES=memory_driver/Makefile memory_driver/crash.c memory_driver/README
@@ -341,6 +341,9 @@ cmdline.o: ${GENERIC_HFILES} cmdline.c
tools.o: ${GENERIC_HFILES} tools.c
${CC} -c ${CRASH_CFLAGS} tools.c ${WARNING_OPTIONS} ${WARNING_ERROR}
+sbitmap.o: ${GENERIC_HFILES} sbitmap.c
+ ${CC} -c ${CRASH_CFLAGS} sbitmap.c ${WARNING_OPTIONS} ${WARNING_ERROR}
+
global_data.o: ${GENERIC_HFILES} global_data.c
${CC} -c ${CRASH_CFLAGS} global_data.c ${WARNING_OPTIONS} ${WARNING_ERROR}
diff --git a/defs.h b/defs.h
index b63741c..d407025 100644
--- a/defs.h
+++ b/defs.h
@@ -18,6 +18,7 @@
#ifndef GDB_COMMON
+#include <stdbool.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdint.h>
@@ -2146,6 +2147,23 @@ struct offset_table { /* stash of commonly-used offsets */
long wait_queue_entry_private;
long wait_queue_head_head;
long wait_queue_entry_entry;
+ long sbitmap_word_depth;
+ long sbitmap_word_word;
+ long sbitmap_word_cleared;
+ long sbitmap_depth;
+ long sbitmap_shift;
+ long sbitmap_map_nr;
+ long sbitmap_map;
+ long sbitmap_queue_sb;
+ long sbitmap_queue_alloc_hint;
+ long sbitmap_queue_wake_batch;
+ long sbitmap_queue_wake_index;
+ long sbitmap_queue_ws;
+ long sbitmap_queue_ws_active;
+ long sbitmap_queue_round_robin;
+ long sbitmap_queue_min_shallow_depth;
+ long sbq_wait_state_wait_cnt;
+ long sbq_wait_state_wait;
};
struct size_table { /* stash of commonly-used sizes */
@@ -2310,6 +2328,10 @@ struct size_table { /* stash of commonly-used sizes */
long prb_desc;
long wait_queue_entry;
long task_struct_state;
+ long sbitmap_word;
+ long sbitmap;
+ long sbitmap_queue;
+ long sbq_wait_state;
};
struct array_table {
@@ -2436,6 +2458,7 @@ DEF_LOADER(ushort);
DEF_LOADER(short);
typedef void *pointer_t;
DEF_LOADER(pointer_t);
+DEF_LOADER(bool);
#define LOADER(TYPE) load_##TYPE
@@ -2449,6 +2472,7 @@ DEF_LOADER(pointer_t);
#define SHORT(ADDR) LOADER(short) ((char *)(ADDR))
#define UCHAR(ADDR) *((unsigned char *)((char *)(ADDR)))
#define VOID_PTR(ADDR) ((void *) (LOADER(pointer_t) ((char *)(ADDR))))
+#define BOOL(ADDR) LOADER(bool) ((char *)(ADDR)))
#else
@@ -2462,6 +2486,7 @@ DEF_LOADER(pointer_t);
#define SHORT(ADDR) *((short *)((char *)(ADDR)))
#define UCHAR(ADDR) *((unsigned char *)((char *)(ADDR)))
#define VOID_PTR(ADDR) *((void **)((char *)(ADDR)))
+#define BOOL(ADDR) *((bool *)((char *)(ADDR)))
#endif /* NEED_ALIGNED_MEM_ACCESS */
@@ -4962,6 +4987,7 @@ void cmd_mach(void); /* main.c */
void cmd_help(void); /* help.c */
void cmd_test(void); /* test.c */
void cmd_ascii(void); /* tools.c */
+void cmd_sbitmapq(void); /* sbitmap.c */
void cmd_bpf(void); /* bfp.c */
void cmd_set(void); /* tools.c */
void cmd_eval(void); /* tools.c */
@@ -5575,6 +5601,7 @@ extern char *help_rd[];
extern char *help_repeat[];
extern char *help_runq[];
extern char *help_ipcs[];
+extern char *help_sbitmapq[];
extern char *help_search[];
extern char *help_set[];
extern char *help_sig[];
@@ -5844,6 +5871,38 @@ void devdump_info(void *, ulonglong, FILE *);
void ipcs_init(void);
ulong idr_find(ulong, int);
+/*
+ * sbitmap.c
+ */
+/* sbitmap helpers */
+struct sbitmap_context {
+ unsigned depth;
+ unsigned shift;
+ unsigned map_nr;
+ ulong map_addr;
+};
+
+typedef bool (*sbitmap_for_each_fn)(unsigned int idx, void *p);
+
+void sbitmap_for_each_set(const struct sbitmap_context *sc,
+ sbitmap_for_each_fn fn, void *data);
+void sbitmap_context_load(ulong addr, struct sbitmap_context *sc);
+
+/* sbitmap_queue helpers */
+typedef bool (*sbitmapq_for_each_fn)(unsigned int idx, ulong addr, void *p);
+
+struct sbitmapq_ops {
+ /* array params associated with the bitmap */
+ ulong addr;
+ ulong size;
+ /* callback params */
+ sbitmapq_for_each_fn fn;
+ void *p;
+};
+
+void sbitmapq_init(void);
+void sbitmapq_for_each_set(ulong addr, struct sbitmapq_ops *ops);
+
#ifdef ARM
void arm_init(int);
void arm_dump_machdep_table(ulong);
diff --git a/global_data.c b/global_data.c
index a316d1c..f9bb7d0 100644
--- a/global_data.c
+++ b/global_data.c
@@ -105,6 +105,7 @@ struct command_table_entry linux_command_table[] = {
{"rd", cmd_rd, help_rd, MINIMAL},
{"repeat", cmd_repeat, help_repeat, 0},
{"runq", cmd_runq, help_runq, REFRESH_TASK_TABLE},
+ {"sbitmapq", cmd_sbitmapq, help_sbitmapq, 0},
{"search", cmd_search, help_search, 0},
{"set", cmd_set, help_set, REFRESH_TASK_TABLE | MINIMAL},
{"sig", cmd_sig, help_sig, REFRESH_TASK_TABLE},
diff --git a/help.c b/help.c
index 04a7eff..d151f2e 100644
--- a/help.c
+++ b/help.c
@@ -962,6 +962,114 @@ char *help_ascii[] = {
NULL
};
+char *help_sbitmapq[] = {
+"sbitmapq",
+"sbitmap_queue struct contents",
+"[-s struct[.member[,member]] -p address [-v]] address",
+" The command dumps the contents of the sbitmap_queue structure and",
+" the used bits in the bitmap. Also, it shows the dump of a structure",
+" array associated with the sbitmap_queue.",
+"",
+" The arguments are as follows:",
+"",
+" -s struct - name of a C-code structure, that is stored in an array",
+" sssociated with sbitmap_queue structure. Use the",
+" \"struct.member\" format in order to display a particular",
+" member of the structure. -s option requires -p option",
+"",
+" -p address - address of a structure array associated with sbitmap_queue",
+" structure. The set bits in sbitmap are used for the index",
+" in an associated array.",
+"",
+" -x - override default output format with hexadecimal format.",
+"",
+" -d - override default output format with decimal format.",
+"",
+" -v - By default, the sbitmap command shows only a used sbitmap",
+" index and a structure address in the associated array.",
+" This flag says to print a formatted display of the",
+" contents of a structure in an associated array. -v option",
+" requires of -s.",
+"",
+"EXAMPLES",
+"",
+" All examples are shown on the base of Linux Target system whit iSCSI",
+" transport.",
+"",
+" Display the common sbitmap information for target session:",
+"",
+" %s> struct -oh se_session 0xc0000000e118c760 | grep sbitmap_queue",
+" [c0000000e118c808] struct sbitmap_queue sess_tag_pool;",
+" %s>",
+" %s> sbitmapq c0000000e118c808",
+" depth = 136",
+" busy = 4",
+" cleared = 26",
+" bits_per_word = 32",
+" map_nr = 5",
+" alloc_hint = {74, 36, 123, 101}",
+" wake_batch = 8",
+" wake_index = 0",
+" ws_active = 0",
+" ws = {",
+" { .wait_cnt = 8, .wait = inactive },",
+" { .wait_cnt = 8, .wait = inactive },",
+" { .wait_cnt = 8, .wait = inactive },",
+" { .wait_cnt = 8, .wait = inactive },",
+" { .wait_cnt = 8, .wait = inactive },",
+" { .wait_cnt = 8, .wait = inactive },",
+" { .wait_cnt = 8, .wait = inactive },",
+" { .wait_cnt = 8, .wait = inactive },",
+" }",
+" round_robin = 0",
+" min_shallow_depth = 4294967295",
+"",
+" 00000000: 0000 0000 0000 0000 0030 0000 0000 0000",
+" 00000010: 00",
+"",
+" Display the addresses of structure are associated with",
+" sbitmap_queue (for iscsi it is 'iscsi_cmd' structure):",
+"",
+" %s> struct se_session 0xc0000000e118c760 | grep sess_cmd_map",
+" sess_cmd_map = 0xc0000000671c0000,",
+" %s>",
+" %s> sbitmapq -s iscsi_cmd -p 0xc0000000671c0000 c0000000e118c808",
+" 76: 0xc0000000671d5600",
+" 77: 0xc0000000671d5a80",
+"",
+
+" Dump of formatted content of structures:",
+"",
+" %s> sbitmapq -s iscsi_cmd -p 0xc0000000671c0000 -v c0000000e118c808",
+" 76 (0xc0000000671d5600):",
+" struct iscsi_cmd {",
+" dataout_timer_flags = 0,",
+" dataout_timeout_retries = 0 '\\000',",
+" error_recovery_count = 0 '\\000',",
+" deferred_i_state = ISTATE_NO_STATE,",
+" i_state = ISTATE_SENT_STATUS,",
+" ...",
+" first_data_sg = 0xc0000000e306b080,",
+" first_data_sg_off = 0,",
+" kmapped_nents = 1,",
+" sense_reason = 0",
+" }",
+" 77 (0xc0000000671d5a80):",
+" struct iscsi_cmd {",
+" dataout_timer_flags = 0,",
+" dataout_timeout_retries = 0 '\\000',",
+" error_recovery_count = 0 '\\000',",
+" deferred_i_state = ISTATE_NO_STATE,",
+" i_state = ISTATE_NEW_CMD,",
+" ...",
+" first_data_sg = 0x0,",
+" first_data_sg_off = 0,",
+" kmapped_nents = 0,",
+" sense_reason = 0",
+" }",
+NULL
+};
+
char *help_quit[] = {
"quit",
"exit this session",
diff --git a/sbitmap.c b/sbitmap.c
new file mode 100644
index 0000000..5343a88
--- /dev/null
+++ b/sbitmap.c
@@ -0,0 +1,664 @@
+/* sbitmap.c - core analysis suite
+ *
+ * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
+ * Copyright (C) 2002-2020 David Anderson
+ * Copyright (C) 2002-2020 Red Hat, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "defs.h"
+
+#define SBQ_WAIT_QUEUES 8
+
+/* sbitmap_queue struct context */
+struct sbitmap_queue_context {
+ ulong sb_addr;
+ ulong alloc_hint;
+ unsigned int wake_batch;
+ int wake_index;
+ ulong ws_addr;
+ int ws_active;
+ bool round_robin;
+ unsigned int min_shallow_depth;
+
+};
+
+struct sbitmapq_data {
+#define SBITMAPQ_DATA_FLAG_STRUCT_NAME (VERBOSE << 1)
+#define SBITMAPQ_DATA_FLAG_STRUCT_ADDR (VERBOSE << 2)
+#define SBITMAPQ_DATA_FLAG_STRUCT_MEMBER (VERBOSE << 3)
+ ulong flags;
+ int radix;
+ /* sbitmap_queue info */
+ ulong addr;
+ /* data array info */
+ ulong data_addr;
+ char *data_name;
+ int data_size;
+};
+
+#define SB_FLAG_INIT 0x01
+
+static uint sb_flags = 0;
+
+static inline unsigned int __const_hweight8(unsigned long w)
+{
+ return
+ (!!((w) & (1ULL << 0))) +
+ (!!((w) & (1ULL << 1))) +
+ (!!((w) & (1ULL << 2))) +
+ (!!((w) & (1ULL << 3))) +
+ (!!((w) & (1ULL << 4))) +
+ (!!((w) & (1ULL << 5))) +
+ (!!((w) & (1ULL << 6))) +
+ (!!((w) & (1ULL << 7)));
+}
+
+#define __const_hweight16(w) (__const_hweight8(w) + __const_hweight8((w) >> 8))
+#define __const_hweight32(w) (__const_hweight16(w) + __const_hweight16((w) >> 16))
+#define __const_hweight64(w) (__const_hweight32(w) + __const_hweight32((w) >> 32))
+
+#define hweight32(w) __const_hweight32(w)
+#define hweight64(w) __const_hweight64(w)
+
+#define BIT(nr) (1UL << (nr))
+
+static inline unsigned long min(unsigned long a, unsigned long b)
+{
+ return (a < b) ? a : b;
+}
+
+static unsigned long __last_word_mask(unsigned long nbits)
+{
+ return ~0UL >> (-(nbits) & (BITS_PER_LONG - 1));
+}
+
+static unsigned long bitmap_hweight_long(unsigned long w)
+{
+ return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
+}
+
+static unsigned long bitmap_weight(unsigned long bitmap, unsigned int bits)
+{
+ unsigned long w = 0;
+
+ w += bitmap_hweight_long(bitmap);
+ if (bits % BITS_PER_LONG)
+ w += bitmap_hweight_long(bitmap & __last_word_mask(bits));
+
+ return w;
+}
+
+static unsigned int __sbitmap_weight(const struct sbitmap_context *sc, bool set)
+{
+ const ulong sbitmap_word_size = SIZE(sbitmap_word);
+ const ulong w_depth_off = OFFSET(sbitmap_word_depth);
+ const ulong w_word_off = OFFSET(sbitmap_word_word);
+ const ulong w_cleared_off = OFFSET(sbitmap_word_cleared);
+
+ unsigned int weight = 0;
+ ulong addr = sc->map_addr;
+ ulong depth, word, cleared;
+ char *sbitmap_word_buf;
+ int i;
+
+ sbitmap_word_buf = GETBUF(sbitmap_word_size);
+
+ for (i = 0; i < sc->map_nr; i++) {
+ readmem(addr, KVADDR, sbitmap_word_buf, sbitmap_word_size, "sbitmap_word", FAULT_ON_ERROR);
+
+ depth = ULONG(sbitmap_word_buf + w_depth_off);
+
+ if (set) {
+ word = ULONG(sbitmap_word_buf + w_word_off);
+ weight += bitmap_weight(word, depth);
+ } else {
+ cleared = ULONG(sbitmap_word_buf + w_cleared_off);
+ weight += bitmap_weight(cleared, depth);
+ }
+
+ addr += sbitmap_word_size;
+ }
+
+ FREEBUF(sbitmap_word_buf);
+
+ return weight;
+}
+
+static unsigned int sbitmap_weight(const struct sbitmap_context *sc)
+{
+ return __sbitmap_weight(sc, true);
+}
+
+static unsigned int sbitmap_cleared(const struct sbitmap_context *sc)
+{
+ return __sbitmap_weight(sc, false);
+}
+
+static void sbitmap_emit_byte(unsigned int offset, uint8_t byte)
+{
+ if ((offset &0xf) == 0) {
+ if (offset != 0)
+ fputc('\n', fp);
+ fprintf(fp, "%08x:", offset);
+ }
+ if ((offset & 0x1) == 0)
+ fputc(' ', fp);
+ fprintf(fp, "%02x", byte);
+}
+
+static void sbitmap_bitmap_show(const struct sbitmap_context *sc)
+{
+ const ulong sbitmap_word_size = SIZE(sbitmap_word);
+ const ulong w_depth_off = OFFSET(sbitmap_word_depth);
+ const ulong w_word_off = OFFSET(sbitmap_word_word);
+ const ulong w_cleared_off = OFFSET(sbitmap_word_cleared);
+
+ uint8_t byte = 0;
+ unsigned int byte_bits = 0;
+ unsigned int offset = 0;
+ ulong addr = sc->map_addr;
+ char *sbitmap_word_buf;
+ int i;
+
+ sbitmap_word_buf = GETBUF(sbitmap_word_size);
+
+ for (i = 0; i < sc->map_nr; i++) {
+ unsigned long word, cleared, word_bits;
+
+ readmem(addr, KVADDR, sbitmap_word_buf, sbitmap_word_size, "sbitmap_word", FAULT_ON_ERROR);
+
+ word = ULONG(sbitmap_word_buf + w_word_off);
+ cleared = ULONG(sbitmap_word_buf + w_cleared_off);
+ word_bits = ULONG(sbitmap_word_buf + w_depth_off);
+
+ word &= ~cleared;
+
+ while (word_bits > 0) {
+ unsigned int bits = min(8 - byte_bits, word_bits);
+
+ byte |= (word & (BIT(bits) - 1)) << byte_bits;
+ byte_bits += bits;
+ if (byte_bits == 8) {
+ sbitmap_emit_byte(offset, byte);
+ byte = 0;
+ byte_bits = 0;
+ offset++;
+ }
+ word >>= bits;
+ word_bits -= bits;
+ }
+
+ addr += sbitmap_word_size;
+ }
+ if (byte_bits) {
+ sbitmap_emit_byte(offset, byte);
+ offset++;
+ }
+ if (offset)
+ fputc('\n', fp);
+
+ FREEBUF(sbitmap_word_buf);
+}
+
+static unsigned long sbitmap_find_next_bit(unsigned long word,
+ unsigned long size, unsigned long offset)
+{
+ if (size > BITS_PER_LONG)
+ error(FATAL, "%s: word size isn't correct\n", __func__);
+
+ for (; offset < size; offset++)
+ if (word & (1UL << offset))
+ return offset;
+
+ return size;
+}
+
+static void __sbitmap_for_each_set(const struct sbitmap_context *sc,
+ unsigned int start, sbitmap_for_each_fn fn, void *data)
+{
+ const ulong sbitmap_word_size = SIZE(sbitmap_word);
+ const ulong w_depth_off = OFFSET(sbitmap_word_depth);
+ const ulong w_word_off = OFFSET(sbitmap_word_word);
+ const ulong w_cleared_off = OFFSET(sbitmap_word_cleared);
+
+ unsigned int index;
+ unsigned int nr;
+ unsigned int scanned = 0;
+ char *sbitmap_word_buf;
+
+ sbitmap_word_buf = GETBUF(sbitmap_word_size);
+
+ if (start >= sc->map_nr)
+ start = 0;
+
+ index = start >> sc->shift;
+ nr = start & ((1U << sc->shift) - 1U);
+
+ while (scanned < sc->depth) {
+ unsigned long w_addr = sc->map_addr + (sbitmap_word_size * index);
+ unsigned long w_depth, w_word, w_cleared;
+ unsigned long word, depth;
+
+ readmem(w_addr, KVADDR, sbitmap_word_buf, sbitmap_word_size, "sbitmap_word", FAULT_ON_ERROR);
+
+ w_depth = ULONG(sbitmap_word_buf + w_depth_off);
+ w_word = ULONG(sbitmap_word_buf + w_word_off);
+ w_cleared = ULONG(sbitmap_word_buf + w_cleared_off);
+
+ depth = min(w_depth - nr, sc->depth - scanned);
+
+ scanned += depth;
+ word = w_word & ~w_cleared;
+ if (!word)
+ goto next;
+
+ /*
+ * On the first iteration of the outer loop, we need to add the
+ * bit offset back to the size of the word for find_next_bit().
+ * On all other iterations, nr is zero, so this is a noop.
+ */
+ depth += nr;
+ while (1) {
+ nr = sbitmap_find_next_bit(word, depth, nr);
+ if (nr >= depth)
+ break;
+ if (!fn((index << sc->shift) + nr, data))
+ return;
+
+ nr++;
+ }
+next:
+ nr = 0;
+ if (++index >= sc->map_nr)
+ index = 0;
+ }
+
+ FREEBUF(sbitmap_word_buf);
+}
+
+void sbitmap_for_each_set(const struct sbitmap_context *sc,
+ sbitmap_for_each_fn fn, void *data)
+{
+ __sbitmap_for_each_set(sc, 0, fn, data);
+}
+
+static void sbitmap_queue_show(const struct sbitmap_queue_context *sqc,
+ const struct sbitmap_context *sc)
+{
+ int cpus = get_cpus_possible();
+ int sbq_wait_state_size, wait_cnt_off, wait_off, list_head_off;
+ char *sbq_wait_state_buf;
+ bool first;
+ int i;
+
+ fprintf(fp, "depth = %u\n", sc->depth);
+ fprintf(fp, "busy = %u\n", sbitmap_weight(sc) - sbitmap_cleared(sc));
+ fprintf(fp, "cleared = %u\n", sbitmap_cleared(sc));
+ fprintf(fp, "bits_per_word = %u\n", 1U << sc->shift);
+ fprintf(fp, "map_nr = %u\n", sc->map_nr);
+
+ fputs("alloc_hint = {", fp);
+ first = true;
+ for (i = 0; i < cpus; i++) {
+ ulong ptr;
+ int val;
+
+ if (!first)
+ fprintf(fp, ", ");
+ first = false;
+
+ ptr = kt->__per_cpu_offset[i] + sqc->alloc_hint;
+ readmem(ptr, KVADDR, &val, sizeof(val), "alloc_hint", FAULT_ON_ERROR);
+
+ fprintf(fp, "%u", val);
+ }
+ fputs("}\n", fp);
+
+ fprintf(fp, "wake_batch = %u\n", sqc->wake_batch);
+ fprintf(fp, "wake_index = %d\n", sqc->wake_index);
+ fprintf(fp, "ws_active = %d\n", sqc->ws_active);
+
+ sbq_wait_state_size = SIZE(sbq_wait_state);
+ wait_cnt_off = OFFSET(sbq_wait_state_wait_cnt);
+ wait_off = OFFSET(sbq_wait_state_wait);
+ list_head_off = OFFSET(wait_queue_head_head);
+
+ sbq_wait_state_buf = GETBUF(sbq_wait_state_size);
+
+ fputs("ws = {\n", fp);
+ for (i = 0; i < SBQ_WAIT_QUEUES; i++) {
+ ulong ws_addr = sqc->ws_addr + (sbq_wait_state_size * i);
+ struct kernel_list_head *lh;
+ ulong wait_cnt_addr, list_head_addr;
+ ulong wait_cnt;
+
+ readmem(ws_addr, KVADDR, sbq_wait_state_buf, sbq_wait_state_size, "sbq_wait_state", FAULT_ON_ERROR);
+
+ wait_cnt = INT(sbq_wait_state_buf + wait_cnt_off);
+ lh = (struct kernel_list_head *)(sbq_wait_state_buf + wait_off + list_head_off);
+
+ fprintf(fp, "\t{ .wait_cnt = %lu, .wait = %s },\n",
+ wait_cnt, (lh->next == lh->prev) ? "inactive" : "active");
+ }
+ fputs("}\n", fp);
+
+ FREEBUF(sbq_wait_state_buf);
+
+ fprintf(fp, "round_robin = %d\n", sqc->round_robin);
+ fprintf(fp, "min_shallow_depth = %u\n", sqc->min_shallow_depth);
+}
+
+static void sbitmap_queue_context_load(ulong addr, struct sbitmap_queue_context *sqc)
+{
+ char *sbitmap_queue_buf;
+
+ sqc->sb_addr = addr + OFFSET(sbitmap_queue_sb);
+
+ sbitmap_queue_buf = GETBUF(SIZE(sbitmap_queue));
+ readmem(addr, KVADDR, sbitmap_queue_buf, SIZE(sbitmap_queue), "sbitmap_queue", FAULT_ON_ERROR);
+
+ sqc->alloc_hint = ULONG(sbitmap_queue_buf + OFFSET(sbitmap_queue_alloc_hint));
+ sqc->wake_batch = UINT(sbitmap_queue_buf + OFFSET(sbitmap_queue_wake_batch));
+ sqc->wake_index = INT(sbitmap_queue_buf + OFFSET(sbitmap_queue_wake_index));
+ sqc->ws_addr = ULONG(sbitmap_queue_buf + OFFSET(sbitmap_queue_ws));
+ sqc->ws_active = INT(sbitmap_queue_buf + OFFSET(sbitmap_queue_ws_active));
+ sqc->round_robin = BOOL(sbitmap_queue_buf + OFFSET(sbitmap_queue_round_robin));
+ sqc->min_shallow_depth = UINT(sbitmap_queue_buf + OFFSET(sbitmap_queue_min_shallow_depth));
+
+ FREEBUF(sbitmap_queue_buf);
+}
+
+void sbitmap_context_load(ulong addr, struct sbitmap_context *sc)
+{
+ char *sbitmap_buf;
+
+ sbitmap_buf = GETBUF(SIZE(sbitmap));
+ readmem(addr, KVADDR, sbitmap_buf, SIZE(sbitmap), "sbitmap", FAULT_ON_ERROR);
+
+ sc->depth = UINT(sbitmap_buf + OFFSET(sbitmap_depth));
+ sc->shift = UINT(sbitmap_buf + OFFSET(sbitmap_shift));
+ sc->map_nr = UINT(sbitmap_buf + OFFSET(sbitmap_map_nr));
+ sc->map_addr = ULONG(sbitmap_buf + OFFSET(sbitmap_map));
+
+ FREEBUF(sbitmap_buf);
+}
+
+static bool for_each_func(unsigned int idx, void *p)
+{
+ struct sbitmapq_ops *ops = p;
+ ulong addr = ops->addr + (ops->size * idx);
+
+ return ops->fn(idx, addr, ops->p);
+}
+
+void sbitmapq_for_each_set(ulong addr, struct sbitmapq_ops *ops)
+{
+ struct sbitmap_queue_context sqc = {0};
+ struct sbitmap_context sc = {0};
+
+ sbitmap_queue_context_load(addr, &sqc);
+ sbitmap_context_load(sqc.sb_addr, &sc);
+
+ sbitmap_for_each_set(&sc, for_each_func, ops);
+}
+
+static void dump_struct_members(const char *s, ulong addr, unsigned radix)
+{
+ int i, argc;
+ char *p1, *p2;
+ char *structname, *members;
+ char *arglist[MAXARGS];
+
+ structname = GETBUF(strlen(s) + 1);
+ members = GETBUF(strlen(s) + 1);
+
+ strcpy(structname, s);
+ p1 = strstr(structname, ".") + 1;
+
+ p2 = strstr(s, ".") + 1;
+ strcpy(members, p2);
+ replace_string(members, ",", ' ');
+ argc = parse_line(members, arglist);
+
+ for (i = 0; i < argc; i++) {
+ *p1 = NULLCHAR;
+ strcat(structname, arglist[i]);
+ dump_struct_member(structname, addr, radix);
+ }
+
+ FREEBUF(structname);
+ FREEBUF(members);
+}
+
+static bool sbitmap_data_print(unsigned int idx, ulong addr, void *p)
+{
+ const struct sbitmapq_data *sd = p;
+ bool verbose = !!(sd->flags & VERBOSE);
+ bool members = !!(sd->flags & SBITMAPQ_DATA_FLAG_STRUCT_MEMBER);
+
+ if (verbose) {
+ fprintf(fp, "%d (0x%08lx):\n", idx, addr);
+ if (members)
+ dump_struct_members(sd->data_name, addr, sd->radix);
+ else
+ dump_struct(sd->data_name, addr, sd->radix);
+ } else
+ fprintf(fp, "%d: 0x%08lx\n", idx, addr);
+
+ return true;
+}
+
+static void sbitmap_queue_data_dump(struct sbitmapq_data *sd)
+{
+ struct sbitmapq_ops ops = {
+ .addr = sd->data_addr,
+ .size = sd->data_size,
+ .fn = sbitmap_data_print,
+ .p = sd
+ };
+
+ sbitmapq_for_each_set(sd->addr, &ops);
+}
+
+static void sbitmap_queue_dump(const struct sbitmapq_data *sd)
+{
+ struct sbitmap_queue_context sqc ={0};
+ struct sbitmap_context sc = {0};
+
+ sbitmap_queue_context_load(sd->addr, &sqc);
+ sbitmap_context_load(sqc.sb_addr, &sc);
+
+ sbitmap_queue_show(&sqc, &sc);
+ fputc('\n', fp);
+ sbitmap_bitmap_show(&sc);
+}
+
+void sbitmapq_init(void)
+{
+ if (sb_flags & SB_FLAG_INIT)
+ return;
+
+ STRUCT_SIZE_INIT(sbitmap_word, "sbitmap_word");
+ STRUCT_SIZE_INIT(sbitmap, "sbitmap");
+ STRUCT_SIZE_INIT(sbitmap_queue, "sbitmap_queue");
+ STRUCT_SIZE_INIT(sbq_wait_state, "sbq_wait_state");
+
+ MEMBER_OFFSET_INIT(sbitmap_word_depth, "sbitmap_word", "depth");
+ MEMBER_OFFSET_INIT(sbitmap_word_word, "sbitmap_word", "word");
+ MEMBER_OFFSET_INIT(sbitmap_word_cleared, "sbitmap_word", "cleared");
+
+ MEMBER_OFFSET_INIT(sbitmap_depth, "sbitmap", "depth");
+ MEMBER_OFFSET_INIT(sbitmap_shift, "sbitmap", "shift");
+ MEMBER_OFFSET_INIT(sbitmap_map_nr, "sbitmap", "map_nr");
+ MEMBER_OFFSET_INIT(sbitmap_map, "sbitmap", "map");
+
+ MEMBER_OFFSET_INIT(sbitmap_queue_sb, "sbitmap_queue", "sb");
+ MEMBER_OFFSET_INIT(sbitmap_queue_alloc_hint, "sbitmap_queue", "alloc_hint");
+ MEMBER_OFFSET_INIT(sbitmap_queue_wake_batch, "sbitmap_queue", "wake_batch");
+ MEMBER_OFFSET_INIT(sbitmap_queue_wake_index, "sbitmap_queue", "wake_index");
+ MEMBER_OFFSET_INIT(sbitmap_queue_ws, "sbitmap_queue", "ws");
+ MEMBER_OFFSET_INIT(sbitmap_queue_ws_active, "sbitmap_queue", "ws_active");
+ MEMBER_OFFSET_INIT(sbitmap_queue_round_robin, "sbitmap_queue", "round_robin");
+ MEMBER_OFFSET_INIT(sbitmap_queue_min_shallow_depth, "sbitmap_queue", "min_shallow_depth");
+
+ MEMBER_OFFSET_INIT(sbq_wait_state_wait_cnt, "sbq_wait_state", "wait_cnt");
+ MEMBER_OFFSET_INIT(sbq_wait_state_wait, "sbq_wait_state", "wait");
+
+ if (!VALID_SIZE(sbitmap_word) ||
+ !VALID_SIZE(sbitmap) ||
+ !VALID_SIZE(sbitmap_queue) ||
+ !VALID_SIZE(sbq_wait_state) ||
+ INVALID_MEMBER(sbitmap_word_depth) ||
+ INVALID_MEMBER(sbitmap_word_word) ||
+ INVALID_MEMBER(sbitmap_word_cleared) ||
+ INVALID_MEMBER(sbitmap_depth) ||
+ INVALID_MEMBER(sbitmap_shift) ||
+ INVALID_MEMBER(sbitmap_map_nr) ||
+ INVALID_MEMBER(sbitmap_map) ||
+ INVALID_MEMBER(sbitmap_queue_sb) ||
+ INVALID_MEMBER(sbitmap_queue_alloc_hint) ||
+ INVALID_MEMBER(sbitmap_queue_wake_batch) ||
+ INVALID_MEMBER(sbitmap_queue_wake_index) ||
+ INVALID_MEMBER(sbitmap_queue_ws) ||
+ INVALID_MEMBER(sbitmap_queue_ws_active) ||
+ INVALID_MEMBER(sbitmap_queue_round_robin) ||
+ INVALID_MEMBER(sbitmap_queue_min_shallow_depth) ||
+ INVALID_MEMBER(sbq_wait_state_wait_cnt) ||
+ INVALID_MEMBER(sbq_wait_state_wait)) {
+ command_not_supported();
+ }
+
+ sb_flags |= SB_FLAG_INIT;
+}
+
+static char *__get_struct_name(const char *s)
+{
+ char *name, *p;
+
+ name = GETBUF(strlen(s) + 1);
+ strcpy(name, s);
+
+ p = strstr(name, ".");
+ *p = NULLCHAR;
+
+ return name;
+}
+
+void cmd_sbitmapq(void)
+{
+ struct sbitmapq_data sd = {0};
+ int c;
+
+ while ((c = getopt(argcnt, args, "s:p:xdv")) != EOF) {
+ switch (c) {
+ case 's':
+ if (sd.flags & SBITMAPQ_DATA_FLAG_STRUCT_NAME)
+ error(FATAL, "-s option (%s) already entered\n", sd.data_name);
+
+ sd.data_name = optarg;
+ sd.flags |= SBITMAPQ_DATA_FLAG_STRUCT_NAME;
+
+ break;
+
+ case 'p':
+ if (sd.flags & SBITMAPQ_DATA_FLAG_STRUCT_ADDR)
+ error(FATAL, "-p option (0x%lx) already entered\n", sd.data_addr);
+ else if (!IS_A_NUMBER(optarg))
+ error(FATAL, "invalid -p option: %s\n", optarg);
+
+ sd.data_addr = htol(optarg, FAULT_ON_ERROR, NULL);
+ if (!IS_KVADDR(sd.data_addr))
+ error(FATAL, "invalid kernel virtual address: %s\n", optarg);
+ sd.flags |= SBITMAPQ_DATA_FLAG_STRUCT_ADDR;
+
+ break;
+
+ case 'v':
+ sd.flags |= VERBOSE;
+ break;
+
+ case 'x':
+ if (sd.radix == 10)
+ error(FATAL, "-d and -x are mutually exclusive\n");
+ sd.radix = 16;
+ break;
+
+ case 'd':
+ if (sd.radix == 16)
+ error(FATAL, "-d and -x are mutually exclusive\n");
+ sd.radix = 10;
+ break;
+
+ default:
+ argerrs++;
+ break;
+ }
+ }
+
+ if (argerrs)
+ cmd_usage(pc->curcmd, SYNOPSIS);
+
+ if (!args[optind]) {
+ error(INFO, "command argument is required\n");
+ cmd_usage(pc->curcmd, SYNOPSIS);
+ } else if (args[optind] && args[optind + 1]) {
+ error(INFO, "too many arguments\n");
+ cmd_usage(pc->curcmd, SYNOPSIS);
+ } else if (!IS_A_NUMBER(args[optind])) {
+ error(FATAL, "invalid command argument: %s\n", args[optind]);
+ }
+
+ sd.addr = htol(args[optind], FAULT_ON_ERROR, NULL);
+ if (!IS_KVADDR(sd.addr))
+ error(FATAL, "invalid kernel virtual address: %s\n", args[optind]);
+
+ if ((sd.flags & SBITMAPQ_DATA_FLAG_STRUCT_NAME) &&
+ !(sd.flags & SBITMAPQ_DATA_FLAG_STRUCT_ADDR)) {
+ error(INFO, "-s option requires -p option");
+ cmd_usage(pc->curcmd, SYNOPSIS);
+ } else if ((sd.flags & SBITMAPQ_DATA_FLAG_STRUCT_ADDR) &&
+ !(sd.flags & SBITMAPQ_DATA_FLAG_STRUCT_NAME)) {
+ error(FATAL, "-p option is used with -s option only\n");
+ cmd_usage(pc->curcmd, SYNOPSIS);
+ }
+
+ if (sd.flags & SBITMAPQ_DATA_FLAG_STRUCT_NAME) {
+ bool error_flag = false;
+
+ if (count_chars(sd.data_name, '.') > 0)
+ sd.flags |= SBITMAPQ_DATA_FLAG_STRUCT_MEMBER;
+
+ if (sd.flags & SBITMAPQ_DATA_FLAG_STRUCT_MEMBER) {
+ char *data_name = __get_struct_name(sd.data_name);
+
+ sd.data_size = STRUCT_SIZE(data_name);
+ if (sd.data_size <= 0)
+ error_flag = true;
+
+ FREEBUF(data_name);
+ } else {
+ sd.data_size = STRUCT_SIZE(sd.data_name);
+ if (sd.data_size <= 0)
+ error_flag = true;
+ }
+ if (error_flag)
+ error(FATAL, "invalid data structure reference: %s\n", sd.data_name);
+ }
+
+ sbitmapq_init();
+
+ if (sd.flags & SBITMAPQ_DATA_FLAG_STRUCT_NAME)
+ sbitmap_queue_data_dump(&sd);
+ else
+ sbitmap_queue_dump(&sd);
+}
--
2.25.1
2 years, 9 months
[PATCH] Fix errors when rebuild with updated gdb-10.2.patch
by HAGIO KAZUHITO(萩尾 一仁)
The gdb-10.2.patch forgot the role that acts as a shell script that
restores gdb files to its original state and exits. Without the patch,
the following errors are emitted when rebuiding crash with an updated
gdb-10.2.patch.
$ make warn
TARGET: X86_64
CRASH: 8.0.0++
GDB: 10.2
+ --- gdb-10.2/Makefile.in.orig
gdb-10.2.patch: line 11: ---: command not found
+ +++ gdb-10.2/Makefile.in
gdb-10.2.patch: line 12: +++: command not found
+ @@ -340,6 +340,9 @@ AR_FOR_BUILD = @AR_FOR_BUILD@
gdb-10.2.patch: line 13: @@: command not found
+ AS_FOR_BUILD = @AS_FOR_BUILD@
gdb-10.2.patch: line 14: AS_FOR_BUILD: command not found
+ CC_FOR_BUILD = @CC_FOR_BUILD@
gdb-10.2.patch: line 15: CC_FOR_BUILD: command not found
+ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
gdb-10.2.patch: line 16: CFLAGS_FOR_BUILD: command not found
gdb-10.2.patch: line 17: syntax error near unexpected token
`${CRASH_TARGET},'
gdb-10.2.patch: line 17: `+ifeq (${CRASH_TARGET}, PPC64)'
Signed-off-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
---
gdb-10.2.patch | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/gdb-10.2.patch b/gdb-10.2.patch
index f5e4c06e6f97..c5aa0bf79691 100644
--- a/gdb-10.2.patch
+++ b/gdb-10.2.patch
@@ -8,6 +8,11 @@
# shell script that can restore any gdb file to its original state prior
# to all subsequent patch applications.
+#tar xvzmf gdb-10.2.tar.gz \
+# gdb-10.2/gdb/symtab.c
+
+exit 0
+
--- gdb-10.2/Makefile.in.orig
+++ gdb-10.2/Makefile.in
@@ -340,6 +340,9 @@ AR_FOR_BUILD = @AR_FOR_BUILD@
--
2.27.0
2 years, 9 months