mirror of https://github.com/crash-utility/crash
Fix "kmem -i" and "swap" commands on Linux 6.10-rc1 and later kernels
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. Tested-by: Li Zhijian <lizhijian@fujitsu.com> Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
This commit is contained in:
parent
196c4b79c1
commit
3452fe802b
1
defs.h
1
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 */
|
||||
|
|
|
@ -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)) {
|
||||
|
|
28
memory.c
28
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),
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in New Issue