Kernel commit 4e5cc99e1e48 ("blk-mq: manage hctx map via xarray") removed
the "queue_hw_ctx" member from struct request_queue at Linux v5.18-rc1,
and replaced it with a struct xarray "hctx_table".Without the patch,
the "dev -d|-D" options will print an error:

  crash> dev -d
  MAJOR GENDISK            NAME       REQUEST_QUEUE      TOTAL  READ WRITE

  dev: invalid structure member offset: request_queue_queue_hw_ctx

With the patch:
  crash> dev -d
  MAJOR GENDISK            NAME       REQUEST_QUEUE      TOTAL  READ WRITE
      8 ffff892147e4ae00   sda        ffff8922c891aa80     240   135   105

Signed-off-by: Lianbo Jiang <[email protected]>
---
 defs.h    |  1 +
 dev.c     | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 symbols.c |  2 ++
 3 files changed, 74 insertions(+)

diff --git a/defs.h b/defs.h
index f3c05fb44e62..fa49e9bdf767 100644
--- a/defs.h
+++ b/defs.h
@@ -2180,6 +2180,7 @@ struct offset_table {                    /* stash of 
commonly-used offsets */
        long blk_mq_tags_nr_tags;
        long blk_mq_tags_rqs;
        long blk_mq_tags_static_rqs;
+       long request_queue_hctx_table;
 };
 
 struct size_table {         /* stash of commonly-used sizes */
diff --git a/dev.c b/dev.c
index 4d574f06494f..64caaf4bd88d 100644
--- a/dev.c
+++ b/dev.c
@@ -4369,12 +4369,81 @@ sbitmap_word_buf_free:
        FREEBUF(sbitmap_word_buf);
 }
 
+static void get_used_tags(unsigned long q, struct diskio *io_counts)
+{
+       unsigned long addr = 0;
+       unsigned long cnt = 0, i = 0;
+       struct list_pair *lp = NULL;
+
+       addr = q + OFFSET(request_queue_hctx_table);
+       cnt = do_xarray(addr, XARRAY_COUNT, NULL);
+       lp = (struct list_pair *)GETBUF(sizeof(struct list_pair) * (cnt + 1));
+       if (!lp)
+               error(FATAL, "fail to get memory for list_pair.\n");
+
+       lp[0].index = cnt;
+       cnt = do_xarray(addr, XARRAY_GATHER, lp);
+       for (i = 0; i < cnt; i++) {
+               ulong tags = 0, sched_tags = 0;
+               unsigned long *rqs = NULL, *static_rqs = NULL;
+               struct blk_mq_tags_context tags_ctx = {0};
+               struct blk_mq_tags_context sched_tags_ctx = {0};
+
+               if(!IS_KVADDR((ulong)lp[i].value))
+                       continue;
+
+               addr = (ulong)lp[i].value + OFFSET(blk_mq_hw_ctx_tags);
+               if (!readmem(addr, KVADDR, &tags, sizeof(ulong),
+                               "blk_mq_hw_ctx.tags", RETURN_ON_ERROR))
+                       goto lp_free;
+
+               addr = (ulong)lp[i].value + OFFSET(blk_mq_hw_ctx_sched_tags);
+               if (!readmem(addr, KVADDR, &sched_tags, sizeof(ulong),
+                               "blk_mq_hw_ctx.sched_tags", RETURN_ON_ERROR))
+                       goto lp_free;
+
+               if (IS_KVADDR(tags)) {
+                       load_blk_mq_tags_context(tags, &tags_ctx);
+                       load_blk_mq_rqs(tags_ctx.rqs, tags_ctx.nr_tags, &rqs);
+                       if (!rqs)
+                               goto next;
+                       find_mq_diskio_by_parsing_bitmap(q, 
tags_ctx.breserved_tags, 0, rqs, &io_counts);
+                       find_mq_diskio_by_parsing_bitmap(q, 
tags_ctx.bitmap_tags, tags_ctx.nr_reserved_tags,
+                                                       rqs, &io_counts);
+                       FREEBUF(rqs);
+               }
+       next:
+               if (IS_KVADDR(sched_tags)) {
+                       load_blk_mq_tags_context(sched_tags, &sched_tags_ctx);
+                       load_blk_mq_rqs(sched_tags_ctx.static_rqs, 
sched_tags_ctx.nr_tags, &static_rqs);
+                       if (!static_rqs)
+                               continue;
+                       find_mq_diskio_by_parsing_bitmap(q, 
sched_tags_ctx.breserved_tags, 0, static_rqs, &io_counts);
+                       find_mq_diskio_by_parsing_bitmap(q, 
sched_tags_ctx.bitmap_tags, sched_tags_ctx.nr_reserved_tags,
+                                                       static_rqs, &io_counts);
+                       FREEBUF(static_rqs);
+               }
+       }
+
+lp_free:
+       FREEBUF(lp);
+}
+
 static void get_mq_diskio_from_hw_queues(unsigned long q, struct diskio 
*io_counts)
 {
        unsigned long *queue_hw_ctx = NULL;
        unsigned long addr = 0;
        unsigned int i, nr_hw_queues;
 
+       if (MEMBER_EXISTS("request_queue", "hctx_table")) {
+               struct diskio tmp = {0};
+
+               get_used_tags(q, &tmp);
+               io_counts->read = tmp.read;
+               io_counts->write = tmp.write;
+               return;
+       }
+
        addr = q + OFFSET(request_queue_nr_hw_queues);
        readmem(addr, KVADDR, &nr_hw_queues, sizeof(uint),
                "request_queue.nr_hw_queues", FAULT_ON_ERROR);
@@ -4804,6 +4873,8 @@ void diskio_init(void)
                        "request_queue", "queue_hw_ctx");
                MEMBER_OFFSET_INIT(request_queue_nr_hw_queues,
                        "request_queue", "nr_hw_queues");
+               MEMBER_OFFSET_INIT(request_queue_hctx_table,
+                               "request_queue", "hctx_table");
                MEMBER_OFFSET_INIT(blk_mq_ctx_rq_dispatched, "blk_mq_ctx",
                        "rq_dispatched");
                MEMBER_OFFSET_INIT(blk_mq_ctx_rq_completed, "blk_mq_ctx",
diff --git a/symbols.c b/symbols.c
index 0612255b6e34..e1d8320c48bb 100644
--- a/symbols.c
+++ b/symbols.c
@@ -10401,6 +10401,8 @@ dump_offset_table(char *spec, ulong makestruct)
                OFFSET(request_queue_queue_hw_ctx));
        fprintf(fp, "       request_queue_nr_hw_queues: %ld\n",
                OFFSET(request_queue_nr_hw_queues));
+       fprintf(fp, "       request_queue_hctx_table: %ld\n",
+               OFFSET(request_queue_hctx_table));
        fprintf(fp, "      blk_mq_ctx_rq_dispatched: %ld\n",
                OFFSET(blk_mq_ctx_rq_dispatched));
        fprintf(fp, "       blk_mq_ctx_rq_completed: %ld\n",
-- 
2.20.1

--
Crash-utility mailing list
[email protected]
https://listman.redhat.com/mailman/listinfo/crash-utility
Contribution Guidelines: https://github.com/crash-utility/crash/wiki

Reply via email to