summaryrefslogtreecommitdiffstats
path: root/fs/dcache.c
diff options
context:
space:
mode:
authorIan Kent <ikent@redhat.com>2016-11-23 16:03:41 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2016-12-03 20:51:47 -0500
commit01619491a5f0766014fe863c5ae480665436e7a2 (patch)
treee9f8f4fcf30337b805c76f8fcc83baa517779359 /fs/dcache.c
parentc6609c0a1c34fc097152b28b496236625673924f (diff)
vfs: add path_has_submounts()
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. Link: http://lkml.kernel.org/r/20161011053403.27645.55242.stgit@pluto.themaw.net Signed-off-by: Ian Kent <raven@themaw.net> Cc: Al Viro <viro@ZenIV.linux.org.uk> Cc: Eric W. Biederman <ebiederm@xmission.com> Cc: Omar Sandoval <osandov@osandov.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/dcache.c')
-rw-r--r--fs/dcache.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index 5c7cc953ac81..8515875854b6 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1306,6 +1306,45 @@ int have_submounts(struct dentry *parent)
1306} 1306}
1307EXPORT_SYMBOL(have_submounts); 1307EXPORT_SYMBOL(have_submounts);
1308 1308
1309struct check_mount {
1310 struct vfsmount *mnt;
1311 unsigned int mounted;
1312};
1313
1314static enum d_walk_ret path_check_mount(void *data, struct dentry *dentry)
1315{
1316 struct check_mount *info = data;
1317 struct path path = { .mnt = info->mnt, .dentry = dentry };
1318
1319 if (likely(!d_mountpoint(dentry)))
1320 return D_WALK_CONTINUE;
1321 if (__path_is_mountpoint(&path)) {
1322 info->mounted = 1;
1323 return D_WALK_QUIT;
1324 }
1325 return D_WALK_CONTINUE;
1326}
1327
1328/**
1329 * path_has_submounts - check for mounts over a dentry in the
1330 * current namespace.
1331 * @parent: path to check.
1332 *
1333 * Return true if the parent or its subdirectories contain
1334 * a mount point in the current namespace.
1335 */
1336int path_has_submounts(const struct path *parent)
1337{
1338 struct check_mount data = { .mnt = parent->mnt, .mounted = 0 };
1339
1340 read_seqlock_excl(&mount_lock);
1341 d_walk(parent->dentry, &data, path_check_mount, NULL);
1342 read_sequnlock_excl(&mount_lock);
1343
1344 return data.mounted;
1345}
1346EXPORT_SYMBOL(path_has_submounts);
1347
1309/* 1348/*
1310 * Called by mount code to set a mountpoint and check if the mountpoint is 1349 * Called by mount code to set a mountpoint and check if the mountpoint is
1311 * reachable (e.g. NFS can unhash a directory dentry and then the complete 1350 * reachable (e.g. NFS can unhash a directory dentry and then the complete