summaryrefslogtreecommitdiff
path: root/fs/super.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2024-09-28 21:31:10 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2024-10-01 19:40:47 -0400
commit9ec9b917b3f6cf676226f074fdcdeceebe1a0b29 (patch)
tree7c71ca81faa20a1e44624f7489fae1264db8e269 /fs/super.c
parent32cb8103ecfacdd5ed8e1eb390221c3f8339de6f (diff)
vfs: use fast_list for superblock's inode listfast_list
Use the new fast_list for super_block.s_inodes. This gives similar performance to Dave's dlock list approach [1]; lock contention is now moved to the lru_list locks. Iteration is now fully lockless - instead we iterate using rcu_read_lock(), which means we must take care for racing with removal. Generally this is already handled - code that iterates over s_inodes takes i_lock and checks i_state, skipping inodes that are I_WILL_FREE|I_FREEING. However, code may also check for nonzero i_sb_list_idx if it wishes to iterate over precisely the inodes that are on the s_inodes list. [1]: https://lore.kernel.org/linux-fsdevel/20231206060629.2827226-4-david@fromorbit.com/ Cc: Christian Brauner <brauner@kernel.org> Cc: Dave Chinner <dchinner@redhat.com> Cc: Waiman Long <longman@redhat.com> Cc: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/super.c')
-rw-r--r--fs/super.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/fs/super.c b/fs/super.c
index 1db230432960..132af76cf5c3 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -274,6 +274,7 @@ static void destroy_super_work(struct work_struct *work)
{
struct super_block *s = container_of(work, struct super_block,
destroy_work);
+ fast_list_exit(&s->s_inodes);
fsnotify_sb_free(s);
security_sb_free(s);
put_user_ns(s->s_user_ns);
@@ -359,8 +360,6 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags,
INIT_HLIST_NODE(&s->s_instances);
INIT_HLIST_BL_HEAD(&s->s_roots);
mutex_init(&s->s_sync_lock);
- INIT_LIST_HEAD(&s->s_inodes);
- spin_lock_init(&s->s_inode_list_lock);
INIT_LIST_HEAD(&s->s_inodes_wb);
spin_lock_init(&s->s_inode_wblist_lock);
@@ -375,6 +374,9 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags,
s->s_time_min = TIME64_MIN;
s->s_time_max = TIME64_MAX;
+ if (fast_list_init(&s->s_inodes))
+ goto fail;
+
s->s_shrink = shrinker_alloc(SHRINKER_NUMA_AWARE | SHRINKER_MEMCG_AWARE,
"sb-%s", type->name);
if (!s->s_shrink)
@@ -646,7 +648,7 @@ void generic_shutdown_super(struct super_block *sb)
* the fscrypt keyring can be destroyed.
*/
fscrypt_destroy_keyring(sb);
-
+#if 0
if (CHECK_DATA_CORRUPTION(!list_empty(&sb->s_inodes),
"VFS: Busy inodes after unmount of %s (%s)",
sb->s_id, sb->s_type->name)) {
@@ -665,6 +667,7 @@ void generic_shutdown_super(struct super_block *sb)
}
spin_unlock(&sb->s_inode_list_lock);
}
+#endif
}
/*
* Broadcast to everyone that grabbed a temporary reference to this