From: Dave Chinner <[email protected]>

For filesytsems that provide their own inode cache that can be
traversed, add a sueprblock method that can be used instead of
iterating the sb->s_inodes list. This allows these filesystems to
avoid having to populate the sb->s_inodes list and hence avoid the
scalability limitations that this list imposes.

Signed-off-by: Dave Chinner <[email protected]>
---
 fs/super.c         | 54 +++++++++++++++++++++++++++++++---------------
 include/linux/fs.h |  4 ++++
 2 files changed, 41 insertions(+), 17 deletions(-)

diff --git a/fs/super.c b/fs/super.c
index 20a9446d943a..971ad4e996e0 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -167,6 +167,31 @@ static void super_wake(struct super_block *sb, unsigned 
int flag)
        wake_up_var(&sb->s_flags);
 }
 
+bool super_iter_iget(struct inode *inode, int flags)
+{
+       bool    ret = false;
+
+       spin_lock(&inode->i_lock);
+       if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE))
+               goto out_unlock;
+
+       /*
+        * Skip over zero refcount inode if the caller only wants
+        * referenced inodes to be iterated.
+        */
+       if ((flags & INO_ITER_REFERENCED) &&
+           !atomic_read(&inode->i_count))
+               goto out_unlock;
+
+       __iget(inode);
+       ret = true;
+out_unlock:
+       spin_unlock(&inode->i_lock);
+       return ret;
+
+}
+EXPORT_SYMBOL_GPL(super_iter_iget);
+
 /**
  * super_iter_inodes - iterate all the cached inodes on a superblock
  * @sb: superblock to iterate
@@ -184,26 +209,15 @@ int super_iter_inodes(struct super_block *sb, ino_iter_fn 
iter_fn,
        struct inode *inode, *old_inode = NULL;
        int ret = 0;
 
+       if (sb->s_op->iter_vfs_inodes) {
+               return sb->s_op->iter_vfs_inodes(sb, iter_fn,
+                               private_data, flags);
+       }
+
        spin_lock(&sb->s_inode_list_lock);
        list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
-               spin_lock(&inode->i_lock);
-               if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) {
-                       spin_unlock(&inode->i_lock);
+               if (!super_iter_iget(inode, flags))
                        continue;
-               }
-
-               /*
-                * Skip over zero refcount inode if the caller only wants
-                * referenced inodes to be iterated.
-                */
-               if ((flags & INO_ITER_REFERENCED) &&
-                   !atomic_read(&inode->i_count)) {
-                       spin_unlock(&inode->i_lock);
-                       continue;
-               }
-
-               __iget(inode);
-               spin_unlock(&inode->i_lock);
                spin_unlock(&sb->s_inode_list_lock);
                iput(old_inode);
 
@@ -261,6 +275,12 @@ void super_iter_inodes_unsafe(struct super_block *sb, 
ino_iter_fn iter_fn,
        struct inode *inode;
        int ret;
 
+       if (sb->s_op->iter_vfs_inodes) {
+               sb->s_op->iter_vfs_inodes(sb, iter_fn,
+                               private_data, INO_ITER_UNSAFE);
+               return;
+       }
+
        rcu_read_lock();
        spin_lock(&sb->s_inode_list_lock);
        list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 0a6a462c45ab..8e82e3dc0618 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2224,6 +2224,7 @@ enum freeze_holder {
 typedef int (*ino_iter_fn)(struct inode *inode, void *priv);
 int super_iter_inodes(struct super_block *sb, ino_iter_fn iter_fn,
                void *private_data, int flags);
+bool super_iter_iget(struct inode *inode, int flags);
 
 struct super_operations {
        struct inode *(*alloc_inode)(struct super_block *sb);
@@ -2258,6 +2259,9 @@ struct super_operations {
        long (*free_cached_objects)(struct super_block *,
                                    struct shrink_control *);
        void (*shutdown)(struct super_block *sb);
+
+       int (*iter_vfs_inodes)(struct super_block *sb, ino_iter_fn iter_fn,
+                       void *private_data, int flags);
 };
 
 /*
-- 
2.45.2


Reply via email to