From 23143230e68516c89f3acf76999223dad4af612f Mon Sep 17 00:00:00 2001 From: Christof Hanke Date: Wed, 9 Sep 2009 16:21:44 +0200 Subject: [PATCH] Moved CForeign check to rxfs_storeInit/storeMore. This is rxfs-specific, so move it out of CacheStoreProc. It must be done before entering the do { } while (moredata) loop proper now, as rxfs_fetchMore is never called during the first iteration (moredata is always 0), but the length may need fixing (note that this was done after what is now the fetchMore op originally). Thus it appears in rxfs_fetchInit. To prevent a bogus call during the first loop iteration, also check for length!=0. Finally, don't bother with fetchMore at all unless CForeign is set. In rxfs_fetchInit, we added an additional check for length_hi being zero. uploade patchset 8. Reviewed-on: http://gerrit.openafs.org/126 Reviewed-by: Derrick Brashear Tested-by: Derrick Brashear --- src/afs/afs_fetchstore.c | 66 +++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/src/afs/afs_fetchstore.c b/src/afs/afs_fetchstore.c index 86f590676..ecb1730af 100644 --- a/src/afs/afs_fetchstore.c +++ b/src/afs/afs_fetchstore.c @@ -612,16 +612,20 @@ afs_CacheStoreVCache(struct dcache **dcList, struct vcache *avc, #endif code = rxfs_storeInit(avc, tc, length, bytes, base, sync, &ops, &rock); + if ( code ) + goto nocall; - if (!code) - code = afs_CacheStoreDCaches(avc, dclist, bytes, anewDV, - &doProcessFS, &OutStatus, - nchunks, nomore, ops, rock); + code = afs_CacheStoreDCaches(avc, dclist, bytes, anewDV, + &doProcessFS, &OutStatus, nchunks, nomore, ops, rock); + +nocall: #ifdef AFS_64BIT_CLIENT if (code == RXGEN_OPCODE && !afs_serverHasNo64Bit(tc)) { afs_serverSetNo64Bit(tc); goto restart; } +#else + continue; /* dummy, label before block end won't work */ #endif /* AFS_64BIT_CLIENT */ } while (afs_Analyze (tc, code, &avc->f.fid, areq, @@ -824,14 +828,26 @@ rxfs_fetchMore(void *r, afs_uint32 *length, afs_uint32 *moredata) register struct rxfs_fetchVariables *v = (struct rxfs_fetchVariables *)r; + /* + * The fetch protocol is extended for the AFS/DFS translator + * to allow multiple blocks of data, each with its own length, + * to be returned. As long as the top bit is set, there are more + * blocks expected. + * + * We do not do this for AFS file servers because they sometimes + * return large negative numbers as the transfer size. + */ RX_AFS_GUNLOCK(); code = rx_Read(v->call, (void *)length, sizeof(afs_int32)); - *length = ntohl(*length); RX_AFS_GLOCK(); + *length = ntohl(*length); if (code != sizeof(afs_int32)) { code = rx_Error(v->call); + *moredata = 0; return (code ? code : -1); /* try to return code, not -1 */ } + *moredata = *length & 0x80000000; + *length &= ~0x80000000; return 0; } @@ -855,7 +871,8 @@ struct fetchOps rxfs_fetchMemOps = { afs_int32 rxfs_fetchInit(register struct afs_conn *tc, struct vcache *avc,afs_offs_t base, - afs_uint32 size, afs_uint32 *alength, struct dcache *adc, + afs_uint32 size, afs_uint32 *alength, afs_uint32 *moredata, + struct dcache *adc, struct osi_file *fP, struct fetchOps **ops, void **rock) { struct rxfs_fetchVariables *v; @@ -951,7 +968,22 @@ rxfs_fetchInit(register struct afs_conn *tc, struct vcache *avc,afs_offs_t base, osi_FreeSmallSpace(v); return code; } - + /* + * The fetch protocol is extended for the AFS/DFS translator + * to allow multiple blocks of data, each with its own length, + * to be returned. As long as the top bit is set, there are more + * blocks expected. + * + * We do not do this for AFS file servers because they sometimes + * return large negative numbers as the transfer size. + * + * Also omit if length > 2^32, as bit 31 is part of the number then. + * Known to never be the case ifndef AFS_64BIT_CLIENT. + */ + if (avc->f.states & CForeign && !length_hi) { + *moredata = length & 0x80000000; + length &= ~0x80000000; + } if (cacheDiskType == AFS_FCACHE_TYPE_UFS) { v->tbuffer = osi_AllocLargeSpace(AFS_LRALLOCSIZ); if (!v->tbuffer) @@ -1018,7 +1050,8 @@ afs_CacheFetchProc(register struct afs_conn *tc, XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHDATA); - code = rxfs_fetchInit(tc, avc, abase, size, &length, adc, fP, &ops, &rock); + code = rxfs_fetchInit( + tc, avc, abase, size, &length, &moredata, adc, fP, &ops, &rock); #ifndef AFS_NOSTATS osi_GetuTime(&xferStartTime); @@ -1027,26 +1060,11 @@ afs_CacheFetchProc(register struct afs_conn *tc, adc->validPos = abase; if ( !code ) do { - if (moredata) { + if ((avc->f.states & CForeign) && moredata && !length) { code = (*ops->more)(rock, &length, &moredata); if ( code ) break; } - /* - * The fetch protocol is extended for the AFS/DFS translator - * to allow multiple blocks of data, each with its own length, - * to be returned. As long as the top bit is set, there are more - * blocks expected. - * - * We do not do this for AFS file servers because they sometimes - * return large negative numbers as the transfer size. - */ - if (avc->f.states & CForeign) { - moredata = length & 0x80000000; - length &= ~0x80000000; - } else { - moredata = 0; - } #ifndef AFS_NOSTATS bytesToXfer += length; #endif /* AFS_NOSTATS */ -- 2.39.5