When we move to holding a full reference on the inode when it is on an LRU list we need to have a mechanism to re-run the LRU add logic. The use case for this is btrfs's snapshot delete, we will lookup all the inodes and try to drop them, but if they're on the LRU we will not call ->drop_inode() because their refcount will be elevated, so we won't know that we need to drop the inode. Fix this by simply removing the inode from it's respective LRU list when we grab a reference to it in a way that we have active users. This will ensure that the logic to add the inode to the LRU or drop the inode will be run on the final iput from the user. Signed-off-by: Josef Bacik --- fs/inode.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/inode.c b/fs/inode.c index 4d39f260901f..399598e90693 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1146,6 +1146,7 @@ static struct inode *find_inode(struct super_block *sb, return ERR_PTR(-ESTALE); } __iget(inode); + inode_lru_list_del(inode); spin_unlock(&inode->i_lock); rcu_read_unlock(); return inode; @@ -1187,6 +1188,7 @@ static struct inode *find_inode_fast(struct super_block *sb, return ERR_PTR(-ESTALE); } __iget(inode); + inode_lru_list_del(inode); spin_unlock(&inode->i_lock); rcu_read_unlock(); return inode; @@ -1653,6 +1655,7 @@ struct inode *igrab(struct inode *inode) spin_lock(&inode->i_lock); if (!(inode->i_state & (I_FREEING|I_WILL_FREE))) { __iget(inode); + inode_lru_list_del(inode); spin_unlock(&inode->i_lock); } else { spin_unlock(&inode->i_lock); -- 2.49.0