FBSD: avoid vrefl()
[openafs.git] / src / afs / FBSD / osi_vcache.c
index 69ac7f8..7c0e21b 100644 (file)
@@ -18,58 +18,75 @@ osi_TryEvictVCache(struct vcache *avc, int *slept, int defersleep)
 {
     struct vnode *vp;
     int code;
+    int evicted = 0;
 
     vp = AFSTOV(avc);
 
     if (!VI_TRYLOCK(vp))
-       return 0;
+       return evicted;
     code = osi_fbsd_checkinuse(avc);
     if (code != 0) {
        VI_UNLOCK(vp);
-       return 0;
+       return evicted;
     }
 
     if ((vp->v_iflag & VI_DOOMED) != 0) {
        VI_UNLOCK(vp);
-       return 1;
+       evicted = 1;
+       return evicted;
     }
 
-    /* must hold the vnode before calling vgone()
-     * This code largely copied from vfs_subr.c:vlrureclaim() */
     vholdl(vp);
 
     ReleaseWriteLock(&afs_xvcache);
     AFS_GUNLOCK();
 
     *slept = 1;
-    /* use the interlock while locking, so no one else can DOOM this */
-    vn_lock(vp, LK_INTERLOCK|LK_EXCLUSIVE|LK_RETRY);
-    vgone(vp);
-    VOP_UNLOCK(vp, 0);
+
+    if (vn_lock(vp, LK_INTERLOCK|LK_EXCLUSIVE|LK_NOWAIT) == 0) {
+       /*
+        * vrecycle() will vgone() only if its usecount is 0. If someone grabbed a
+        * new usecount ref just now, the vgone() will be skipped, and vrecycle
+        * will return 0.
+        */
+       if (vrecycle(vp) != 0) {
+           evicted = 1;
+       }
+
+       VOP_UNLOCK(vp, 0);
+    }
+
     vdrop(vp);
 
     AFS_GLOCK();
     ObtainWriteLock(&afs_xvcache, 340);
-    return 1;
+
+    return evicted;
 }
 
 struct vcache *
-osi_NewVnode(void) {
+osi_NewVnode(void)
+{
     struct vcache *tvc;
 
     tvc = afs_osi_Alloc(sizeof(struct vcache));
+    if (tvc == NULL) {
+       return NULL;
+    }
     tvc->v = NULL; /* important to clean this, or use memset 0 */
 
     return tvc;
 }
 
 void
-osi_PrePopulateVCache(struct vcache *avc) {
+osi_PrePopulateVCache(struct vcache *avc)
+{
     memset(avc, 0, sizeof(struct vcache));
 }
 
 void
-osi_AttachVnode(struct vcache *avc, int seq) {
+osi_AttachVnode(struct vcache *avc, int seq)
+{
     struct vnode *vp;
 
     ReleaseWriteLock(&afs_xvcache);
@@ -103,8 +120,25 @@ osi_AttachVnode(struct vcache *avc, int seq) {
 }
 
 void
-osi_PostPopulateVCache(struct vcache *avc) {
+osi_PostPopulateVCache(struct vcache *avc)
+{
     avc->v->v_mount = afs_globalVFS;
     vSetType(avc, VREG);
 }
 
+int
+osi_vnhold(struct vcache *avc)
+{
+    struct vnode *vp = AFSTOV(avc);
+
+    vref(vp);
+    VI_LOCK(vp);
+    if ((vp->v_iflag & VI_DOOMED) != 0) {
+       VI_UNLOCK(vp);
+       vrele(vp);
+       return ENOENT;
+    }
+
+    VI_UNLOCK(vp);
+    return 0;
+}