Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/kern When mounting a file system re-lookup and lock the ...
details: https://anonhg.NetBSD.org/src/rev/ef8ca81b264d
branches: trunk
changeset: 755675:ef8ca81b264d
user: hannken <hannken%NetBSD.org@localhost>
date: Tue Jun 15 09:43:36 2010 +0000
description:
When mounting a file system re-lookup and lock the directory we mount on
after the file system is setup by VFS_MOUNT(). This way recursive vnode
locks are no longer needed here and mounts on null mounts no longer fail
as described in PR #43439 (mount_null panic: lockdebug_wantlock: locking
against myself).
Based on a proposal from and
Reviewed by: David A. Holland <dholland%netbsd.org@localhost>
diffstat:
sys/kern/vfs_syscalls.c | 108 +++++++++++++++++++++++++++--------------------
1 files changed, 62 insertions(+), 46 deletions(-)
diffs (207 lines):
diff -r ed6a4c417d00 -r ef8ca81b264d sys/kern/vfs_syscalls.c
--- a/sys/kern/vfs_syscalls.c Tue Jun 15 06:36:08 2010 +0000
+++ b/sys/kern/vfs_syscalls.c Tue Jun 15 09:43:36 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: vfs_syscalls.c,v 1.404 2010/03/03 00:47:31 yamt Exp $ */
+/* $NetBSD: vfs_syscalls.c,v 1.405 2010/06/15 09:43:36 hannken Exp $ */
/*-
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -66,7 +66,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.404 2010/03/03 00:47:31 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.405 2010/06/15 09:43:36 hannken Exp $");
#ifdef _KERNEL_OPT
#include "opt_fileassoc.h"
@@ -290,11 +290,12 @@
static int
mount_domount(struct lwp *l, struct vnode **vpp, struct vfsops *vfsops,
- const char *path, int flags, void *data, size_t *data_len, u_int recurse)
+ const char *path, int flags, void *data, size_t *data_len)
{
struct mount *mp;
struct vnode *vp = *vpp;
struct vattr va;
+ struct nameidata nd;
int error;
error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT,
@@ -327,19 +328,6 @@
return EINVAL;
}
- if ((error = vinvalbuf(vp, V_SAVE, l->l_cred, l, 0, 0)) != 0) {
- vfs_delref(vfsops);
- return error;
- }
-
- /*
- * Check if a file-system is not already mounted on this vnode.
- */
- if (vp->v_mountedhere != NULL) {
- vfs_delref(vfsops);
- return EBUSY;
- }
-
if ((mp = vfs_mountalloc(vfsops, vp)) == NULL) {
vfs_delref(vfsops);
return ENOMEM;
@@ -363,30 +351,55 @@
error = VFS_MOUNT(mp, path, data, data_len);
mp->mnt_flag &= ~MNT_OP_FLAGS;
+ if (error != 0)
+ goto err_unmounted;
+
+ /*
+ * Validate and prepare the mount point.
+ */
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT,
+ UIO_USERSPACE, path);
+ error = namei(&nd);
+ if (error != 0) {
+ goto err_mounted;
+ }
+ if (nd.ni_vp != vp) {
+ vput(nd.ni_vp);
+ error = EINVAL;
+ goto err_mounted;
+ }
+ if (vp->v_mountedhere != NULL) {
+ vput(nd.ni_vp);
+ error = EBUSY;
+ goto err_mounted;
+ }
+ error = vinvalbuf(vp, V_SAVE, l->l_cred, l, 0, 0);
+ if (error != 0) {
+ vput(nd.ni_vp);
+ goto err_mounted;
+ }
+
/*
* Put the new filesystem on the mount list after root.
*/
cache_purge(vp);
- if (error != 0) {
- vp->v_mountedhere = NULL;
- mutex_exit(&mp->mnt_updating);
- vfs_unbusy(mp, false, NULL);
- vfs_destroy(mp);
- return error;
- }
-
mp->mnt_iflag &= ~IMNT_WANTRDWR;
+
mutex_enter(&mountlist_lock);
- vp->v_mountedhere = mp;
CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
mutex_exit(&mountlist_lock);
- vn_restorerecurse(vp, recurse);
- VOP_UNLOCK(vp, 0);
- checkdirs(vp);
if ((mp->mnt_flag & (MNT_RDONLY | MNT_ASYNC)) == 0)
error = vfs_allocate_syncvnode(mp);
+ if (error == 0)
+ vp->v_mountedhere = mp;
+ vput(nd.ni_vp);
+ if (error != 0)
+ goto err_onmountlist;
+
+ checkdirs(vp);
+ mutex_exit(&mp->mnt_updating);
+
/* Hold an additional reference to the mount across VFS_START(). */
- mutex_exit(&mp->mnt_updating);
vfs_unbusy(mp, true, NULL);
(void) VFS_STATVFS(mp, &mp->mnt_stat);
error = VFS_START(mp, 0);
@@ -396,6 +409,24 @@
vfs_destroy(mp);
*vpp = NULL;
return error;
+
+err_onmountlist:
+ mutex_enter(&mountlist_lock);
+ CIRCLEQ_REMOVE(&mountlist, mp, mnt_list);
+ mp->mnt_iflag |= IMNT_GONE;
+ mutex_exit(&mountlist_lock);
+
+err_mounted:
+ if (VFS_UNMOUNT(mp, MNT_FORCE) != 0)
+ panic("Unmounting fresh file system failed");
+
+err_unmounted:
+ vp->v_mountedhere = NULL;
+ mutex_exit(&mp->mnt_updating);
+ vfs_unbusy(mp, false, NULL);
+ vfs_destroy(mp);
+
+ return error;
}
static int
@@ -457,7 +488,6 @@
{
struct vnode *vp;
void *data_buf = data;
- u_int recurse;
bool vfsopsrele = false;
int error;
@@ -470,33 +500,20 @@
*/
error = namei_simple_user(path, NSM_FOLLOW_TRYEMULROOT, &vp);
if (error != 0) {
- /* XXXgcc */
vp = NULL;
- recurse = 0;
goto done;
}
- /*
- * A lookup in VFS_MOUNT might result in an attempt to
- * lock this vnode again, so make the lock recursive.
- */
if (vfsops == NULL) {
if (flags & (MNT_GETARGS | MNT_UPDATE)) {
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
- recurse = vn_setrecurse(vp);
vfsops = vp->v_mount->mnt_op;
} else {
/* 'type' is userspace */
error = mount_get_vfsops(type, &vfsops);
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
- recurse = vn_setrecurse(vp);
if (error != 0)
goto done;
vfsopsrele = true;
}
- } else {
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
- recurse = vn_setrecurse(vp);
}
if (data != NULL && data_seg == UIO_USERSPACE) {
@@ -540,7 +557,7 @@
/* Locking is handled internally in mount_domount(). */
KASSERT(vfsopsrele == true);
error = mount_domount(l, &vp, vfsops, path, flags, data_buf,
- &data_len, recurse);
+ &data_len);
vfsopsrele = false;
}
@@ -548,8 +565,7 @@
if (vfsopsrele)
vfs_delref(vfsops);
if (vp != NULL) {
- vn_restorerecurse(vp, recurse);
- vput(vp);
+ vrele(vp);
}
if (data_buf != data)
kmem_free(data_buf, data_len);
Home |
Main Index |
Thread Index |
Old Index