mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
fs: don't lose inodes that another LRU walker is isolating
When inode_lru_isolate() finds an unused inode that still has page cache, it sets I_LRU_ISOLATING, drops i_lock and the list_lru lock, invalidates the page cache, clears the flag again and returns LRU_RETRY so that the restarted walk can free the inode. Another walker of the same list can reach the inode in that window. It sees a non-zero i_state and takes the inode off the LRU, as it would an inode that is in use. Page cache deletion requeues the inode once the mapping is shrinkable, so this is harmless if it happens before the last deletion. If it happens after, nothing puts the inode back: it stays in memory, unused, clean and without page cache, out of reach of the shrinker and of drop_caches, until it is looked up again or the filesystem is unmounted. Before commit2a0629834c("vfs: Don't evict inode under the inode lru traversing context") the pin was an i_count reference, and the final iput() put the inode back on the LRU. Skip inodes that are being isolated and leave them to the walker that pinned them, which restarts its walk once it has unpinned them. The window is reached by any unused inode with page cache on CONFIG_HIGHMEM kernels, and otherwise by inodes whose page cache is a single shadow entry at index 0. On an i386 HIGHMEM guest, eight concurrent "echo 2 > /proc/sys/vm/drop_caches" over 2000 freshly read one-page ext4 files leave roughly 400 of the inodes off the LRU per round; on x86_64, with the files' pages first evicted through memory.reclaim, 3 to 4 per round. With this patch, none in either case. Fixes:2a0629834c("vfs: Don't evict inode under the inode lru traversing context") Cc: stable@vger.kernel.org Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com> Link: https://patch.msgid.link/20261009142431.713875-1-nick@karaolidis.com Reviewed-by: Zhihao Cheng <chengzhihao1@huawei.com> Reviewed-by: Jan Kara <jack@suse.cz> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
This commit is contained in:
parent
c60f9fe198
commit
8dc4116041
|
|
@ -941,6 +941,12 @@ static enum lru_status inode_lru_isolate(struct list_head *item,
|
|||
if (!spin_trylock(&inode->i_lock))
|
||||
return LRU_SKIP;
|
||||
|
||||
/* Another walker is dropping its page cache, leave it to that one */
|
||||
if (inode_state_read(inode) & I_LRU_ISOLATING) {
|
||||
spin_unlock(&inode->i_lock);
|
||||
return LRU_SKIP;
|
||||
}
|
||||
|
||||
/*
|
||||
* Inodes can get referenced, redirtied, or repopulated while
|
||||
* they're already on the LRU, and this can make them
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user