Skip to content

Commit 36341f6

Browse files
Ram PaiLinus Torvalds
authored andcommitted
[PATCH] mount expiry fixes
- clean up the ugliness in may_umount_tree() - fix a bug in do_loopback(). after cloning a tree, do_loopback() unlinks only the topmost mount of the cloned tree, leaving behind the children mounts on their corresponding expiry list. Signed-off-by: Ram Pai <[email protected]> Signed-off-by: Al Viro <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 70fbcdf commit 36341f6

File tree

1 file changed

+22
-42
lines changed

1 file changed

+22
-42
lines changed

fs/namespace.c

Lines changed: 22 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727

2828
extern int __init init_rootfs(void);
2929

30+
#define CL_EXPIRE 0x01
31+
3032
#ifdef CONFIG_SYSFS
3133
extern int __init sysfs_init(void);
3234
#else
@@ -165,7 +167,8 @@ static struct vfsmount *next_mnt(struct vfsmount *p, struct vfsmount *root)
165167
return list_entry(next, struct vfsmount, mnt_child);
166168
}
167169

168-
static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root)
170+
static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root,
171+
int flag)
169172
{
170173
struct super_block *sb = old->mnt_sb;
171174
struct vfsmount *mnt = alloc_vfsmnt(old->mnt_devname);
@@ -181,10 +184,12 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root)
181184

182185
/* stick the duplicate mount on the same expiry list
183186
* as the original if that was on one */
184-
spin_lock(&vfsmount_lock);
185-
if (!list_empty(&old->mnt_expire))
186-
list_add(&mnt->mnt_expire, &old->mnt_expire);
187-
spin_unlock(&vfsmount_lock);
187+
if (flag & CL_EXPIRE) {
188+
spin_lock(&vfsmount_lock);
189+
if (!list_empty(&old->mnt_expire))
190+
list_add(&mnt->mnt_expire, &old->mnt_expire);
191+
spin_unlock(&vfsmount_lock);
192+
}
188193
}
189194
return mnt;
190195
}
@@ -331,36 +336,14 @@ struct seq_operations mounts_op = {
331336
*/
332337
int may_umount_tree(struct vfsmount *mnt)
333338
{
334-
struct list_head *next;
335-
struct vfsmount *this_parent = mnt;
336-
int actual_refs;
337-
int minimum_refs;
339+
int actual_refs = 0;
340+
int minimum_refs = 0;
341+
struct vfsmount *p;
338342

339343
spin_lock(&vfsmount_lock);
340-
actual_refs = atomic_read(&mnt->mnt_count);
341-
minimum_refs = 2;
342-
repeat:
343-
next = this_parent->mnt_mounts.next;
344-
resume:
345-
while (next != &this_parent->mnt_mounts) {
346-
struct vfsmount *p =
347-
list_entry(next, struct vfsmount, mnt_child);
348-
349-
next = next->next;
350-
344+
for (p = mnt; p; p = next_mnt(p, mnt)) {
351345
actual_refs += atomic_read(&p->mnt_count);
352346
minimum_refs += 2;
353-
354-
if (!list_empty(&p->mnt_mounts)) {
355-
this_parent = p;
356-
goto repeat;
357-
}
358-
}
359-
360-
if (this_parent != mnt) {
361-
next = this_parent->mnt_child.next;
362-
this_parent = this_parent->mnt_parent;
363-
goto resume;
364347
}
365348
spin_unlock(&vfsmount_lock);
366349

@@ -596,12 +579,13 @@ static int lives_below_in_same_fs(struct dentry *d, struct dentry *dentry)
596579
}
597580
}
598581

599-
static struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry)
582+
static struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
583+
int flag)
600584
{
601585
struct vfsmount *res, *p, *q, *r, *s;
602586
struct nameidata nd;
603587

604-
res = q = clone_mnt(mnt, dentry);
588+
res = q = clone_mnt(mnt, dentry, flag);
605589
if (!q)
606590
goto Enomem;
607591
q->mnt_mountpoint = mnt->mnt_mountpoint;
@@ -619,7 +603,7 @@ static struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry)
619603
p = s;
620604
nd.mnt = q;
621605
nd.dentry = p->mnt_mountpoint;
622-
q = clone_mnt(p, p->mnt_root);
606+
q = clone_mnt(p, p->mnt_root, flag);
623607
if (!q)
624608
goto Enomem;
625609
spin_lock(&vfsmount_lock);
@@ -701,18 +685,13 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse)
701685

702686
err = -ENOMEM;
703687
if (recurse)
704-
mnt = copy_tree(old_nd.mnt, old_nd.dentry);
688+
mnt = copy_tree(old_nd.mnt, old_nd.dentry, 0);
705689
else
706-
mnt = clone_mnt(old_nd.mnt, old_nd.dentry);
690+
mnt = clone_mnt(old_nd.mnt, old_nd.dentry, 0);
707691

708692
if (!mnt)
709693
goto out;
710694

711-
/* stop bind mounts from expiring */
712-
spin_lock(&vfsmount_lock);
713-
list_del_init(&mnt->mnt_expire);
714-
spin_unlock(&vfsmount_lock);
715-
716695
err = graft_tree(mnt, nd);
717696
if (err) {
718697
LIST_HEAD(umount_list);
@@ -1155,7 +1134,8 @@ int copy_namespace(int flags, struct task_struct *tsk)
11551134

11561135
down_write(&tsk->namespace->sem);
11571136
/* First pass: copy the tree topology */
1158-
new_ns->root = copy_tree(namespace->root, namespace->root->mnt_root);
1137+
new_ns->root = copy_tree(namespace->root, namespace->root->mnt_root,
1138+
CL_EXPIRE);
11591139
if (!new_ns->root) {
11601140
up_write(&tsk->namespace->sem);
11611141
kfree(new_ns);

0 commit comments

Comments
 (0)