shared mounts handling: move
PATCH 13/18 shared mounts handling: move
From: Ram Pai <[email protected]>
Date: 1131402003 -0500
Handling of mount --move in presense of shared mounts (see Documentation/sharedsubtree.txt in the end of patch series for detailed description).
---
fs/namespace.c | 63 +++++++++++++++++++++++++++++++++++++++++--------------- 1 files changed, 46 insertions(+), 17 deletions(-)
f530c48214f7fd8ff91d6d8c245373438be97ce2
fs/namespace.c +46 -17
@@ -660,7 +660,10 @@ Enomem:/* * @source_mnt : mount tree to be attached -* @nd : place the mount tree @source_mnt is attached +* @nd : place the mount tree @source_mnt is attached +* @parent_nd : if non-null, detach the source_mnt from its parent and +* store the parent mount and mountpoint dentry. +* (done when source_mnt is moved) * * NOTE: in the table below explains the semantics when a source mount * of a given type is attached to a destination mount of a given type.
@@ -685,6 +688,21 @@ Enomem:* (+) the cloned mount is created under the destination mount and is marked * as shared. The cloned mount is added to the peer group of the source * mount. +* --------------------------------------------- +* | MOVE MOUNT OPERATION | +* |******************************************** +* | source-->| shared | private | +* | dest | | | +* | | | | | +* | v | | | +* |******************************************** +* | shared | shared (+) | shared (+) | +* | | | | +* |non-shared| shared (+*) | private | +* ********************************************* +* (+) the mount is moved to the destination. And is then propagated to all +* the mounts in the propagation tree of the destination mount. +* (+*) the mount is moved to the destination. * * if the source mount is a tree, the operations explained above is * applied to each mount in the tree.
@@ -692,7 +710,7 @@ Enomem:* in allocations. */ static int attach_recursive_mnt (struct vfsmount *source_mnt, -struct nameidata *nd) +struct nameidata *nd,struct nameidata *parent_nd) {LIST_HEAD (tree_list);struct vfsmount *dest_mnt = nd->mnt;
@@ -708,8 +726,14 @@ static int attach_recursive_mnt(struct v }spin_lock (&vfsmount_lock); -mnt_set_mountpoint (dest_mnt, dest_dentry, source_mnt); -commit_tree (source_mnt); +if (parent_nd) { +detach_mnt (source_mnt, parent_nd); +attach_mnt (source_mnt, nd); +touch_namespace (current->namespace); + }else { +mnt_set_mountpoint (dest_mnt, dest_dentry, source_mnt); +commit_tree (source_mnt); + }list_for_each_entry_safe (child, p, &tree_list, mnt_hash) {list_del_init (&child->mnt_hash);
@@ -740,7 +764,7 @@ static int graft_tree(struct vfsmount *m err = -ENOENT ;if (IS_ROOT (nd->dentry) || !d_unhashed (nd->dentry)) - err =attach_recursive_mnt (mnt, nd); + err =attach_recursive_mnt (mnt, nd,NULL ); out_unlock:up (&nd->dentry->d_inode->i_sem);if (!err)
@@ -869,35 +893,36 @@ static int do_move_mount(struct nameidatif (IS_DEADDIR (nd->dentry->d_inode)) goto out1; -spin_lock (&vfsmount_lock);if (!IS_ROOT (nd->dentry) &&d_unhashed (nd->dentry)) - goto out2; + goto out1; err = -EINVAL ;if (old_nd.dentry != old_nd.mnt->mnt_root) - goto out2; + goto out1;if (old_nd.mnt == old_nd.mnt->mnt_parent) - goto out2; + goto out1;if (S_ISDIR (nd->dentry->d_inode->i_mode) !=S_ISDIR (old_nd.dentry->d_inode->i_mode)) - goto out2; - + goto out1; +/* +* Don't move a mount residing in a shared parent. +*/ +if (old_nd.mnt->mnt_parent &&IS_MNT_SHARED (old_nd.mnt->mnt_parent)) + goto out1; err = -ELOOP ;for (p = nd->mnt; p->mnt_parent != p; p = p->mnt_parent)if (p == old_nd.mnt) - goto out2; - err =0 ; + goto out1; -detach_mnt (old_nd.mnt, &parent_nd); -attach_mnt (old_nd.mnt, nd); -touch_namespace (current->namespace); +if ((err =attach_recursive_mnt (old_nd.mnt, nd, &parent_nd))) + goto out1; +spin_lock (&vfsmount_lock);/* if the mount is moved, it should no longer be expire * automatically */ list_del_init (&old_nd.mnt->mnt_expire); -out2:spin_unlock (&vfsmount_lock); out1:up (&nd->dentry->d_inode->i_sem);
@@ -1467,6 +1492,10 @@ asmlinkage long sys_pivot_root(const chadown_write (&namespace_sem);down (&old_nd.dentry->d_inode->i_sem); error = -EINVAL ; +if (IS_MNT_SHARED (old_nd.mnt) || +IS_MNT_SHARED (new_nd.mnt->mnt_parent) || +IS_MNT_SHARED (user_nd.mnt->mnt_parent)) + goto out2;if (!check_mnt (user_nd.mnt)) goto out2; error = -ENOENT ;
Quoted 6 lines
From: Ram Pai <[email protected]>
Date: 1131402003 -0500Handling of mount --move in presense of shared mounts (see
Documentation/sharedsubtree.txtin the end of patch series for detailed description).
This patch seems to be totally wrong. It copies the mounts instead of moving them in the propagated cases.
Am I missing something?
Miklos
Quoted 11 lines · Miklos Szeredi
Quoted 6 lines
From: Ram Pai <[email protected]>
Date: 1131402003 -0500Handling of mount --move in presense of shared mounts (see
Documentation/sharedsubtree.txtin the end of patch series for detailed description).This patch seems to be totally wrong. It copies the mounts instead of moving them in the propagated cases.
Am I missing something?
Yes, you are. We move a single subtree (which has no peers at all) to mountpoint that gives propagation. The subtree itself gets moved to specified mountpoint; for the rest of points in propagation tree of that mountpoint we have no choice but to create copies.