diff --git a/src/afs/VNOPS/afs_vnop_lookup.c b/src/afs/VNOPS/afs_vnop_lookup.c index 1b076c05b9..ee6d34f7c5 100644 --- a/src/afs/VNOPS/afs_vnop_lookup.c +++ b/src/afs/VNOPS/afs_vnop_lookup.c @@ -810,6 +810,36 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp) tcp = afs_Conn(&adp->fid, areqp, SHARED_LOCK, &rxconn); if (tcp) { hostp = tcp->srvr->server; + + for (i = 0; i < fidIndex; i++) { + /* we must set tvcp->callback before the BulkStatus call, so + * we can detect concurrent InitCallBackState's */ + + afid.Cell = adp->fid.Cell; + afid.Fid.Volume = adp->fid.Fid.Volume; + afid.Fid.Vnode = fidsp[i].Vnode; + afid.Fid.Unique = fidsp[i].Unique; + + do { + retry = 0; + ObtainReadLock(&afs_xvcache); + tvcp = afs_FindVCache(&afid, &retry, 0 /* !stats&!lru */); + ReleaseReadLock(&afs_xvcache); + } while (tvcp && retry); + + if (!tvcp) { + continue; + } + + if ((tvcp->states & CBulkFetching) && + (tvcp->m.Length == statSeqNo)) { + tvcp->callback = hostp; + } + + afs_PutVCache(tvcp); + tvcp = NULL; + } + XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_BULKSTATUS); RX_AFS_GUNLOCK();