long startTime; /* time we started the call,
* for callback expiration base
*/
+ int ftype[4] = {VNON, VREG, VDIR, VLNK}; /* verify type is as expected */
afs_size_t statSeqNo = 0; /* Valued of file size to detect races */
int code; /* error code */
long newIndex; /* new index in the dir */
+ struct DirBuffer entry; /* Buffer for dir manipulation */
struct DirEntry *dirEntryp; /* dir entry we are examining */
int i;
struct VenusFid afid; /* file ID we are using now */
struct volume *volp = 0; /* volume ptr */
struct VenusFid dotdot = {0, {0, 0, 0}};
int flagIndex = 0; /* First file with bulk fetch flag set */
- int inlinebulk = 0; /* Did we use InlineBulk RPC or not? */
struct rx_connection *rxconn;
XSTATS_DECLS;
dotdot.Cell = 0;
dirCookie = newIndex << 5;
/* get a ptr to the dir entry */
- dirEntryp =
- (struct DirEntry *)afs_dir_GetBlob(dcp, newIndex);
- if (!dirEntryp)
+ code = afs_dir_GetBlob(dcp, newIndex, &entry);
+ if (code)
break;
+ dirEntryp = (struct DirEntry *)entry.data;
/* dont copy more than we have room for */
if (fidIndex >= nentries) {
- DRelease(dirEntryp, 0);
+ DRelease(&entry, 0);
break;
}
do {
retry = 0;
ObtainWriteLock(&afs_xvcache, 130);
- tvcp = afs_FindVCache(&tfid, &retry, IS_WLOCK|FIND_BULKDEAD /* no stats | LRU */ );
+ tvcp = afs_FindVCache(&tfid, &retry, IS_WLOCK /* no stats | LRU */ );
if (tvcp && retry) {
ReleaseWriteLock(&afs_xvcache);
afs_PutVCache(tvcp);
tvcp = afs_NewBulkVCache(&tfid, hostp, statSeqNo);
if (tvcp)
{
- ObtainWriteLock(&tvcp->lock, 505);
- ReleaseWriteLock(&afs_xvcache);
- afs_RemoveVCB(&tfid);
- ReleaseWriteLock(&tvcp->lock);
+ ObtainWriteLock(&tvcp->lock, 505);
+#ifdef AFS_DARWIN80_ENV
+ /* use even/odd hack to guess file versus dir.
+ let links be reaped. oh well. */
+ if (dirEntryp->fid.vnode & 1)
+ tvcp->f.m.Type = VDIR;
+ else
+ tvcp->f.m.Type = VREG;
+ /* finalize to a best guess */
+ afs_darwin_finalizevnode(tvcp, VTOAFS(adp), NULL, 0, 1);
+ /* re-acquire usecount that finalizevnode disposed of */
+ vnode_ref(AFSTOV(tvcp));
+#endif
+ ReleaseWriteLock(&afs_xvcache);
+ afs_RemoveVCB(&tfid);
+ ReleaseWriteLock(&tvcp->lock);
} else {
- ReleaseWriteLock(&afs_xvcache);
+ ReleaseWriteLock(&afs_xvcache);
}
} else {
ReleaseWriteLock(&afs_xvcache);
}
if (!tvcp)
{
- DRelease(dirEntryp, 0);
+ DRelease(&entry, 0);
ReleaseReadLock(&dcp->lock);
ReleaseReadLock(&adp->lock);
afs_PutDCache(dcp);
* used by this dir entry.
*/
temp = afs_dir_NameBlobs(dirEntryp->name) << 5;
- DRelease(dirEntryp, 0);
+ DRelease(&entry, 0);
if (temp <= 0)
break;
dirCookie += temp;
XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_BULKSTATUS);
if (!(tcp->parent->srvr->server->flags & SNO_INLINEBULK)) {
- retryonce:
RX_AFS_GUNLOCK();
code =
RXAFS_InlineBulkStatus(rxconn, &fidParm, &statParm,
RX_AFS_GLOCK();
if (code == RXGEN_OPCODE) {
tcp->parent->srvr->server->flags |= SNO_INLINEBULK;
- inlinebulk = 0;
RX_AFS_GUNLOCK();
code =
RXAFS_BulkStatus(rxconn, &fidParm, &statParm,
&cbParm, &volSync);
RX_AFS_GLOCK();
- } else {
- inlinebulk = 1;
- if (!code && ((&statsp[0])->errorCode)) {
- /*
- * If this is an error needing retry, do so.
- * Retryable errors are all whole-volume or
- * whole-server.
- */
- if (afs_Analyze(tcp, rxconn, (&statsp[0])->errorCode,
- &adp->f.fid, areqp,
- AFS_STATS_FS_RPCIDX_BULKSTATUS,
- SHARED_LOCK, NULL) != 0)
- goto retryonce;
- }
+ } else if (!code) {
+ /* The InlineBulkStatus call itself succeeded, but we
+ * may have failed to stat the first entry. Use the error
+ * from the first entry for processing. */
+ code = (&statsp[0])->errorCode;
}
} else {
- inlinebulk = 0;
RX_AFS_GUNLOCK();
code =
RXAFS_BulkStatus(rxconn, &fidParm, &statParm, &cbParm,
do {
retry = 0;
ObtainReadLock(&afs_xvcache);
- tvcp = afs_FindVCache(&afid, &retry, FIND_CDEAD /* !stats&!lru */);
+ tvcp = afs_FindVCache(&afid, &retry, 0/* !stats&!lru */);
ReleaseReadLock(&afs_xvcache);
} while (tvcp && retry);
* matches the value we placed there when we set the CBulkFetching
* flag, then someone else has done something with this node,
* and we may not have the latest status information for this
- * file. Leave the entry alone.
+ * file. Leave the entry alone. There's also a file type
+ * change here, for OSX bulkstat support.
*/
- if (!(tvcp->f.states & CBulkFetching) || (tvcp->f.m.Length != statSeqNo)) {
+ if (!(tvcp->f.states & CBulkFetching)
+ || (tvcp->f.m.Length != statSeqNo)
+ || (ftype[(&statsp[i])->FileType] != vType(tvcp))) {
flagIndex++;
ReleaseWriteLock(&tvcp->lock);
afs_PutVCache(tvcp);
afs_DequeueCallback(tvcp);
if ((tvcp->f.states & CForeign) || (vType(tvcp) == VDIR))
osi_dnlc_purgedp(tvcp); /* if it (could be) a directory */
- } else {
+ } else
/* re-acquire the usecount that finalizevnode disposed of */
vnode_ref(AFSTOV(tvcp));
- }
} else
#endif
ReleaseWriteLock(&afs_xcbhash);
do {
retry = 0;
ObtainReadLock(&afs_xvcache);
- tvcp = afs_FindVCache(&afid, &retry, FIND_CDEAD /* !stats&!lru */);
+ tvcp = afs_FindVCache(&afid, &retry, 0 /* !stats&!lru */);
ReleaseReadLock(&afs_xvcache);
} while (tvcp && retry);
if (tvcp != NULL) {
if (volp)
afs_PutVolume(volp, READ_LOCK);
- /* If we did the InlineBulk RPC pull out the return code */
- if (inlinebulk && code == 0) {
- if ((&statsp[0])->errorCode) {
- afs_Analyze(tcp, rxconn, (&statsp[0])->errorCode, &adp->f.fid, areqp,
- AFS_STATS_FS_RPCIDX_BULKSTATUS, SHARED_LOCK, NULL);
- code = (&statsp[0])->errorCode;
- }
- } else {
- code = 0;
- }
done2:
osi_FreeLargeSpace((char *)fidsp);
osi_Free((char *)statsp, AFSCBMAX * sizeof(AFSFetchStatus));
}
/* was: (AFS_DEC_ENV) || defined(AFS_OSF30_ENV) || defined(AFS_NCR_ENV) */
+#ifdef AFS_DARWIN80_ENV
+int AFSDOBULK = 1;
+#else
static int AFSDOBULK = 1;
+#endif
static_inline int
osi_lookup_isdot(const char *aname)