Re: [RFC 18/26] union-mount: Changes to the namespace handling

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Jul 30, 2007 at 06:13:41PM +0200, Jan Blunck wrote:
> Creates the proper struct union_mount when mounting something into a
> union. If the topmost filesystem isn't capable of handling the white-out
> filetype it could only be mount read-only.
>

Jan,

I think it is important to allow pivot_root of union mount points. Here
is an attempt to achieve that.

From: Bharata B Rao <[email protected]>

Allow pivot_root to  work with union mount points.

If the current root filesystem is a union, then allow pivot_root
only if it's last component is a root, which allows it to be detached as a
complete union. Similarly if the new root filesystem is a union,
it's last component should be a root, so that it can be completely detached
from it's current mount point as a union and mounted back as root filesystem.

Signed-off-by: Bharata B Rao <[email protected]>
---
 fs/namespace.c        |   17 +++++++++++++++--
 fs/union.c            |   12 ++++++++++++
 include/linux/union.h |    2 ++
 3 files changed, 29 insertions(+), 2 deletions(-)

--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -171,6 +171,13 @@ static void detach_mnt(struct vfsmount *
 	old_nd->dentry->d_mounted--;
 }
 
+static void detach_last_mnt(struct nameidata *nd, struct nameidata *old_nd)
+{
+	if (IS_MNT_UNION(nd->mnt))
+		while (follow_union_down(&nd->mnt, &nd->dentry));
+	detach_mnt(nd->mnt, old_nd);
+}
+
 void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry,
 			struct vfsmount *child_mnt)
 {
@@ -1878,6 +1885,9 @@ asmlinkage long sys_pivot_root(const cha
 	if (!check_mnt(new_nd.mnt))
 		goto out1;
 
+	if (IS_MNT_UNION(new_nd.mnt) && !last_union_is_root(&new_nd))
+		goto out1;
+
 	error = __user_walk(put_old, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &old_nd);
 	if (error)
 		goto out1;
@@ -1901,6 +1911,9 @@ asmlinkage long sys_pivot_root(const cha
 		goto out2;
 	if (!check_mnt(user_nd.mnt))
 		goto out2;
+	if (IS_MNT_UNION(user_nd.mnt) && !last_union_is_root(&user_nd))
+		goto out2;
+
 	error = -ENOENT;
 	if (IS_DEADDIR(new_nd.dentry->d_inode))
 		goto out2;
@@ -1934,8 +1947,8 @@ asmlinkage long sys_pivot_root(const cha
 			goto out3;
 	} else if (!is_subdir(old_nd.dentry, new_nd.dentry))
 		goto out3;
-	detach_mnt(new_nd.mnt, &parent_nd);
-	detach_mnt(user_nd.mnt, &root_parent);
+	detach_last_mnt(&new_nd, &parent_nd);
+	detach_last_mnt(&user_nd, &root_parent);
 	attach_mnt(user_nd.mnt, &old_nd);     /* mount old root on put_old */
 	attach_mnt(new_nd.mnt, &root_parent); /* mount new_root on / */
 	touch_mnt_namespace(current->nsproxy->mnt_ns);
--- a/fs/union.c
+++ b/fs/union.c
@@ -507,6 +507,18 @@ void detach_mnt_union(struct vfsmount *m
 	return;
 }
 
+/*
+ * last_union_is_root - Check if the last component of the union stack
+ * is a root.
+ */
+int last_union_is_root(struct nameidata *nd)
+{
+	struct vfsmount *mnt = nd->mnt;
+	struct dentry *dentry = nd->dentry;
+
+	while (follow_union_down(&mnt, &dentry));
+	return IS_ROOT(dentry) ? 1: 0;
+}
 
 /*
  * Union mounts support for readdir.
--- a/include/linux/union.h
+++ b/include/linux/union.h
@@ -53,6 +53,7 @@ extern void __shrink_d_unions(struct den
 extern int attach_mnt_union(struct vfsmount *, struct vfsmount *,
 			    struct dentry *);
 extern void detach_mnt_union(struct vfsmount *);
+extern int last_union_is_root(struct nameidata *nd);
 extern int readdir_union(struct file *, void *, filldir_t);
 extern int is_dir_unioned(struct path *);
 extern int union_relookup_topmost(struct nameidata *, int);
@@ -74,6 +75,7 @@ extern int union_copyup(struct nameidata
 #define __shrink_d_unions(x)		do { } while (0)
 #define attach_mnt_union(x, y, z)	do { } while (0)
 #define detach_mnt_union(x)		do { } while (0)
+#define last_union_is_root(x)		({ (0); })
 #define union_relookup_topmost(x, y)	({ BUG(); (0); })
 #define union_create_topmost(x, y, z)	({ BUG(); (NULL); })
 #define __union_copyup(x, y, z)		({ BUG(); (0); })

This applies on top of your patchset plus my subsequent fixes [1] and
[2].

[1] http://lkml.org/lkml/2007/8/6/10.
[2] http://lkml.org/lkml/2007/8/6/114.

Regards,
Bharata.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux