summaryrefslogtreecommitdiffstats
path: root/fs/proc/inode.c
diff options
context:
space:
mode:
authorKonstantin Khlebnikov <khlebnikov@yandex-team.ru>2017-02-10 10:35:02 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-08-15 18:14:43 +0200
commitb96e215e539509cae8bfe468689b70661cf511b4 (patch)
tree1ef03b5f942cffd587af5d5448960775efca8cb7 /fs/proc/inode.c
parente31578c6fb0b89ceb8ef943528279571dfc0f8dc (diff)
downloadlinux-stable-b96e215e539509cae8bfe468689b70661cf511b4.tar.gz
linux-stable-b96e215e539509cae8bfe468689b70661cf511b4.tar.bz2
linux-stable-b96e215e539509cae8bfe468689b70661cf511b4.zip
proc/sysctl: prune stale dentries during unregistering
commit d6cffbbe9a7e51eb705182965a189457c17ba8a3 upstream. Currently unregistering sysctl table does not prune its dentries. Stale dentries could slowdown sysctl operations significantly. For example, command: # for i in {1..100000} ; do unshare -n -- sysctl -a &> /dev/null ; done creates a millions of stale denties around sysctls of loopback interface: # sysctl fs.dentry-state fs.dentry-state = 25812579 24724135 45 0 0 0 All of them have matching names thus lookup have to scan though whole hash chain and call d_compare (proc_sys_compare) which checks them under system-wide spinlock (sysctl_lock). # time sysctl -a > /dev/null real 1m12.806s user 0m0.016s sys 1m12.400s Currently only memory reclaimer could remove this garbage. But without significant memory pressure this never happens. This patch collects sysctl inodes into list on sysctl table header and prunes all their dentries once that table unregisters. Konstantin Khlebnikov <khlebnikov@yandex-team.ru> writes: > On 10.02.2017 10:47, Al Viro wrote: >> how about >> the matching stats *after* that patch? > > dcache size doesn't grow endlessly, so stats are fine > > # sysctl fs.dentry-state > fs.dentry-state = 92712 58376 45 0 0 0 > > # time sysctl -a &>/dev/null > > real 0m0.013s > user 0m0.004s > sys 0m0.008s Signed-off-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> Suggested-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/proc/inode.c')
-rw-r--r--fs/proc/inode.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index e69ebe648a34..c2afe39f0b9e 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -43,10 +43,11 @@ static void proc_evict_inode(struct inode *inode)
de = PDE(inode);
if (de)
pde_put(de);
+
head = PROC_I(inode)->sysctl;
if (head) {
RCU_INIT_POINTER(PROC_I(inode)->sysctl, NULL);
- sysctl_head_put(head);
+ proc_sys_evict_inode(inode, head);
}
}