summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjohn stultz <johnstul@us.ibm.com>2010-05-19 22:19:46 -0700
committerThomas Gleixner <tglx@linutronix.de>2010-05-20 09:44:30 +0200
commite86825210e29c0be2691e7055f942555d02a4314 (patch)
treed17a70397ee5ef9b6a0c938fd92633159e251eb7
parent44b341ae13557f646061530d281fbc19c5ae9111 (diff)
downloadlwn-e86825210e29c0be2691e7055f942555d02a4314.tar.gz
lwn-e86825210e29c0be2691e7055f942555d02a4314.zip
fs: namespace: Fix fuse mount fallout
> WARNING: at fs/namespace.c:648 commit_tree+0xf1/0x10b() > Pid: 14002, comm: fusermount Not tainted 2.6.33.3-rt19 #32 > Call Trace: > [<ffffffff81040e67>] warn_slowpath_common+0x7c/0x94 > [<ffffffff81040e93>] warn_slowpath_null+0x14/0x16 > [<ffffffff81115811>] commit_tree+0xf1/0x10b > [<ffffffff8111661d>] attach_recursive_mnt+0xf2/0x188 > [<ffffffff811167b3>] graft_tree+0x100/0x102 > [<ffffffff8111765b>] do_mount+0x386/0x7ae > [<ffffffff810d55f2>] ? strndup_user+0x5d/0x85 > [<ffffffff81117b0b>] sys_mount+0x88/0xc2 > [<ffffffff81002d32>] system_call_fastpath+0x16/0x1b Looks like the fuse mounts are more interesting here and are tripping up the MNT_MOUNTED logic. Trivial cases: MNT_MOUNTED gets set by: attach_mnt commit_tree MNT_MOUNTED gets unset by: detach_mnt unmount_tree So there's a nice symmetry there. We also clear MNT_MOUNTED in clone_mnt(), since we're creating a unmounted copy that we will latter call attach_mnt() upon. Now, here's where things get messy: copy_tree(): Earlier, we didn't set MNT_MOUNTED on the first clone on the root of the mnt to be copied. This caused problems with new namespaces since after it is copied, we don't call attach_mnt or commit_tree. So when the namespace is removed, and we call unmount_tree, and hit a WARN_ON. Similarly, if we bombed out in copy_tree due to a ENOMEM, we call umount_tree on the mnt and will hit the WARN_ON as well. The same issue hits us with collect_mounts and drop_collected_mounts, where we copy_tree() and then unmount_tree() and hit the WARN_ON. This seemed broken, so I set MNT_MOUNTED on the root cloned mnt in copy_tree and it resolved the above asymmetries. However, do_loopback is more complicated, since it calls either copy_tree or clone_mnt (depending on the recursive flag) and then grafts that mnt which calls commit_tree()/attach_mnt(). Leaving clone_mnt(), the mnt is not set as MNT_MOUNTED, but now with my change to copy_tree(), it sets the root as MNT_MOUNTED. This then causes a WARN_ON in the commit_tree() called by graft_tree(). The fix below simply clears the recently set MNT_MOUNTED flag after copy_tree() returns, before calling graft_tree(). Signed-off-by: John Stultz <johnstul@us.ibm.com> Cc: Carsten Emde <C.Emde@osadl.org> Cc: "Luis Claudio R. Goncalves" <lclaudio@uudg.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--fs/namespace.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index 4e9a3de3319c..ad39c7f2d292 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1675,9 +1675,13 @@ static int do_loopback(struct path *path, char *old_name,
goto out;
err = -ENOMEM;
- if (recurse)
+ if (recurse) {
mnt = copy_tree(old_path.mnt, old_path.dentry, 0);
- else
+ /* Annoying. Since we graft the rootfs, we need to unmark
+ * it as mounted. */
+ WARN_ON(!(mnt->mnt_flags & MNT_MOUNTED));
+ mnt->mnt_flags &= ~MNT_MOUNTED;
+ } else
mnt = clone_mnt(old_path.mnt, old_path.dentry, 0);
if (!mnt)