All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] (part 1) fs/super.c cleanups
@ 2001-05-23  3:26 Alexander Viro
  2001-05-23  4:15 ` [PATCH] (part 2) " Alexander Viro
  0 siblings, 1 reply; 5+ messages in thread
From: Alexander Viro @ 2001-05-23  3:26 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-kernel

	Linus, since we have sane kill_super() now, the long-promised
cleanups are coming ;-) I'm going to feed them in small incremental
chunks, so if you see something unacceptable - yell. It may turn out
to be a result of bad choice of chunk boundaries, so...

	OK, here comes the chunk #1:

	* we have different rules for ->mnt_parent and ->mnt_mountpoint
in case of root filesystem(s). I.e. in case if vfsmount is not mounted
on anything (root and kern_mount() stuff). In that case we have
	mnt->mnt_parent == mnt
	mnt->mnt_mountpoint == mnt->mnt_root.
We shouldn't hold ->d_count of ->mnt_mountpoint. It's inconsistent with
the way we treat ->mnt_parent, it's not needed (->mnt_root is pinned
down just fine), it complicates the logics and it's conceptually wrong -
sure, going upwards from root leaves us where we were (thus the rules
above), but we don't have anything actually mounted on the root.
	Change: now ->mnt_mountpoint holds a reference to dentry only
if mnt is actually mounted on something. It will allow to simplify a
lot of stuff, since we get the same rules as we have for ->mnt_parent.

	* pivot_root(2) was slightly broken. It is OK to have new_root
not at the root of filesystem. However, it should be a mountpoint. Which
is actually not a restriction - mount --bind foo foo will make foo a
mountpoint just fine.
	Change: add the missing check, remove the broken attempts to handle
that case.

	Patch follows. Please, apply.
								Al
PS: next chunk simplifies the move_vfsmnt() and friends - both API and
internals.

diff -urN S5-pre5/fs/super.c S5-pre5-mountpoint/fs/super.c
--- S5-pre5/fs/super.c	Tue May 22 16:44:21 2001
+++ S5-pre5-mountpoint/fs/super.c	Tue May 22 22:54:54 2001
@@ -337,7 +337,7 @@
 	if (nd && !IS_ROOT(nd->dentry) && d_unhashed(nd->dentry))
 		goto fail;
 	mnt->mnt_root = dget(root);
-	mnt->mnt_mountpoint = nd ? dget(nd->dentry) : dget(root);
+	mnt->mnt_mountpoint = nd ? dget(nd->dentry) : root;
 	mnt->mnt_parent = nd ? mntget(nd->mnt) : mnt;
 
 	if (nd) {
@@ -388,7 +388,7 @@
 	}
 
 	/* flip the linkage */
-	mnt->mnt_mountpoint = dget(mountpoint);
+	mnt->mnt_mountpoint = parent ? dget(mountpoint) : mnt->mnt_root;
 	mnt->mnt_parent = parent ? mntget(parent) : mnt;
 	list_del(&mnt->mnt_clash);
 	list_del(&mnt->mnt_child);
@@ -402,9 +402,10 @@
 	spin_unlock(&dcache_lock);
 
 	/* put the old stuff */
-	dput(old_mountpoint);
-	if (old_parent != mnt)
+	if (old_parent != mnt) {
+		dput(old_mountpoint);
 		mntput(old_parent);
+	}
 }
 
 /*
@@ -419,10 +420,10 @@
 	list_del(&mnt->mnt_child);
 	spin_unlock(&dcache_lock);
 	/* Now we can work safely */
-	if (mnt->mnt_parent != mnt)
+	if (mnt->mnt_parent != mnt) {
+		dput(mnt->mnt_mountpoint);
 		mntput(mnt->mnt_parent);
-
-	dput(mnt->mnt_mountpoint);
+	}
 	dput(mnt->mnt_root);
 	if (mnt->mnt_devname)
 		kfree(mnt->mnt_devname);
@@ -1612,8 +1613,9 @@
  *  - we don't move root/cwd if they are not at the root (reason: if something
  *    cared enough to change them, it's probably wrong to force them elsewhere)
  *  - it's okay to pick a root that isn't the root of a file system, e.g.
- *    /nfs/my_root where /nfs is the mount point. Better avoid creating
- *    unreachable mount points this way, though.
+ *    /nfs/my_root where /nfs is the mount point. It must be a mountpoint,
+ *    though, so you may need to say mount --bind /nfs/my_root /nfs/my_root
+ *    first.
  */
 
 asmlinkage long sys_pivot_root(const char *new_root, const char *put_old)
@@ -1669,6 +1671,8 @@
 	if (new_nd.mnt == root_mnt || old_nd.mnt == root_mnt)
 		goto out2; /* loop */
 	error = -EINVAL;
+	if (new_nd.mnt->mnt_root != new_nd.dentry)
+		goto out2; /* not a mountpoint */
 	tmp = old_nd.mnt; /* make sure we can reach put_old from new_root */
 	spin_lock(&dcache_lock);
 	if (tmp != new_nd.mnt) {
@@ -1685,7 +1689,7 @@
 		goto out3;
 	spin_unlock(&dcache_lock);
 
-	move_vfsmnt(new_nd.mnt, new_nd.dentry, NULL, NULL);
+	move_vfsmnt(new_nd.mnt, NULL, NULL, NULL);
 	move_vfsmnt(root_mnt, old_nd.dentry, old_nd.mnt, NULL);
 	chroot_fs_refs(root,root_mnt,new_nd.dentry,new_nd.mnt);
 	error = 0;


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH] (part 2) fs/super.c cleanups
  2001-05-23  3:26 [PATCH] (part 1) fs/super.c cleanups Alexander Viro
@ 2001-05-23  4:15 ` Alexander Viro
  2001-05-23  4:25   ` Andrew Morton
  2001-05-23  6:10   ` [PATCH] (part 3) " Alexander Viro
  0 siblings, 2 replies; 5+ messages in thread
From: Alexander Viro @ 2001-05-23  4:15 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-kernel

	OK, here's chunk #2.

	* two helper functions added: attach_mnt() and detach_mnt().
attach_mnt() adds leaf to mount tree, detach_mnt() - removes.
	Locking rules: both require mount_sem and dcache_lock being
held by callers.
	The rest of stuff doing manipulations of mount tree converted
to using these two.

	* move_vfsmnt() takes nameidata of the new attachment point
now.

	* pivot_root() taught how to work in chroot environment (not
a security issue, since it requires root anyway, but why not handle
it correctly if it comes for free?)
	It used to tear the chroot subtree away. Now it reattaches
new root to the place where old used to be (if any).
	If process root is not on a mountpoint (or global root) -
-EINVAL.
	That way it works as expected in chroot environment. Price:
extra if and call of attach_mnt(). Variant in the current tree screws
up in these conditions.

	Patch (incremental to the previous) follow. Please, apply.
								   Al
PS: the next chunk is (finally) GC for struct vfsmount.

diff -urN S5-pre5-mountpoint/fs/super.c S5-pre5-mnt_detach/fs/super.c
--- S5-pre5-mountpoint/fs/super.c	Tue May 22 23:27:25 2001
+++ S5-pre5-mnt_detach/fs/super.c	Tue May 22 23:55:59 2001
@@ -282,6 +282,24 @@
 
 static LIST_HEAD(vfsmntlist);
 
+static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd)
+{
+	old_nd->dentry = mnt->mnt_mountpoint;
+	old_nd->mnt = mnt->mnt_parent;
+	mnt->mnt_parent = mnt;
+	mnt->mnt_mountpoint = mnt->mnt_root;
+	list_del_init(&mnt->mnt_child);
+	list_del_init(&mnt->mnt_clash);
+}
+
+static void attach_mnt(struct vfsmount *mnt, struct nameidata *nd)
+{
+	mnt->mnt_parent = mntget(nd->mnt);
+	mnt->mnt_mountpoint = dget(nd->dentry);
+	list_add(&mnt->mnt_clash, &nd->dentry->d_vfsmnt);
+	list_add(&mnt->mnt_child, &nd->mnt->mnt_mounts);
+}
+
 /**
  *	add_vfsmnt - add a new mount node
  *	@nd: location of mountpoint or %NULL if we want a root node
@@ -337,13 +355,12 @@
 	if (nd && !IS_ROOT(nd->dentry) && d_unhashed(nd->dentry))
 		goto fail;
 	mnt->mnt_root = dget(root);
-	mnt->mnt_mountpoint = nd ? dget(nd->dentry) : root;
-	mnt->mnt_parent = nd ? mntget(nd->mnt) : mnt;
 
 	if (nd) {
-		list_add(&mnt->mnt_child, &nd->mnt->mnt_mounts);
-		list_add(&mnt->mnt_clash, &nd->dentry->d_vfsmnt);
+		attach_mnt(mnt, nd);
 	} else {
+		mnt->mnt_mountpoint = mnt->mnt_root;
+		mnt->mnt_parent = mnt;
 		INIT_LIST_HEAD(&mnt->mnt_child);
 		INIT_LIST_HEAD(&mnt->mnt_clash);
 	}
@@ -362,12 +379,10 @@
 }
 
 static void move_vfsmnt(struct vfsmount *mnt,
-			struct dentry *mountpoint,
-			struct vfsmount *parent,
+			struct nameidata *nd, 
 			const char *dev_name)
 {
-	struct dentry *old_mountpoint;
-	struct vfsmount *old_parent;
+	struct nameidata parent_nd;
 	char *new_devname = NULL;
 
 	if (dev_name) {
@@ -377,35 +392,19 @@
 	}
 
 	spin_lock(&dcache_lock);
-	old_mountpoint = mnt->mnt_mountpoint;
-	old_parent = mnt->mnt_parent;
+	detach_mnt(mnt, &parent_nd);
+	attach_mnt(mnt, nd);
 
-	/* flip names */
 	if (new_devname) {
 		if (mnt->mnt_devname)
 			kfree(mnt->mnt_devname);
 		mnt->mnt_devname = new_devname;
 	}
-
-	/* flip the linkage */
-	mnt->mnt_mountpoint = parent ? dget(mountpoint) : mnt->mnt_root;
-	mnt->mnt_parent = parent ? mntget(parent) : mnt;
-	list_del(&mnt->mnt_clash);
-	list_del(&mnt->mnt_child);
-	if (parent) {
-		list_add(&mnt->mnt_child, &parent->mnt_mounts);
-		list_add(&mnt->mnt_clash, &mountpoint->d_vfsmnt);
-	} else {
-		INIT_LIST_HEAD(&mnt->mnt_child);
-		INIT_LIST_HEAD(&mnt->mnt_clash);
-	}
 	spin_unlock(&dcache_lock);
 
 	/* put the old stuff */
-	if (old_parent != mnt) {
-		dput(old_mountpoint);
-		mntput(old_parent);
-	}
+	if (parent_nd.mnt != mnt)
+		path_release(&parent_nd);
 }
 
 /*
@@ -413,18 +412,16 @@
  */
 static void remove_vfsmnt(struct vfsmount *mnt)
 {
+	struct nameidata parent_nd;
 	/* First of all, remove it from all lists */
+	detach_mnt(mnt, &parent_nd);
 	list_del(&mnt->mnt_instances);
-	list_del(&mnt->mnt_clash);
 	list_del(&mnt->mnt_list);
-	list_del(&mnt->mnt_child);
 	spin_unlock(&dcache_lock);
 	/* Now we can work safely */
-	if (mnt->mnt_parent != mnt) {
-		dput(mnt->mnt_mountpoint);
-		mntput(mnt->mnt_parent);
-	}
 	dput(mnt->mnt_root);
+	if (parent_nd.mnt != mnt)
+		path_release(&parent_nd);
 	if (mnt->mnt_devname)
 		kfree(mnt->mnt_devname);
 	kfree(mnt);
@@ -1623,7 +1620,7 @@
 	struct dentry *root;
 	struct vfsmount *root_mnt;
 	struct vfsmount *tmp;
-	struct nameidata new_nd, old_nd;
+	struct nameidata new_nd, old_nd, parent_nd, root_parent;
 	char *name;
 	int error;
 
@@ -1671,6 +1668,8 @@
 	if (new_nd.mnt == root_mnt || old_nd.mnt == root_mnt)
 		goto out2; /* loop */
 	error = -EINVAL;
+	if (root_mnt->mnt_root != root)
+		goto out2;
 	if (new_nd.mnt->mnt_root != new_nd.dentry)
 		goto out2; /* not a mountpoint */
 	tmp = old_nd.mnt; /* make sure we can reach put_old from new_root */
@@ -1687,12 +1686,18 @@
 			goto out3;
 	} 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);
+	if (root_parent.mnt != root_mnt)
+		attach_mnt(new_nd.mnt, &root_parent);
 	spin_unlock(&dcache_lock);
-
-	move_vfsmnt(new_nd.mnt, NULL, NULL, NULL);
-	move_vfsmnt(root_mnt, old_nd.dentry, old_nd.mnt, NULL);
 	chroot_fs_refs(root,root_mnt,new_nd.dentry,new_nd.mnt);
 	error = 0;
+	if (root_parent.mnt != root_mnt)
+		path_release(&root_parent);
+	if (parent_nd.mnt != new_nd.mnt)
+		path_release(&parent_nd);
 out2:
 	up(&old_nd.dentry->d_inode->i_zombie);
 	up(&mount_sem);
@@ -1769,7 +1774,7 @@
 		return error;
 	}
 	/* FIXME: we should hold i_zombie on nd.dentry */
-	move_vfsmnt(old_rootmnt, nd.dentry, nd.mnt, "/dev/root.old");
+	move_vfsmnt(old_rootmnt, &nd, "/dev/root.old");
 	mntput(old_rootmnt);
 	path_release(&nd);
 	return 0;


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] (part 2) fs/super.c cleanups
  2001-05-23  4:15 ` [PATCH] (part 2) " Alexander Viro
@ 2001-05-23  4:25   ` Andrew Morton
  2001-05-23  4:39     ` Alexander Viro
  2001-05-23  6:10   ` [PATCH] (part 3) " Alexander Viro
  1 sibling, 1 reply; 5+ messages in thread
From: Andrew Morton @ 2001-05-23  4:25 UTC (permalink / raw)
  To: Alexander Viro; +Cc: linux-kernel

Alexander Viro wrote:
> 
>         Locking rules: both require mount_sem and dcache_lock being
> held by callers.
>

It would help a lot if locking rules were commented in 
the source, rather than on linux-kernel.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] (part 2) fs/super.c cleanups
  2001-05-23  4:25   ` Andrew Morton
@ 2001-05-23  4:39     ` Alexander Viro
  0 siblings, 0 replies; 5+ messages in thread
From: Alexander Viro @ 2001-05-23  4:39 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-kernel



On Wed, 23 May 2001, Andrew Morton wrote:

> Alexander Viro wrote:
> > 
> >         Locking rules: both require mount_sem and dcache_lock being
> > held by callers.
> >
> 
> It would help a lot if locking rules were commented in 
> the source, rather than on linux-kernel.

They will change in the next chunks. In particular, we'll need
rwlock for these two instead of mount_sem.

Current locking rules for fs/super.c are mess. It used to be completely
under BKL and nobody cared much about races there, so lots of things
are sloppy. As usual - there is no such thing as SMP-only race...

New variant makes much more sense, but I'm feeding it in small chunks and
one of the obvious requirements is that at every stage situation should
be better or same as on the previous step. It's -STABLE, damnit.


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] (part 3) fs/super.c cleanups
  2001-05-23  4:15 ` [PATCH] (part 2) " Alexander Viro
  2001-05-23  4:25   ` Andrew Morton
@ 2001-05-23  6:10   ` Alexander Viro
  1 sibling, 0 replies; 5+ messages in thread
From: Alexander Viro @ 2001-05-23  6:10 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-kernel

	OK, chunk #3: beginnings of garbage collection for vfsmounts
and cleanup of do_umount() path.

	* kill_super() had always been conditional on the
list_empty(&s->s_mounts). Check had been pulled inside kill_super(),
if we still have other mounts of that superblock kill_super() simply
returns.  All callers of kill_super() call it unconditionally now.

	* remove_vfsmnt() was an interesting (and obnoxious) beast.
It used to do the following: we called it with dcache_lock held and
passed it the last reference to struct vfsmount *. It detached the
thing from the tree, dropped dcache_lock, freed vfsmount and returned,
leaving us to call kill_super() (if that was the last vfsmount over
that superblock, that is). Ugly and I'm the one to blame here - I
plead the bad taste attack.  It's gone now.  First of all, detaching
from the tree is done by callers of remove_vfsmnt() now. The rest +
call of kill_super() became __mntput(mnt) - it frees the thing and
kills superblock if needed.
	Notice that last reference to vfsmount was _always_ dropped that way.
mntput() called BUG(); if the reference dropped to 0.  The next step is
obvious - now we call __mntput() instead.

	* rules for mntput() had been changed: instead of old "thou shalt
not give the last reference up with mntput()" it's "the last reference
should be killed by mntput() from fs/super.c (old remove_vfsmount() callers)."
	That restriction will be lifted as soon as we get sane locking
(->s_umount instead of the mount_sem crap) on read_super() and friends.
For the time being we simply extend the definition of mntput() - all old
callers never hit the last reference, new ones always do.

	* do_umount() leaves the final call of mntput() to its callers
(each exit path used to end either on remove_vfsmnt() or on mntput()).
As the result we got rid of
	dput(nd.dentry);
	/* It drops nd.mnt */
	do_umount(nd.mnt, 0);
stuff - now it's nice and sane
	do_umount(nd.mnt, 0);
	path_release(&nd);

So there... BTW, kern_umount() turned into mntput()

Linus, if you feel that this one would be better off split into several
steps - please, tell, if it's clean enough - please apply ;-)
								Al
PS: I'm holding the next chunk in case if you have objections to ones
that had been sent so far or want to split the last one.  If you are
OK with these - the next step is saner exclusion (based on ->s_umount).
That will remove all limitations from mntput() and close a bunch of existing
races.

diff -urN S5-pre5-mnt_detach/fs/super.c S5-pre5-GC/fs/super.c
--- S5-pre5-mnt_detach/fs/super.c	Wed May 23 00:19:59 2001
+++ S5-pre5-GC/fs/super.c	Wed May 23 01:21:30 2001
@@ -407,24 +407,20 @@
 		path_release(&parent_nd);
 }
 
-/*
- * Called with spinlock held, releases it.
- */
-static void remove_vfsmnt(struct vfsmount *mnt)
+static void kill_super(struct super_block *);
+
+void __mntput(struct vfsmount *mnt)
 {
-	struct nameidata parent_nd;
-	/* First of all, remove it from all lists */
-	detach_mnt(mnt, &parent_nd);
+	struct super_block *sb = mnt->mnt_sb;
+
+	dput(mnt->mnt_root);
+	spin_lock(&dcache_lock);
 	list_del(&mnt->mnt_instances);
-	list_del(&mnt->mnt_list);
 	spin_unlock(&dcache_lock);
-	/* Now we can work safely */
-	dput(mnt->mnt_root);
-	if (parent_nd.mnt != mnt)
-		path_release(&parent_nd);
 	if (mnt->mnt_devname)
 		kfree(mnt->mnt_devname);
 	kfree(mnt);
+	kill_super(sb);
 }
 
 
@@ -872,6 +868,12 @@
 	struct file_system_type *fs = sb->s_type;
 	struct super_operations *sop = sb->s_op;
 
+	spin_lock(&dcache_lock);
+	if (!list_empty(&sb->s_mounts)) {
+		spin_unlock(&dcache_lock);
+		return;
+	}
+	spin_unlock(&dcache_lock);
 	down_write(&sb->s_umount);
 	sb->s_root = NULL;
 	/* Need to clean after the sucker */
@@ -964,16 +966,6 @@
 	return mnt;
 }
 
-/* Call only after unregister_filesystem() - it's a final cleanup */
-
-void kern_umount(struct vfsmount *mnt)
-{
-	struct super_block *sb = mnt->mnt_sb;
-	spin_lock(&dcache_lock);
-	remove_vfsmnt(mnt);
-	kill_super(sb);
-}
-
 /*
  * Doesn't take quota and stuff into account. IOW, in some cases it will
  * give false negatives. The main reason why it's here is that we need
@@ -989,6 +981,7 @@
 static int do_umount(struct vfsmount *mnt, int flags)
 {
 	struct super_block * sb = mnt->mnt_sb;
+	struct nameidata parent_nd;
 
 	/*
 	 * No sense to grab the lock for this test, but test itself looks
@@ -1005,7 +998,6 @@
 		 * Special case for "unmounting" root ...
 		 * we just try to remount it readonly.
 		 */
-		mntput(mnt);
 		return do_remount("/", MS_RDONLY, NULL);
 	}
 
@@ -1014,14 +1006,16 @@
 	if (mnt->mnt_instances.next != mnt->mnt_instances.prev) {
 		if (atomic_read(&mnt->mnt_count) > 2) {
 			spin_unlock(&dcache_lock);
-			mntput(mnt);
 			return -EBUSY;
 		}
 		if (sb->s_type->fs_flags & FS_SINGLE)
 			put_filesystem(sb->s_type);
-		/* We hold two references, so mntput() is safe */
+		detach_mnt(mnt, &parent_nd);
+		list_del(&mnt->mnt_list);
+		spin_unlock(&dcache_lock);
 		mntput(mnt);
-		remove_vfsmnt(mnt);
+		if (parent_nd.mnt != mnt)
+			path_release(&parent_nd);
 		return 0;
 	}
 	spin_unlock(&dcache_lock);
@@ -1053,15 +1047,16 @@
 	spin_lock(&dcache_lock);
 	if (atomic_read(&mnt->mnt_count) > 2) {
 		spin_unlock(&dcache_lock);
-		mntput(mnt);
 		return -EBUSY;
 	}
 
 	/* OK, that's the point of no return */
+	detach_mnt(mnt, &parent_nd);
+	list_del(&mnt->mnt_list);
+	spin_unlock(&dcache_lock);
 	mntput(mnt);
-	remove_vfsmnt(mnt);
-
-	kill_super(sb);
+	if (parent_nd.mnt != mnt)
+		path_release(&parent_nd);
 	return 0;
 }
 
@@ -1079,7 +1074,6 @@
 	char *kname;
 	int retval;
 
-	lock_kernel();
 	kname = getname(name);
 	retval = PTR_ERR(kname);
 	if (IS_ERR(kname))
@@ -1098,16 +1092,16 @@
 	if (!capable(CAP_SYS_ADMIN) && current->uid!=nd.mnt->mnt_owner)
 		goto dput_and_out;
 
-	dput(nd.dentry);
-	/* puts nd.mnt */
 	down(&mount_sem);
+	lock_kernel();
 	retval = do_umount(nd.mnt, flags);
+	unlock_kernel();
+	path_release(&nd);
 	up(&mount_sem);
 	goto out;
 dput_and_out:
 	path_release(&nd);
 out:
-	unlock_kernel();
 	return retval;
 }
 
@@ -1370,8 +1364,7 @@
 fail:
 	if (fstype->fs_flags & FS_SINGLE)
 		put_filesystem(fstype);
-	if (list_empty(&sb->s_mounts))
-		kill_super(sb);
+	kill_super(sb);
 	goto unlock_out;
 }
 
@@ -1732,10 +1725,9 @@
 	if (!error) {
 		if (devfs_nd.mnt->mnt_sb->s_magic == DEVFS_SUPER_MAGIC &&
 		    devfs_nd.dentry == devfs_nd.mnt->mnt_root) {
-			dput(devfs_nd.dentry);
 			down(&mount_sem);
-			/* puts devfs_nd.mnt */
 			do_umount(devfs_nd.mnt, 0);
+			path_release(&devfs_nd);
 			up(&mount_sem);
 		} else 
 			path_release(&devfs_nd);
@@ -1762,6 +1754,7 @@
 		printk(KERN_NOTICE "Trying to unmount old root ... ");
 		if (!blivet) {
 			blivet = do_umount(old_rootmnt, 0);
+			mntput(old_rootmnt);
 			if (!blivet) {
 				ioctl_by_bdev(ramdisk, BLKFLSBUF, 0);
 				printk("okay\n");
diff -urN S5-pre5-mnt_detach/include/linux/fs.h S5-pre5-GC/include/linux/fs.h
--- S5-pre5-mnt_detach/include/linux/fs.h	Tue May 22 16:44:21 2001
+++ S5-pre5-GC/include/linux/fs.h	Wed May 23 01:18:03 2001
@@ -908,10 +908,10 @@
 extern int register_filesystem(struct file_system_type *);
 extern int unregister_filesystem(struct file_system_type *);
 extern struct vfsmount *kern_mount(struct file_system_type *);
-extern void kern_umount(struct vfsmount *);
 extern int may_umount(struct vfsmount *);
 extern long do_mount(char *, char *, char *, unsigned long, void *);
 
+#define kern_umount mntput
 
 extern int vfs_statfs(struct super_block *, struct statfs *);
 
diff -urN S5-pre5-mnt_detach/include/linux/mount.h S5-pre5-GC/include/linux/mount.h
--- S5-pre5-mnt_detach/include/linux/mount.h	Fri Feb 16 18:33:56 2001
+++ S5-pre5-GC/include/linux/mount.h	Wed May 23 01:11:04 2001
@@ -39,11 +39,13 @@
 	return mnt;
 }
 
+extern void __mntput(struct vfsmount *mnt);
+
 static inline void mntput(struct vfsmount *mnt)
 {
 	if (mnt) {
 		if (atomic_dec_and_test(&mnt->mnt_count))
-			BUG();
+			__mntput(mnt);
 	}
 }
 
diff -urN S5-pre5-mnt_detach/kernel/ksyms.c S5-pre5-GC/kernel/ksyms.c
--- S5-pre5-mnt_detach/kernel/ksyms.c	Tue May 22 16:44:21 2001
+++ S5-pre5-GC/kernel/ksyms.c	Wed May 23 01:12:06 2001
@@ -320,7 +320,7 @@
 EXPORT_SYMBOL(register_filesystem);
 EXPORT_SYMBOL(unregister_filesystem);
 EXPORT_SYMBOL(kern_mount);
-EXPORT_SYMBOL(kern_umount);
+EXPORT_SYMBOL(__mntput);
 EXPORT_SYMBOL(may_umount);
 
 /* executable format registration */


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2001-05-23  6:10 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2001-05-23  3:26 [PATCH] (part 1) fs/super.c cleanups Alexander Viro
2001-05-23  4:15 ` [PATCH] (part 2) " Alexander Viro
2001-05-23  4:25   ` Andrew Morton
2001-05-23  4:39     ` Alexander Viro
2001-05-23  6:10   ` [PATCH] (part 3) " Alexander Viro

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.