version 1.334, 2008/02/15 13:06:02 |
version 1.334.6.4, 2008/06/29 09:33:14 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
|
* must display the following acknowledgement: |
|
* This product includes software developed by the NetBSD |
|
* Foundation, Inc. and its contributors. |
|
* 4. Neither the name of The NetBSD Foundation nor the names of its |
|
* contributors may be used to endorse or promote products derived |
|
* from this software without specific prior written permission. |
|
* |
* |
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
|
|
* This file contains vfs subroutines which are heavily dependant on |
* This file contains vfs subroutines which are heavily dependant on |
* the kernel and are not suitable for standalone use. Examples include |
* the kernel and are not suitable for standalone use. Examples include |
* routines involved vnode and mountpoint management. |
* routines involved vnode and mountpoint management. |
|
* |
|
* Note on v_usecount and locking: |
|
* |
|
* At nearly all points it is known that v_usecount could be zero, the |
|
* vnode interlock will be held. |
|
* |
|
* To change v_usecount away from zero, the interlock must be held. To |
|
* change from a non-zero value to zero, again the interlock must be |
|
* held. |
|
* |
|
* Changing the usecount from a non-zero value to a non-zero value can |
|
* safely be done using atomic operations, without the interlock held. |
*/ |
*/ |
|
|
#include <sys/cdefs.h> |
#include <sys/cdefs.h> |
Line 125 static vnodelst_t vnode_hold_list = TAIL |
|
Line 130 static vnodelst_t vnode_hold_list = TAIL |
|
static vnodelst_t vrele_list = TAILQ_HEAD_INITIALIZER(vrele_list); |
static vnodelst_t vrele_list = TAILQ_HEAD_INITIALIZER(vrele_list); |
|
|
static int vrele_pending; |
static int vrele_pending; |
|
static int vrele_gen; |
static kmutex_t vrele_lock; |
static kmutex_t vrele_lock; |
static kcondvar_t vrele_cv; |
static kcondvar_t vrele_cv; |
static lwp_t *vrele_lwp; |
static lwp_t *vrele_lwp; |
|
|
* before doing this. If the vnode gains another reference while |
* before doing this. If the vnode gains another reference while |
* being cleaned out then we lose - retry. |
* being cleaned out then we lose - retry. |
*/ |
*/ |
vp->v_usecount++; |
atomic_inc_uint(&vp->v_usecount); |
vclean(vp, DOCLOSE); |
vclean(vp, DOCLOSE); |
if (vp->v_usecount == 1) { |
if (vp->v_usecount == 1) { |
/* We're about to dirty it. */ |
/* We're about to dirty it. */ |
|
|
* Don't return to freelist - the holder of the last |
* Don't return to freelist - the holder of the last |
* reference will destroy it. |
* reference will destroy it. |
*/ |
*/ |
KASSERT(vp->v_usecount > 1); |
vrelel(vp, 0); /* releases vp->v_interlock */ |
vp->v_usecount--; |
|
mutex_exit(&vp->v_interlock); |
|
mutex_enter(&vnode_free_list_lock); |
mutex_enter(&vnode_free_list_lock); |
goto retry; |
goto retry; |
} |
} |
|
|
|
|
/* |
/* |
* Mark a mount point as busy, and gain a new reference to it. Used to |
* Mark a mount point as busy, and gain a new reference to it. Used to |
* synchronize access and to delay unmounting. |
* prevent the file system from being unmounted during critical sections. |
* |
* |
* => Interlock is not released on failure. |
* => The caller must hold a pre-existing reference to the mount. |
* => If no interlock, the caller is expected to already hold a reference |
* => Will fail if the file system is being unmounted, or is unmounted. |
* on the mount. |
|
* => If interlocked, the interlock must prevent the last reference to |
|
* the mount from disappearing. |
|
*/ |
*/ |
int |
int |
vfs_busy(struct mount *mp, const krw_t op, kmutex_t *interlock) |
vfs_busy(struct mount *mp, struct mount **nextp) |
{ |
{ |
|
|
KASSERT(mp->mnt_refcnt > 0); |
KASSERT(mp->mnt_refcnt > 0); |
|
|
atomic_inc_uint(&mp->mnt_refcnt); |
if (__predict_false(!rw_tryenter(&mp->mnt_unmounting, RW_READER))) { |
if (interlock != NULL) { |
if (nextp != NULL) { |
mutex_exit(interlock); |
KASSERT(mutex_owned(&mountlist_lock)); |
} |
*nextp = CIRCLEQ_NEXT(mp, mnt_list); |
if (mp->mnt_writer == curlwp) { |
} |
mp->mnt_recursecnt++; |
return EBUSY; |
} else { |
} |
rw_enter(&mp->mnt_lock, op); |
if (__predict_false((mp->mnt_iflag & IMNT_GONE) != 0)) { |
if (op == RW_WRITER) { |
rw_exit(&mp->mnt_unmounting); |
KASSERT(mp->mnt_writer == NULL); |
if (nextp != NULL) { |
mp->mnt_writer = curlwp; |
KASSERT(mutex_owned(&mountlist_lock)); |
} |
*nextp = CIRCLEQ_NEXT(mp, mnt_list); |
} |
|
if ((mp->mnt_iflag & IMNT_GONE) != 0) { |
|
vfs_unbusy(mp, false); |
|
if (interlock != NULL) { |
|
mutex_enter(interlock); |
|
} |
} |
return ENOENT; |
return ENOENT; |
} |
} |
|
if (nextp != NULL) { |
return 0; |
mutex_exit(&mountlist_lock); |
} |
|
|
|
/* |
|
* As vfs_busy(), but return immediatley if the mount cannot be |
|
* locked without waiting. |
|
*/ |
|
int |
|
vfs_trybusy(struct mount *mp, krw_t op, kmutex_t *interlock) |
|
{ |
|
|
|
KASSERT(mp->mnt_refcnt > 0); |
|
|
|
if (mp->mnt_writer == curlwp) { |
|
mp->mnt_recursecnt++; |
|
} else { |
|
if (!rw_tryenter(&mp->mnt_lock, op)) { |
|
return EBUSY; |
|
} |
|
if (op == RW_WRITER) { |
|
KASSERT(mp->mnt_writer == NULL); |
|
mp->mnt_writer = curlwp; |
|
} |
|
} |
} |
atomic_inc_uint(&mp->mnt_refcnt); |
atomic_inc_uint(&mp->mnt_refcnt); |
if ((mp->mnt_iflag & IMNT_GONE) != 0) { |
|
vfs_unbusy(mp, false); |
|
return ENOENT; |
|
} |
|
if (interlock != NULL) { |
|
mutex_exit(interlock); |
|
} |
|
return 0; |
return 0; |
} |
} |
|
|
/* |
/* |
* Unlock a busy filesystem and drop reference to it. If 'keepref' is |
* Unbusy a busy filesystem. |
* true, unlock but preserve the reference. |
* |
|
* => If keepref is true, preserve reference added by vfs_busy(). |
|
* => If nextp != NULL, acquire mountlist_lock. |
*/ |
*/ |
void |
void |
vfs_unbusy(struct mount *mp, bool keepref) |
vfs_unbusy(struct mount *mp, bool keepref, struct mount **nextp) |
{ |
{ |
|
|
KASSERT(mp->mnt_refcnt > 0); |
KASSERT(mp->mnt_refcnt > 0); |
|
|
if (mp->mnt_writer == curlwp) { |
if (nextp != NULL) { |
KASSERT(rw_write_held(&mp->mnt_lock)); |
mutex_enter(&mountlist_lock); |
if (mp->mnt_recursecnt != 0) { |
|
mp->mnt_recursecnt--; |
|
} else { |
|
mp->mnt_writer = NULL; |
|
rw_exit(&mp->mnt_lock); |
|
} |
|
} else { |
|
rw_exit(&mp->mnt_lock); |
|
} |
} |
|
rw_exit(&mp->mnt_unmounting); |
if (!keepref) { |
if (!keepref) { |
vfs_destroy(mp); |
vfs_destroy(mp); |
} |
} |
|
if (nextp != NULL) { |
|
KASSERT(mutex_owned(&mountlist_lock)); |
|
*nextp = CIRCLEQ_NEXT(mp, mnt_list); |
|
} |
} |
} |
|
|
/* |
/* |
Line 416 vfs_rootmountalloc(const char *fstypenam |
|
Line 382 vfs_rootmountalloc(const char *fstypenam |
|
if (mp == NULL) |
if (mp == NULL) |
return ENOMEM; |
return ENOMEM; |
mp->mnt_refcnt = 1; |
mp->mnt_refcnt = 1; |
rw_init(&mp->mnt_lock); |
rw_init(&mp->mnt_unmounting); |
|
mutex_init(&mp->mnt_updating, MUTEX_DEFAULT, IPL_NONE); |
mutex_init(&mp->mnt_renamelock, MUTEX_DEFAULT, IPL_NONE); |
mutex_init(&mp->mnt_renamelock, MUTEX_DEFAULT, IPL_NONE); |
(void)vfs_busy(mp, RW_WRITER, NULL); |
(void)vfs_busy(mp, NULL); |
TAILQ_INIT(&mp->mnt_vnodelist); |
TAILQ_INIT(&mp->mnt_vnodelist); |
mp->mnt_op = vfsp; |
mp->mnt_op = vfsp; |
mp->mnt_flag = MNT_RDONLY; |
mp->mnt_flag = MNT_RDONLY; |
Line 458 getnewvnode(enum vtagtype tag, struct mo |
|
Line 425 getnewvnode(enum vtagtype tag, struct mo |
|
/* |
/* |
* Mark filesystem busy while we're creating a |
* Mark filesystem busy while we're creating a |
* vnode. If unmount is in progress, this will |
* vnode. If unmount is in progress, this will |
* wait; if the unmount succeeds (only if umount |
* fail. |
* -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, NULL); |
if (error) |
if (error) |
return error; |
return error; |
} |
} |
Line 509 getnewvnode(enum vtagtype tag, struct mo |
|
Line 474 getnewvnode(enum vtagtype tag, struct mo |
|
vp = getcleanvnode(); |
vp = getcleanvnode(); |
if (vp == NULL) { |
if (vp == NULL) { |
if (mp != NULL) { |
if (mp != NULL) { |
vfs_unbusy(mp, false); |
vfs_unbusy(mp, false, NULL); |
} |
} |
if (tryalloc) { |
if (tryalloc) { |
printf("WARNING: unable to allocate new " |
printf("WARNING: unable to allocate new " |
"vnode, retrying...\n"); |
"vnode, retrying...\n"); |
(void) tsleep(&lbolt, PRIBIO, "newvn", hz); |
kpause("newvn", false, hz, NULL); |
goto try_again; |
goto try_again; |
} |
} |
tablefull("vnode", "increase kern.maxvnodes or NVNODE"); |
tablefull("vnode", "increase kern.maxvnodes or NVNODE"); |
Line 553 getnewvnode(enum vtagtype tag, struct mo |
|
Line 518 getnewvnode(enum vtagtype tag, struct mo |
|
if (mp != NULL) { |
if (mp != NULL) { |
if ((mp->mnt_iflag & IMNT_MPSAFE) != 0) |
if ((mp->mnt_iflag & IMNT_MPSAFE) != 0) |
vp->v_vflag |= VV_MPSAFE; |
vp->v_vflag |= VV_MPSAFE; |
vfs_unbusy(mp, true); |
vfs_unbusy(mp, true, NULL); |
} |
} |
|
|
return (0); |
return (0); |
Line 749 getdevvp(dev_t dev, vnode_t **vpp, enum |
|
Line 714 getdevvp(dev_t dev, vnode_t **vpp, enum |
|
} |
} |
|
|
/* |
/* |
|
* Try to gain a reference to a vnode, without acquiring its interlock. |
|
* The caller must hold a lock that will prevent the vnode from being |
|
* recycled or freed. |
|
*/ |
|
bool |
|
vtryget(vnode_t *vp) |
|
{ |
|
u_int use, next; |
|
|
|
/* |
|
* If the vnode is being freed, don't make life any harder |
|
* for vclean() by adding another reference without waiting. |
|
* This is not strictly necessary, but we'll do it anyway. |
|
*/ |
|
if (__predict_false((vp->v_iflag & (VI_XLOCK | VI_FREEING)) != 0)) { |
|
return false; |
|
} |
|
for (use = vp->v_usecount;; use = next) { |
|
if (use == 0) { |
|
/* Need interlock held if first reference. */ |
|
return false; |
|
} |
|
next = atomic_cas_uint(&vp->v_usecount, use, use + 1); |
|
if (__predict_true(next == use)) { |
|
return true; |
|
} |
|
} |
|
} |
|
|
|
/* |
* Grab a particular vnode from the free list, increment its |
* Grab a particular vnode from the free list, increment its |
* reference count and lock it. If the vnode lock bit is set the |
* reference count and lock it. If the vnode lock bit is set the |
* vnode is being eliminated in vgone. In that case, we can not |
* vnode is being eliminated in vgone. In that case, we can not |
Line 772 vget(vnode_t *vp, int flags) |
|
Line 767 vget(vnode_t *vp, int flags) |
|
*/ |
*/ |
if (vp->v_usecount == 0) { |
if (vp->v_usecount == 0) { |
vremfree(vp); |
vremfree(vp); |
} |
vp->v_usecount = 1; |
if (++vp->v_usecount == 0) { |
} else { |
vpanic(vp, "vget: usecount overflow"); |
atomic_inc_uint(&vp->v_usecount); |
} |
} |
|
|
/* |
/* |
Line 817 vput(vnode_t *vp) |
|
Line 812 vput(vnode_t *vp) |
|
} |
} |
|
|
/* |
/* |
|
* Try to drop reference on a vnode. Abort if we are releasing the |
|
* last reference. |
|
*/ |
|
static inline bool |
|
vtryrele(vnode_t *vp) |
|
{ |
|
u_int use, next; |
|
|
|
for (use = vp->v_usecount;; use = next) { |
|
if (use == 1) { |
|
return false; |
|
} |
|
next = atomic_cas_uint(&vp->v_usecount, use, use - 1); |
|
if (__predict_true(next == use)) { |
|
return true; |
|
} |
|
} |
|
} |
|
|
|
/* |
* Vnode release. If reference count drops to zero, call inactive |
* Vnode release. If reference count drops to zero, call inactive |
* routine and either return to freelist or free to the pool. |
* routine and either return to freelist or free to the pool. |
*/ |
*/ |
Line 838 vrelel(vnode_t *vp, int flags) |
|
Line 853 vrelel(vnode_t *vp, int flags) |
|
* If not the last reference, just drop the reference count |
* If not the last reference, just drop the reference count |
* and unlock. |
* and unlock. |
*/ |
*/ |
if (vp->v_usecount > 1) { |
if (vtryrele(vp)) { |
vp->v_usecount--; |
|
vp->v_iflag |= VI_INACTREDO; |
vp->v_iflag |= VI_INACTREDO; |
mutex_exit(&vp->v_interlock); |
mutex_exit(&vp->v_interlock); |
return; |
return; |
Line 855 vrelel(vnode_t *vp, int flags) |
|
Line 869 vrelel(vnode_t *vp, int flags) |
|
retry: |
retry: |
if ((vp->v_iflag & VI_CLEAN) == 0) { |
if ((vp->v_iflag & VI_CLEAN) == 0) { |
recycle = false; |
recycle = false; |
|
vp->v_iflag |= VI_INACTNOW; |
|
|
/* |
/* |
* XXX This ugly block can be largely eliminated if |
* XXX This ugly block can be largely eliminated if |
* locking is pushed down into the file systems. |
* locking is pushed down into the file systems. |
Line 899 vrelel(vnode_t *vp, int flags) |
|
Line 915 vrelel(vnode_t *vp, int flags) |
|
*/ |
*/ |
KASSERT(mutex_owned(&vp->v_interlock)); |
KASSERT(mutex_owned(&vp->v_interlock)); |
KASSERT((vp->v_iflag & VI_INACTPEND) == 0); |
KASSERT((vp->v_iflag & VI_INACTPEND) == 0); |
|
vp->v_iflag &= ~VI_INACTNOW; |
vp->v_iflag |= VI_INACTPEND; |
vp->v_iflag |= VI_INACTPEND; |
mutex_enter(&vrele_lock); |
mutex_enter(&vrele_lock); |
TAILQ_INSERT_TAIL(&vrele_list, vp, v_freelist); |
TAILQ_INSERT_TAIL(&vrele_list, vp, v_freelist); |
Line 928 vrelel(vnode_t *vp, int flags) |
|
Line 945 vrelel(vnode_t *vp, int flags) |
|
*/ |
*/ |
VOP_INACTIVE(vp, &recycle); |
VOP_INACTIVE(vp, &recycle); |
mutex_enter(&vp->v_interlock); |
mutex_enter(&vp->v_interlock); |
|
vp->v_iflag &= ~VI_INACTNOW; |
if (!recycle) { |
if (!recycle) { |
if (vp->v_usecount > 1) { |
if (vtryrele(vp)) { |
vp->v_usecount--; |
|
mutex_exit(&vp->v_interlock); |
mutex_exit(&vp->v_interlock); |
return; |
return; |
} |
} |
Line 951 vrelel(vnode_t *vp, int flags) |
|
Line 968 vrelel(vnode_t *vp, int flags) |
|
atomic_add_int(&uvmexp.filepages, |
atomic_add_int(&uvmexp.filepages, |
vp->v_uobj.uo_npages); |
vp->v_uobj.uo_npages); |
} |
} |
vp->v_iflag &= ~(VI_TEXT|VI_EXECMAP|VI_WRMAP|VI_MAPPED); |
vp->v_iflag &= ~(VI_TEXT|VI_EXECMAP|VI_WRMAP); |
vp->v_vflag &= ~VV_MAPPED; |
vp->v_vflag &= ~VV_MAPPED; |
|
|
/* |
/* |
Line 964 vrelel(vnode_t *vp, int flags) |
|
Line 981 vrelel(vnode_t *vp, int flags) |
|
KASSERT(vp->v_usecount > 0); |
KASSERT(vp->v_usecount > 0); |
} |
} |
|
|
if (--vp->v_usecount != 0) { |
if (atomic_dec_uint_nv(&vp->v_usecount) != 0) { |
/* Gained another reference while being reclaimed. */ |
/* Gained another reference while being reclaimed. */ |
mutex_exit(&vp->v_interlock); |
mutex_exit(&vp->v_interlock); |
return; |
return; |
Line 1007 vrele(vnode_t *vp) |
|
Line 1024 vrele(vnode_t *vp) |
|
|
|
KASSERT((vp->v_iflag & VI_MARKER) == 0); |
KASSERT((vp->v_iflag & VI_MARKER) == 0); |
|
|
|
if ((vp->v_iflag & VI_INACTNOW) == 0 && vtryrele(vp)) { |
|
return; |
|
} |
mutex_enter(&vp->v_interlock); |
mutex_enter(&vp->v_interlock); |
vrelel(vp, 0); |
vrelel(vp, 0); |
} |
} |
Line 1019 vrele_thread(void *cookie) |
|
Line 1039 vrele_thread(void *cookie) |
|
for (;;) { |
for (;;) { |
mutex_enter(&vrele_lock); |
mutex_enter(&vrele_lock); |
while (TAILQ_EMPTY(&vrele_list)) { |
while (TAILQ_EMPTY(&vrele_list)) { |
|
vrele_gen++; |
|
cv_broadcast(&vrele_cv); |
cv_timedwait(&vrele_cv, &vrele_lock, hz); |
cv_timedwait(&vrele_cv, &vrele_lock, hz); |
} |
} |
vp = TAILQ_FIRST(&vrele_list); |
vp = TAILQ_FIRST(&vrele_list); |
Line 1033 vrele_thread(void *cookie) |
|
Line 1055 vrele_thread(void *cookie) |
|
mutex_enter(&vp->v_interlock); |
mutex_enter(&vp->v_interlock); |
KASSERT((vp->v_iflag & VI_INACTPEND) != 0); |
KASSERT((vp->v_iflag & VI_INACTPEND) != 0); |
vp->v_iflag &= ~VI_INACTPEND; |
vp->v_iflag &= ~VI_INACTPEND; |
if (vp->v_usecount > 1) { |
|
vp->v_usecount--; |
|
mutex_exit(&vp->v_interlock); |
|
continue; |
|
} |
|
vrelel(vp, 0); |
vrelel(vp, 0); |
} |
} |
} |
} |
Line 1098 vref(vnode_t *vp) |
|
Line 1115 vref(vnode_t *vp) |
|
{ |
{ |
|
|
KASSERT((vp->v_iflag & VI_MARKER) == 0); |
KASSERT((vp->v_iflag & VI_MARKER) == 0); |
|
KASSERT(vp->v_usecount != 0); |
|
|
mutex_enter(&vp->v_interlock); |
atomic_inc_uint(&vp->v_usecount); |
if (vp->v_usecount <= 0) { |
|
vpanic(vp, "vref used where vget required"); |
|
} |
|
if (++vp->v_usecount == 0) { |
|
vpanic(vp, "vref: usecount overflow"); |
|
} |
|
mutex_exit(&vp->v_interlock); |
|
} |
} |
|
|
/* |
/* |
|
|
vflush(struct mount *mp, vnode_t *skipvp, int flags) |
vflush(struct mount *mp, vnode_t *skipvp, int flags) |
{ |
{ |
vnode_t *vp, *mvp; |
vnode_t *vp, *mvp; |
int busy = 0, when = 0; |
int busy = 0, when = 0, gen; |
|
|
|
/* |
|
* First, flush out any vnode references from vrele_list. |
|
*/ |
|
mutex_enter(&vrele_lock); |
|
gen = vrele_gen; |
|
do { |
|
cv_broadcast(&vrele_cv); |
|
cv_wait(&vrele_cv, &vrele_lock); |
|
} while (gen == vrele_gen); |
|
mutex_exit(&vrele_lock); |
|
|
/* Allocate a marker vnode. */ |
/* Allocate a marker vnode. */ |
if ((mvp = vnalloc(mp)) == NULL) |
if ((mvp = vnalloc(mp)) == NULL) |
return (ENOMEM); |
return (ENOMEM); |
|
|
mutex_enter(&mntvnode_lock); |
|
/* |
/* |
* NOTE: not using the TAILQ_FOREACH here since in this loop vgone() |
* NOTE: not using the TAILQ_FOREACH here since in this loop vgone() |
* and vclean() are called |
* and vclean() are called |
*/ |
*/ |
|
mutex_enter(&mntvnode_lock); |
for (vp = TAILQ_FIRST(&mp->mnt_vnodelist); vp != NULL; |
for (vp = TAILQ_FIRST(&mp->mnt_vnodelist); vp != NULL; |
vp = vflushnext(mvp, &when)) { |
vp = vflushnext(mvp, &when)) { |
vmark(mvp, vp); |
vmark(mvp, vp); |
Line 1197 vflush(struct mount *mp, vnode_t *skipvp |
|
Line 1219 vflush(struct mount *mp, vnode_t *skipvp |
|
if (vp->v_usecount == 0) { |
if (vp->v_usecount == 0) { |
mutex_exit(&mntvnode_lock); |
mutex_exit(&mntvnode_lock); |
vremfree(vp); |
vremfree(vp); |
vp->v_usecount++; |
vp->v_usecount = 1; |
vclean(vp, DOCLOSE); |
vclean(vp, DOCLOSE); |
vrelel(vp, 0); |
vrelel(vp, 0); |
mutex_enter(&mntvnode_lock); |
mutex_enter(&mntvnode_lock); |
Line 1211 vflush(struct mount *mp, vnode_t *skipvp |
|
Line 1233 vflush(struct mount *mp, vnode_t *skipvp |
|
*/ |
*/ |
if (flags & FORCECLOSE) { |
if (flags & FORCECLOSE) { |
mutex_exit(&mntvnode_lock); |
mutex_exit(&mntvnode_lock); |
vp->v_usecount++; |
atomic_inc_uint(&vp->v_usecount); |
if (vp->v_type != VBLK && vp->v_type != VCHR) { |
if (vp->v_type != VBLK && vp->v_type != VCHR) { |
vclean(vp, DOCLOSE); |
vclean(vp, DOCLOSE); |
vrelel(vp, 0); |
vrelel(vp, 0); |
Line 1358 vrecycle(vnode_t *vp, kmutex_t *inter_lk |
|
Line 1380 vrecycle(vnode_t *vp, kmutex_t *inter_lk |
|
if (inter_lkp) |
if (inter_lkp) |
mutex_exit(inter_lkp); |
mutex_exit(inter_lkp); |
vremfree(vp); |
vremfree(vp); |
vp->v_usecount++; |
vp->v_usecount = 1; |
vclean(vp, DOCLOSE); |
vclean(vp, DOCLOSE); |
vrelel(vp, 0); |
vrelel(vp, 0); |
return (1); |
return (1); |
Line 1494 vrevoke(vnode_t *vp) |
|
Line 1516 vrevoke(vnode_t *vp) |
|
mutex_exit(&specfs_lock); |
mutex_exit(&specfs_lock); |
if (vq->v_usecount == 0) { |
if (vq->v_usecount == 0) { |
vremfree(vq); |
vremfree(vq); |
|
vq->v_usecount = 1; |
|
} else { |
|
atomic_inc_uint(&vq->v_usecount); |
} |
} |
vq->v_usecount++; |
|
vclean(vq, DOCLOSE); |
vclean(vq, DOCLOSE); |
vrelel(vq, 0); |
vrelel(vq, 0); |
mutex_enter(&specfs_lock); |
mutex_enter(&specfs_lock); |
Line 1637 sysctl_kern_vnode(SYSCTLFN_ARGS) |
|
Line 1661 sysctl_kern_vnode(SYSCTLFN_ARGS) |
|
mutex_enter(&mountlist_lock); |
mutex_enter(&mountlist_lock); |
for (mp = CIRCLEQ_FIRST(&mountlist); mp != (void *)&mountlist; |
for (mp = CIRCLEQ_FIRST(&mountlist); mp != (void *)&mountlist; |
mp = nmp) { |
mp = nmp) { |
if (vfs_trybusy(mp, RW_READER, &mountlist_lock)) { |
if (vfs_busy(mp, &nmp)) { |
nmp = CIRCLEQ_NEXT(mp, mnt_list); |
|
continue; |
continue; |
} |
} |
savebp = bp; |
savebp = bp; |
Line 1680 sysctl_kern_vnode(SYSCTLFN_ARGS) |
|
Line 1703 sysctl_kern_vnode(SYSCTLFN_ARGS) |
|
mutex_enter(&mntvnode_lock); |
mutex_enter(&mntvnode_lock); |
} |
} |
mutex_exit(&mntvnode_lock); |
mutex_exit(&mntvnode_lock); |
mutex_enter(&mountlist_lock); |
|
nmp = CIRCLEQ_NEXT(mp, mnt_list); |
|
vfs_unbusy(mp, false); |
|
vnfree(mvp); |
vnfree(mvp); |
|
vfs_unbusy(mp, false, &nmp); |
} |
} |
mutex_exit(&mountlist_lock); |
mutex_exit(&mountlist_lock); |
sysctl_relock(); |
sysctl_relock(); |
Line 1765 vfs_unmountall(struct lwp *l) |
|
Line 1786 vfs_unmountall(struct lwp *l) |
|
printf("\nunmounting %s (%s)...", |
printf("\nunmounting %s (%s)...", |
mp->mnt_stat.f_mntonname, mp->mnt_stat.f_mntfromname); |
mp->mnt_stat.f_mntonname, mp->mnt_stat.f_mntfromname); |
#endif |
#endif |
/* |
atomic_inc_uint(&mp->mnt_refcnt); |
* XXX Freeze syncer. Must do this before locking the |
|
* mount point. See dounmount() for details. |
|
*/ |
|
mutex_enter(&syncer_mutex); |
|
if (vfs_busy(mp, RW_WRITER, NULL)) { |
|
mutex_exit(&syncer_mutex); |
|
continue; |
|
} |
|
if ((error = dounmount(mp, MNT_FORCE, l)) != 0) { |
if ((error = dounmount(mp, MNT_FORCE, l)) != 0) { |
printf("unmount of %s failed with error %d\n", |
printf("unmount of %s failed with error %d\n", |
mp->mnt_stat.f_mntonname, error); |
mp->mnt_stat.f_mntonname, error); |
Line 1870 vfs_mountroot(void) |
|
Line 1883 vfs_mountroot(void) |
|
|
|
default: |
default: |
printf("%s: inappropriate for root file system\n", |
printf("%s: inappropriate for root file system\n", |
root_device->dv_xname); |
device_xname(root_device)); |
return (ENODEV); |
return (ENODEV); |
} |
} |
|
|
Line 1906 vfs_mountroot(void) |
|
Line 1919 vfs_mountroot(void) |
|
mutex_exit(&vfs_list_lock); |
mutex_exit(&vfs_list_lock); |
|
|
if (v == NULL) { |
if (v == NULL) { |
printf("no file system for %s", root_device->dv_xname); |
printf("no file system for %s", device_xname(root_device)); |
if (device_class(root_device) == DV_DISK) |
if (device_class(root_device) == DV_DISK) |
printf(" (dev 0x%x)", rootdev); |
printf(" (dev 0x%x)", rootdev); |
printf("\n"); |
printf("\n"); |