In the Linux kernel, the following vulnerability has been resolved: vfs: fix race between eviceinodes() and findinode()&iput() Hi, all Recently I noticed a bug[1] in btrfs, after digged it into and I believe it'a race in vfs. Let's assume there's a inode (ie ino 261) with icount 1 is called by iput(), and there's a concurrent thread calling genericshutdownsuper(). cpu0: cpu1: iput() // icount is 1 ->spinlock(inode) ->dec icount to 0 ->iputfinal() genericshutdownsuper() ->inodeaddlru() ->evictinodes() // cause some reason[2] ->if (atomicread(inode->icount)) continue; // return before // inode 261 passed the above check // listlruaddobj() // and then schedule out ->spinunlock() // note here: the inode 261 // was still at sb list and hash list, // and IFREEING|IWILLFREE was not been set btrfsiget() // after some function calls ->findinode() // found the above inode 261 ->spinlock(inode) // check IFREEING|IWILLFREE // and passed ->iget() ->spinunlock(inode) // schedule back ->spinlock(inode) // check (INEW|IFREEING|IWILLFREE) flags, // passed and set IFREEING iput() ->spinunlock(inode) ->spinlock(inode) ->evict() // dec icount to 0 ->iputfinal() ->spinunlock() ->evict() Now, we have two threads simultaneously evicting the same inode, which may trigger the BUG(inode->istate & ICLEAR) statement both within clearinode() and iput(). To fix the bug, recheck the inode->icount after holding ilock. Because in the most scenarios, the first check is valid, and the overhead of spinlock() can be reduced. If there is any misunderstanding, please let me know, thanks. [1]: https://lore.kernel.org/linux-btrfs/000000000000eabe1d0619c48986@google.com/ [2]: The reason might be 1. SBACTIVE was removed or 2. mapping_shrinkable() return false when I reproduced the bug.