Messages in this thread Patch in this message | ![/](/images/icornerl.gif) | | From | Andries.Brouwer@cwi ... | Date | Sun, 18 May 2003 16:46:05 +0200 (MEST) | Subject | [PATCH] namespace fix |
| |
After # mount --rbind /tmp /mnt (on 2.5.68) I have a corrupted namespace. Umounting /mnt fails, and /proc/mounts contains ... /dev/root /mnt ext3 rw 0 0 proc /mnt/proc proc rw 0 0 usbfs /mnt/proc/bus/usb usbfs rw 0 0 /dev/hdb5 /mnt/usr reiserfs rw 0 0 ... where of course no directories /mnt/proc or /mnt/usr exist.
This is caused by the fact that copy_tree() thinks that the dentry it is called with is the root of the filesystem. If it is not, confusion arose.
This confusion is fixed by the patch (against 2.5.69-bk12) below.
Andries
diff -u --recursive --new-file -X /linux/dontdiff a/fs/namespace.c b/fs/namespace.c --- a/fs/namespace.c Sun May 18 00:44:23 2003 +++ b/fs/namespace.c Sun May 18 17:17:21 2003 @@ -418,36 +418,54 @@ #endif } +static int +lives_below_in_same_fs(struct dentry *d, struct dentry *dentry) +{ + while (1) { + if (d == dentry) + return 1; + if (d == NULL || d == d->d_parent) + return 0; + d = d->d_parent; + } +} + static struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry) { - struct vfsmount *p, *next, *q, *res; + struct vfsmount *res, *p, *q, *r, *s; + struct list_head *h; struct nameidata nd; - p = mnt; - res = nd.mnt = q = clone_mnt(p, dentry); + res = q = clone_mnt(mnt, dentry); if (!q) goto Enomem; - q->mnt_parent = q; - q->mnt_mountpoint = p->mnt_mountpoint; + q->mnt_mountpoint = mnt->mnt_mountpoint; + + p = mnt; + for (h = mnt->mnt_mounts.next; h != &mnt->mnt_mounts; h = h->next) { + r = list_entry(h, struct vfsmount, mnt_child); + if (!lives_below_in_same_fs(r->mnt_mountpoint, dentry)) + continue; - while ( (next = next_mnt(p, mnt)) != NULL) { - while (p != next->mnt_parent) { - p = p->mnt_parent; - q = q->mnt_parent; + for (s = r; s; s = next_mnt(s, r)) { + while (p != s->mnt_parent) { + p = p->mnt_parent; + q = q->mnt_parent; + } + p = s; + nd.mnt = q; + nd.dentry = p->mnt_mountpoint; + q = clone_mnt(p, p->mnt_root); + if (!q) + goto Enomem; + spin_lock(&dcache_lock); + list_add_tail(&q->mnt_list, &res->mnt_list); + attach_mnt(q, &nd); + spin_unlock(&dcache_lock); } - p = next; - nd.mnt = q; - nd.dentry = p->mnt_mountpoint; - q = clone_mnt(p, p->mnt_root); - if (!q) - goto Enomem; - spin_lock(&dcache_lock); - list_add_tail(&q->mnt_list, &res->mnt_list); - attach_mnt(q, &nd); - spin_unlock(&dcache_lock); } return res; -Enomem: + Enomem: if (res) { spin_lock(&dcache_lock); umount_tree(res); - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| ![\](/images/icornerr.gif) |