linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Alexander Viro <viro@math.psu.edu>
To: Linus Torvalds <torvalds@transmeta.com>
Cc: linux-kernel@vger.kernel.org
Subject: [PATCH] lazy umount (3/4)
Date: Fri, 14 Sep 2001 15:03:12 -0400 (EDT)	[thread overview]
Message-ID: <Pine.GSO.4.21.0109141502430.11172-100000@weyl.math.psu.edu> (raw)
In-Reply-To: <Pine.GSO.4.21.0109141502090.11172-100000@weyl.math.psu.edu>

Part 3/4:
	New function - check_mnt(). Checks that vfsmount is an ancestor
of root_vfsmnt.  Calls added - since we are going to do lazy umount we
should take care of mounting on something that is busy, but already umounted.
Fixed leak in pivot_root(2)


diff -urN S10-pre9-root_vfsmnt/fs/super.c S10-pre9-check_mnt/fs/super.c
--- S10-pre9-root_vfsmnt/fs/super.c	Fri Sep 14 14:03:34 2001
+++ S10-pre9-check_mnt/fs/super.c	Fri Sep 14 14:04:01 2001
@@ -327,6 +327,15 @@
 	return p;
 }
 
+static int check_mnt(struct vfsmount *mnt)
+{
+	spin_lock(&dcache_lock);
+	while (mnt->mnt_parent != mnt)
+		mnt = mnt->mnt_parent;
+	spin_unlock(&dcache_lock);
+	return mnt == root_vfsmnt;
+}
+
 static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd)
 {
 	old_nd->dentry = mnt->mnt_mountpoint;
@@ -1226,6 +1235,8 @@
 	retval = -EINVAL;
 	if (nd.dentry != nd.mnt->mnt_root)
 		goto dput_and_out;
+	if (!check_mnt(nd.mnt))
+		goto dput_and_out;
 
 	retval = -EPERM;
 	if (!capable(CAP_SYS_ADMIN) && current->uid!=nd.mnt->mnt_owner)
@@ -1277,7 +1288,7 @@
 static int do_loopback(struct nameidata *nd, char *old_name)
 {
 	struct nameidata old_nd;
-	struct vfsmount *mnt;
+	struct vfsmount *mnt = NULL;
 	int err;
 
 	err = mount_is_safe(nd);
@@ -1293,12 +1304,16 @@
 		return err;
 
 	down(&mount_sem);
-	err = -ENOMEM;
-	mnt = clone_mnt(old_nd.mnt, old_nd.dentry);
+	err = -EINVAL;
+	if (check_mnt(nd->mnt)) {
+		err = -ENOMEM;
+		mnt = clone_mnt(old_nd.mnt, old_nd.dentry);
+	}
 	if (mnt) {
 		err = graft_tree(mnt, nd);
 		mntput(mnt);
 	}
+
 	up(&mount_sem);
 	path_release(&old_nd);
 	return err;
@@ -1318,6 +1333,9 @@
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
+	if (!check_mnt(nd->mnt))
+		return -EINVAL;
+
 	if (nd->dentry != nd->mnt->mnt_root)
 		return -EINVAL;
 
@@ -1396,27 +1414,31 @@
 			int mnt_flags, char *name, void *data)
 {
 	struct vfsmount *mnt = do_kern_mount(type, flags, name, data);
-	int retval = PTR_ERR(mnt);
+	int err = PTR_ERR(mnt);
 
 	if (IS_ERR(mnt))
 		goto out;
 
-	mnt->mnt_flags = mnt_flags;
-
 	down(&mount_sem);
 	/* Something was mounted here while we slept */
 	while(d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry))
 		;
+	err = -EINVAL;
+	if (!check_mnt(nd->mnt))
+		goto unlock;
 
 	/* Refuse the same filesystem on the same mount point */
+	err = -EBUSY;
 	if (nd->mnt->mnt_sb == mnt->mnt_sb && nd->mnt->mnt_root == nd->dentry)
-		retval = -EBUSY;
-	else
-		retval = graft_tree(mnt, nd);
+		goto unlock;
+
+	mnt->mnt_flags = mnt_flags;
+	err = graft_tree(mnt, nd);
+unlock:
 	up(&mount_sem);
 	mntput(mnt);
 out:
-	return retval;
+	return err;
 }
 
 static int copy_mount_options (const void *data, unsigned long *where)
@@ -1772,10 +1794,8 @@
 
 asmlinkage long sys_pivot_root(const char *new_root, const char *put_old)
 {
-	struct dentry *root;
-	struct vfsmount *root_mnt;
 	struct vfsmount *tmp;
-	struct nameidata new_nd, old_nd, parent_nd, root_parent;
+	struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd;
 	char *name;
 	int error;
 
@@ -1794,11 +1814,14 @@
 	putname(name);
 	if (error)
 		goto out0;
+	error = -EINVAL;
+	if (!check_mnt(new_nd.mnt))
+		goto out1;
 
 	name = getname(put_old);
 	error = PTR_ERR(name);
 	if (IS_ERR(name))
-		goto out0;
+		goto out1;
 	error = 0;
 	if (path_init(name, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd))
 		error = path_walk(name, &old_nd);
@@ -1807,11 +1830,14 @@
 		goto out1;
 
 	read_lock(&current->fs->lock);
-	root_mnt = mntget(current->fs->rootmnt);
-	root = dget(current->fs->root);
+	user_nd.mnt = mntget(current->fs->rootmnt);
+	user_nd.dentry = dget(current->fs->root);
 	read_unlock(&current->fs->lock);
 	down(&mount_sem);
 	down(&old_nd.dentry->d_inode->i_zombie);
+	error = -EINVAL;
+	if (!check_mnt(user_nd.mnt))
+		goto out2;
 	error = -ENOENT;
 	if (IS_DEADDIR(new_nd.dentry->d_inode))
 		goto out2;
@@ -1820,10 +1846,10 @@
 	if (d_unhashed(old_nd.dentry) && !IS_ROOT(old_nd.dentry))
 		goto out2;
 	error = -EBUSY;
-	if (new_nd.mnt == root_mnt || old_nd.mnt == root_mnt)
+	if (new_nd.mnt == user_nd.mnt || old_nd.mnt == user_nd.mnt)
 		goto out2; /* loop */
 	error = -EINVAL;
-	if (root_mnt->mnt_root != root)
+	if (user_nd.mnt->mnt_root != user_nd.dentry)
 		goto out2;
 	if (new_nd.mnt->mnt_root != new_nd.dentry)
 		goto out2; /* not a mountpoint */
@@ -1842,19 +1868,18 @@
 	} else if (!is_subdir(old_nd.dentry, new_nd.dentry))
 		goto out3;
 	detach_mnt(new_nd.mnt, &parent_nd);
-	detach_mnt(root_mnt, &root_parent);
-	attach_mnt(root_mnt, &old_nd);
+	detach_mnt(user_nd.mnt, &root_parent);
+	attach_mnt(user_nd.mnt, &old_nd);
 	attach_mnt(new_nd.mnt, &root_parent);
 	spin_unlock(&dcache_lock);
-	chroot_fs_refs(root,root_mnt,new_nd.dentry,new_nd.mnt);
+	chroot_fs_refs(user_nd.dentry,user_nd.mnt,new_nd.dentry,new_nd.mnt);
 	error = 0;
 	path_release(&root_parent);
 	path_release(&parent_nd);
 out2:
 	up(&old_nd.dentry->d_inode->i_zombie);
 	up(&mount_sem);
-	dput(root);
-	mntput(root_mnt);
+	path_release(&user_nd);
 	path_release(&old_nd);
 out1:
 	path_release(&new_nd);



  reply	other threads:[~2001-09-14 19:03 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-09-14 19:01 [PATCH] lazy umount (1/4) Alexander Viro
2001-09-14 19:02 ` [PATCH] lazy umount (2/4) Alexander Viro
2001-09-14 19:03   ` Alexander Viro [this message]
2001-09-14 19:03     ` [PATCH] lazy umount (4/4) Alexander Viro
2001-09-14 20:43 ` [PATCH] lazy umount (1/4) Linus Torvalds
2001-09-14 20:54   ` Alexander Viro
2001-09-15 12:32 ` jlnance
2001-09-15 20:51   ` Mike Fedyk
2001-09-17 10:06     ` Matthias Andree
2001-09-16 16:37 ` Alex Stewart
2001-09-17  6:57   ` Forced umount (was lazy umount) Ville Herva
2001-09-17  7:03     ` Aaron Lehmann
2001-09-17  8:38       ` Alexander Viro
2001-09-17 10:21         ` Matthias Andree
2001-09-17 10:47           ` Tigran Aivazian
2001-09-17 23:21             ` Alex Stewart
2001-09-17 23:23             ` Xavier Bestel
2001-09-18  1:04               ` Alex Stewart
2001-09-18 20:19                 ` Pavel Machek
2001-09-17  8:29   ` Xavier Bestel
2001-09-17  8:39     ` Alexander Viro
2001-09-17 10:04 ` [PATCH] lazy umount (1/4) Matthias Andree
2001-09-17 12:13   ` Alan Cox
2001-09-18  0:24     ` Alex Stewart
2001-09-18  0:39       ` Matthias Andree
2001-09-18  8:56         ` Alexander Viro
2001-09-18  9:08           ` Matthias Andree
2001-09-18 13:03             ` Alan Cox
2001-09-18  9:07     ` David Woodhouse
2001-09-17 14:43 ` David Woodhouse

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Pine.GSO.4.21.0109141502430.11172-100000@weyl.math.psu.edu \
    --to=viro@math.psu.edu \
    --cc=linux-kernel@vger.kernel.org \
    --cc=torvalds@transmeta.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).