]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/5.1.5/fsnotify-fix-unlink-performance-regression.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 5.1.5 / fsnotify-fix-unlink-performance-regression.patch
CommitLineData
08dc4bc5
GKH
1From 4d8e7055a4058ee191296699803c5090e14f0dff Mon Sep 17 00:00:00 2001
2From: Amir Goldstein <amir73il@gmail.com>
3Date: Sun, 5 May 2019 12:15:49 +0300
4Subject: fsnotify: fix unlink performance regression
5
6From: Amir Goldstein <amir73il@gmail.com>
7
8commit 4d8e7055a4058ee191296699803c5090e14f0dff upstream.
9
10__fsnotify_parent() has an optimization in place to avoid unneeded
11take_dentry_name_snapshot(). When fsnotify_nameremove() was changed
12not to call __fsnotify_parent(), we left out the optimization.
13Kernel test robot reported a 5% performance regression in concurrent
14unlink() workload.
15
16Reported-by: kernel test robot <rong.a.chen@intel.com>
17Link: https://lore.kernel.org/lkml/20190505062153.GG29809@shao2-debian/
18Link: https://lore.kernel.org/linux-fsdevel/20190104090357.GD22409@quack2.suse.cz/
19Fixes: 5f02a8776384 ("fsnotify: annotate directory entry modification events")
20CC: stable@vger.kernel.org
21Signed-off-by: Amir Goldstein <amir73il@gmail.com>
22Signed-off-by: Jan Kara <jack@suse.cz>
23Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
24
25---
26 fs/notify/fsnotify.c | 41 +++++++++++++++++++++++++++++++++++++++
27 include/linux/fsnotify.h | 33 -------------------------------
28 include/linux/fsnotify_backend.h | 4 +++
29 3 files changed, 45 insertions(+), 33 deletions(-)
30
31--- a/fs/notify/fsnotify.c
32+++ b/fs/notify/fsnotify.c
33@@ -108,6 +108,47 @@ void fsnotify_sb_delete(struct super_blo
34 }
35
36 /*
37+ * fsnotify_nameremove - a filename was removed from a directory
38+ *
39+ * This is mostly called under parent vfs inode lock so name and
40+ * dentry->d_parent should be stable. However there are some corner cases where
41+ * inode lock is not held. So to be on the safe side and be reselient to future
42+ * callers and out of tree users of d_delete(), we do not assume that d_parent
43+ * and d_name are stable and we use dget_parent() and
44+ * take_dentry_name_snapshot() to grab stable references.
45+ */
46+void fsnotify_nameremove(struct dentry *dentry, int isdir)
47+{
48+ struct dentry *parent;
49+ struct name_snapshot name;
50+ __u32 mask = FS_DELETE;
51+
52+ /* d_delete() of pseudo inode? (e.g. __ns_get_path() playing tricks) */
53+ if (IS_ROOT(dentry))
54+ return;
55+
56+ if (isdir)
57+ mask |= FS_ISDIR;
58+
59+ parent = dget_parent(dentry);
60+ /* Avoid unneeded take_dentry_name_snapshot() */
61+ if (!(d_inode(parent)->i_fsnotify_mask & FS_DELETE) &&
62+ !(dentry->d_sb->s_fsnotify_mask & FS_DELETE))
63+ goto out_dput;
64+
65+ take_dentry_name_snapshot(&name, dentry);
66+
67+ fsnotify(d_inode(parent), mask, d_inode(dentry), FSNOTIFY_EVENT_INODE,
68+ name.name, 0);
69+
70+ release_dentry_name_snapshot(&name);
71+
72+out_dput:
73+ dput(parent);
74+}
75+EXPORT_SYMBOL(fsnotify_nameremove);
76+
77+/*
78 * Given an inode, first check if we care what happens to our children. Inotify
79 * and dnotify both tell their parents about events. If we care about any event
80 * on a child we run all of our children and set a dentry flag saying that the
81--- a/include/linux/fsnotify.h
82+++ b/include/linux/fsnotify.h
83@@ -152,39 +152,6 @@ static inline void fsnotify_vfsmount_del
84 }
85
86 /*
87- * fsnotify_nameremove - a filename was removed from a directory
88- *
89- * This is mostly called under parent vfs inode lock so name and
90- * dentry->d_parent should be stable. However there are some corner cases where
91- * inode lock is not held. So to be on the safe side and be reselient to future
92- * callers and out of tree users of d_delete(), we do not assume that d_parent
93- * and d_name are stable and we use dget_parent() and
94- * take_dentry_name_snapshot() to grab stable references.
95- */
96-static inline void fsnotify_nameremove(struct dentry *dentry, int isdir)
97-{
98- struct dentry *parent;
99- struct name_snapshot name;
100- __u32 mask = FS_DELETE;
101-
102- /* d_delete() of pseudo inode? (e.g. __ns_get_path() playing tricks) */
103- if (IS_ROOT(dentry))
104- return;
105-
106- if (isdir)
107- mask |= FS_ISDIR;
108-
109- parent = dget_parent(dentry);
110- take_dentry_name_snapshot(&name, dentry);
111-
112- fsnotify(d_inode(parent), mask, d_inode(dentry), FSNOTIFY_EVENT_INODE,
113- name.name, 0);
114-
115- release_dentry_name_snapshot(&name);
116- dput(parent);
117-}
118-
119-/*
120 * fsnotify_inoderemove - an inode is going away
121 */
122 static inline void fsnotify_inoderemove(struct inode *inode)
123--- a/include/linux/fsnotify_backend.h
124+++ b/include/linux/fsnotify_backend.h
125@@ -355,6 +355,7 @@ extern int __fsnotify_parent(const struc
126 extern void __fsnotify_inode_delete(struct inode *inode);
127 extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt);
128 extern void fsnotify_sb_delete(struct super_block *sb);
129+extern void fsnotify_nameremove(struct dentry *dentry, int isdir);
130 extern u32 fsnotify_get_cookie(void);
131
132 static inline int fsnotify_inode_watches_children(struct inode *inode)
133@@ -524,6 +525,9 @@ static inline void __fsnotify_vfsmount_d
134 static inline void fsnotify_sb_delete(struct super_block *sb)
135 {}
136
137+static inline void fsnotify_nameremove(struct dentry *dentry, int isdir)
138+{}
139+
140 static inline void fsnotify_update_flags(struct dentry *dentry)
141 {}
142