On 11/06/2024 10:40, HAGIO KAZUHITO(萩尾 一仁) wrote: > Kernel commit 798cb7f9aec3 ("swapon(2)/swapoff(2): don't bother with > block size") removed swap_info_struct.old_block_size member at Linux > 6.10-rc1. The crash-utility has used this to determine whether a swap > is a partition or file and to determine the way to get the swap path. > > Withtout the patch, the "kmem -i" and "swap" commands fail with the > following error messsage: > > crash> kmem -i > ... > TOTAL HUGE 13179392 50.3 GB ---- > HUGE FREE 13179392 50.3 GB 100% of TOTAL HUGE > > swap: invalid (optional) structure member offsets: swap_info_struct_swap_device or swap_info_struct_old_block_size > FILE: memory.c LINE: 16032 FUNCTION: dump_swap_info() > > The swap_file member of recent swap_info_struct is a pointer to a > struct file (once upon a time it was dentry), use this fact directly. > > Signed-off-by: Kazuhito Hagio <k-hagio-ab@xxxxxxx> Thanks for the fix. It works for me. Feel free to add Tested-by: Li Zhijian <lizhijian@xxxxxxxxxxx> > --- > NOTE: This patch can be applied on top of my '[PATCH] Fix "kmem -v" > option on Linux 6.9 and later kernels' patch. Otherwise, please adjust > the hunk for offset_table. > > defs.h | 1 + > filesys.c | 1 + > memory.c | 28 +++++++++++++++++++++++----- > symbols.c | 1 + > 4 files changed, 26 insertions(+), 5 deletions(-) > > diff --git a/defs.h b/defs.h > index 95de33188070..64bf785b7a1b 100644 > --- a/defs.h > +++ b/defs.h > @@ -2242,6 +2242,7 @@ struct offset_table { /* stash of commonly-used offsets */ > long log_caller_id; > long vmap_node_busy; > long rb_list_head; > + long file_f_inode; > }; > > struct size_table { /* stash of commonly-used sizes */ > diff --git a/filesys.c b/filesys.c > index 81fe856699e1..406ebb299780 100644 > --- a/filesys.c > +++ b/filesys.c > @@ -2038,6 +2038,7 @@ vfs_init(void) > MEMBER_OFFSET_INIT(file_f_dentry, "file", "f_dentry"); > MEMBER_OFFSET_INIT(file_f_vfsmnt, "file", "f_vfsmnt"); > MEMBER_OFFSET_INIT(file_f_count, "file", "f_count"); > + MEMBER_OFFSET_INIT(file_f_inode, "file", "f_inode"); > MEMBER_OFFSET_INIT(path_mnt, "path", "mnt"); > MEMBER_OFFSET_INIT(path_dentry, "path", "dentry"); > if (INVALID_MEMBER(file_f_dentry)) { > diff --git a/memory.c b/memory.c > index acb8507cfb75..28f901f16adf 100644 > --- a/memory.c > +++ b/memory.c > @@ -16075,6 +16075,8 @@ dump_swap_info(ulong swapflags, ulong *totalswap_pages, ulong *totalused_pages) > char buf3[BUFSIZE]; > char buf4[BUFSIZE]; > char buf5[BUFSIZE]; > + int swap_file_is_file = > + STREQ(MEMBER_TYPE_NAME("swap_info_struct", "swap_file"), "file"); > > if (!symbol_exists("nr_swapfiles")) > error(FATAL, "nr_swapfiles doesn't exist in this kernel!\n"); > @@ -16118,9 +16120,21 @@ dump_swap_info(ulong swapflags, ulong *totalswap_pages, ulong *totalused_pages) > swap_file = ULONG(vt->swap_info_struct + > OFFSET(swap_info_struct_swap_file)); > > - swap_device = INT(vt->swap_info_struct + > - OFFSET_OPTION(swap_info_struct_swap_device, > - swap_info_struct_old_block_size)); > + /* Linux 6.10 and later */ > + if (INVALID_MEMBER(swap_info_struct_swap_device) && > + INVALID_MEMBER(swap_info_struct_old_block_size) && > + swap_file_is_file) { > + ulong inode; > + ushort mode; > + readmem(swap_file + OFFSET(file_f_inode), KVADDR, &inode, > + sizeof(ulong), "swap_file.f_inode", FAULT_ON_ERROR); > + readmem(inode + OFFSET(inode_i_mode), KVADDR, &mode, > + sizeof(ushort), "inode.i_mode", FAULT_ON_ERROR); > + swap_device = S_ISBLK(mode); > + } else > + swap_device = INT(vt->swap_info_struct + > + OFFSET_OPTION(swap_info_struct_swap_device, > + swap_info_struct_old_block_size)); > > pages = INT(vt->swap_info_struct + > OFFSET(swap_info_struct_pages)); > @@ -16161,8 +16175,12 @@ dump_swap_info(ulong swapflags, ulong *totalswap_pages, ulong *totalused_pages) > OFFSET(swap_info_struct_swap_vfsmnt)); > get_pathname(swap_file, buf, BUFSIZE, > 1, vfsmnt); > - } else if (VALID_MEMBER > - (swap_info_struct_old_block_size)) { > + } else if (VALID_MEMBER(swap_info_struct_old_block_size) || > + swap_file_is_file) { > + /* > + * Linux 6.10 and later kernels do not have old_block_size, > + * but this still should work, if swap_file is file. > + */ > devname = vfsmount_devname(file_to_vfsmnt(swap_file), > buf1, BUFSIZE); > get_pathname(file_to_dentry(swap_file), > diff --git a/symbols.c b/symbols.c > index 283b98a8fbfe..0bf050ab62d0 100644 > --- a/symbols.c > +++ b/symbols.c > @@ -10522,6 +10522,7 @@ dump_offset_table(char *spec, ulong makestruct) > OFFSET(file_f_count)); > fprintf(fp, " file_f_path: %ld\n", > OFFSET(file_f_path)); > + fprintf(fp, " file_f_inode: %ld\n", OFFSET(file_f_inode)); > fprintf(fp, " path_mnt: %ld\n", > OFFSET(path_mnt)); > fprintf(fp, " path_dentry: %ld\n", -- Crash-utility mailing list -- devel@xxxxxxxxxxxxxxxxxxxxxxxxxxx To unsubscribe send an email to devel-leave@xxxxxxxxxxxxxxxxxxxxxxxxxxx https://${domain_name}/admin/lists/devel.lists.crash-utility.osci.io/ Contribution Guidelines: https://github.com/crash-utility/crash/wiki