[PATCH 11/11] fs: fix potential soft lockup when 'sb->s_inodes' has large number of inodes
Ye Bin
yebin at huaweicloud.com
Mon Nov 18 11:45:08 UTC 2024
From: Ye Bin <yebin10 at huawei.com>
If the memory is sufficient, a large number of inodes that do not
meet the conditions may exist in the 'sb->s_inodes' list when
evict_inodes()/invalidate_inodes() traverse the 'sb->s_inodes' list.
Then it maybe trigger soft lockup.
To solve potential soft lockup, move need_resched() check from tail
to head when traverse the 'sb->s_inodes' list.
Signed-off-by: Ye Bin <yebin10 at huawei.com>
---
fs/inode.c | 49 +++++++++++++++++++++++++------------------------
1 file changed, 25 insertions(+), 24 deletions(-)
diff --git a/fs/inode.c b/fs/inode.c
index b78895af8779..e865fc1f5a95 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -867,6 +867,21 @@ void evict_inodes(struct super_block *sb)
again:
spin_lock(&sb->s_inode_list_lock);
sb_for_each_inodes_continue_safe(inode, next, &sb->s_inodes) {
+ /*
+ * We can have a ton of inodes to evict at unmount time given
+ * enough memory, check to see if we need to go to sleep for a
+ * bit so we don't livelock.
+ */
+ if (need_resched()) {
+ list_del(&cursor.i_sb_list);
+ list_add_tail(&cursor.i_sb_list, &inode->i_sb_list);
+ inode = &cursor;
+ spin_unlock(&sb->s_inode_list_lock);
+ cond_resched();
+ dispose_list(&dispose);
+ goto again;
+ }
+
if (atomic_read(&inode->i_count))
continue;
@@ -884,21 +899,6 @@ void evict_inodes(struct super_block *sb)
inode_lru_list_del(inode);
spin_unlock(&inode->i_lock);
list_add(&inode->i_lru, &dispose);
-
- /*
- * We can have a ton of inodes to evict at unmount time given
- * enough memory, check to see if we need to go to sleep for a
- * bit so we don't livelock.
- */
- if (need_resched()) {
- list_del(&cursor.i_sb_list);
- list_add(&cursor.i_sb_list, &inode->i_sb_list);
- inode = &cursor;
- spin_unlock(&sb->s_inode_list_lock);
- cond_resched();
- dispose_list(&dispose);
- goto again;
- }
}
list_del(&cursor.i_sb_list);
spin_unlock(&sb->s_inode_list_lock);
@@ -926,6 +926,16 @@ void invalidate_inodes(struct super_block *sb)
again:
spin_lock(&sb->s_inode_list_lock);
sb_for_each_inodes_continue_safe(inode, next, &sb->s_inodes) {
+ if (need_resched()) {
+ list_del(&cursor.i_sb_list);
+ list_add_tail(&cursor.i_sb_list, &inode->i_sb_list);
+ inode = &cursor;
+ spin_unlock(&sb->s_inode_list_lock);
+ cond_resched();
+ dispose_list(&dispose);
+ goto again;
+ }
+
spin_lock(&inode->i_lock);
if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) {
spin_unlock(&inode->i_lock);
@@ -940,15 +950,6 @@ void invalidate_inodes(struct super_block *sb)
inode_lru_list_del(inode);
spin_unlock(&inode->i_lock);
list_add(&inode->i_lru, &dispose);
- if (need_resched()) {
- list_del(&cursor.i_sb_list);
- list_add(&cursor.i_sb_list, &inode->i_sb_list);
- inode = &cursor;
- spin_unlock(&sb->s_inode_list_lock);
- cond_resched();
- dispose_list(&dispose);
- goto again;
- }
}
list_del(&cursor.i_sb_list);
spin_unlock(&sb->s_inode_list_lock);
--
2.34.1
More information about the Linux-security-module-archive
mailing list