[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20161011053403.27645.55242.stgit@pluto.themaw.net>
Date: Tue, 11 Oct 2016 13:34:03 +0800
From: Ian Kent <raven@...maw.net>
To: Andrew Morton <akpm@...ux-foundation.org>
Cc: autofs mailing list <autofs@...r.kernel.org>,
Kernel Mailing List <linux-kernel@...r.kernel.org>,
"Eric W. Biederman" <ebiederm@...ssion.com>,
linux-fsdevel <linux-fsdevel@...r.kernel.org>,
Omar Sandoval <osandov@...ndov.com>,
Al Viro <viro@...IV.linux.org.uk>
Subject: [PATCH 3/8] vfs - add path_has_submounts()
From: Ian Kent <ikent@...hat.com>
d_mountpoint() can only be used reliably to establish if a dentry is
not mounted in any namespace. It isn't aware of the possibility there
may be multiple mounts using the given dentry, possibly in a different
namespace.
Add function, path_has_submounts(), that checks is a struct path contains
mounts (or is a mountpoint itself) to handle this case.
Signed-off-by: Ian Kent <raven@...maw.net>
Cc: Al Viro <viro@...IV.linux.org.uk>
Cc: Eric W. Biederman <ebiederm@...ssion.com>
Cc: Omar Sandoval <osandov@...ndov.com>
---
fs/dcache.c | 35 +++++++++++++++++++++++++++++++++++
include/linux/dcache.h | 1 +
2 files changed, 36 insertions(+)
diff --git a/fs/dcache.c b/fs/dcache.c
index 5c7cc95..872f04e 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1306,6 +1306,41 @@ int have_submounts(struct dentry *parent)
}
EXPORT_SYMBOL(have_submounts);
+struct check_mount {
+ struct vfsmount *mnt;
+ unsigned int mounted;
+};
+
+static enum d_walk_ret path_check_mount(void *data, struct dentry *dentry)
+{
+ struct check_mount *info = data;
+ struct path path = { .mnt = info->mnt, .dentry = dentry };
+
+ if (path_is_mountpoint(&path)) {
+ info->mounted = 1;
+ return D_WALK_QUIT;
+ }
+ return D_WALK_CONTINUE;
+}
+
+/**
+ * path_has_submounts - check for mounts over a dentry in the
+ * current namespace.
+ * @parent: path to check.
+ *
+ * Return true if the parent or its subdirectories contain
+ * a mount point in the current namespace.
+ */
+int path_has_submounts(struct path *parent)
+{
+ struct check_mount data = { .mnt = parent->mnt, .mounted = 0 };
+
+ d_walk(parent->dentry, &data, path_check_mount, NULL);
+
+ return data.mounted;
+}
+EXPORT_SYMBOL(path_has_submounts);
+
/*
* Called by mount code to set a mountpoint and check if the mountpoint is
* reachable (e.g. NFS can unhash a directory dentry and then the complete
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 798bc04..e351646 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -255,6 +255,7 @@ extern void d_prune_aliases(struct inode *);
/* test whether we have any submounts in a subdir tree */
extern int have_submounts(struct dentry *);
+extern int path_has_submounts(struct path *);
/*
* This adds the entry to the hash queues.
Powered by blists - more mailing lists