CEE reported an issue that "dev -d/-D" reports incorrect value
of read/write:
crash> dev -d
MAJOR GENDISK NAME REQUEST_QUEUE TOTAL ASYNC SYNC
8 ffff90528df86000 sda ffff9052a3d61800 144 144 0
8 ffff905280718c00 sdb ffff9052a3d63c00 48 48 0
crash> epython rqlist
ffff90528e94a5c0 sda is unknown, deadline: 89.992 (90) rq_alloc: 0.196
ffff90528e92f700 sda is unknown, deadline: 89.998 (90) rq_alloc: 0.202
ffff90528e95ccc0 sda is unknown, deadline: 89.999 (90) rq_alloc: 0.203
ffff90528e968bc0 sdb is unknown, deadline: 89.997 (90) rq_alloc: 0.201
The value of 144 ASYNC is incorrect and epython rqlist only show 3 items for sda.
The reason is, mq_check_inflight() may get the same rq multiple times during
iteration, so they are counted repeatly.
This patch will add a rq repetition check. After apply the patch:
crash> dev -d
MAJOR GENDISK NAME REQUEST_QUEUE TOTAL READ WRITE
8 ffff90528df86000 sda ffff9052a3d61800 3 3 0
8 ffff905280718c00 sdb ffff9052a3d63c00 1 1 0
Signed-off-by: Tao Liu <ltao(a)redhat.com>
---
dev.c | 43 ++++++++++++++++++++++++++++++++++++++++---
1 file changed, 40 insertions(+), 3 deletions(-)
diff --git a/dev.c b/dev.c
index 9d38aef..b0434cf 100644
--- a/dev.c
+++ b/dev.c
@@ -4316,6 +4316,9 @@ struct bt_iter_data {
ulong tags;
uint reserved;
uint nr_reserved_tags;
+ ulong **rq_list;
+ int *rq_list_len;
+ int *rq_list_cap;
busy_tag_iter_fn *fn;
void *data;
};
@@ -4381,10 +4384,30 @@ static bool bt_iter(uint bitnr, void *data)
if (!readmem(addr, KVADDR, &rq, sizeof(ulong), "blk_mq_tags.rqs[]",
RETURN_ON_ERROR))
return FALSE;
+ for (int i = 0; i < *iter_data->rq_list_len; i++) {
+ /* Skip the handled rq */
+ if ((*iter_data->rq_list)[i] == rq)
+ return TRUE;
+ }
+ /* Mark the rq is handled */
+ (*iter_data->rq_list)[(*iter_data->rq_list_len)++] = rq;
+ if (*iter_data->rq_list_len > *iter_data->rq_list_cap / 2) {
+ *iter_data->rq_list_cap <<= 1;
+ ulong *tmp = reallocarray(*iter_data->rq_list,
+ *iter_data->rq_list_cap, sizeof(ulong));
+ if (!tmp) {
+ free(*iter_data->rq_list);
+ error(FATAL, "cannot reallocarray rq_list array");
+ }
+ *iter_data->rq_list = tmp;
+ }
+
return iter_data->fn(rq, iter_data->data);
}
-static void bt_for_each(ulong q, ulong tags, ulong sbq, uint reserved, uint
nr_resvd_tags, struct diskio *dio)
+static void bt_for_each(ulong q, ulong tags, ulong sbq, uint reserved,
+ uint nr_resvd_tags, ulong **rq_list, int *rq_list_len,
+ int *rq_list_cap, struct diskio *dio)
{
struct sbitmap_context sc = {0};
struct mq_inflight mi = {
@@ -4395,6 +4418,9 @@ static void bt_for_each(ulong q, ulong tags, ulong sbq, uint
reserved, uint nr_r
.tags = tags,
.reserved = reserved,
.nr_reserved_tags = nr_resvd_tags,
+ .rq_list = rq_list,
+ .rq_list_len = rq_list_len,
+ .rq_list_cap = rq_list_cap,
.fn = mq_check_inflight,
.data = &mi,
};
@@ -4407,10 +4433,18 @@ static void queue_for_each_hw_ctx(ulong q, ulong *hctx, uint cnt,
struct diskio
{
uint i;
int bitmap_tags_is_ptr = 0;
+ ulong *rq_list;
+ int rq_list_len = 0;
+ int rq_list_cap = 1;
if (MEMBER_TYPE("blk_mq_tags", "bitmap_tags") == TYPE_CODE_PTR)
bitmap_tags_is_ptr = 1;
+ rq_list = calloc(rq_list_cap, sizeof(ulong));
+ if (!rq_list) {
+ error(FATAL, "cannot malloc rq_list array");
+ }
+
for (i = 0; i < cnt; i++) {
ulong addr = 0, tags = 0;
uint nr_reserved_tags = 0;
@@ -4432,15 +4466,18 @@ static void queue_for_each_hw_ctx(ulong q, ulong *hctx, uint cnt,
struct diskio
!readmem(addr, KVADDR, &addr, sizeof(ulong),
"blk_mq_tags.bitmap_tags", RETURN_ON_ERROR))
break;
- bt_for_each(q, tags, addr, 1, nr_reserved_tags, dio);
+ bt_for_each(q, tags, addr, 1, nr_reserved_tags, &rq_list,
+ &rq_list_len, &rq_list_cap, dio);
}
addr = tags + OFFSET(blk_mq_tags_bitmap_tags);
if (bitmap_tags_is_ptr &&
!readmem(addr, KVADDR, &addr, sizeof(ulong),
"blk_mq_tags.bitmap_tags", RETURN_ON_ERROR))
break;
- bt_for_each(q, tags, addr, 0, nr_reserved_tags, dio);
+ bt_for_each(q, tags, addr, 1, nr_reserved_tags, &rq_list,
+ &rq_list_len, &rq_list_cap, dio);
}
+ free(rq_list);
}
static void get_mq_diskio_from_hw_queues(ulong q, struct diskio *dio)
--
2.47.0