On kernels that contain commit 1008fe6dc36d ("block: remove the all_bdevs
list"), without the patch, the "kmem -i" option fails halfway with the
error message 'kmem: cannot resolve: "all_bdevs"'.

Signed-off-by: Kazuhito Hagio <k-hagio...@nec.com>
---
# sorry, resending this because I sent with inappropriate setting..

 defs.h    |  2 ++
 memory.c  | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 symbols.c |  4 ++++
 3 files changed, 64 insertions(+)

diff --git a/defs.h b/defs.h
index 17e98763362b..dfc09bc86618 100644
--- a/defs.h
+++ b/defs.h
@@ -2089,6 +2089,8 @@ struct offset_table {                    /* stash of 
commonly-used offsets */
        long size_class_size;
        long gendisk_private_data;
        long zram_table_entry;
+       long super_block_s_inodes;
+       long inode_i_sb_list;
 };
 
 struct size_table {         /* stash of commonly-used sizes */
diff --git a/memory.c b/memory.c
index 2bea1288251a..c951827162cb 100644
--- a/memory.c
+++ b/memory.c
@@ -252,6 +252,7 @@ static ulonglong get_vm_flags(char *);
 static void PG_reserved_flag_init(void);
 static void PG_slab_flag_init(void);
 static ulong nr_blockdev_pages(void);
+static ulong nr_blockdev_pages_v2(void);
 void sparse_mem_init(void);
 void dump_mem_sections(int);
 void dump_memory_blocks(int);
@@ -501,6 +502,9 @@ vm_init(void)
        if (INVALID_MEMBER(address_space_nrpages))
                MEMBER_OFFSET_INIT(address_space_nrpages, "address_space", 
"__nrpages");
 
+       MEMBER_OFFSET_INIT(super_block_s_inodes, "super_block", "s_inodes");
+       MEMBER_OFFSET_INIT(inode_i_sb_list, "inode", "i_sb_list");
+
        MEMBER_OFFSET_INIT(gendisk_major, "gendisk", "major");
        MEMBER_OFFSET_INIT(gendisk_fops, "gendisk", "fops");
        MEMBER_OFFSET_INIT(gendisk_disk_name, "gendisk", "disk_name");
@@ -8608,6 +8612,9 @@ nr_blockdev_pages(void)
        ulong nrpages;
        char *block_device_buf, *inode_buf, *address_space_buf;
 
+       if (!kernel_symbol_exists("all_bdevs"))
+               return nr_blockdev_pages_v2();
+
         ld = &list_data;
         BZERO(ld, sizeof(struct list_data));
        get_symbol_data("all_bdevs", sizeof(void *), &ld->start);
@@ -8652,6 +8659,57 @@ nr_blockdev_pages(void)
 } 
 
 /*
+ *  Emulate 5.9 nr_blockdev_pages() function.
+ */
+static ulong
+nr_blockdev_pages_v2(void)
+{
+       struct list_data list_data, *ld;
+       ulong bd_sb, address_space;
+       ulong nrpages;
+       int i, inode_count;
+       char *inode_buf, *address_space_buf;
+
+       ld = &list_data;
+       BZERO(ld, sizeof(struct list_data));
+
+       get_symbol_data("blockdev_superblock", sizeof(void *), &bd_sb);
+       readmem(bd_sb + OFFSET(super_block_s_inodes), KVADDR, &ld->start,
+               sizeof(ulong), "blockdev_superblock.s_inodes", FAULT_ON_ERROR);
+
+       if (empty_list(ld->start))
+               return 0;
+       ld->flags |= LIST_ALLOCATE;
+       ld->end = bd_sb + OFFSET(super_block_s_inodes);
+       ld->list_head_offset = OFFSET(inode_i_sb_list);
+
+       inode_buf = GETBUF(SIZE(inode));
+       address_space_buf = GETBUF(SIZE(address_space));
+
+       inode_count = do_list(ld);
+
+       /*
+        *  go through the s_inodes list, emulating:
+        *
+        *      ret += inode->i_mapping->nrpages;
+        */
+       for (i = nrpages = 0; i < inode_count; i++) {
+               readmem(ld->list_ptr[i], KVADDR, inode_buf, SIZE(inode), "inode 
buffer",
+                       FAULT_ON_ERROR);
+               address_space = ULONG(inode_buf + OFFSET(inode_i_mapping));
+               readmem(address_space, KVADDR, address_space_buf, 
SIZE(address_space),
+                       "address_space buffer", FAULT_ON_ERROR);
+               nrpages += ULONG(address_space_buf + 
OFFSET(address_space_nrpages));
+       }
+
+       FREEBUF(ld->list_ptr);
+       FREEBUF(inode_buf);
+       FREEBUF(address_space_buf);
+
+       return nrpages;
+}
+
+/*
  *  dump_vmlist() displays information from the vmlist.
  */
 
diff --git a/symbols.c b/symbols.c
index 2fecaee093a2..123ed00913e1 100644
--- a/symbols.c
+++ b/symbols.c
@@ -9452,6 +9452,8 @@ dump_offset_table(char *spec, ulong makestruct)
                OFFSET(inode_i_fop)); 
        fprintf(fp, "               inode_i_mapping: %ld\n",
                OFFSET(inode_i_mapping));
+       fprintf(fp, "               inode_i_sb_list: %ld\n",
+               OFFSET(inode_i_sb_list));
 
         fprintf(fp, "             vfsmount_mnt_next: %ld\n", 
                OFFSET(vfsmount_mnt_next));
@@ -9488,6 +9490,8 @@ dump_offset_table(char *spec, ulong makestruct)
                OFFSET(super_block_s_type));
         fprintf(fp, "           super_block_s_files: %ld\n", 
                OFFSET(super_block_s_files));
+       fprintf(fp, "          super_block_s_inodes: %ld\n",
+               OFFSET(super_block_s_inodes));
 
        fprintf(fp, "               nlm_file_f_file: %ld\n",
                OFFSET(nlm_file_f_file));
-- 
1.8.3.1


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

Reply via email to