From 4bc04a79e75ffa5ad852dfb475bfcb3b263b4e57 Mon Sep 17 00:00:00 2001 From: Derrick Brashear Date: Fri, 12 Feb 2010 16:46:33 -0500 Subject: [PATCH] macos bulkstat support add KPI-based bulkstat support for macos Change-Id: I6d9afa968db5930d392a6298dc5094f3cb500a1b Reviewed-on: http://gerrit.openafs.org/1303 Reviewed-by: Derrick Brashear Tested-by: Derrick Brashear --- src/afs/DARWIN/osi_prototypes.h | 5 ++- src/afs/DARWIN/osi_vfsops.c | 2 +- src/afs/DARWIN/osi_vnodeops.c | 34 ++++++++++------ src/afs/VNOPS/afs_vnop_lookup.c | 69 +++++++++++++++++++++++---------- src/afs/afs_callback.c | 38 +++++++++++------- src/afs/afs_pioctl.c | 9 ++++- src/afs/afs_vcache.c | 51 +++++++++++++++++------- 7 files changed, 143 insertions(+), 65 deletions(-) diff --git a/src/afs/DARWIN/osi_prototypes.h b/src/afs/DARWIN/osi_prototypes.h index 4a9b6b251..5cd4663b1 100644 --- a/src/afs/DARWIN/osi_prototypes.h +++ b/src/afs/DARWIN/osi_prototypes.h @@ -35,7 +35,8 @@ extern void osi_VM_NukePages(struct vnode *vp, off_t offset, off_t size); 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_ */ diff --git a/src/afs/DARWIN/osi_vfsops.c b/src/afs/DARWIN/osi_vfsops.c index 48df74c28..4076b7144 100644 --- a/src/afs/DARWIN/osi_vfsops.c +++ b/src/afs/DARWIN/osi_vfsops.c @@ -276,7 +276,7 @@ afs_root(struct mount *mp, struct vnode **vpp) #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; diff --git a/src/afs/DARWIN/osi_vnodeops.c b/src/afs/DARWIN/osi_vnodeops.c index 911ac2900..77c2e4cc0 100644 --- a/src/afs/DARWIN/osi_vnodeops.c +++ b/src/afs/DARWIN/osi_vnodeops.c @@ -343,7 +343,7 @@ afs_vop_lookup(ap) 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; @@ -428,7 +428,7 @@ afs_vop_create(ap) 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; @@ -1482,7 +1482,7 @@ afs_vop_mkdir(ap) } 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 */ @@ -2010,7 +2010,7 @@ afs_vop_cmap(ap) #endif int -afs_darwin_getnewvnode(struct vcache *avc) +afs_darwin_getnewvnode(struct vcache *avc, int recycle) { #ifdef AFS_DARWIN80_ENV vnode_t vp; @@ -2029,7 +2029,8 @@ afs_darwin_getnewvnode(struct vcache *avc) 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; @@ -2046,14 +2047,16 @@ afs_darwin_getnewvnode(struct vcache *avc) /* 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(); @@ -2066,8 +2069,10 @@ afs_darwin_finalizevnode(struct vcache *avc, struct vnode *dvp, struct component /* 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) @@ -2092,6 +2097,9 @@ afs_darwin_finalizevnode(struct vcache *avc, struct vnode *dvp, struct component 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); @@ -2103,10 +2111,12 @@ afs_darwin_finalizevnode(struct vcache *avc, struct vnode *dvp, struct component 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 diff --git a/src/afs/VNOPS/afs_vnop_lookup.c b/src/afs/VNOPS/afs_vnop_lookup.c index 31a6cc185..be81ff32a 100644 --- a/src/afs/VNOPS/afs_vnop_lookup.c +++ b/src/afs/VNOPS/afs_vnop_lookup.c @@ -399,7 +399,7 @@ afs_EvalFakeStat_int(struct vcache **avcp, struct afs_fakestat_state *state, #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)); @@ -628,6 +628,9 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp) { 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. */ @@ -664,9 +667,7 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp) 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 @@ -824,15 +825,6 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp) 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 @@ -974,9 +966,13 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp) 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"); } @@ -992,7 +988,20 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp) * 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; @@ -1143,6 +1152,23 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp) 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 */ @@ -1150,7 +1176,14 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp) } /* 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 */ @@ -1194,11 +1227,7 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp) } /* 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) diff --git a/src/afs/afs_callback.c b/src/afs/afs_callback.c index a4ea288ab..ed6754298 100644 --- a/src/afs/afs_callback.c +++ b/src/afs/afs_callback.c @@ -455,17 +455,17 @@ loop1: 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; @@ -475,6 +475,11 @@ loop1: 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); @@ -549,17 +554,17 @@ loop2: 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; @@ -569,6 +574,11 @@ loop2: 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); diff --git a/src/afs/afs_pioctl.c b/src/afs/afs_pioctl.c index 79baf27d8..1a387936d 100644 --- a/src/afs/afs_pioctl.c +++ b/src/afs/afs_pioctl.c @@ -3401,11 +3401,13 @@ DECL_PIOCTL(PFlushVolumeData) 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)); @@ -3419,6 +3421,11 @@ DECL_PIOCTL(PFlushVolumeData) 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 diff --git a/src/afs/afs_vcache.c b/src/afs/afs_vcache.c index ade8bc663..81819e1be 100644 --- a/src/afs/afs_vcache.c +++ b/src/afs/afs_vcache.c @@ -1026,7 +1026,7 @@ afs_NewVCache_int(struct VenusFid *afid, struct server *serverp, int seq) #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 @@ -2337,11 +2337,13 @@ afs_GetRootVCache(struct VenusFid *afid, struct vrequest *areq, 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; @@ -2352,6 +2354,11 @@ afs_GetRootVCache(struct VenusFid *afid, struct vrequest *areq, AFS_GLOCK(); continue; } + if (tvc->f.states & (CBulkFetching|CDeadVnode)) { + AFS_GUNLOCK(); + vnode_recycle(AFSTOV(tvc)); + AFS_GLOCK(); + } #endif break; } @@ -2885,10 +2892,12 @@ afs_FindVCache(struct VenusFid *afid, afs_int32 * retry, afs_int32 flag) 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; @@ -2899,6 +2908,11 @@ afs_FindVCache(struct VenusFid *afid, afs_int32 * retry, afs_int32 flag) AFS_GLOCK(); continue; } + if (tvc->f.states & (CBulkFetching|CDeadVnode)) { + AFS_GUNLOCK(); + vnode_recycle(AFSTOV(tvc)); + AFS_GLOCK(); + } #endif break; } @@ -3016,11 +3030,13 @@ afs_NFSFindVCache(struct vcache **avcp, struct VenusFid *afid) 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. */ @@ -3034,6 +3050,11 @@ afs_NFSFindVCache(struct vcache **avcp, struct VenusFid *afid) 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) { -- 2.39.5