darwin-updates-20040613
[openafs.git] / src / afs / DARWIN / osi_vm.c
index b590b4c..0c2b1a1 100644 (file)
@@ -8,13 +8,14 @@
  */
 
 #include <afsconfig.h>
-#include "../afs/param.h"
+#include "afs/param.h"
 
-RCSID("$Header$");
+RCSID
+    ("$Header$");
 
-#include "../afs/sysincludes.h" /* Standard vendor system headers */
-#include "../afs/afsincludes.h" /* Afs-based standard headers */
-#include "../afs/afs_stats.h"  /* statistics */
+#include "afs/sysincludes.h"   /* Standard vendor system headers */
+#include "afsincludes.h"       /* Afs-based standard headers */
+#include "afs/afs_stats.h"     /* statistics */
 #include <sys/ubc.h>
 
 /* Try to discard pages, in order to recycle a vcache entry.
@@ -34,11 +35,9 @@ RCSID("$Header$");
  * OSF/1 Locking:  VN_LOCK has been called.
  */
 int
-osi_VM_FlushVCache(avc, slept)
-    struct vcache *avc;
-    int *slept;
+osi_VM_FlushVCache(struct vcache *avc, int *slept)
 {
-    struct vnode *vp=(struct vnode *)avc;
+    struct vnode *vp = AFSTOV(avc);
 #ifdef AFS_DARWIN14_ENV
     if (UBCINFOEXISTS(vp))
        return EBUSY;
@@ -56,13 +55,36 @@ osi_VM_FlushVCache(avc, slept)
     AFS_GUNLOCK();
     cache_purge(vp);
 #ifndef AFS_DARWIN14_ENV
-    if (UBCINFOEXISTS(vp))
-       {
-                ubc_clean(vp, 1);
-                ubc_uncache(vp);
-                ubc_release(vp);
-               ubc_info_free(vp);
+    if (UBCINFOEXISTS(vp)) {
+       ubc_clean(vp, 1);
+       ubc_uncache(vp);
+       ubc_release(vp);
+       ubc_info_free(vp);
+    }
+#else
+    /* This is literally clean_up_name_parent_ptrs() */
+    /* Critical to clean up any state attached to the vnode here since it's
+       being recycled, and we're not letting refcnt drop to 0 to trigger
+       normal recycling. */
+    if (VNAME(vp) || VPARENT(vp)) {
+       char *tmp1;
+       struct vnode *tmp2;
+
+       /* do it this way so we don't block before clearing 
+          these fields. */
+       tmp1 = VNAME(vp);
+       tmp2 = VPARENT(vp);
+       VNAME(vp) = NULL;
+       VPARENT(vp) = NULL;
+            
+       if (tmp1) {
+           remove_name(tmp1);
        }
+            
+       if (tmp2) {
+           vrele(tmp2);
+       }
+    }
 #endif
 
     AFS_GLOCK();
@@ -77,17 +99,16 @@ osi_VM_FlushVCache(avc, slept)
  * re-obtained.
  */
 void
-osi_VM_StoreAllSegments(avc)
-    struct vcache *avc;
+osi_VM_StoreAllSegments(struct vcache *avc)
 {
-    struct vnode *vp=(struct vnode *)avc;
+    struct vnode *vp = AFSTOV(avc);
     ReleaseWriteLock(&avc->lock);
     AFS_GUNLOCK();
     if (UBCINFOEXISTS(vp)) {
        ubc_pushdirty(vp);
     }
     AFS_GLOCK();
-    ObtainWriteLock(&avc->lock,94);
+    ObtainWriteLock(&avc->lock, 94);
 }
 
 /* Try to invalidate pages, for "fs flush" or "fs flushv"; or
@@ -100,26 +121,23 @@ osi_VM_StoreAllSegments(avc)
  * be some pages around when we return, newly created by concurrent activity.
  */
 void
-osi_VM_TryToSmush(avc, acred, sync)
-    struct vcache *avc;
-    struct AFS_UCRED *acred;
-    int sync;
+osi_VM_TryToSmush(struct vcache *avc, struct AFS_UCRED *acred, int sync)
 {
-    struct vnode *vp=(struct vnode *)avc;
+    struct vnode *vp = AFSTOV(avc);
     void *object;
     kern_return_t kret;
     off_t size, lastpg;
-    
+
     ReleaseWriteLock(&avc->lock);
     AFS_GUNLOCK();
-    if (UBCINFOEXISTS(vp))  {
-        size=ubc_getsize(vp);
-        kret=ubc_invalidate(vp,0,size); 
-        if (kret != 1) /* should be KERN_SUCCESS */
-            printf("TryToSmush: invalidate failed (error = %d)\n", kret);
+    if (UBCINFOEXISTS(vp)) {
+       size = ubc_getsize(vp);
+       kret = ubc_invalidate(vp, 0, size);
+       if (kret != 1)          /* should be KERN_SUCCESS */
+           printf("TryToSmush: invalidate failed (error = %d)\n", kret);
     }
     AFS_GLOCK();
-    ObtainWriteLock(&avc->lock,59);
+    ObtainWriteLock(&avc->lock, 59);
 }
 
 /* Purge VM for a file when its callback is revoked.
@@ -130,22 +148,20 @@ osi_VM_TryToSmush(avc, acred, sync)
    this, and also making sure that ubc's idea of the filesize is right more
    often */
 void
-osi_VM_FlushPages(avc, credp)
-    struct vcache *avc;
-    struct AFS_UCRED *credp;
+osi_VM_FlushPages(struct vcache *avc, struct AFS_UCRED *credp)
 {
-    struct vnode *vp=(struct vnode *)avc;
+    struct vnode *vp = AFSTOV(avc);
     void *object;
     kern_return_t kret;
     off_t size;
-    if (UBCINFOEXISTS(vp))  {
-        size=ubc_getsize(vp);
-        kret=ubc_invalidate(vp,0,size);
-        if (kret != 1) /* Should be KERN_SUCCESS */
-          printf("VMFlushPages: invalidate failed (error = %d)\n", kret);
-        /* XXX what about when not CStatd */
-        if (avc->states & CStatd && size != avc->m.Length) 
-            ubc_setsize(vp, avc->m.Length);
+    if (UBCINFOEXISTS(vp)) {
+       size = ubc_getsize(vp);
+       kret = ubc_invalidate(vp, 0, size);
+       if (kret != 1)          /* Should be KERN_SUCCESS */
+           printf("VMFlushPages: invalidate failed (error = %d)\n", kret);
+       /* XXX what about when not CStatd */
+       if (avc->states & CStatd && size != avc->m.Length)
+           ubc_setsize(vp, avc->m.Length);
     }
 }
 
@@ -156,199 +172,205 @@ osi_VM_FlushPages(avc, credp)
  * it only works on Solaris.
  */
 void
-osi_VM_Truncate(avc, alen, acred)
-    struct vcache *avc;
-    int alen;
-    struct AFS_UCRED *acred;
+osi_VM_Truncate(struct vcache *avc, int alen, struct AFS_UCRED *acred)
 {
-    struct vnode *vp=(struct vnode *)avc;
-    if (UBCINFOEXISTS(vp))  {
+    struct vnode *vp = AFSTOV(avc);
+    if (UBCINFOEXISTS(vp)) {
        ubc_setsize(vp, alen);
     }
 }
 
-extern struct  AFS_UCRED afs_osi_cred;
-extern afs_rwlock_t afs_xvcache;
 /* vnreclaim and vinactive are probably not aggressive enough to keep
    enough afs vcaches free, so we try to do some of it ourselves */
 /* XXX there's probably not nearly enough locking here */
-void osi_VM_TryReclaim(avc, slept)
-     struct vcache *avc;
-     int *slept;
+void
+osi_VM_TryReclaim(struct vcache *avc, int *slept)
 {
-    struct proc *p=current_proc();
-    struct vnode *vp=(struct vnode *)avc;
+    struct proc *p = current_proc();
+    struct vnode *vp = AFSTOV(avc);
     void *obj;
 
     if (slept)
-       *slept=0;
-    VN_HOLD(vp); /* remove from inactive list */
+       *slept = 0;
+    VN_HOLD(vp);               /* remove from inactive list */
     if (!simple_lock_try(&vp->v_interlock)) {
-        AFS_RELE(vp);
-        return;
+       AFS_RELE(vp);
+       return;
     }
     if (!UBCINFOEXISTS(vp) || vp->v_count != 2) {
-        simple_unlock(&vp->v_interlock);
+       simple_unlock(&vp->v_interlock);
+       AFS_RELE(vp);
+       return;
+    }
+    if (ISSET(vp->v_flag, VUINACTIVE)) {
+       simple_unlock(&vp->v_interlock);
         AFS_RELE(vp);
+        printf("vnode %x still inactive!", vp);
         return;
     }
 #ifdef AFS_DARWIN14_ENV
-    if (vp->v_ubcinfo->ui_refcount > 1) {
-        simple_unlock(&vp->v_interlock);
-        AFS_RELE(vp);
-        return;
+    if (vp->v_ubcinfo->ui_refcount > 1 || vp->v_ubcinfo->ui_mapped) {
+       simple_unlock(&vp->v_interlock);
+       AFS_RELE(vp);
+       return;
     }
 #else
     if (vp->v_ubcinfo->ui_holdcnt) {
-        simple_unlock(&vp->v_interlock);
-        AFS_RELE(vp);
-        return;
+       simple_unlock(&vp->v_interlock);
+       AFS_RELE(vp);
+       return;
     }
 #endif
     if (slept && ubc_issetflags(vp, UI_WASMAPPED)) {
-       /* We can't possibly release this in time for this NewVCache to get it */
-        simple_unlock(&vp->v_interlock);
-        AFS_RELE(vp);
-        return;
+       /* We can't possibly release this in time for this NewVCache to get it */
+       simple_unlock(&vp->v_interlock);
+       AFS_RELE(vp);
+       return;
     }
 
-    vp->v_usecount--; /* we want the usecount to be 1 */
+    vp->v_usecount--;          /* we want the usecount to be 1 */
 
     if (slept) {
-        ReleaseWriteLock(&afs_xvcache);
-        *slept=1;
+       ReleaseWriteLock(&afs_xvcache);
+       *slept = 1;
     } else
-        ReleaseReadLock(&afs_xvcache);
+       ReleaseReadLock(&afs_xvcache);
     AFS_GUNLOCK();
-    obj=0;
+    obj = 0;
     if (ubc_issetflags(vp, UI_WASMAPPED)) {
-        simple_unlock(&vp->v_interlock);
+       simple_unlock(&vp->v_interlock);
 #ifdef  AFS_DARWIN14_ENV
-        ubc_release_named(vp);
+       ubc_release_named(vp);
 #else
-        ubc_release(vp);
+       ubc_release(vp);
 #endif
-        if (ubc_issetflags(vp, UI_HASOBJREF))
-            printf("ubc_release didn't release the reference?!\n");
-    } else if (!vn_lock(vp, LK_EXCLUSIVE|LK_INTERLOCK,current_proc())) {
+       if (ubc_issetflags(vp, UI_HASOBJREF))
+           printf("ubc_release didn't release the reference?!\n");
+    } else if (!vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK, current_proc())) {
 #ifdef AFS_DARWIN14_ENV
-        obj = ubc_getobject(vp,UBC_HOLDOBJECT);
+       obj = ubc_getobject(vp, UBC_HOLDOBJECT);
 #else
 #ifdef AFS_DARWIN13_ENV
-        obj = ubc_getobject(vp,(UBC_NOREACTIVATE|UBC_HOLDOBJECT));
+       obj = ubc_getobject(vp, (UBC_NOREACTIVATE | UBC_HOLDOBJECT));
 #else
-        obj = ubc_getobject(vp);
+       obj = ubc_getobject(vp);
 #endif
 #endif
-        (void)ubc_clean(vp, 1);
-        vinvalbuf(vp, V_SAVE, &afs_osi_cred, p, 0, 0);
-        if (vp->v_usecount == 1)
-           VOP_INACTIVE(vp, p);
-        else
-           VOP_UNLOCK(vp, 0, p);
-        if (obj) {
-        if (ISSET(vp->v_flag, VTERMINATE))
-            panic("afs_vnreclaim: already teminating");
-        SET(vp->v_flag, VTERMINATE);
-        memory_object_destroy(obj, 0);
-        while (ISSET(vp->v_flag, VTERMINATE)) {
-              SET(vp->v_flag, VTERMWANT);
-              tsleep((caddr_t)&vp->v_ubcinfo, PINOD, "afs_vnreclaim", 0);
-        }
-        }
-   } else {
-        if (simple_lock_try(&vp->v_interlock))
-            panic("afs_vnreclaim: slept, but did no work :(");
-        if (UBCINFOEXISTS(vp) && vp->v_count == 1) {
-           vp->v_usecount++;
-           simple_unlock(&vp->v_interlock);
-           VN_RELE(vp);
-        } else 
-           simple_unlock(&vp->v_interlock);
-   }
-   AFS_GLOCK();
-   if (slept)
-      ObtainWriteLock(&afs_xvcache,175);
-   else
-      ObtainReadLock(&afs_xvcache);
+       (void)ubc_clean(vp, 1);
+       vinvalbuf(vp, V_SAVE, &afs_osi_cred, p, 0, 0);
+       if (vp->v_usecount == 1)
+           VOP_INACTIVE(vp, p);
+       else
+           VOP_UNLOCK(vp, 0, p);
+       if (obj) {
+           if (ISSET(vp->v_flag, VTERMINATE))
+               panic("afs_vnreclaim: already teminating");
+           SET(vp->v_flag, VTERMINATE);
+           memory_object_destroy(obj, 0);
+           while (ISSET(vp->v_flag, VTERMINATE)) {
+               SET(vp->v_flag, VTERMWANT);
+               tsleep((caddr_t) & vp->v_ubcinfo, PINOD, "afs_vnreclaim", 0);
+           }
+       }
+    } else {
+       if (simple_lock_try(&vp->v_interlock))
+           panic("afs_vnreclaim: slept, but did no work :(");
+       if (UBCINFOEXISTS(vp) && vp->v_count == 1) {
+           vp->v_usecount++;
+           simple_unlock(&vp->v_interlock);
+           VN_RELE(vp);
+       } else
+           simple_unlock(&vp->v_interlock);
+    }
+    AFS_GLOCK();
+    if (slept)
+       ObtainWriteLock(&afs_xvcache, 175);
+    else
+       ObtainReadLock(&afs_xvcache);
 }
 
-void osi_VM_NukePages(struct vnode *vp, off_t offset, off_t size) {
-
+void
+osi_VM_NukePages(struct vnode *vp, off_t offset, off_t size)
+{
     void *object;
-    struct vcache *avc = (struct vcache *)vp;
+    struct vcache *avc = VTOAFS(vp);
 
 #ifdef AFS_DARWIN14_ENV
-    offset=trunc_page(offset);
-    size=round_page(size+1);
+    offset = trunc_page(offset);
+    size = round_page(size + 1);
     while (size) {
-        ubc_page_op(vp, (vm_offset_t)offset, 
-                              UPL_POP_SET | UPL_POP_BUSY | UPL_POP_DUMP,
-                              0, 0);
-        size-=PAGE_SIZE;
-        offset+=PAGE_SIZE;
+       ubc_page_op(vp, (vm_offset_t) offset,
+                   UPL_POP_SET | UPL_POP_BUSY | UPL_POP_DUMP, 0, 0);
+       size -= PAGE_SIZE;
+       offset += PAGE_SIZE;
     }
 #else
-    object=NULL;
+    object = NULL;
 #ifdef AFS_DARWIN13_ENV
     if (UBCINFOEXISTS(vp))
-        object = ubc_getobject(vp, UBC_NOREACTIVATE);
+       object = ubc_getobject(vp, UBC_NOREACTIVATE);
 #else
     if (UBCINFOEXISTS(vp))
-        object = ubc_getobject(vp);
+       object = ubc_getobject(vp);
 #endif
     if (!object)
-        return;
+       return;
 
-    offset=trunc_page(offset);
-    size=round_page(size+1);
+    offset = trunc_page(offset);
+    size = round_page(size + 1);
 
 #ifdef AFS_DARWIN13_ENV
     while (size) {
-        memory_object_page_op(object, (vm_offset_t)offset, 
-                              UPL_POP_SET | UPL_POP_BUSY | UPL_POP_DUMP,
-                              0, 0);
-        size-=PAGE_SIZE;
-        offset+=PAGE_SIZE;
+       memory_object_page_op(object, (vm_offset_t) offset,
+                             UPL_POP_SET | UPL_POP_BUSY | UPL_POP_DUMP, 0,
+                             0);
+       size -= PAGE_SIZE;
+       offset += PAGE_SIZE;
     }
-#else 
+#else
     /* This is all we can do, and it's not enough. sucks to be us */
     ubc_setsize(vp, offset);
-    size=(offset + size > avc->m.Length) ? offset + size : avc->m.Length;
+    size = (offset + size > avc->m.Length) ? offset + size : avc->m.Length;
     ubc_setsize(vp, size);
 #endif
 #endif
-
 }
-int osi_VM_Setup(struct vcache *avc) {
-   int error;
-   struct vnode *vp=(struct vnode *)avc;
 
-   if (UBCISVALID(vp) && (avc->states & CStatd)) {
-      if (!UBCINFOEXISTS(vp) && !ISSET(vp->v_flag, VTERMINATE)) {
-         osi_vnhold(avc,0);  
-         AFS_GUNLOCK();
-         if ((error=ubc_info_init(&avc->v)))  {
-             AFS_GLOCK();
-             AFS_RELE(avc);
-             return error;
-         }
+int
+osi_VM_Setup(struct vcache *avc, int force)
+{
+    int error;
+    struct vnode *vp = AFSTOV(avc);
+
+    if (UBCISVALID(vp) && ((avc->states & CStatd) || force)) {
+       if (!UBCINFOEXISTS(vp) && !ISSET(vp->v_flag, VTERMINATE)) {
+           osi_vnhold(avc, 0);
+           avc->states |= CUBCinit;
+           AFS_GUNLOCK();
+           if ((error = ubc_info_init(&avc->v))) {
+               AFS_GLOCK();
+               avc->states &= ~CUBCinit;
+               AFS_RELE(avc);
+               return error;
+           }
 #ifndef AFS_DARWIN14_ENV
-         simple_lock(&avc->v.v_interlock);
-         if (!ubc_issetflags(&avc->v, UI_HASOBJREF))
+           simple_lock(&avc->v.v_interlock);
+           if (!ubc_issetflags(&avc->v, UI_HASOBJREF))
 #ifdef AFS_DARWIN13_ENV
-            if (ubc_getobject(&avc->v, (UBC_NOREACTIVATE|UBC_HOLDOBJECT)))
-                   panic("VM_Setup: null object");
+               if (ubc_getobject
+                   (&avc->v, (UBC_NOREACTIVATE | UBC_HOLDOBJECT)))
+                   panic("VM_Setup: null object");
 #else
-            (void)_ubc_getobject(&avc->v, 1); /* return value not used */
+               (void)_ubc_getobject(&avc->v, 1);       /* return value not used */
 #endif
-         simple_unlock(&avc->v.v_interlock);
+           simple_unlock(&avc->v.v_interlock);
 #endif
-         AFS_GLOCK();
-         AFS_RELE(avc);
-      }
-      if (UBCINFOEXISTS(&avc->v))
-          ubc_setsize(&avc->v, avc->m.Length);
-   }
-   return 0;
+           AFS_GLOCK();
+           avc->states &= ~CUBCinit;
+           AFS_RELE(avc);
+       }
+       if (UBCINFOEXISTS(&avc->v))
+           ubc_setsize(&avc->v, avc->m.Length);
+    }
+    return 0;
 }