extern int osi_VM_Setup(struct vcache *avc, int force);
/* osi_vnodeops.c */
-extern int afs_darwin_getnewvnode(struct vcache *avc);
+extern int afs_darwin_getnewvnode(struct vcache *avc, int recycle);
extern int afs_darwin_finalizevnode(struct vcache *avc, struct vnode *parent,
- struct componentname *cnp, int isroot);
+ struct componentname *cnp, int isroot,
+ int locked);
#endif /* _OSI_PROTO_H_ */
#ifdef AFS_DARWIN80_ENV
if (tvp) {
AFS_GUNLOCK();
- error = afs_darwin_finalizevnode(tvp, NULL, NULL, 1);
+ error = afs_darwin_finalizevnode(tvp, NULL, NULL, 1, 0);
AFS_GLOCK();
if (error)
tvp = NULL;
return (error);
}
#ifdef AFS_DARWIN80_ENV
- if ((error=afs_darwin_finalizevnode(vcp, ap->a_dvp, ap->a_cnp, 0))) {
+ if ((error=afs_darwin_finalizevnode(vcp, ap->a_dvp, ap->a_cnp, 0, 0))) {
DROPNAME();
*ap->a_vpp = 0;
return error;
if (vcp) {
#ifdef AFS_DARWIN80_ENV
- if ((error=afs_darwin_finalizevnode(vcp, ap->a_dvp, ap->a_cnp, 0))) {
+ if ((error=afs_darwin_finalizevnode(vcp, ap->a_dvp, ap->a_cnp, 0, 0))) {
DROPNAME();
*ap->a_vpp=0;
return error;
}
if (vcp) {
#ifdef AFS_DARWIN80_ENV
- afs_darwin_finalizevnode(vcp, ap->a_dvp, ap->a_cnp, 0);
+ afs_darwin_finalizevnode(vcp, ap->a_dvp, ap->a_cnp, 0, 0);
#endif
*ap->a_vpp = AFSTOV(vcp);
#ifndef AFS_DARWIN80_ENV /* XXX needed for multi-mount thing, but can't have it yet */
#endif
int
-afs_darwin_getnewvnode(struct vcache *avc)
+afs_darwin_getnewvnode(struct vcache *avc, int recycle)
{
#ifdef AFS_DARWIN80_ENV
vnode_t vp;
vnode_addfsref(vp);
vnode_ref(vp);
avc->v = vp;
- vnode_recycle(vp); /* terminate as soon as iocount drops */
+ if (recycle)
+ vnode_recycle(vp); /* terminate as soon as iocount drops */
avc->f.states |= CDeadVnode;
}
return error;
/* if this fails, then tvc has been unrefed and may have been freed.
Don't touch! */
int
-afs_darwin_finalizevnode(struct vcache *avc, struct vnode *dvp, struct componentname *cnp, int isroot)
+afs_darwin_finalizevnode(struct vcache *avc, struct vnode *dvp, struct componentname *cnp, int isroot, int locked)
{
vnode_t ovp;
vnode_t nvp;
int error;
struct vnode_fsparam par;
- AFS_GLOCK();
- ObtainWriteLock(&avc->lock,325);
+ if (!locked) {
+ AFS_GLOCK();
+ ObtainWriteLock(&avc->lock,325);
+ }
ovp = AFSTOV(avc);
if (!(avc->f.states & CDeadVnode) && vnode_vtype(ovp) != VNON) {
AFS_GUNLOCK();
/* Can end up in reclaim... drop GLOCK */
vnode_rele(ovp);
AFS_GLOCK();
- ReleaseWriteLock(&avc->lock);
- AFS_GUNLOCK();
+ if (!locked) {
+ ReleaseWriteLock(&avc->lock);
+ AFS_GUNLOCK();
+ }
return 0;
}
if ((avc->f.states & CDeadVnode) && vnode_vtype(ovp) != VNON)
if ((avc->f.states & CDeadVnode) && vnode_vtype(ovp) != VNON)
printf("vcache %p should not be CDeadVnode", avc);
if (avc->v == ovp) {
+ if (avc->f.states & CBulkFetching) {
+ vnode_recycle(ovp);
+ }
if (!(avc->f.states & CVInit)) {
vnode_clearfsnode(ovp);
vnode_removefsref(ovp);
vnode_put(ovp);
vnode_rele(ovp);
AFS_GLOCK();
- ReleaseWriteLock(&avc->lock);
+ if (!locked)
+ ReleaseWriteLock(&avc->lock);
if (!error)
afs_osi_Wakeup(&avc->f.states);
- AFS_GUNLOCK();
+ if (!locked)
+ AFS_GUNLOCK();
return error;
}
#endif
#ifdef AFS_DARWIN80_ENV
root_vp->f.m.Type = VDIR;
AFS_GUNLOCK();
- code = afs_darwin_finalizevnode(root_vp, NULL, NULL, 0);
+ code = afs_darwin_finalizevnode(root_vp, NULL, NULL, 0, 0);
AFS_GLOCK();
if (code) goto done;
vnode_ref(AFSTOV(root_vp));
{
int nentries; /* # of entries to prefetch */
int nskip; /* # of slots in the LRU queue to skip */
+#ifdef AFS_DARWIN80_ENV
+ struct vnode *lruvp;
+#endif
struct vcache *lruvcp; /* vcache ptr of our goal pos in LRU queue */
struct dcache *dcp; /* chunk containing the dir block */
afs_size_t temp; /* temp for holding chunk length, &c. */
dotdot.Cell = 0;
dotdot.Fid.Unique = 0;
dotdot.Fid.Vnode = 0;
-#ifdef AFS_DARWIN80_ENV
- panic("bulkstatus doesn't work on AFS_DARWIN80_ENV. don't call it");
-#endif
+
/* first compute some basic parameters. We dont want to prefetch more
* than a fraction of the cache in any given call, and we want to preserve
* a portion of the LRU queue in any event, so as to avoid thrashing
goto done; /* can happen if afs_NewVCache fails */
}
-#ifdef AFS_DARWIN80_ENV
- if (tvcp->f.states & CVInit) {
- /* XXX don't have status yet, so creating the vnode is
- not yet useful. we would get CDeadVnode set, and the
- upcoming PutVCache will cause the vcache to be flushed &
- freed, which in turn means the bulkstatus results won't
- be used */
- }
-#endif
/* WARNING: afs_DoBulkStat uses the Length field to store a
* sequence number for each bulk status request. Under no
* circumstances should afs_DoBulkStat store a sequence number
refpanic("Bulkstat VLRU inconsistent");
}
for (tq = VLRU.next; tq != &VLRU; tq = QNext(tq)) {
- if (--nskip <= 0)
- break;
- else if (QNext(QPrev(tq)) != tq) {
+ if (--nskip <= 0) {
+#ifdef AFS_DARWIN80_ENV
+ if (!(QTOV(tq)->f.states & CDeadVnode))
+#endif
+ break;
+ }
+ if (QNext(QPrev(tq)) != tq) {
BStvc = QTOV(tq);
refpanic("BulkStat VLRU inconsistent");
}
* doesn't hurt nearly as much.
*/
retry = 0;
+#ifdef AFS_DARWIN80_ENV
+ lruvp = AFSTOV(lruvcp);
+ if (vnode_get(lruvp)) /* this bumps ref count */
+ retry = 1;
+ else if (vnode_ref(lruvp)) {
+ AFS_GUNLOCK();
+ /* AFSTOV(lruvcp) may be NULL */
+ vnode_put(lruvp);
+ AFS_GLOCK();
+ retry = 1;
+ }
+#else
osi_vnhold(lruvcp, &retry);
+#endif
ReleaseReadLock(&afs_xvcache); /* could be read lock */
if (retry)
goto reskip;
osi_dnlc_purgedp(tvcp); /* if it (could be) a directory */
}
ReleaseWriteLock(&afs_xcbhash);
+#ifdef AFS_DARWIN80_ENV
+ /* reclaim->FlushVCache will need xcbhash */
+ if (tvcp->f.states & CDeadVnode) {
+ /* passing in a parent hangs getting the vnode lock */
+ code = afs_darwin_finalizevnode(tvcp, NULL, NULL, 0, 1);
+ if (code) {
+ /* It's gonna get recycled - shouldn't happen */
+ tvcp->callback = 0;
+ tvcp->f.states &= ~(CStatd | CUnique);
+ afs_DequeueCallback(tvcp);
+ if ((tvcp->f.states & CForeign) || (vType(tvcp) == VDIR))
+ osi_dnlc_purgedp(tvcp); /* if it (could be) a directory */
+ } else
+ /* re-acquire the usecount that finalizevnode disposed of */
+ vnode_ref(AFSTOV(tvcp));
+ }
+#endif
ReleaseWriteLock(&tvcp->lock);
/* finally, we're done with the entry */
} /* for all files we got back */
/* finally return the pointer into the LRU queue */
+#ifdef AFS_DARWIN80_ENV
+ AFS_GUNLOCK();
+ vnode_put(lruvp);
+ vnode_rele(lruvp);
+ AFS_GLOCK();
+#else
afs_PutVCache(lruvcp);
+#endif
done:
/* Be sure to turn off the CBulkFetching flags */
}
/* was: (AFS_DEC_ENV) || defined(AFS_OSF30_ENV) || defined(AFS_NCR_ENV) */
-#ifdef AFS_DARWIN80_ENV
-#define AFSDOBULK 0
-#else
static int AFSDOBULK = 1;
-#endif
int
#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
afs_osi_Sleep(&tvc->f.states);
goto loop1;
}
-#ifdef AFS_DARWIN80_ENV
- if (tvc->f.states & CDeadVnode) {
- ReleaseReadLock(&afs_xvcache);
- afs_osi_Sleep(&tvc->f.states);
- goto loop1;
- }
-#endif
#if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
VN_HOLD(AFSTOV(tvc));
#else
#ifdef AFS_DARWIN80_ENV
+ if (tvc->f.states & CDeadVnode) {
+ if (!(tvc->f.states & CBulkFetching)) {
+ ReleaseReadLock(&afs_xvcache);
+ afs_osi_Sleep(&tvc->f.states);
+ goto loop1;
+ }
+ }
vp = AFSTOV(tvc);
if (vnode_get(vp))
continue;
AFS_GLOCK();
continue;
}
+ if (tvc->f.states & (CBulkFetching|CDeadVnode)) {
+ AFS_GUNLOCK();
+ vnode_recycle(AFSTOV(tvc));
+ AFS_GLOCK();
+ }
#else
#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
osi_vnhold(tvc, 0);
afs_osi_Sleep(&tvc->f.states);
goto loop2;
}
-#ifdef AFS_DARWIN80_ENV
- if (tvc->f.states & CDeadVnode) {
- ReleaseReadLock(&afs_xvcache);
- afs_osi_Sleep(&tvc->f.states);
- goto loop2;
- }
-#endif
#if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
VN_HOLD(AFSTOV(tvc));
#else
#ifdef AFS_DARWIN80_ENV
+ if (tvc->f.states & CDeadVnode) {
+ if (!(tvc->f.states & CBulkFetching)) {
+ ReleaseReadLock(&afs_xvcache);
+ afs_osi_Sleep(&tvc->f.states);
+ goto loop2;
+ }
+ }
vp = AFSTOV(tvc);
if (vnode_get(vp))
continue;
AFS_GLOCK();
continue;
}
+ if (tvc->f.states & (CBulkFetching|CDeadVnode)) {
+ AFS_GUNLOCK();
+ vnode_recycle(AFSTOV(tvc));
+ AFS_GLOCK();
+ }
#else
#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
osi_vnhold(tvc, 0);
goto loop;
}
#ifdef AFS_DARWIN80_ENV
- if (tvc->f.states & CDeadVnode) {
+ if (tvc->f.states & CDeadVnode) {
+ if (!(tvc->f.states & CBulkFetching)) {
ReleaseReadLock(&afs_xvcache);
afs_osi_Sleep(&tvc->f.states);
goto loop;
}
+ }
#endif
#if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
VN_HOLD(AFSTOV(tvc));
AFS_GLOCK();
continue;
}
+ if (tvc->f.states & (CBulkFetching|CDeadVnode)) {
+ AFS_GUNLOCK();
+ vnode_recycle(AFSTOV(tvc));
+ AFS_GLOCK();
+ }
#elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
osi_vnhold(tvc, 0);
#else
#ifdef AFS_DARWIN_ENV
ReleaseWriteLock(&afs_xvcache);
AFS_GUNLOCK();
- afs_darwin_getnewvnode(tvc); /* includes one refcount */
+ afs_darwin_getnewvnode(tvc, seq ? 0 : 1); /* includes one refcount */
AFS_GLOCK();
ObtainWriteLock(&afs_xvcache,338);
#ifdef AFS_DARWIN80_ENV
goto rootvc_loop;
}
#ifdef AFS_DARWIN80_ENV
- if (tvc->f.states & CDeadVnode) {
- ReleaseSharedLock(&afs_xvcache);
- afs_osi_Sleep(&tvc->f.states);
- goto rootvc_loop;
- }
+ if (tvc->f.states & CDeadVnode) {
+ if (!(tvc->f.states & CBulkFetching)) {
+ ReleaseSharedLock(&afs_xvcache);
+ afs_osi_Sleep(&tvc->f.states);
+ goto rootvc_loop;
+ }
+ }
tvp = AFSTOV(tvc);
if (vnode_get(tvp)) /* this bumps ref count */
continue;
AFS_GLOCK();
continue;
}
+ if (tvc->f.states & (CBulkFetching|CDeadVnode)) {
+ AFS_GUNLOCK();
+ vnode_recycle(AFSTOV(tvc));
+ AFS_GLOCK();
+ }
#endif
break;
}
goto findloop;
}
#ifdef AFS_DARWIN80_ENV
- if (tvc->f.states & CDeadVnode) {
- findvc_sleep(tvc, flag);
- goto findloop;
- }
+ if (tvc->f.states & CDeadVnode) {
+ if (!(tvc->f.states & CBulkFetching)) {
+ findvc_sleep(tvc, flag);
+ goto findloop;
+ }
+ }
tvp = AFSTOV(tvc);
if (vnode_get(tvp))
continue;
AFS_GLOCK();
continue;
}
+ if (tvc->f.states & (CBulkFetching|CDeadVnode)) {
+ AFS_GUNLOCK();
+ vnode_recycle(AFSTOV(tvc));
+ AFS_GLOCK();
+ }
#endif
break;
}
goto loop;
}
#ifdef AFS_DARWIN80_ENV
- if (tvc->f.states & CDeadVnode) {
- ReleaseSharedLock(&afs_xvcache);
- afs_osi_Sleep(&tvc->f.states);
- goto loop;
- }
+ if (tvc->f.states & CDeadVnode) {
+ if (!(tvc->f.states & CBulkFetching)) {
+ ReleaseSharedLock(&afs_xvcache);
+ afs_osi_Sleep(&tvc->f.states);
+ goto loop;
+ }
+ }
tvp = AFSTOV(tvc);
if (vnode_get(tvp)) {
/* This vnode no longer exists. */
AFS_GLOCK();
continue;
}
+ if (tvc->f.states & (CBulkFetching|CDeadVnode)) {
+ AFS_GUNLOCK();
+ vnode_recycle(AFSTOV(tvc));
+ AFS_GLOCK();
+ }
#endif /* AFS_DARWIN80_ENV */
count++;
if (found_tvc) {