Re: [syzbot] [mm?] BUG: sleeping function called from invalid context in shmem_undo_range

From: Arjan van de Ven

Date: Thu Apr 23 2026 - 22:34:13 EST


This email is created by automation to help kernel developers
deal with a large volume of AI generated bug reports by decoding
oopses into more actionable information.


Decoded Backtrace

shmem_undo_range (mm/shmem.c:1108-1151) -- crash site
------------------------------------------------------
1108 static void shmem_undo_range(struct inode *inode, loff_t lstart,
1109 uoff_t lend, bool unfalloc)
1110 {
1111 struct address_space *mapping = inode->i_mapping;
1112 struct shmem_inode_info *info = SHMEM_I(inode);
1113 pgoff_t start = (lstart + PAGE_SIZE - 1) >> PAGE_SHIFT;
1114 pgoff_t end = (lend + 1) >> PAGE_SHIFT;
1115 struct folio_batch fbatch;
1116 pgoff_t indices[FOLIO_BATCH_SIZE];
1117 struct folio *folio;
1118 bool same_folio;
1119 long nr_swaps_freed = 0;
1120 pgoff_t index;
1121 int i;
...
1129 folio_batch_init(&fbatch);
1130 index = start;
1131 while (index < end && find_lock_entries(mapping, &index,
1132 end - 1, &fbatch, indices)) {
1133 for (i = 0; i < folio_batch_count(&fbatch); i++) {
1134 folio = fbatch.folios[i];
1135 if (xa_is_value(folio)) {
...
1143 }
1144 if (!unfalloc || !folio_test_uptodate(folio))
1145 truncate_inode_folio(mapping, folio);
1146 folio_unlock(folio);
1147 }
1148 folio_batch_remove_exceptionals(&fbatch);
1149 folio_batch_release(&fbatch);
1150 cond_resched(); /* <-- BUG fires here; RCU nest depth=1 */
1151 }

filename_unlinkat (fs/namei.c:5526-5587) -- top-level caller
-------------------------------------------------------------
5526 int filename_unlinkat(int dfd, struct filename *name)
5527 {
...
5545 error = mnt_want_write(path.mnt); /* lock #0 (sb_writers) */
5546 if (error)
5547 goto exit_path_put;
5548 retry_deleg:
5549 dentry = start_dirop(path.dentry, &last, lookup_flags);
...
5563 inode = dentry->d_inode;
5564 ihold(inode);
5565 error = security_path_unlink(&path, dentry);
5566 if (error)
5567 goto exit_end_dirop;
5568 error = vfs_unlink(mnt_idmap(path.mnt), path.dentry->d_inode,
5569 dentry, &delegated_inode);
5570 exit_end_dirop:
5571 end_dirop(dentry);
5572 iput(inode); /* triggers shmem_evict_inode -> shmem_undo_range */
...
5579 mnt_drop_write(path.mnt);
...
5587 }


Tentative Analysis

The crash is triggered by running rm(1) on a tmpfs/shmem file. The call
chain is:

sys_unlink -> filename_unlinkat -> iput -> iput_final -> evict
-> shmem_evict_inode -> shmem_truncate_range -> shmem_undo_range
-> cond_resched() <-- BUG fires here

At crash time, two locks are held (in acquisition order):

#0 sb_writers#5 -- acquired at filename_unlinkat+0x1ad
(fs/namei.c:5545 -- mnt_want_write)
#1 rcu_read_lock -- acquired at rcu_lock_acquire.constprop.0
(include/linux/rcupdate.h:300)

Lock #1 (rcu_read_lock) was acquired AFTER mnt_want_write (lock #0 is
always recorded first in the lockdep list) and before the iput() call
at line 5572. That window contains start_dirop(), security_path_unlink()
and vfs_unlink() (which calls fsnotify_unlink() and d_delete_notify() on
the success path).

On a PREEMPT(full) kernel, rcu_read_lock() increments
current->rcu_read_lock_nesting instead of disabling preemption.
cond_resched() -> __cond_resched() -> __might_resched() checks that
counter, finds it is 1 (not 0), and fires the BUG.

The same leaked rcu_read_lock persists all the way back to userspace
("lock held when returning to user space!"), and a timer interrupt
firing during the syscall produces a third warning:
"Voluntary context switch within RCU read-side critical section!"

All three messages are symptoms of a single rcu_read_lock() call that
is never matched by an rcu_read_unlock() somewhere between
mnt_want_write and iput in filename_unlinkat.


Potential Solution

Find the rcu_read_lock() call that is missing its matching
rcu_read_unlock() in the vfs_unlink() / fsnotify_unlink() /
d_delete_notify() code path. Adding a WARN_ON(rcu_read_lock_held())
to iput() (alongside the existing might_sleep() check) should produce
a backtrace pointing at the exact acquisition site on the next
reproduction.


More information

Oops-Analysis: http://oops.fenrus.org/reports/lkml/69eab803.a00a0220.17a17.004b.GAE_google.com/report.html
Assisted-by: GitHub Copilot:claude-sonnet-4.6 linux-kernel-oops-x86.