
This is a backport of a collection of 12 upstream patches. The main one being the switch to use a rwsem instead. The next important one being the switch of the rwsem to be a per filesystem lock instead of global. See the individual patches for details. They did not require much work or wiggling to get them applied. They all come from Linus' tree and are easily located. As such I have not modified their individual headers with upstream commit ids. Verification: - two scripts, the concept behind them supplied by Vefa Bicakci. The first one causes a lot of concurrent contention in sysfs. The second script highlights how well systemd is also contending. Run Script1 followed by Script2 Without this change, Script2 has timeouts and fails. Script1: for i in `seq 20`; do (while :; do find /sys/fs/cgroup/ -type f -readable -print0 \ 2>/dev/null | xargs -0 -n 20 -r cat >&/dev/null ; done) & done for i in `seq 10`; do (while :; do systemd-run --scope -q sleep 0.5 >/dev/null; done) & done Script2: while true; do date -Is /usr/bin/time -f %e systemctl enable -q lighttpd.service || break /usr/bin/time -f %e systemctl disable -q lighttpd.service || break /usr/bin/time -f %e systemctl restart -q lighttpd.service || break sleep 0.5 || break done - also soak testing to ensure that these patches don't introduce issues Partial-Bug: 2016028 Signed-off-by: Jim Somerville <jim.somerville@windriver.com> Change-Id: I6ad64cd7c90f756c6eb904065febfeb516e73009
132 lines
3.6 KiB
Diff
132 lines
3.6 KiB
Diff
From b4cb1f9c968c93893b8f092b4360f3da7237afec Mon Sep 17 00:00:00 2001
|
|
From: Ian Kent <raven@themaw.net>
|
|
Date: Tue, 15 Jun 2021 18:25:53 +0800
|
|
Subject: [PATCH] kernfs: move revalidate to be near lookup
|
|
|
|
While the dentry operation kernfs_dop_revalidate() is grouped with
|
|
dentry type functions it also has a strong affinity to the inode
|
|
operation ->lookup().
|
|
|
|
It makes sense to locate this function near to kernfs_iop_lookup()
|
|
because we will be adding VFS negative dentry caching to reduce path
|
|
lookup overhead for non-existent paths.
|
|
|
|
There's no functional change from this patch.
|
|
|
|
Signed-off-by: Ian Kent <raven@themaw.net>
|
|
Reviewed-by: Miklos Szeredi <mszeredi@redhat.com>
|
|
Link: https://lore.kernel.org/r/162375275365.232295.8995526416263659926.stgit@web.messagingengine.com
|
|
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|
Signed-off-by: Jim Somerville <jim.somerville@windriver.com>
|
|
---
|
|
fs/kernfs/dir.c | 86 ++++++++++++++++++++++++-------------------------
|
|
1 file changed, 43 insertions(+), 43 deletions(-)
|
|
|
|
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
|
|
index 8b3c86a502da..c16571cbb997 100644
|
|
--- a/fs/kernfs/dir.c
|
|
+++ b/fs/kernfs/dir.c
|
|
@@ -556,49 +556,6 @@ void kernfs_put(struct kernfs_node *kn)
|
|
}
|
|
EXPORT_SYMBOL_GPL(kernfs_put);
|
|
|
|
-static int kernfs_dop_revalidate(struct dentry *dentry, unsigned int flags)
|
|
-{
|
|
- struct kernfs_node *kn;
|
|
-
|
|
- if (flags & LOOKUP_RCU)
|
|
- return -ECHILD;
|
|
-
|
|
- /* Always perform fresh lookup for negatives */
|
|
- if (d_really_is_negative(dentry))
|
|
- goto out_bad_unlocked;
|
|
-
|
|
- kn = kernfs_dentry_node(dentry);
|
|
- mutex_lock(&kernfs_mutex);
|
|
-
|
|
- /* The kernfs node has been deactivated */
|
|
- if (!kernfs_active(kn))
|
|
- goto out_bad;
|
|
-
|
|
- /* The kernfs node has been moved? */
|
|
- if (kernfs_dentry_node(dentry->d_parent) != kn->parent)
|
|
- goto out_bad;
|
|
-
|
|
- /* The kernfs node has been renamed */
|
|
- if (strcmp(dentry->d_name.name, kn->name) != 0)
|
|
- goto out_bad;
|
|
-
|
|
- /* The kernfs node has been moved to a different namespace */
|
|
- if (kn->parent && kernfs_ns_enabled(kn->parent) &&
|
|
- kernfs_info(dentry->d_sb)->ns != kn->ns)
|
|
- goto out_bad;
|
|
-
|
|
- mutex_unlock(&kernfs_mutex);
|
|
- return 1;
|
|
-out_bad:
|
|
- mutex_unlock(&kernfs_mutex);
|
|
-out_bad_unlocked:
|
|
- return 0;
|
|
-}
|
|
-
|
|
-const struct dentry_operations kernfs_dops = {
|
|
- .d_revalidate = kernfs_dop_revalidate,
|
|
-};
|
|
-
|
|
/**
|
|
* kernfs_node_from_dentry - determine kernfs_node associated with a dentry
|
|
* @dentry: the dentry in question
|
|
@@ -1081,6 +1038,49 @@ struct kernfs_node *kernfs_create_empty_dir(struct kernfs_node *parent,
|
|
return ERR_PTR(rc);
|
|
}
|
|
|
|
+static int kernfs_dop_revalidate(struct dentry *dentry, unsigned int flags)
|
|
+{
|
|
+ struct kernfs_node *kn;
|
|
+
|
|
+ if (flags & LOOKUP_RCU)
|
|
+ return -ECHILD;
|
|
+
|
|
+ /* Always perform fresh lookup for negatives */
|
|
+ if (d_really_is_negative(dentry))
|
|
+ goto out_bad_unlocked;
|
|
+
|
|
+ kn = kernfs_dentry_node(dentry);
|
|
+ mutex_lock(&kernfs_mutex);
|
|
+
|
|
+ /* The kernfs node has been deactivated */
|
|
+ if (!kernfs_active(kn))
|
|
+ goto out_bad;
|
|
+
|
|
+ /* The kernfs node has been moved? */
|
|
+ if (kernfs_dentry_node(dentry->d_parent) != kn->parent)
|
|
+ goto out_bad;
|
|
+
|
|
+ /* The kernfs node has been renamed */
|
|
+ if (strcmp(dentry->d_name.name, kn->name) != 0)
|
|
+ goto out_bad;
|
|
+
|
|
+ /* The kernfs node has been moved to a different namespace */
|
|
+ if (kn->parent && kernfs_ns_enabled(kn->parent) &&
|
|
+ kernfs_info(dentry->d_sb)->ns != kn->ns)
|
|
+ goto out_bad;
|
|
+
|
|
+ mutex_unlock(&kernfs_mutex);
|
|
+ return 1;
|
|
+out_bad:
|
|
+ mutex_unlock(&kernfs_mutex);
|
|
+out_bad_unlocked:
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+const struct dentry_operations kernfs_dops = {
|
|
+ .d_revalidate = kernfs_dop_revalidate,
|
|
+};
|
|
+
|
|
static struct dentry *kernfs_iop_lookup(struct inode *dir,
|
|
struct dentry *dentry,
|
|
unsigned int flags)
|
|
--
|
|
2.25.1
|
|
|