* FAILED: patch "[PATCH] fs: rotate inodes whose page cache could not be dropped" failed to apply to 6.1-stable tree
@ 2026-11-07 10:53 Sasha Levin
2026-11-11 3:11 ` [PATCH 6.1.y] fs: rotate inodes whose page cache could not be dropped Sasha Levin
0 siblings, 1 reply; 2+ messages in thread
From: Sasha Levin @ 2026-11-07 10:53 UTC (permalink / raw)
To: nick, jack, chengzhihao1, brauner; +Cc: stable
The patch below does not apply to the 6.1-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.1.y
git checkout FETCH_HEAD
git cherry-pick -x 8ee09f597763acfd31c62a578ba88b792fc41b24
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '20261107055331-failed-6.1-8ee09f597763@kernel.org' --subject-prefix 'PATCH 6.1.y' 'HEAD^..'
Thanks,
Sasha
------------------ original commit in Linus's tree ------------------
From 8ee09f597763acfd31c62a578ba88b792fc41b24 Mon Sep 17 00:00:00 2001
From: Nikolaos Karaolidis <nick@karaolidis.com>
Date: Fri, 16 Oct 2026 10:25:15 +0000
Subject: [PATCH] fs: rotate inodes whose page cache could not be dropped
When inode_lru_isolate() drops the page cache of an unused inode, it
has to unlock the list, so it returns LRU_RETRY and the walk restarts
at the head of the list, where the inode still is. If
invalidate_mapping_pages() could not empty the mapping, the restarted
walk strips the same inode again, and so on until nr_to_walk runs out.
Every walk of that list then ends on this inode, and nothing behind it
is reclaimed for as long as its cache stays.
Before commit 2a0629834cd8 ("vfs: Don't evict inode under the inode lru
traversing context") the walker pinned the inode with a reference, and
dropping it in iput_final() set I_REFERENCED, so the restarted walk
rotated the inode to the tail. Set I_REFERENCED again when the mapping
is still populated after the invalidation, in the same i_lock section
that clears I_LRU_ISOLATING. inode_unpin_lru_isolating() now expects
i_lock to be held, like inode_pin_lru_isolating().
On CONFIG_HIGHMEM kernels this can happen to any unused inode: a folio
is left behind if it is locked, under writeback, spliced into a pipe,
or still in another CPU's LRU-add batch after being read. Without
HIGHMEM it happens to DAX inodes whose only entry is at index 0, which
mapping_shrinkable() lets onto the LRU and invalidate_mapping_pages()
never removes.
Fixes: 2a0629834cd8 ("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/20261016102515.111285-1-nick@karaolidis.com
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Zhihao Cheng <chengzhihao1@huawei.com>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
fs/inode.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/fs/inode.c b/fs/inode.c
index 1cb6293b237a3..d6353b8d1e634 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -593,12 +593,11 @@ static void inode_pin_lru_isolating(struct inode *inode)
static void inode_unpin_lru_isolating(struct inode *inode)
{
- spin_lock(&inode->i_lock);
+ lockdep_assert_held(&inode->i_lock);
WARN_ON(!(inode_state_read(inode) & I_LRU_ISOLATING));
inode_state_clear(inode, I_LRU_ISOLATING);
/* Called with inode->i_lock which ensures memory ordering. */
inode_wake_up_bit(inode, __I_LRU_ISOLATING);
- spin_unlock(&inode->i_lock);
}
static void inode_wait_for_lru_isolating(struct inode *inode)
@@ -981,7 +980,13 @@ static enum lru_status inode_lru_isolate(struct list_head *item,
else
__count_vm_events(PGINODESTEAL, reap);
mm_account_reclaimed_pages(reap);
+
+ spin_lock(&inode->i_lock);
+ /* The walk restarts here: don't retry leftovers right away */
+ if (!mapping_empty(&inode->i_data))
+ inode_state_set(inode, I_REFERENCED);
inode_unpin_lru_isolating(inode);
+ spin_unlock(&inode->i_lock);
return LRU_RETRY;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 2+ messages in thread* [PATCH 6.1.y] fs: rotate inodes whose page cache could not be dropped
2026-11-07 10:53 FAILED: patch "[PATCH] fs: rotate inodes whose page cache could not be dropped" failed to apply to 6.1-stable tree Sasha Levin
@ 2026-11-11 3:11 ` Sasha Levin
0 siblings, 0 replies; 2+ messages in thread
From: Sasha Levin @ 2026-11-11 3:11 UTC (permalink / raw)
To: stable
Cc: Nikolaos Karaolidis, Jan Kara, Zhihao Cheng,
Christian Brauner (Amutable), Sasha Levin
From: Nikolaos Karaolidis <nick@karaolidis.com>
[ Upstream commit 8ee09f597763acfd31c62a578ba88b792fc41b24 ]
When inode_lru_isolate() drops the page cache of an unused inode, it
has to unlock the list, so it returns LRU_RETRY and the walk restarts
at the head of the list, where the inode still is. If
invalidate_mapping_pages() could not empty the mapping, the restarted
walk strips the same inode again, and so on until nr_to_walk runs out.
Every walk of that list then ends on this inode, and nothing behind it
is reclaimed for as long as its cache stays.
Before commit 2a0629834cd8 ("vfs: Don't evict inode under the inode lru
traversing context") the walker pinned the inode with a reference, and
dropping it in iput_final() set I_REFERENCED, so the restarted walk
rotated the inode to the tail. Set I_REFERENCED again when the mapping
is still populated after the invalidation, in the same i_lock section
that clears I_LRU_ISOLATING. inode_unpin_lru_isolating() now expects
i_lock to be held, like inode_pin_lru_isolating().
On CONFIG_HIGHMEM kernels this can happen to any unused inode: a folio
is left behind if it is locked, under writeback, spliced into a pipe,
or still in another CPU's LRU-add batch after being read. Without
HIGHMEM it happens to DAX inodes whose only entry is at index 0, which
mapping_shrinkable() lets onto the LRU and invalidate_mapping_pages()
never removes.
Fixes: 2a0629834cd8 ("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/20261016102515.111285-1-nick@karaolidis.com
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Zhihao Cheng <chengzhihao1@huawei.com>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
[ sashal: replaced inode_state_set() with direct inode->i_state bit manipulation ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/inode.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/fs/inode.c b/fs/inode.c
index 99e980ddbdceb..8e430ccb23c6e 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -496,12 +496,11 @@ static void inode_pin_lru_isolating(struct inode *inode)
static void inode_unpin_lru_isolating(struct inode *inode)
{
- spin_lock(&inode->i_lock);
+ lockdep_assert_held(&inode->i_lock);
WARN_ON(!(inode->i_state & I_LRU_ISOLATING));
inode->i_state &= ~I_LRU_ISOLATING;
smp_mb();
wake_up_bit(&inode->i_state, __I_LRU_ISOLATING);
- spin_unlock(&inode->i_lock);
}
static void inode_wait_for_lru_isolating(struct inode *inode)
@@ -909,7 +908,13 @@ static enum lru_status inode_lru_isolate(struct list_head *item,
if (current->reclaim_state)
current->reclaim_state->reclaimed_slab += reap;
}
+
+ spin_lock(&inode->i_lock);
+ /* The walk restarts here: don't retry leftovers right away */
+ if (!mapping_empty(&inode->i_data))
+ inode->i_state |= I_REFERENCED;
inode_unpin_lru_isolating(inode);
+ spin_unlock(&inode->i_lock);
spin_lock(lru_lock);
return LRU_RETRY;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-11-11 3:11 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-07 10:53 FAILED: patch "[PATCH] fs: rotate inodes whose page cache could not be dropped" failed to apply to 6.1-stable tree Sasha Levin
2026-11-11 3:11 ` [PATCH 6.1.y] fs: rotate inodes whose page cache could not be dropped Sasha Levin
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.