if (UBCINFOEXISTS(vp))
return EBUSY;
#endif
- if (avc->vrefCount)
+ if (avc->vrefCount > DARWIN_REFBASE)
return EBUSY;
if (avc->opens)
struct proc *p = current_proc();
struct vnode *vp = AFSTOV(avc);
void *obj;
+#ifdef AFS_DARWIN14_ENV
+ int didhold;
+#endif
if (slept)
*slept = 0;
AFS_RELE(vp);
return;
}
- if (!UBCINFOEXISTS(vp) || vp->v_count != 2) {
+ if (!UBCINFOEXISTS(vp) || vp->v_usecount != 2+DARWIN_REFBASE) {
simple_unlock(&vp->v_interlock);
AFS_RELE(vp);
return;
AFS_RELE(vp);
return;
}
+ if (ISSET(vp->v_flag, VORECLAIM)) {
+ simple_unlock(&vp->v_interlock);
+ AFS_RELE(vp);
+ return;
+ }
#else
if (vp->v_ubcinfo->ui_holdcnt) {
simple_unlock(&vp->v_interlock);
return;
}
+#ifndef AFS_DARWIN14_ENV
vp->v_usecount--; /* we want the usecount to be 1 */
+#endif
if (slept) {
ReleaseWriteLock(&afs_xvcache);
#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())) {
+ } else {
#ifdef AFS_DARWIN14_ENV
- obj = ubc_getobject(vp, UBC_HOLDOBJECT);
+ SET(vp->v_flag, VORECLAIM);
+#endif
+ if (!vn_lock(vp, LK_EXCLUSIVE|LK_INTERLOCK,current_proc())) {
+#ifdef AFS_DARWIN14_ENV
+ obj = ubc_getobject(vp,UBC_HOLDOBJECT);
+ if ((didhold = ubc_hold(vp)))
+ (void)ubc_clean(vp, 0);
#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);
+#endif
+ (void)ubc_clean(vp, 1);
+#endif
+ vinvalbuf(vp, V_SAVE, &afs_osi_cred, p, 0, 0);
+ if (vp->v_usecount ==
+#ifdef AFS_DARWIN14_ENV
+ 2 + DARWIN_REFBASE
#else
- obj = ubc_getobject(vp);
+ 1
#endif
+ )
+ VOP_INACTIVE(vp, p);
+ else
+ VOP_UNLOCK(vp, 0, p);
+#ifdef AFS_DARWIN14_ENV
+ if (didhold)
+ ubc_rele(vp);
#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);
+ 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
+#ifdef AFS_DARWIN14_ENV
+ simple_lock(&vp->v_interlock);
+ CLR(vp->v_flag, VORECLAIM);
+ if (ISSET((vp)->v_flag, VXWANT)) {
+ CLR((vp)->v_flag, VXWANT);
+ wakeup((caddr_t)(vp));
+ }
+ vp->v_usecount--;
simple_unlock(&vp->v_interlock);
+#endif
+ } else {
+#ifdef AFS_DARWIN14_ENV
+ CLR(vp->v_flag, VORECLAIM);
+#endif
+ if (simple_lock_try(&vp->v_interlock))
+ panic("afs_vnreclaim: slept, but did no work :(");
+ if (UBCINFOEXISTS(vp) && vp->v_count == DARWIN_REFBASE +
+#ifdef AFS_DARWIN14_ENV
+ 2
+#else
+ 1
+#endif
+ ) {
+#ifndef AFS_DARWIN14_ENV
+ /* We left the refcount high in 1.4 */
+ vp->v_usecount++;
+#endif
+ simple_unlock(&vp->v_interlock);
+ VN_RELE(vp);
+ } else {
+#ifdef AFS_DARWIN14_ENV
+ /* We left the refcount high in 1.4 */
+ vp->v_usecount--;
+#endif
+ simple_unlock(&vp->v_interlock);
+ }
+ }
}
AFS_GLOCK();
if (slept)
- ObtainWriteLock(&afs_xvcache, 175);
+ ObtainWriteLock(&afs_xvcache,175);
else
- ObtainReadLock(&afs_xvcache);
+ ObtainReadLock(&afs_xvcache);
}
void
printf("afs: WARNING: ui_refcount panic averted\n");
}
}
+ if (UBCINFOMISSING(ap->a_vp) ||
+ UBCINFORECLAIMED(ap->a_vp)) {
+ if (UBCINFORECLAIMED(ap->a_vp) && ISSET(ap->a_vp->v_flag,
+ (VXLOCK|VORECLAIM))) {
+ printf("no ubc for %x in close, reclaim set\n", ap->a_vp);
+ return (ENXIO);
+ } else {
+ printf("no ubc for %x in close, put back\n", ap->a_vp);
+ ubc_info_init(ap->a_vp);
+ }
+ }
#endif
return code;
cache_purge(vp);
if (!error && UBCINFOEXISTS(vp)) {
#ifdef AFS_DARWIN14_ENV
- (void)ubc_uncache(vp);
+ /* If crashes continue in ubc_hold, comment this out */
+ /* (void)ubc_uncache(vp);*/
#else
int wasmapped = ubc_issetflags(vp, UI_WASMAPPED);
int hasobjref = ubc_issetflags(vp, UI_HASOBJREF);
Ttvcr = VREFCOUNT(tvc);
#ifdef AFS_AIX_ENV
if (tvc && (VREFCOUNT(tvc) > 2) && tvc->opens > 0
- && !(tvc->states & CUnlinked)) {
+ && !(tvc->states & CUnlinked))
+#else
+#ifdef AFS_DARWIN14_ENV
+ if (tvc && (VREFCOUNT(tvc) > 1 + DARWIN_REFBASE) && tvc->opens > 0 && !(tvc->states & CUnlinked))
#else
if (tvc && (VREFCOUNT(tvc) > 1) && tvc->opens > 0
- && !(tvc->states & CUnlinked)) {
+ && !(tvc->states & CUnlinked))
+#endif
#endif
+ {
char *unlname = newname();
ReleaseWriteLock(&adp->lock);
struct VenusFid dirFid;
register struct dcache *tdc;
afs_int32 code = 0;
+ int oldref;
if (NBObtainWriteLock(&avc->lock, 423))
return 0;
cred = avc->uncred;
avc->uncred = NULL;
-#ifdef AFS_DARWIN_ENV
+#if defined(AFS_DARWIN_ENV) && !defined(AFS_DARWIN14_ENV)
/* this is called by vrele (via VOP_INACTIVE) when the refcount
* is 0. we can't just call VN_HOLD since vref will panic.
* we can't just call osi_vnhold because a later AFS_RELE will call
*/
avc->states &= ~(CUnlinked | CUnlinkedDel);
+#ifdef AFS_DARWIN14_ENV
+ if (VREFCOUNT(avc) < 4) {
+ oldref = 4 - VREFCOUNT(avc);
+ VREFCOUNT_SET(avc, 4);
+ }
+#endif
ReleaseWriteLock(&avc->lock);
dirFid.Cell = avc->fid.Cell;
osi_FreeSmallSpace(unlname);
crfree(cred);
#ifdef AFS_DARWIN_ENV
+#ifndef AFS_DARWIN14_ENV
osi_Assert(VREFCOUNT(avc) == 1);
VREFCOUNT_SET(avc, 0);
+#else
+ if (oldref) {
+ int newref = VREFCOUNT(avc) - oldref;
+ VREFCOUNT_SET(avc, newref);
+ }
+#endif
#endif
}
} else {
refpanic("VLRU inconsistent");
}
#ifdef AFS_DARWIN_ENV
+ if ((VREFCOUNT(tvc) < DARWIN_REFBASE) ||
+ (VREFCOUNT(tvc) < 1+DARWIN_REFBASE &&
+ UBCINFOEXISTS(&tvc->v))) {
+ VREFCOUNT_SET(tvc,
+ DARWIN_REFBASE + (UBCINFOEXISTS(&tvc->v) ? 1 : 0));
+ }
if (tvc->opens == 0 && ((tvc->states & CUnlinkedDel) == 0)
- && VREFCOUNT(tvc) == 1 && UBCINFOEXISTS(&tvc->v)) {
+ && VREFCOUNT(tvc) == DARWIN_REFBASE+1
+ && UBCINFOEXISTS(&tvc->v)) {
osi_VM_TryReclaim(tvc, &fv_slept);
if (fv_slept) {
uq = VLRU.prev;
}
#endif
- if (VREFCOUNT(tvc) == 0 && tvc->opens == 0
+ if (VREFCOUNT(tvc) ==
+#ifdef AFS_DARWIN_ENV
+ DARWIN_REFBASE
+#else
+ 0
+#endif
+ && tvc->opens == 0
&& (tvc->states & CUnlinkedDel) == 0) {
#if defined(AFS_XBSD_ENV)
/*
/* VLISTNONE(&tvc->v); */
tvc->v.v_freelist.tqe_next = 0;
tvc->v.v_freelist.tqe_prev = (struct vnode **)0xdeadb;
- /*tvc->vrefCount++; */
+ tvc->vrefCount+=DARWIN_REFBASE;
#endif
/*
* The proper value for mvstat (for root fids) is setup by the caller.
}
}
#ifdef AFS_DARWIN_ENV
- if (VREFCOUNT(tvc) == 1 && UBCINFOEXISTS(&tvc->v)) {
+ if (VREFCOUNT(tvc) == 1+DARWIN_REFBASE
+ && UBCINFOEXISTS(&tvc->v)) {
if (tvc->opens)
panic("flushactive open, hasubc, but refcnt 1");
osi_VM_TryReclaim(tvc, 0);
if (vg)
continue;
#endif /* AFS_OSF_ENV */
+#ifdef AFS_DARWIN14_ENV
+ /* It'd really suck if we allowed duplicate vcaches for the
+ same fid to happen. Wonder if this will work? */
+ struct vnode *vp = AFSTOV(tvc);
+ if (vp->v_flag & (VXLOCK|VORECLAIM|VTERMINATE)) {
+ printf("precluded FindVCache on %x (%d:%d:%d)\n",
+ vp, tvc->fid.Fid.Volume, tvc->fid.Fid.Vnode,
+ tvc->fid.Fid.Unique);
+ simple_lock(&vp->v_interlock);
+ SET(vp->v_flag, VTERMWANT);
+ simple_unlock(&vp->v_interlock);
+ (void)tsleep((caddr_t)&vp->v_ubcinfo, PINOD, "vget1", 0);
+ printf("VTERMWANT ended on %x\n", vp);
+ continue;
+ }
+#endif
break;
}
}
#define AFS_DARWIN_ENV
#define AFS_NONFSTRANS
#define AFS_SYSCALL 230
+#define DARWIN_REFBASE 0
/* File system entry (used if mount.h doesn't define MOUNT_AFS */
#define AFS_MOUNT_AFS "afs"
#define AFS_USR_DARWIN_ENV
#define AFS_NONFSTRANS
#define AFS_SYSCALL 230
+#define DARWIN_REFBASE 0
/* File system entry (used if mount.h doesn't define MOUNT_AFS */
#define AFS_MOUNT_AFS "afs"
#define AFS_DARWIN13_ENV
#define AFS_NONFSTRANS
#define AFS_SYSCALL 230
+#define DARWIN_REFBASE 0
/* File system entry (used if mount.h doesn't define MOUNT_AFS */
#define AFS_MOUNT_AFS "afs"
#define AFS_USR_DARWIN13_ENV
#define AFS_NONFSTRANS
#define AFS_SYSCALL 230
+#define DARWIN_REFBASE 0
/* File system entry (used if mount.h doesn't define MOUNT_AFS */
#define AFS_MOUNT_AFS "afs"
#define AFS_NONFSTRANS
#define AFS_SYSCALL 230
#define AFS_NAMEI_ENV 1
+#define DARWIN_REFBASE 0
/* File system entry (used if mount.h doesn't define MOUNT_AFS */
#define AFS_MOUNT_AFS "afs"
#define AFS_USR_DARWIN14_ENV
#define AFS_NONFSTRANS
#define AFS_SYSCALL 230
+#define DARWIN_REFBASE 0
/* File system entry (used if mount.h doesn't define MOUNT_AFS */
#define AFS_MOUNT_AFS "afs"
#define AFS_NONFSTRANS
#define AFS_SYSCALL 230
#define AFS_NAMEI_ENV 1
+#define DARWIN_REFBASE 3
/* File system entry (used if mount.h doesn't define MOUNT_AFS */
#define AFS_MOUNT_AFS "afs"
#define AFS_USR_DARWIN70_ENV
#define AFS_NONFSTRANS
#define AFS_SYSCALL 230
+#define DARWIN_REFBASE 0
/* File system entry (used if mount.h doesn't define MOUNT_AFS */
#define AFS_MOUNT_AFS "afs"