mirror of
https://git.openafs.org/openafs.git
synced 2025-01-19 23:40:13 +00:00
Windows: add cm_BPlusDirEnumBulkStatOne
cm_BPlusDirEnumBulkStatOne() is similar to cm_BPlusDirEnumBulkStat() except that it is used to obtain the status info for one FID in particular via RXAFS_InlineBulkStat, the parent directory FID, and up to 48 other FIDs in the same directory which do not currently have a registered callback. The parent directory is included to prevent the directory FID callback from expiring when a directory such as /afs/andrew.cmu.edu/usr/ that requires more status objects then exist in the cache are continuously recycled. Up to 48 other FIDs are requested since in most cases on Windows every entry in a directory is required for an enumeration. Change-Id: Ic53134498ac0e776232a6f9c97cdb26367959546 Reviewed-on: http://gerrit.openafs.org/5345 Reviewed-by: Jeffrey Altman <jaltman@openafs.org> Tested-by: Jeffrey Altman <jaltman@openafs.org>
This commit is contained in:
parent
1a0dd342cc
commit
0954e0ef9a
@ -2397,6 +2397,114 @@ cm_BPlusDirEnumBulkStat(cm_direnum_t *enump)
|
||||
return code;
|
||||
}
|
||||
|
||||
/*
|
||||
* Similar to cm_BPlusDirEnumBulkStat() except that only
|
||||
* one RPC is issued containing the provided scp FID and up to
|
||||
* AFSCBMAX - 1 other FIDs for which the status info has yet
|
||||
* to be obtained.
|
||||
*/
|
||||
long
|
||||
cm_BPlusDirEnumBulkStatOne(cm_direnum_t *enump, cm_scache_t *scp)
|
||||
{
|
||||
cm_scache_t *dscp = enump->dscp;
|
||||
cm_user_t *userp = enump->userp;
|
||||
cm_bulkStat_t *bsp;
|
||||
afs_uint32 code = 0;
|
||||
afs_uint32 i;
|
||||
cm_req_t req;
|
||||
|
||||
cm_InitReq(&req);
|
||||
req.flags = enump->reqFlags;
|
||||
|
||||
if ( dscp->fid.cell == AFS_FAKE_ROOT_CELL_ID )
|
||||
return 0;
|
||||
|
||||
bsp = malloc(sizeof(cm_bulkStat_t));
|
||||
if (!bsp)
|
||||
return ENOMEM;
|
||||
memset(bsp, 0, sizeof(cm_bulkStat_t));
|
||||
|
||||
/*
|
||||
* In order to prevent the directory callback from expiring
|
||||
* on really large directories with many symlinks to mount
|
||||
* points such as /afs/andrew.cmu.edu/usr/, always include
|
||||
* the directory fid in the search.
|
||||
*/
|
||||
if (lock_TryWrite(&dscp->rw)) {
|
||||
bsp->fids[bsp->counter].Volume = dscp->fid.volume;
|
||||
bsp->fids[bsp->counter].Vnode = dscp->fid.vnode;
|
||||
bsp->fids[bsp->counter].Unique = dscp->fid.unique;
|
||||
bsp->counter++;
|
||||
lock_ReleaseWrite(&dscp->rw);
|
||||
}
|
||||
|
||||
/* First process the requested scp if we can */
|
||||
if (lock_TryWrite(&scp->rw)) {
|
||||
bsp->fids[bsp->counter].Volume = scp->fid.volume;
|
||||
bsp->fids[bsp->counter].Vnode = scp->fid.vnode;
|
||||
bsp->fids[bsp->counter].Unique = scp->fid.unique;
|
||||
bsp->counter++;
|
||||
lock_ReleaseWrite(&scp->rw);
|
||||
}
|
||||
|
||||
if (enump->count <= AFSCBMAX - 1) {
|
||||
i = 0;
|
||||
} else {
|
||||
/*
|
||||
* Find the requested FID in the enumeration
|
||||
* and start from there.
|
||||
*/
|
||||
for (i=0; i < enump->count && cm_FidCmp(&scp->fid, &enump->entry[i].fid); i++);
|
||||
}
|
||||
|
||||
for ( ; bsp->counter < AFSCBMAX && i < enump->count; i++) {
|
||||
cm_scache_t *tscp;
|
||||
int count = bsp->counter;
|
||||
|
||||
if ( !wcscmp(L".", enump->entry[i].name) || !wcscmp(L"..", enump->entry[i].name) ) {
|
||||
continue;
|
||||
} else {
|
||||
tscp = cm_FindSCache(&enump->entry[i].fid);
|
||||
if (scp == tscp) {
|
||||
enump->entry[i].flags |= CM_DIRENUM_FLAG_GOT_STATUS;
|
||||
cm_ReleaseSCache(tscp);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (tscp) {
|
||||
if (lock_TryWrite(&tscp->rw)) {
|
||||
/* we have an entry that we can look at */
|
||||
if (!(tscp->flags & CM_SCACHEFLAG_EACCESS) && cm_HaveCallback(tscp)) {
|
||||
/* we have a callback on it. Don't bother
|
||||
* fetching this stat entry, since we're happy
|
||||
* with the info we have.
|
||||
*/
|
||||
lock_ReleaseWrite(&tscp->rw);
|
||||
cm_ReleaseSCache(tscp);
|
||||
enump->entry[i].flags |= CM_DIRENUM_FLAG_GOT_STATUS;
|
||||
continue;
|
||||
}
|
||||
lock_ReleaseWrite(&tscp->rw);
|
||||
} /* got lock */
|
||||
if (scp != tscp)
|
||||
cm_ReleaseSCache(tscp);
|
||||
} /* found entry */
|
||||
|
||||
bsp->fids[count].Volume = enump->entry[i].fid.volume;
|
||||
bsp->fids[count].Vnode = enump->entry[i].fid.vnode;
|
||||
bsp->fids[count].Unique = enump->entry[i].fid.unique;
|
||||
bsp->counter++;
|
||||
enump->entry[i].flags |= CM_DIRENUM_FLAG_GOT_STATUS;
|
||||
}
|
||||
|
||||
if (bsp->counter > 0)
|
||||
code = cm_TryBulkStatRPC(dscp, bsp, userp, &req);
|
||||
|
||||
free(bsp);
|
||||
return code;
|
||||
}
|
||||
|
||||
static long
|
||||
cm_BPlusDirEnumBulkStatNext(cm_direnum_t *enump)
|
||||
{
|
||||
|
@ -179,6 +179,7 @@ long cm_BPlusDirPeekNextEnumEntry(cm_direnum_t *enump, cm_direnum_entry_t **entr
|
||||
long cm_BPlusDirFreeEnumeration(cm_direnum_t *enump);
|
||||
long cm_BPlusDirEnumTest(cm_scache_t * dscp, cm_user_t *userp, cm_req_t *reqp, afs_uint32 locked);
|
||||
long cm_BPlusDirEnumBulkStat(cm_direnum_t *enump);
|
||||
long cm_BPlusDirEnumBulkStatOne(cm_direnum_t *enump, cm_scache_t *scp);
|
||||
|
||||
long cm_InitBPlusDir(void);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user