diff options
Diffstat (limited to 'usr/src/uts/common/fs/vnode.c')
-rw-r--r-- | usr/src/uts/common/fs/vnode.c | 60 |
1 files changed, 40 insertions, 20 deletions
diff --git a/usr/src/uts/common/fs/vnode.c b/usr/src/uts/common/fs/vnode.c index 568df766cf..1a885bf32e 100644 --- a/usr/src/uts/common/fs/vnode.c +++ b/usr/src/uts/common/fs/vnode.c @@ -814,16 +814,37 @@ done: void vn_rele(vnode_t *vp) { - if (vp->v_count == 0) - cmn_err(CE_PANIC, "vn_rele: vnode ref count 0"); + VERIFY(vp->v_count > 0); mutex_enter(&vp->v_lock); if (vp->v_count == 1) { mutex_exit(&vp->v_lock); VOP_INACTIVE(vp, CRED(), NULL); - } else { + return; + } + vp->v_count--; + mutex_exit(&vp->v_lock); +} + +/* + * Release a vnode referenced by the DNLC. Multiple DNLC references are treated + * as a single reference, so v_count is not decremented until the last DNLC hold + * is released. This makes it possible to distinguish vnodes that are referenced + * only by the DNLC. + */ +void +vn_rele_dnlc(vnode_t *vp) +{ + VERIFY((vp->v_count > 0) && (vp->v_count_dnlc > 0)); + mutex_enter(&vp->v_lock); + if (--vp->v_count_dnlc == 0) { + if (vp->v_count == 1) { + mutex_exit(&vp->v_lock); + VOP_INACTIVE(vp, CRED(), NULL); + return; + } vp->v_count--; - mutex_exit(&vp->v_lock); } + mutex_exit(&vp->v_lock); } /* @@ -836,17 +857,16 @@ vn_rele(vnode_t *vp) void vn_rele_stream(vnode_t *vp) { - if (vp->v_count == 0) - cmn_err(CE_PANIC, "vn_rele: vnode ref count 0"); + VERIFY(vp->v_count > 0); mutex_enter(&vp->v_lock); vp->v_stream = NULL; if (vp->v_count == 1) { mutex_exit(&vp->v_lock); VOP_INACTIVE(vp, CRED(), NULL); - } else { - vp->v_count--; - mutex_exit(&vp->v_lock); + return; } + vp->v_count--; + mutex_exit(&vp->v_lock); } int @@ -2190,7 +2210,6 @@ vn_cache_constructor(void *buf, void *cdrarg, int kmflags) mutex_init(&vp->v_lock, NULL, MUTEX_DEFAULT, NULL); cv_init(&vp->v_cv, NULL, CV_DEFAULT, NULL); rw_init(&vp->v_nbllock, NULL, RW_DEFAULT, NULL); - rw_init(&vp->v_mslock, NULL, RW_DEFAULT, NULL); vp->v_femhead = NULL; /* Must be done before vn_reinit() */ vp->v_path = NULL; vp->v_mpssdata = NULL; @@ -2208,7 +2227,6 @@ vn_cache_destructor(void *buf, void *cdrarg) vp = buf; - rw_destroy(&vp->v_mslock); rw_destroy(&vp->v_nbllock); cv_destroy(&vp->v_cv); mutex_destroy(&vp->v_lock); @@ -2284,6 +2302,7 @@ void vn_reinit(vnode_t *vp) { vp->v_count = 1; + vp->v_count_dnlc = 0; vp->v_vfsp = NULL; vp->v_stream = NULL; vp->v_vfsmountedhere = NULL; @@ -2294,17 +2313,8 @@ vn_reinit(vnode_t *vp) vp->v_filocks = NULL; vp->v_shrlocks = NULL; vp->v_pages = NULL; - vp->v_npages = 0; - vp->v_msnpages = 0; - vp->v_scanfront = NULL; - vp->v_scanback = NULL; vp->v_locality = NULL; - vp->v_scantime = 0; - vp->v_mset = 0; - vp->v_msflags = 0; - vp->v_msnext = NULL; - vp->v_msprev = NULL; vp->v_xattrdir = NULL; /* Handles v_femhead, v_path, and the r/w/map counts */ @@ -2339,6 +2349,7 @@ vn_free(vnode_t *vp) * never be anything else. */ ASSERT((vp->v_count == 0) || (vp->v_count == 1)); + ASSERT(vp->v_count_dnlc == 0); if (vp->v_path != NULL) { kmem_free(vp->v_path, strlen(vp->v_path) + 1); vp->v_path = NULL; @@ -2573,6 +2584,15 @@ vn_mountedvfs(vnode_t *vp) } /* + * Return nonzero if the vnode is referenced by the dnlc, zero if not. + */ +int +vn_in_dnlc(vnode_t *vp) +{ + return (vp->v_count_dnlc > 0); +} + +/* * vn_has_other_opens() checks whether a particular file is opened by more than * just the caller and whether the open is for read and/or write. * This routine is for calling after the caller has already called VOP_OPEN() |