[RFC PATCH 0/3] fs/proc: split the inode list for procfs

Huang Shijie posted 3 patches 1 week, 4 days ago
There is a newer version of this series
fs/drop_caches.c               |  4 ++
fs/inode.c                     | 80 ++++++++++++++++++++++------------
fs/proc/inode.c                | 53 ++++++++++++++++++++++
fs/proc/internal.h             |  2 +
fs/proc/root.c                 |  6 +++
fs/super.c                     | 45 +++++++++++++++----
include/linux/fs/super_types.h | 22 +++++++++-
include/linux/proc_fs.h        |  1 +
8 files changed, 176 insertions(+), 37 deletions(-)
[RFC PATCH 0/3] fs/proc: split the inode list for procfs
Posted by Huang Shijie 1 week, 4 days ago
The global s_inode_list_lock is heavily contended in procfs
on a 384-CPU, 12-NUMA-node Hygon machine running Hadoop TestDFSIO:
  #hadoop jar xxxx.jar TestDFSIO -read -nrFiles 1000 -size 100MB

The hadoop will create lot of threads during the test.
The perf shows it consuming ~90% of the lock hotspot in procfs.
The lock is hit from both directions:
   -- inode creation (~49%) :
           getdents64 ->
              proc_readfd_common ->
	         new_inode ->
		   inode_sb_list_add()

   -- inode eviction (~41%):
           process exit ->
	      release_task ->
	         proc_invalidate_siblings_dcache ->
		     evict ->
		        inode_sb_list_del()

This patch set tries to resolve this issue by:
    patch 1: "fs/drop_caches: do not scan procfs in drop_pagecache_sb()"
       This patch skips the scan for procfs in drop caches.

    patch 2: Add a new helper to detect the empty inode list    

    patch 3: split the inode list.


After this patch, the above TestDFSIO can get over 50% better performance
in exec time. And the procfs lock hotspot becomes nearly 1%.

Huang Shijie (3):
  fs/drop_caches: do not scan procfs in drop_pagecache_sb()
  fs/super: introduce a helper sb_inodes_empty()
  fs/proc: split the inode list

 fs/drop_caches.c               |  4 ++
 fs/inode.c                     | 80 ++++++++++++++++++++++------------
 fs/proc/inode.c                | 53 ++++++++++++++++++++++
 fs/proc/internal.h             |  2 +
 fs/proc/root.c                 |  6 +++
 fs/super.c                     | 45 +++++++++++++++----
 include/linux/fs/super_types.h | 22 +++++++++-
 include/linux/proc_fs.h        |  1 +
 8 files changed, 176 insertions(+), 37 deletions(-)

-- 
2.53.0
[syzbot ci] Re: fs/proc: split the inode list for procfs
Posted by syzbot ci 1 week, 4 days ago
syzbot ci has tested the following series

[v1] fs/proc: split the inode list for procfs
https://lore.kernel.org/all/20260914061449.4024632-1-huangsj@hygon.cn
* [RFC PATCH 1/3] fs/drop_caches: do not scan procfs in drop_pagecache_sb()
* [RFC PATCH 2/3] fs/super: introduce a helper sb_inodes_empty()
* [RFC PATCH 3/3] fs/proc: split the inode list

and found the following issue:
KASAN: slab-out-of-bounds Read in hook_sb_delete

Full report is available here:
https://ci.syzbot.org/series/736afa16-0dc2-40e7-9a6c-74db419044d7

***

KASAN: slab-out-of-bounds Read in hook_sb_delete

tree:      vfs
URL:       https://kernel.googlesource.com/pub/scm/linux/kernel/git/vfs/vfs.git
base:      15aa70de9f706fb0e3852f636b8a0a9d5bc048ab
arch:      amd64
compiler:  Debian clang version 22.1.8 (++20260613092233+e80beda6e255-1~exp1~20260613092250.77), Debian LLD 22.1.8
config:    https://ci.syzbot.org/builds/cd4bf6c8-aad6-4b38-b003-31dcd0a8a4bf/config

ima: No TPM chip found, activating TPM-bypass!
Loading compiled-in module X.509 certificates
Loaded X.509 cert 'Build time autogenerated kernel key: affe42cfbb2369724f6c4c4a3fe3f0b2fe4692dc'
ima: Allocated hash algorithm: sha256
ima: No architecture policies found
evm: Initialising EVM extended attributes:
evm: security.selinux (disabled)
evm: security.SMACK64 (disabled)
evm: security.SMACK64EXEC (disabled)
evm: security.SMACK64TRANSMUTE (disabled)
evm: security.SMACK64MMAP (disabled)
evm: security.apparmor
evm: security.ima
evm: security.capability
evm: HMAC attrs: 0x1
PM:   Magic number: 10:739:371
usb usb44-port5: hash matches
udc dummy_udc.27: hash matches
dummy_udc dummy_udc.27: hash matches
usb usb12-port1: hash matches
netconsole: network logging started
gtp: GTP module loaded (pdp ctx size 128 bytes)
rdma_rxe: loaded
cfg80211: Loading compiled-in X.509 certificates for regulatory database
Loaded X.509 cert 'sforshee: 00b28ddf47aef9cea7'
Loaded X.509 cert 'wens: 61c038651aabdcf94bd0ac7ff06c7248db18c600'
clk: Disabling unused clocks
ALSA device list:
  #0: Dummy 1
  #1: Loopback 1
  #2: Virtual MIDI Card 1
md: Waiting for all devices to be available before autodetect
md: If you don't use raid, use raid=noautodetect
md: Autodetecting RAID arrays.
md: autorun ...
md: ... autorun DONE.
EXT4-fs (sda1): mounted filesystem b4773fba-1738-4da0-8a90-0fe043d0a496 ro with ordered data mode. Quota mode: none.
VFS: Mounted root (ext4 filesystem) readonly on device 8:1.
devtmpfs: mounted
VFS: Pivoted into new rootfs
Freeing unused kernel image (initmem) memory: 27172K
Write protecting the kernel read-only data: 223232k
Freeing unused kernel image (text/rodata gap) memory: 1552K
Freeing unused kernel image (rodata/data gap) memory: 804K
x86/mm: Checked W+X mappings: passed, no W+X pages found.
x86/mm: Checking user space page tables
x86/mm: Checked W+X mappings: passed, no W+X pages found.
Failed to set sysctl parameter 'max_rcu_stall_to_panic=1': parameter not found
Run /sbin/init as init process
==================================================================
BUG: KASAN: slab-out-of-bounds in _raw_spin_lock+0x2e/0x40
Read of size 1 at addr ffff88810eea9ce0 by task init/1

CPU: 0 UID: 0 PID: 1 Comm: init Not tainted syzkaller #0 PREEMPT(full) 
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
Call Trace:
 <TASK>
 dump_stack_lvl+0xe8/0x150
 print_address_description+0x55/0x1e0
 print_report+0x58/0x70
 kasan_report+0x117/0x150
 __kasan_check_byte+0x2a/0x40
 lock_acquire+0x7d/0x350
 _raw_spin_lock+0x2e/0x40
 hook_sb_delete+0x15d/0xd10
 security_sb_delete+0x76/0x110
 generic_shutdown_super+0xb2/0x3d0
 kill_anon_super+0x3b/0x70
 proc_kill_sb+0x47/0x180
 deactivate_locked_super+0xbc/0x110
 cleanup_mnt+0x3d3/0x460
 mntput_no_expire_slowpath+0xa58/0xbf0
 __fput+0x6a4/0xa50
 task_work_run+0x1d9/0x270
 exit_to_user_mode_loop+0x204/0x770
 ret_from_fork+0x593/0xb70
 ret_from_fork_asm+0x1a/0x30
 </TASK>

Allocated by task 1:
 kasan_save_track+0x3e/0x80
 __kasan_kmalloc+0x93/0xb0
 __kmalloc_flags_noprof+0x532/0x7a0
 __alloc_empty_sheaf+0x28/0x40
 __pcs_replace_empty_main+0x43b/0x6c0
 kmem_cache_alloc_noprof+0x399/0x600
 bio_alloc_bioset+0x271/0xc60
 ext4_mpage_readpages+0x12a7/0x1c40
 read_pages+0x193/0x5a0
 page_cache_ra_unbounded+0x754/0x9d0
 page_cache_ra_order+0xb47/0xee0
 filemap_get_pages+0x86d/0x1ec0
 filemap_read+0x426/0x11e0
 ext4_file_read_iter+0x553/0xad0
 __kernel_read+0x4ca/0x960
 integrity_kernel_read+0x89/0xd0
 ima_calc_file_hash+0x451/0x890
 ima_collect_measurement+0x51b/0xa00
 process_measurement+0x1272/0x1c10
 ima_file_mmap+0x1b0/0x200
 security_mmap_file+0x773/0xa20
 vm_mmap_pgoff+0x134/0x4e0
 elf_load+0x237/0x6a0
 load_elf_interp+0x4da/0xb50
 load_elf_binary+0x1bda/0x28d0
 bprm_execve+0x930/0x1590
 kernel_execve+0x8c3/0x9c0
 try_to_run_init_process+0x13/0x60
 kernel_init+0xb2/0x1d0
 ret_from_fork+0x514/0xb70
 ret_from_fork_asm+0x1a/0x30

The buggy address belongs to the object at ffff88810eea9c00
 which belongs to the cache kmalloc-128 of size 128
The buggy address is located 96 bytes to the right of
 allocated 128-byte region [ffff88810eea9c00, ffff88810eea9c80)

The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x10eea9
flags: 0x17ff00000000000(node=0|zone=2|lastcpupid=0x7ff)
page_type: f5(slab)
raw: 017ff00000000000 ffff888100041a00 dead000000000122 0000000000000000
raw: 0000000000000000 0000000000100010 00000000f5000000 0000000000000000
page dumped because: kasan: bad access detected
page_owner tracks the page as allocated
page last allocated via order 0, migratetype Unmovable, gfp_mask 0xd2c40(GFP_NOFS|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC), pid 1, tgid 1 (swapper/0), ts 18944299736
 post_alloc_hook+0x1f9/0x250
 get_page_from_freelist+0x2209/0x2280
 __alloc_frozen_pages_noprof+0x217/0x5a0
 allocate_slab+0x7d/0x620
 refill_objects+0x2d5/0x350
 __pcs_replace_empty_main+0x2c8/0x6c0
 __kmalloc_noprof+0x47b/0x720
 tomoyo_commit_ok+0x29/0x1d0
 tomoyo_update_domain+0x4ea/0x7e0
 tomoyo_update_mount_acl+0x11c/0x2d0
 tomoyo_write_file+0xae4/0xc50
 tomoyo_supervisor+0xff8/0x1560
 tomoyo_mount_permission+0x670/0x9e0
 security_sb_mount+0xe4/0x320
 path_mount+0xbc/0x1050
 init_mount+0xc3/0x110
page_owner free stack trace missing

Memory state around the buggy address:
 ffff88810eea9b80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
 ffff88810eea9c00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>ffff88810eea9c80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
                                                       ^
 ffff88810eea9d00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 ffff88810eea9d80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
==================================================================


***

If these findings have caused you to resend the series or submit a
separate fix, please add the following tag to your commit message:
  Tested-by: syzbot@syzkaller.appspotmail.com

---
This report is generated by a bot. It may contain errors.
syzbot ci engineers can be reached at syzkaller@googlegroups.com.

To test a fix for this bug, please reply with `#syz test`
(on a separate line) and attach the patch to the email.

Notes:
- The patch will be applied on top of the tested series (as an
  incremental fix).
- To test a new version of the whole series, please send it directly
  to syzbot@lists.linux.dev.
- Arguments like custom git repos and branches are not supported.