diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2020-02-21 08:33:57 -0600 |
---|---|---|
committer | Eric W. Biederman <ebiederm@xmission.com> | 2020-02-21 14:06:42 -0600 |
commit | 080f6276fccfb3923691e57c1b44a627eabd1a25 (patch) | |
tree | 8592faa930076dd09e229fc573436f8c0655c058 | |
parent | 26dbc60f385ff9cff475ea2a3bad02e80fd6fa43 (diff) | |
download | linux-080f6276fccfb3923691e57c1b44a627eabd1a25.tar.bz2 |
proc: In proc_prune_siblings_dcache cache an aquired super block
Because there are likely to be several sysctls in a row on the
same superblock cache the super_block after the count has
been raised and don't deactivate it until we are processing
another super_block.
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
-rw-r--r-- | fs/proc/inode.c | 14 |
1 files changed, 10 insertions, 4 deletions
diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 74ce4a8d05eb..fa2dc732cd77 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -108,10 +108,11 @@ void proc_prune_siblings_dcache(struct hlist_head *inodes, spinlock_t *lock) struct inode *inode; struct proc_inode *ei; struct hlist_node *node; - struct super_block *sb; + struct super_block *old_sb = NULL; rcu_read_lock(); for (;;) { + struct super_block *sb; node = hlist_first_rcu(inodes); if (!node) break; @@ -122,23 +123,28 @@ void proc_prune_siblings_dcache(struct hlist_head *inodes, spinlock_t *lock) inode = &ei->vfs_inode; sb = inode->i_sb; - if (!atomic_inc_not_zero(&sb->s_active)) + if ((sb != old_sb) && !atomic_inc_not_zero(&sb->s_active)) continue; inode = igrab(inode); rcu_read_unlock(); + if (sb != old_sb) { + if (old_sb) + deactivate_super(old_sb); + old_sb = sb; + } if (unlikely(!inode)) { - deactivate_super(sb); rcu_read_lock(); continue; } d_prune_aliases(inode); iput(inode); - deactivate_super(sb); rcu_read_lock(); } rcu_read_unlock(); + if (old_sb) + deactivate_super(old_sb); } static int proc_show_options(struct seq_file *seq, struct dentry *root) |