At evict_inodes() time, we no longer have SB_ACTIVE set, so we can easily go through the normal iput path to clear any inodes. Update dispose_list() to check how we need to free the inode, and then grab a full reference to the inode while we're looping through the remaining inodes, and simply iput them at the end. Since we're just calling iput we don't really care about the i_count on the inode at the current time. Remove the i_count checks and just call iput on every inode we find. Signed-off-by: Josef Bacik --- fs/inode.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/fs/inode.c b/fs/inode.c index 399598e90693..ede9118bb649 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -933,7 +933,7 @@ static void evict(struct inode *inode) * Dispose-list gets a local list with local inodes in it, so it doesn't * need to worry about list corruption and SMP locks. */ -static void dispose_list(struct list_head *head) +static void dispose_list(struct list_head *head, bool for_lru) { while (!list_empty(head)) { struct inode *inode; @@ -941,8 +941,12 @@ static void dispose_list(struct list_head *head) inode = list_first_entry(head, struct inode, i_lru); list_del_init(&inode->i_lru); - evict(inode); - iobj_put(inode); + if (for_lru) { + evict(inode); + iobj_put(inode); + } else { + iput(inode); + } cond_resched(); } } @@ -964,21 +968,13 @@ void evict_inodes(struct super_block *sb) again: spin_lock(&sb->s_inode_list_lock); list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { - if (icount_read(inode)) - continue; - spin_lock(&inode->i_lock); - if (icount_read(inode)) { - spin_unlock(&inode->i_lock); - continue; - } if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) { spin_unlock(&inode->i_lock); continue; } - inode->i_state |= I_FREEING; - iobj_get(inode); + __iget(inode); inode_lru_list_del(inode); spin_unlock(&inode->i_lock); list_add(&inode->i_lru, &dispose); @@ -991,13 +987,13 @@ void evict_inodes(struct super_block *sb) if (need_resched()) { spin_unlock(&sb->s_inode_list_lock); cond_resched(); - dispose_list(&dispose); + dispose_list(&dispose, false); goto again; } } spin_unlock(&sb->s_inode_list_lock); - dispose_list(&dispose); + dispose_list(&dispose, false); } EXPORT_SYMBOL_GPL(evict_inodes); @@ -1108,7 +1104,7 @@ long prune_icache_sb(struct super_block *sb, struct shrink_control *sc) freed = list_lru_shrink_walk(&sb->s_inode_lru, sc, inode_lru_isolate, &freeable); - dispose_list(&freeable); + dispose_list(&freeable, true); return freed; } -- 2.49.0