Re: [v2] sbitmapq command

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Kazu,

Thank you for supporting me with my first patch to crash.

04.02.2022 4:52, HAGIO KAZUHITO(萩尾 一仁) пишет:
> Hi Sergey,
>
> -----Original Message-----
>> 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)
> Thank you for the update, the patch looks nice and clean!
>
> I have two slight questions inline with "Question:".
>
> As for the others, I've changed the code at my end and been testing,
> so I can post it when the questions are solved.
>
>> Signed-off-by: Sergey Samoylenko <s.samoylenko@xxxxxxxxx>
>> ---
>>   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;
>>   };
> The corresponding entries are needed in "help -o" output.
>
> --- a/symbols.c
> +++ b/symbols.c
> @@ -10690,6 +10690,24 @@ dump_offset_table(char *spec, ulong makestruct)
>          fprintf(fp, "            uts_namespace_name: %ld\n",
>                  OFFSET(uts_namespace_name));
>   
> +       fprintf(fp, "            sbitmap_word_depth: %ld\n", OFFSET(sbitmap_word_depth));
> +       fprintf(fp, "             sbitmap_word_word: %ld\n", OFFSET(sbitmap_word_word));
> +       fprintf(fp, "          sbitmap_word_cleared: %ld\n", OFFSET(sbitmap_word_cleared));
> +       fprintf(fp, "                 sbitmap_depth: %ld\n", OFFSET(sbitmap_depth));
> +       fprintf(fp, "                 sbitmap_shift: %ld\n", OFFSET(sbitmap_shift));
> +       fprintf(fp, "                sbitmap_map_nr: %ld\n", OFFSET(sbitmap_map_nr));
> +       fprintf(fp, "                   sbitmap_map: %ld\n", OFFSET(sbitmap_map));
> +       fprintf(fp, "              sbitmap_queue_sb: %ld\n", OFFSET(sbitmap_queue_sb));
> +       fprintf(fp, "      sbitmap_queue_alloc_hint: %ld\n", OFFSET(sbitmap_queue_alloc_hint));
> +       fprintf(fp, "      sbitmap_queue_wake_batch: %ld\n", OFFSET(sbitmap_queue_wake_batch));
> +       fprintf(fp, "      sbitmap_queue_wake_index: %ld\n", OFFSET(sbitmap_queue_wake_index));
> +       fprintf(fp, "              sbitmap_queue_ws: %ld\n", OFFSET(sbitmap_queue_ws));
> +       fprintf(fp, "       sbitmap_queue_ws_active: %ld\n", OFFSET(sbitmap_queue_ws_active));
> +       fprintf(fp, "     sbitmap_queue_round_robin: %ld\n", OFFSET(sbitmap_queue_round_robin));
> +       fprintf(fp, "sbitmap_queue_min_shallow_depth: %ld\n", OFFSET(sbitmap_queue_min_shallow_depth));
> +       fprintf(fp, "       sbq_wait_state_wait_cnt: %ld\n", OFFSET(sbq_wait_state_wait_cnt));
> +       fprintf(fp, "           sbq_wait_state_wait: %ld\n", OFFSET(sbq_wait_state_wait));
> +
>          fprintf(fp, "\n                    size_table:\n");
>          fprintf(fp, "                          page: %ld\n", SIZE(page));
>          fprintf(fp, "                    page_flags: %ld\n", SIZE(page_flags));
> @@ -10955,6 +10973,10 @@ dump_offset_table(char *spec, ulong makestruct)
>          fprintf(fp, "             printk_ringbuffer: %ld\n", SIZE(printk_ringbuffer));
>          fprintf(fp, "                      prb_desc: %ld\n", SIZE(prb_desc));
>   
> +       fprintf(fp, "                  sbitmap_word: %ld\n", SIZE(sbitmap_word));
> +       fprintf(fp, "                       sbitmap: %ld\n", SIZE(sbitmap));
> +       fprintf(fp, "                 sbitmap_queue: %ld\n", SIZE(sbitmap_queue));
> +       fprintf(fp, "                sbq_wait_state: %ld\n", SIZE(sbq_wait_state));
>   
>           fprintf(fp, "\n                   array_table:\n");
>          /*
Didn't notice this output. Thanks, added.
>>   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",
> s/sssociated/associated/
>
>> +"               \"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.",
> I'd like to change these to the crash style like this:
>
> "   -s struct  name of a C-code structure, that is stored in an array",
> "              associated 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",
> s/whit/with/
Fixed help and typos.
>
>> +"  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.
> Question:
> Would you like to change these copyright notices to yours?
> If you have a proper one, please let me know.
>
> e.g. in crash_target.c:
>   * Copyright (c) 2021 VMware, Inc.
Fixed copyright.
>
>> + *
>> + * 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;
> Question: Is "(start >= sc->depth)" correct here? Currently start is 
> always zero, though. 
I have a plan to add range options to dump data attached to the 
sbitmap_queue.
It will allow me to go through the bitmap from any index, not only first.
>
>> +
>> +	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;
> will remove these unused variables:
>
> $ make clean ; make warn
> ...
> sbitmap.c: In function ‘sbitmap_queue_show’:
> sbitmap.c:342:24: warning: unused variable ‘list_head_addr’ [-Wunused-variable]
>     ulong wait_cnt_addr, list_head_addr;
>                          ^~~~~~~~~~~~~~
> sbitmap.c:342:9: warning: unused variable ‘wait_cnt_addr’ [-Wunused-variable]
>     ulong wait_cnt_addr, list_head_addr;
>           ^~~~~~~~~~~~~
fixed
>
>> +		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);
>> +	}
> The error_flag can be removed and this block can be shortened,
> will change like this:
>
>          if (sd.flags & SBITMAPQ_DATA_FLAG_STRUCT_NAME) {
>                  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);
>                          FREEBUF(data_name);
>                  } else
>                          sd.data_size = STRUCT_SIZE(sd.data_name);
>
>                  if (sd.data_size <= 0)
>                          error(FATAL, "invalid data structure reference: %s\n", sd.data_name);
>          }
>
> Thanks,
> Kazu
Agree, It looks better. Fixed.
>> +
>> +	sbitmapq_init();
>> +
>> +	if (sd.flags & SBITMAPQ_DATA_FLAG_STRUCT_NAME)
>> +		sbitmap_queue_data_dump(&sd);
>> +	else
>> +		sbitmap_queue_dump(&sd);
>> +}
>> --
>> 2.25.1
>>
>>
>> --
>> Crash-utility mailing list
>> Crash-utility@xxxxxxxxxx
>> https://listman.redhat.com/mailman/listinfo/crash-utility
Thanks,
Sergey

--
Crash-utility mailing list
Crash-utility@xxxxxxxxxx
https://listman.redhat.com/mailman/listinfo/crash-utility




[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux