kern/38135 vfs_busy/vfs_trybusy confusion
The symptom was that sometimes file systems would occasionally not appear in output from 'df' or 'mount' if the system was busy. Resolution: - Make mount locks work somewhat like vm_map locks. - vfs_trybusy() now only fails if the mount is gone, or if someone is unmounting the file system. Simple contention on mnt_lock doesn't cause it to fail. - vfs_busy() will wait even if the file system is being unmounted.
This commit is contained in:
parent
94ff46d894
commit
e3610f1886
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: coda_psdev.c,v 1.43 2008/04/24 18:39:22 ad Exp $ */
|
||||
/* $NetBSD: coda_psdev.c,v 1.44 2008/04/29 23:51:04 ad Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
@ -54,7 +54,7 @@
|
||||
/* These routines are the device entry points for Venus. */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: coda_psdev.c,v 1.43 2008/04/24 18:39:22 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: coda_psdev.c,v 1.44 2008/04/29 23:51:04 ad Exp $");
|
||||
|
||||
extern int coda_nc_initialized; /* Set if cache has been initialized */
|
||||
|
||||
@ -202,7 +202,7 @@ vc_nb_close(dev_t dev, int flag, int mode, struct lwp *l)
|
||||
*/
|
||||
mutex_enter(&syncer_mutex);
|
||||
VTOC(mi->mi_rootvp)->c_flags |= C_UNMOUNTING;
|
||||
if (vfs_busy(mi->mi_vfsp, RW_WRITER, NULL)) {
|
||||
if (vfs_busy(mi->mi_vfsp, RW_WRITER)) {
|
||||
mutex_exit(&syncer_mutex);
|
||||
return (EBUSY);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: vfs_syscalls_20.c,v 1.26 2008/03/21 21:54:58 ad Exp $ */
|
||||
/* $NetBSD: vfs_syscalls_20.c,v 1.27 2008/04/29 23:51:04 ad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
@ -37,7 +37,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls_20.c,v 1.26 2008/03/21 21:54:58 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls_20.c,v 1.27 2008/04/29 23:51:04 ad Exp $");
|
||||
|
||||
#include "opt_compat_netbsd.h"
|
||||
#include "opt_compat_43.h"
|
||||
@ -222,8 +222,7 @@ compat_20_sys_getfsstat(struct lwp *l, const struct compat_20_sys_getfsstat_args
|
||||
count = 0;
|
||||
for (mp = CIRCLEQ_FIRST(&mountlist); mp != (void *)&mountlist;
|
||||
mp = nmp) {
|
||||
if (vfs_trybusy(mp, RW_READER, &mountlist_lock)) {
|
||||
nmp = CIRCLEQ_NEXT(mp, mnt_list);
|
||||
if (vfs_trybusy(mp, RW_READER, &nmp)) {
|
||||
continue;
|
||||
}
|
||||
if (sfsp && count < maxcount) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: puffs_msgif.c,v 1.68 2008/01/31 08:23:04 tnn Exp $ */
|
||||
/* $NetBSD: puffs_msgif.c,v 1.69 2008/04/29 23:51:04 ad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved.
|
||||
@ -30,7 +30,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: puffs_msgif.c,v 1.68 2008/01/31 08:23:04 tnn Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: puffs_msgif.c,v 1.69 2008/04/29 23:51:04 ad Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/atomic.h>
|
||||
@ -1051,7 +1051,7 @@ puffs_msgif_close(void *this)
|
||||
* is already a goner.
|
||||
* XXX: skating on the thin ice of modern calling conventions ...
|
||||
*/
|
||||
if (vfs_busy(mp, RW_WRITER, NULL)) {
|
||||
if (vfs_busy(mp, RW_WRITER)) {
|
||||
mutex_exit(&syncer_mutex);
|
||||
vfs_destroy(mp);
|
||||
return 0;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: union_vnops.c,v 1.30 2008/02/27 19:59:48 matt Exp $ */
|
||||
/* $NetBSD: union_vnops.c,v 1.31 2008/04/29 23:51:04 ad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992, 1993, 1994, 1995
|
||||
@ -72,7 +72,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: union_vnops.c,v 1.30 2008/02/27 19:59:48 matt Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: union_vnops.c,v 1.31 2008/04/29 23:51:04 ad Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -249,7 +249,7 @@ union_lookup1(struct vnode *udvp, struct vnode **dvpp, struct vnode **vpp,
|
||||
*/
|
||||
while (dvp != udvp && (dvp->v_type == VDIR) &&
|
||||
(mp = dvp->v_mountedhere)) {
|
||||
if (vfs_busy(mp, RW_READER, 0))
|
||||
if (vfs_busy(mp, RW_READER))
|
||||
continue;
|
||||
vput(dvp);
|
||||
error = VFS_ROOT(mp, &tdvp);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: vfs_lookup.c,v 1.104 2008/01/30 11:47:00 ad Exp $ */
|
||||
/* $NetBSD: vfs_lookup.c,v 1.105 2008/04/29 23:51:04 ad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1989, 1993
|
||||
@ -37,7 +37,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.104 2008/01/30 11:47:00 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.105 2008/04/29 23:51:04 ad Exp $");
|
||||
|
||||
#include "opt_magiclinks.h"
|
||||
|
||||
@ -776,7 +776,7 @@ unionlookup:
|
||||
*/
|
||||
while (dp->v_type == VDIR && (mp = dp->v_mountedhere) &&
|
||||
(cnp->cn_flags & NOCROSSMOUNT) == 0) {
|
||||
if (vfs_busy(mp, RW_READER, 0))
|
||||
if (vfs_busy(mp, RW_READER))
|
||||
continue;
|
||||
|
||||
KASSERT(ndp->ni_dvp != dp);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: vfs_subr.c,v 1.337 2008/04/28 20:24:05 martin Exp $ */
|
||||
/* $NetBSD: vfs_subr.c,v 1.338 2008/04/29 23:51:04 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997, 1998, 2004, 2005, 2007, 2008 The NetBSD Foundation, Inc.
|
||||
@ -75,7 +75,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.337 2008/04/28 20:24:05 martin Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.338 2008/04/29 23:51:04 ad Exp $");
|
||||
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_compat_netbsd.h"
|
||||
@ -282,25 +282,15 @@ try_nextlist:
|
||||
return vp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark a mount point as busy, and gain a new reference to it. Used to
|
||||
* synchronize access and to delay unmounting.
|
||||
*
|
||||
* => Interlock is not released on failure.
|
||||
* => If no interlock, the caller is expected to already hold a reference
|
||||
* on the mount.
|
||||
* => If interlocked, the interlock must prevent the last reference to
|
||||
* the mount from disappearing.
|
||||
*/
|
||||
int
|
||||
vfs_busy(struct mount *mp, const krw_t op, kmutex_t *interlock)
|
||||
static inline int
|
||||
vfs_dobusy(struct mount *mp, const krw_t op, struct mount **nextp)
|
||||
{
|
||||
|
||||
KASSERT(mp->mnt_refcnt > 0);
|
||||
|
||||
atomic_inc_uint(&mp->mnt_refcnt);
|
||||
if (interlock != NULL) {
|
||||
mutex_exit(interlock);
|
||||
if (nextp != NULL) {
|
||||
mutex_exit(&mountlist_lock);
|
||||
}
|
||||
if (mp->mnt_writer == curlwp) {
|
||||
mp->mnt_recursecnt++;
|
||||
@ -311,11 +301,12 @@ vfs_busy(struct mount *mp, const krw_t op, kmutex_t *interlock)
|
||||
mp->mnt_writer = curlwp;
|
||||
}
|
||||
}
|
||||
if ((mp->mnt_iflag & IMNT_GONE) != 0) {
|
||||
vfs_unbusy(mp, false);
|
||||
if (interlock != NULL) {
|
||||
mutex_enter(interlock);
|
||||
if (__predict_false((mp->mnt_iflag & IMNT_GONE) != 0)) {
|
||||
if (nextp != NULL) {
|
||||
mutex_enter(&mountlist_lock);
|
||||
*nextp = CIRCLEQ_NEXT(mp, mnt_list);
|
||||
}
|
||||
vfs_unbusy(mp, false);
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
@ -323,35 +314,62 @@ vfs_busy(struct mount *mp, const krw_t op, kmutex_t *interlock)
|
||||
}
|
||||
|
||||
/*
|
||||
* As vfs_busy(), but return immediately if the mount cannot be
|
||||
* locked without waiting.
|
||||
* Mark a mount point as busy, and gain a new reference to it. Used to
|
||||
* synchronize access and to delay unmounting.
|
||||
*
|
||||
* => The caller is expected to hold a reference to the mount.
|
||||
*/
|
||||
int
|
||||
vfs_trybusy(struct mount *mp, krw_t op, kmutex_t *interlock)
|
||||
vfs_busy(struct mount *mp, const krw_t op)
|
||||
{
|
||||
int error;
|
||||
|
||||
KASSERT(mp->mnt_refcnt > 0);
|
||||
|
||||
if (mp->mnt_writer == curlwp) {
|
||||
mp->mnt_recursecnt++;
|
||||
} else {
|
||||
if (!rw_tryenter(&mp->mnt_lock, op)) {
|
||||
return EBUSY;
|
||||
for (;;) {
|
||||
error = vfs_dobusy(mp, op, NULL);
|
||||
if (error != 0) {
|
||||
return error;
|
||||
}
|
||||
if (op == RW_WRITER) {
|
||||
KASSERT(mp->mnt_writer == NULL);
|
||||
mp->mnt_writer = curlwp;
|
||||
if (__predict_true(mp->mnt_unmounter == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
mutex_enter(&mount_lock);
|
||||
if (mp->mnt_unmounter != NULL) {
|
||||
vfs_unbusy(mp, false);
|
||||
cv_wait(&mount_cv, &mount_lock);
|
||||
}
|
||||
mutex_exit(&mount_lock);
|
||||
}
|
||||
atomic_inc_uint(&mp->mnt_refcnt);
|
||||
if ((mp->mnt_iflag & IMNT_GONE) != 0) {
|
||||
}
|
||||
|
||||
/*
|
||||
* As vfs_busy(), but return error if the file system is being
|
||||
* unmounted (and do not wait for the unmount).
|
||||
*
|
||||
* => If namep != NULL, mountlist_lock is understood to be held. On
|
||||
* failure a pointer to the next mount will be returned via namep.
|
||||
*
|
||||
* => If namep == NULL, the caller is expected to hold a reference
|
||||
* to the mount.
|
||||
*/
|
||||
int
|
||||
vfs_trybusy(struct mount *mp, krw_t op, struct mount **nextp)
|
||||
{
|
||||
lwp_t *l;
|
||||
int error;
|
||||
|
||||
KASSERT(nextp == NULL || mutex_owned(&mountlist_lock));
|
||||
|
||||
error = vfs_dobusy(mp, op, nextp);
|
||||
l = mp->mnt_unmounter;
|
||||
if (error == 0 && (l != NULL && l != curlwp)) {
|
||||
if (nextp != NULL) {
|
||||
mutex_enter(&mountlist_lock);
|
||||
*nextp = CIRCLEQ_NEXT(mp, mnt_list);
|
||||
}
|
||||
vfs_unbusy(mp, false);
|
||||
return ENOENT;
|
||||
error = EBUSY;
|
||||
}
|
||||
if (interlock != NULL) {
|
||||
mutex_exit(interlock);
|
||||
}
|
||||
return 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -411,7 +429,7 @@ vfs_rootmountalloc(const char *fstypename, const char *devname,
|
||||
mp->mnt_refcnt = 1;
|
||||
rw_init(&mp->mnt_lock);
|
||||
mutex_init(&mp->mnt_renamelock, MUTEX_DEFAULT, IPL_NONE);
|
||||
(void)vfs_busy(mp, RW_WRITER, NULL);
|
||||
(void)vfs_busy(mp, RW_WRITER);
|
||||
TAILQ_INIT(&mp->mnt_vnodelist);
|
||||
mp->mnt_op = vfsp;
|
||||
mp->mnt_flag = MNT_RDONLY;
|
||||
@ -455,7 +473,7 @@ getnewvnode(enum vtagtype tag, struct mount *mp, int (**vops)(void *),
|
||||
* -f), this will return an error. If the
|
||||
* unmount fails, we'll keep going afterwards.
|
||||
*/
|
||||
error = vfs_busy(mp, RW_READER, NULL);
|
||||
error = vfs_busy(mp, RW_READER);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
@ -1630,8 +1648,7 @@ sysctl_kern_vnode(SYSCTLFN_ARGS)
|
||||
mutex_enter(&mountlist_lock);
|
||||
for (mp = CIRCLEQ_FIRST(&mountlist); mp != (void *)&mountlist;
|
||||
mp = nmp) {
|
||||
if (vfs_trybusy(mp, RW_READER, &mountlist_lock)) {
|
||||
nmp = CIRCLEQ_NEXT(mp, mnt_list);
|
||||
if (vfs_trybusy(mp, RW_READER, &nmp)) {
|
||||
continue;
|
||||
}
|
||||
savebp = bp;
|
||||
@ -1763,7 +1780,7 @@ vfs_unmountall(struct lwp *l)
|
||||
* mount point. See dounmount() for details.
|
||||
*/
|
||||
mutex_enter(&syncer_mutex);
|
||||
if (vfs_busy(mp, RW_WRITER, NULL)) {
|
||||
if (vfs_busy(mp, RW_WRITER)) {
|
||||
mutex_exit(&syncer_mutex);
|
||||
continue;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: vfs_subr2.c,v 1.20 2008/04/28 20:24:05 martin Exp $ */
|
||||
/* $NetBSD: vfs_subr2.c,v 1.21 2008/04/29 23:51:04 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997, 1998, 2004, 2005, 2007, 2008 The NetBSD Foundation, Inc.
|
||||
@ -75,7 +75,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_subr2.c,v 1.20 2008/04/28 20:24:05 martin Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_subr2.c,v 1.21 2008/04/29 23:51:04 ad Exp $");
|
||||
|
||||
#include "opt_ddb.h"
|
||||
|
||||
@ -123,6 +123,8 @@ kmutex_t mntvnode_lock;
|
||||
kmutex_t vnode_free_list_lock;
|
||||
kmutex_t specfs_lock;
|
||||
kmutex_t vfs_list_lock;
|
||||
kmutex_t mount_lock;
|
||||
kcondvar_t mount_cv;
|
||||
|
||||
struct mntlist mountlist = /* mounted filesystem list */
|
||||
CIRCLEQ_HEAD_INITIALIZER(mountlist);
|
||||
@ -154,6 +156,8 @@ vntblinit(void)
|
||||
mutex_init(&vnode_free_list_lock, MUTEX_DEFAULT, IPL_NONE);
|
||||
mutex_init(&specfs_lock, MUTEX_DEFAULT, IPL_NONE);
|
||||
mutex_init(&vfs_list_lock, MUTEX_DEFAULT, IPL_NONE);
|
||||
mutex_init(&mount_lock, MUTEX_DEFAULT, IPL_NONE);
|
||||
cv_init(&mount_cv, "mount");
|
||||
|
||||
mount_specificdata_domain = specificdata_domain_create();
|
||||
|
||||
@ -194,6 +198,7 @@ vfs_destroy(struct mount *mp)
|
||||
if (atomic_dec_uint_nv(&mp->mnt_refcnt) > 0) {
|
||||
return;
|
||||
}
|
||||
KASSERT(mp->mnt_unmounter == NULL);
|
||||
specificdata_fini(mount_specificdata_domain, &mp->mnt_specdataref);
|
||||
rw_destroy(&mp->mnt_lock);
|
||||
if (mp->mnt_op != NULL) {
|
||||
@ -716,8 +721,7 @@ printlockedvnodes(void)
|
||||
mutex_enter(&mountlist_lock);
|
||||
for (mp = CIRCLEQ_FIRST(&mountlist); mp != (void *)&mountlist;
|
||||
mp = nmp) {
|
||||
if (vfs_trybusy(mp, RW_READER, &mountlist_lock)) {
|
||||
nmp = CIRCLEQ_NEXT(mp, mnt_list);
|
||||
if (vfs_trybusy(mp, RW_READER, &nmp)) {
|
||||
continue;
|
||||
}
|
||||
TAILQ_FOREACH(vp, &mp->mnt_vnodelist, v_mntvnodes) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: vfs_syscalls.c,v 1.352 2008/04/29 15:51:23 ad Exp $ */
|
||||
/* $NetBSD: vfs_syscalls.c,v 1.353 2008/04/29 23:51:04 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2008 The NetBSD Foundation, Inc.
|
||||
@ -63,7 +63,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.352 2008/04/29 15:51:23 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.353 2008/04/29 23:51:04 ad Exp $");
|
||||
|
||||
#include "opt_compat_netbsd.h"
|
||||
#include "opt_compat_43.h"
|
||||
@ -187,7 +187,7 @@ mount_update(struct lwp *l, struct vnode *vp, const char *path, int flags,
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
if (vfs_trybusy(mp, RW_WRITER, 0)) {
|
||||
if (vfs_busy(mp, RW_WRITER)) {
|
||||
error = EPERM;
|
||||
goto out;
|
||||
}
|
||||
@ -337,7 +337,7 @@ mount_domount(struct lwp *l, struct vnode **vpp, struct vfsops *vfsops,
|
||||
TAILQ_INIT(&mp->mnt_vnodelist);
|
||||
rw_init(&mp->mnt_lock);
|
||||
mutex_init(&mp->mnt_renamelock, MUTEX_DEFAULT, IPL_NONE);
|
||||
(void)vfs_busy(mp, RW_WRITER, 0);
|
||||
(void)vfs_busy(mp, RW_WRITER);
|
||||
|
||||
mp->mnt_vnodecovered = vp;
|
||||
mp->mnt_stat.f_owner = kauth_cred_geteuid(l->l_cred);
|
||||
@ -416,7 +416,7 @@ mount_getargs(struct lwp *l, struct vnode *vp, const char *path, int flags,
|
||||
if ((vp->v_vflag & VV_ROOT) == 0)
|
||||
return EINVAL;
|
||||
|
||||
if (vfs_trybusy(mp, RW_WRITER, NULL))
|
||||
if (vfs_busy(mp, RW_WRITER))
|
||||
return EPERM;
|
||||
|
||||
mp->mnt_flag &= ~MNT_OP_FLAGS;
|
||||
@ -653,7 +653,7 @@ sys_unmount(struct lwp *l, const struct sys_unmount_args *uap, register_t *retva
|
||||
* mount point. See dounmount() for details.
|
||||
*/
|
||||
mutex_enter(&syncer_mutex);
|
||||
error = vfs_busy(mp, RW_WRITER, NULL);
|
||||
error = vfs_busy(mp, RW_WRITER);
|
||||
vrele(vp);
|
||||
if (error != 0) {
|
||||
mutex_exit(&syncer_mutex);
|
||||
@ -663,6 +663,34 @@ sys_unmount(struct lwp *l, const struct sys_unmount_args *uap, register_t *retva
|
||||
return (dounmount(mp, SCARG(uap, flags), l));
|
||||
}
|
||||
|
||||
/*
|
||||
* Lock mount and keep additional reference across unmount.
|
||||
*/
|
||||
static void
|
||||
dounmount_lock(struct mount *mp)
|
||||
{
|
||||
|
||||
KASSERT(rw_write_held(&mp->mnt_lock));
|
||||
KASSERT(mp->mnt_unmounter == NULL);
|
||||
|
||||
mp->mnt_unmounter = curlwp;
|
||||
vfs_unbusy(mp, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Unlock mount and drop additional reference.
|
||||
*/
|
||||
static void
|
||||
dounmount_unlock(struct mount *mp)
|
||||
{
|
||||
|
||||
mutex_enter(&mount_lock);
|
||||
mp->mnt_unmounter = NULL;
|
||||
cv_broadcast(&mount_cv);
|
||||
mutex_exit(&mount_lock);
|
||||
vfs_destroy(mp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do the actual file system unmount. File system is assumed to have been
|
||||
* marked busy by the caller.
|
||||
@ -683,6 +711,7 @@ dounmount(struct mount *mp, int flags, struct lwp *l)
|
||||
return (error);
|
||||
#endif /* NVERIEXEC > 0 */
|
||||
|
||||
dounmount_lock(mp);
|
||||
used_syncer = (mp->mnt_syncer != NULL);
|
||||
|
||||
/*
|
||||
@ -726,7 +755,7 @@ dounmount(struct mount *mp, int flags, struct lwp *l)
|
||||
mp->mnt_flag |= async;
|
||||
if (used_syncer)
|
||||
mutex_exit(&syncer_mutex);
|
||||
vfs_unbusy(mp, false);
|
||||
dounmount_unlock(mp);
|
||||
return (error);
|
||||
}
|
||||
vfs_scrubvnlist(mp);
|
||||
@ -741,7 +770,7 @@ dounmount(struct mount *mp, int flags, struct lwp *l)
|
||||
if (used_syncer)
|
||||
mutex_exit(&syncer_mutex);
|
||||
vfs_hooks_unmount(mp);
|
||||
vfs_unbusy(mp, false);
|
||||
dounmount_unlock(mp);
|
||||
vfs_destroy(mp);
|
||||
if (coveredvp != NULLVP)
|
||||
vrele(coveredvp);
|
||||
@ -767,9 +796,9 @@ sys_sync(struct lwp *l, const void *v, register_t *retval)
|
||||
l = &lwp0;
|
||||
|
||||
mutex_enter(&mountlist_lock);
|
||||
for (mp = mountlist.cqh_last; mp != (void *)&mountlist; mp = nmp) {
|
||||
if (vfs_trybusy(mp, RW_READER, &mountlist_lock)) {
|
||||
nmp = mp->mnt_list.cqe_prev;
|
||||
for (mp = CIRCLEQ_FIRST(&mountlist); mp != (void *)&mountlist;
|
||||
mp = nmp) {
|
||||
if (vfs_trybusy(mp, RW_READER, &nmp)) {
|
||||
continue;
|
||||
}
|
||||
if ((mp->mnt_flag & MNT_RDONLY) == 0) {
|
||||
@ -780,7 +809,7 @@ sys_sync(struct lwp *l, const void *v, register_t *retval)
|
||||
mp->mnt_flag |= MNT_ASYNC;
|
||||
}
|
||||
mutex_enter(&mountlist_lock);
|
||||
nmp = mp->mnt_list.cqe_prev;
|
||||
nmp = mp->mnt_list.cqe_next;
|
||||
vfs_unbusy(mp, false);
|
||||
|
||||
}
|
||||
@ -988,8 +1017,7 @@ do_sys_getvfsstat(struct lwp *l, void *sfsp, size_t bufsize, int flags,
|
||||
count = 0;
|
||||
for (mp = CIRCLEQ_FIRST(&mountlist); mp != (void *)&mountlist;
|
||||
mp = nmp) {
|
||||
if (vfs_trybusy(mp, RW_READER, &mountlist_lock)) {
|
||||
nmp = CIRCLEQ_NEXT(mp, mnt_list);
|
||||
if (vfs_trybusy(mp, RW_READER, &nmp)) {
|
||||
continue;
|
||||
}
|
||||
if (sfsp && count < maxcount) {
|
||||
@ -1083,7 +1111,7 @@ sys_fchdir(struct lwp *l, const struct sys_fchdir_args *uap, register_t *retval)
|
||||
goto out;
|
||||
}
|
||||
while ((mp = vp->v_mountedhere) != NULL) {
|
||||
if (vfs_busy(mp, RW_READER, NULL))
|
||||
if (vfs_busy(mp, RW_READER))
|
||||
continue;
|
||||
vput(vp);
|
||||
error = VFS_ROOT(mp, &tdp);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: procfs_linux.c,v 1.50 2008/04/24 18:39:25 ad Exp $ */
|
||||
/* $NetBSD: procfs_linux.c,v 1.51 2008/04/29 23:51:05 ad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Wasabi Systems, Inc.
|
||||
@ -36,7 +36,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: procfs_linux.c,v 1.50 2008/04/24 18:39:25 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: procfs_linux.c,v 1.51 2008/04/29 23:51:05 ad Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -559,8 +559,7 @@ procfs_domounts(struct lwp *curl, struct proc *p,
|
||||
mutex_enter(&mountlist_lock);
|
||||
for (mp = CIRCLEQ_FIRST(&mountlist); mp != (void *)&mountlist;
|
||||
mp = nmp) {
|
||||
if (vfs_trybusy(mp, RW_READER, &mountlist_lock)) {
|
||||
nmp = CIRCLEQ_NEXT(mp, mnt_list);
|
||||
if (vfs_trybusy(mp, RW_READER, &nmp)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: sync_vnops.c,v 1.22 2008/01/30 11:47:02 ad Exp $ */
|
||||
/* $NetBSD: sync_vnops.c,v 1.23 2008/04/29 23:51:05 ad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 1997 Marshall Kirk McKusick. All Rights Reserved.
|
||||
@ -32,7 +32,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sync_vnops.c,v 1.22 2008/01/30 11:47:02 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: sync_vnops.c,v 1.23 2008/04/29 23:51:05 ad Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/proc.h>
|
||||
@ -157,16 +157,14 @@ sync_fsync(v)
|
||||
* Walk the list of vnodes pushing all that are dirty and
|
||||
* not already on the sync list.
|
||||
*/
|
||||
mutex_enter(&mountlist_lock);
|
||||
if (vfs_trybusy(mp, RW_WRITER, &mountlist_lock) == 0) {
|
||||
if (vfs_trybusy(mp, RW_WRITER, NULL) == 0) {
|
||||
asyncflag = mp->mnt_flag & MNT_ASYNC;
|
||||
mp->mnt_flag &= ~MNT_ASYNC;
|
||||
VFS_SYNC(mp, MNT_LAZY, ap->a_cred);
|
||||
if (asyncflag)
|
||||
mp->mnt_flag |= MNT_ASYNC;
|
||||
vfs_unbusy(mp, false);
|
||||
} else
|
||||
mutex_exit(&mountlist_lock);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: nfs_export.c,v 1.34 2008/04/28 20:24:10 martin Exp $ */
|
||||
/* $NetBSD: nfs_export.c,v 1.35 2008/04/29 23:51:05 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997, 1998, 2004, 2005 The NetBSD Foundation, Inc.
|
||||
@ -75,7 +75,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: nfs_export.c,v 1.34 2008/04/28 20:24:10 martin Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: nfs_export.c,v 1.35 2008/04/29 23:51:05 ad Exp $");
|
||||
|
||||
#include "opt_compat_netbsd.h"
|
||||
#include "opt_inet.h"
|
||||
@ -242,7 +242,7 @@ mountd_set_exports_list(const struct mountd_exports_list *mel, struct lwp *l)
|
||||
}
|
||||
|
||||
/* Mark the file system busy. */
|
||||
error = vfs_busy(mp, RW_READER, NULL);
|
||||
error = vfs_busy(mp, RW_READER);
|
||||
vput(vp);
|
||||
if (error != 0)
|
||||
return error;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: mount.h,v 1.174 2008/04/29 18:18:09 ad Exp $ */
|
||||
/* $NetBSD: mount.h,v 1.175 2008/04/29 23:51:05 ad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1991, 1993
|
||||
@ -108,7 +108,7 @@ struct mount {
|
||||
struct vnode *mnt_syncer; /* syncer vnode */
|
||||
void *mnt_transinfo; /* for FS-internal use */
|
||||
void *mnt_data; /* private data */
|
||||
struct lwp *mnt_writer; /* who is [un]mounting */
|
||||
struct lwp *mnt_unmounter; /* who is unmounting */
|
||||
krwlock_t mnt_lock; /* mount structure lock */
|
||||
kmutex_t mnt_renamelock; /* per-fs rename lock */
|
||||
int mnt_refcnt; /* ref count on this structure */
|
||||
@ -120,6 +120,7 @@ struct mount {
|
||||
struct statvfs mnt_stat; /* cache of filesystem stats */
|
||||
specificdata_reference
|
||||
mnt_specdataref; /* subsystem specific data */
|
||||
struct lwp *mnt_writer; /* who holds write lock */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -333,8 +334,8 @@ int vfs_mountedon(struct vnode *);/* is a vfs mounted on vp */
|
||||
int vfs_mountroot(void);
|
||||
void vfs_shutdown(void); /* unmount and sync file systems */
|
||||
void vfs_unmountall(struct lwp *); /* unmount file systems */
|
||||
int vfs_busy(struct mount *, const krw_t, kmutex_t *);
|
||||
int vfs_trybusy(struct mount *, const krw_t, kmutex_t *);
|
||||
int vfs_busy(struct mount *, const krw_t);
|
||||
int vfs_trybusy(struct mount *, const krw_t, struct mount **);
|
||||
int vfs_rootmountalloc(const char *, const char *, struct mount **);
|
||||
void vfs_unbusy(struct mount *, bool);
|
||||
int vfs_attach(struct vfsops *);
|
||||
@ -352,8 +353,9 @@ extern CIRCLEQ_HEAD(mntlist, mount) mountlist; /* mounted filesystem list */
|
||||
extern struct vfsops *vfssw[]; /* filesystem type table */
|
||||
extern int nvfssw;
|
||||
extern kmutex_t mountlist_lock;
|
||||
extern kmutex_t spechash_lock;
|
||||
extern kmutex_t vfs_list_lock;
|
||||
extern kmutex_t mount_lock;
|
||||
extern kcondvar_t mount_cv;
|
||||
|
||||
long makefstype(const char *);
|
||||
int dounmount(struct mount *, int, struct lwp *);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: lfs_bio.c,v 1.111 2008/04/28 20:24:11 martin Exp $ */
|
||||
/* $NetBSD: lfs_bio.c,v 1.112 2008/04/29 23:51:05 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2008 The NetBSD Foundation, Inc.
|
||||
@ -60,7 +60,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: lfs_bio.c,v 1.111 2008/04/28 20:24:11 martin Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: lfs_bio.c,v 1.112 2008/04/29 23:51:05 ad Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -576,8 +576,7 @@ lfs_flush(struct lfs *fs, int flags, int only_onefs)
|
||||
|
||||
if (only_onefs) {
|
||||
KASSERT(fs != NULL);
|
||||
if (vfs_trybusy(fs->lfs_ivnode->v_mount, RW_READER,
|
||||
&mountlist_lock))
|
||||
if (vfs_trybusy(fs->lfs_ivnode->v_mount, RW_READER, NULL))
|
||||
goto errout;
|
||||
mutex_enter(&lfs_lock);
|
||||
lfs_flush_fs(fs, flags);
|
||||
@ -588,9 +587,8 @@ lfs_flush(struct lfs *fs, int flags, int only_onefs)
|
||||
mutex_enter(&mountlist_lock);
|
||||
for (mp = CIRCLEQ_FIRST(&mountlist); mp != (void *)&mountlist;
|
||||
mp = nmp) {
|
||||
if (vfs_trybusy(mp, RW_READER, &mountlist_lock)) {
|
||||
if (vfs_trybusy(mp, RW_READER, &nmp)) {
|
||||
DLOG((DLOG_FLUSH, "lfs_flush: fs vfs_busy\n"));
|
||||
nmp = CIRCLEQ_NEXT(mp, mnt_list);
|
||||
continue;
|
||||
}
|
||||
if (strncmp(&mp->mnt_stat.f_fstypename[0], MOUNT_LFS,
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: lfs_vfsops.c,v 1.257 2008/04/29 18:18:09 ad Exp $ */
|
||||
/* $NetBSD: lfs_vfsops.c,v 1.258 2008/04/29 23:51:05 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2007, 2007
|
||||
@ -61,7 +61,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: lfs_vfsops.c,v 1.257 2008/04/29 18:18:09 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: lfs_vfsops.c,v 1.258 2008/04/29 23:51:05 ad Exp $");
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "opt_lfs.h"
|
||||
@ -213,8 +213,7 @@ lfs_writerd(void *arg)
|
||||
mutex_enter(&mountlist_lock);
|
||||
for (mp = CIRCLEQ_FIRST(&mountlist); mp != (void *)&mountlist;
|
||||
mp = nmp) {
|
||||
if (vfs_trybusy(mp, RW_WRITER, &mountlist_lock)) {
|
||||
nmp = CIRCLEQ_NEXT(mp, mnt_list);
|
||||
if (vfs_trybusy(mp, RW_WRITER, &nmp)) {
|
||||
continue;
|
||||
}
|
||||
if (strncmp(mp->mnt_stat.f_fstypename, MOUNT_LFS,
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: mfs_vfsops.c,v 1.93 2008/04/29 18:18:09 ad Exp $ */
|
||||
/* $NetBSD: mfs_vfsops.c,v 1.94 2008/04/29 23:51:05 ad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1990, 1993, 1994
|
||||
@ -32,7 +32,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: mfs_vfsops.c,v 1.93 2008/04/29 18:18:09 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: mfs_vfsops.c,v 1.94 2008/04/29 23:51:05 ad Exp $");
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "opt_compat_netbsd.h"
|
||||
@ -373,7 +373,7 @@ mfs_start(struct mount *mp, int flags)
|
||||
* Add a reference to the mfsnode to prevent it disappearing in
|
||||
* this routine.
|
||||
*/
|
||||
if ((error = vfs_busy(mp, RW_READER, NULL)) != 0)
|
||||
if ((error = vfs_busy(mp, RW_READER)) != 0)
|
||||
return error;
|
||||
vp = VFSTOUFS(mp)->um_devvp;
|
||||
mfsp = VTOMFS(vp);
|
||||
|
Loading…
Reference in New Issue
Block a user