{
struct afs_stats_xferData *xferP;
osi_timeval_t xferStopTime;
- XSTATS_DECLS;
+ osi_timeval_t elapsedTime;
xferP = &(afs_stats_cmfullperf.rpc.fsXferTimes[idx]);
osi_GetuTime(&xferStopTime);
/* rock and operations for RX_FILESERVER */
-struct rxfs_storeVariables {
- struct rx_call *call;
- char *tbuffer;
- struct iovec *tiov;
- afs_uint32 tnio;
- afs_int32 hasNo64bit;
- struct AFSStoreStatus InStatus;
-};
+
afs_int32
rxfs_storeUfsPrepare(void *r, afs_uint32 size, afs_uint32 *tlen)
return -33; /* XXX */
size -= tlen;
}
- return code;
+ return 0;
}
afs_int32
static
struct storeOps rxfs_storeUfsOps = {
+#if (defined(AFS_SGI_ENV) && !defined(__c99))
rxfs_storeUfsPrepare,
rxfs_storeUfsRead,
rxfs_storeUfsWrite,
rxfs_storePadd,
rxfs_storeClose,
rxfs_storeDestroy
+#else
+ .prepare = rxfs_storeUfsPrepare,
+ .read = rxfs_storeUfsRead,
+ .write = rxfs_storeUfsWrite,
+ .status = rxfs_storeStatus,
+ .padd = rxfs_storePadd,
+ .close = rxfs_storeClose,
+ .destroy = rxfs_storeDestroy,
+#ifdef AFS_LINUX26_ENV
+ .storeproc = afs_linux_storeproc
+#endif
+#endif
};
static
struct storeOps rxfs_storeMemOps = {
+#if (defined(AFS_SGI_ENV) && !defined(__c99))
rxfs_storeMemPrepare,
rxfs_storeMemRead,
rxfs_storeMemWrite,
rxfs_storePadd,
rxfs_storeClose,
rxfs_storeDestroy
+#else
+ .prepare = rxfs_storeMemPrepare,
+ .read = rxfs_storeMemRead,
+ .write = rxfs_storeMemWrite,
+ .status = rxfs_storeStatus,
+ .padd = rxfs_storePadd,
+ .close = rxfs_storeClose,
+ .destroy = rxfs_storeDestroy
+#endif
};
afs_int32
v->InStatus.ClientModTime = avc->f.m.Date;
v->InStatus.Mask = AFS_SETMODTIME;
+ v->vcache = avc;
if (sync & AFS_SYNC)
v->InStatus.Mask |= AFS_FSYNC;
RX_AFS_GUNLOCK();
return 0;
}
+afs_int32
+afs_GenericStoreProc(struct storeOps *ops, void *rock,
+ struct dcache *tdc, int *shouldwake,
+ afs_size_t *bytesXferred)
+{
+ struct rxfs_storeVariables *svar = rock;
+ afs_uint32 tlen, bytesread, byteswritten;
+ afs_int32 code;
+ int offset = 0;
+ afs_size_t size;
+ struct osi_file *tfile;
+
+ size = tdc->f.chunkBytes;
+
+ tfile = afs_CFileOpen(&tdc->f.inode);
+
+ while ( size > 0 ) {
+ code = (*ops->prepare)(rock, size, &tlen);
+ if ( code )
+ break;
+
+ code = (*ops->read)(rock, tfile, offset, tlen, &bytesread);
+ if (code)
+ break;
+
+ tlen = bytesread;
+ code = (*ops->write)(rock, tlen, &byteswritten);
+ if (code)
+ break;
+#ifndef AFS_NOSTATS
+ *bytesXferred += byteswritten;
+#endif /* AFS_NOSTATS */
+
+ offset += tlen;
+ size -= tlen;
+ /*
+ * if file has been locked on server, can allow
+ * store to continue
+ */
+ if (shouldwake && *shouldwake && ((*ops->status)(rock) == 0)) {
+ *shouldwake = 0; /* only do this once */
+ afs_wakeup(svar->vcache);
+ }
+ }
+ afs_CFileClose(tfile);
+
+ return code;
+}
+
unsigned int storeallmissing = 0;
/*!
* Called for each chunk upon store.
int *shouldwake = NULL;
unsigned int i;
afs_int32 code = 0;
+ afs_size_t bytesXferred;
#ifndef AFS_NOSTATS
osi_timeval_t xferStartTime; /*FS xfer start time */
afs_size_t bytesToXfer = 10000; /* # bytes to xfer */
- afs_size_t bytesXferred = 10000; /* # bytes actually xferred */
#endif /* AFS_NOSTATS */
XSTATS_DECLS;
for (i = 0; i < nchunks && !code; i++) {
int stored = 0;
- struct osi_file *tfile;
- int offset = 0;
struct dcache *tdc = dclist[i];
afs_int32 size = tdc->f.chunkBytes;
if (!tdc) {
else if ((afs_uint32) avc->asynchrony >= (bytes - stored))
shouldwake = &nomore;
}
- tfile = afs_CFileOpen(&tdc->f.inode);
afs_Trace4(afs_iclSetp, CM_TRACE_STOREPROC, ICL_TYPE_POINTER, avc,
ICL_TYPE_FID, &(avc->f.fid), ICL_TYPE_OFFSET,
* to ship here.
*/
bytesToXfer = size;
- bytesXferred = 0;
osi_GetuTime(&xferStartTime);
#endif /* AFS_NOSTATS */
+ bytesXferred = 0;
- while ( size > 0 ) {
- afs_uint32 tlen;
- afs_int32 bytesread, byteswritten;
- code = (*ops->prepare)(rock, size, &tlen);
- if ( code )
- break;
-
- code = (*ops->read)(rock, tfile, offset, tlen, &bytesread);
- if (code)
- break;
-
- tlen = bytesread;
- code = (*ops->write)(rock, tlen, &byteswritten);
- if (code)
- break;
-#ifndef AFS_NOSTATS
- bytesXferred += byteswritten;
-#endif /* AFS_NOSTATS */
+ code = (*ops->storeproc)(ops, rock, tdc, shouldwake,
+ &bytesXferred);
- offset += tlen;
- size -= tlen;
- /*
- * if file has been locked on server, can allow
- * store to continue
- */
- if (shouldwake && *shouldwake && ((*ops->status)(rock) == 0)) {
- *shouldwake = 0; /* only do this once */
- afs_wakeup(avc);
- }
- }
afs_Trace4(afs_iclSetp, CM_TRACE_STOREPROC, ICL_TYPE_POINTER, avc,
ICL_TYPE_FID, &(avc->f.fid), ICL_TYPE_OFFSET,
ICL_HANDLE_OFFSET(avc->f.m.Length), ICL_TYPE_INT32, size);
&xferStartTime, bytesToXfer, bytesXferred);
#endif /* AFS_NOSTATS */
- afs_CFileClose(tfile);
if ((tdc->f.chunkBytes < afs_OtherCSize)
&& (i < (nchunks - 1)) && code == 0) {
code = (*ops->padd)(rock, afs_OtherCSize - tdc->f.chunkBytes);
ICL_HANDLE_OFFSET(base), ICL_TYPE_OFFSET,
ICL_HANDLE_OFFSET(bytes), ICL_TYPE_OFFSET,
ICL_HANDLE_OFFSET(length));
- tc = afs_Conn(&avc->f.fid, areq, 0);
do {
+ tc = afs_Conn(&avc->f.fid, areq, 0);
+
#ifdef AFS_64BIT_CLIENT
restart:
#endif
code = rxfs_storeInit(avc, tc, base, bytes, length,
- sync, &ops, &rock);
- if ( code )
- goto nocall;
-
- code = afs_CacheStoreDCaches(avc, dclist, bytes, anewDV,
- &doProcessFS, &OutStatus, nchunks, nomore, ops, rock);
+ sync, &ops, &rock);
+ if ( !code ) {
+ 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,
struct rx_call *call;
char *tbuffer;
struct iovec *iov;
- afs_uint32 nio;
+ afs_int32 nio;
afs_int32 hasNo64bit;
afs_int32 iovno;
afs_int32 iovmax;
}
afs_int32
-rxfs_fetchMore(void *r, afs_uint32 *length, afs_uint32 *moredata)
+rxfs_fetchMore(void *r, afs_int32 *length, afs_uint32 *moredata)
{
afs_int32 code;
struct rxfs_fetchVariables *v = (struct rxfs_fetchVariables *)r;
* 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));
- 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 */
+ if (*moredata) {
+ RX_AFS_GUNLOCK();
+ code = rx_Read(v->call, (void *)length, sizeof(afs_int32));
+ 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;
afs_int32
rxfs_fetchInit(struct afs_conn *tc, struct vcache *avc, afs_offs_t base,
- afs_uint32 size, afs_uint32 *alength, afs_uint32 *moredata,
- struct dcache *adc,
+ afs_uint32 size, afs_int32 *alength, struct dcache *adc,
struct osi_file *fP, struct fetchOps **ops, void **rock)
{
struct rxfs_fetchVariables *v;
- int code = 0, code1;
- afs_uint32 length_hi = 0, length, bytes;
+ int code = 0, code1 = 0;
+#ifdef AFS_64BIT_CLIENT
+ afs_uint32 length_hi = 0;
+#endif
+ afs_uint32 length, bytes;
v = (struct rxfs_fetchVariables *) osi_AllocSmallSpace(sizeof(struct rxfs_fetchVariables));
if (!v)
ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, code,
ICL_TYPE_OFFSET,
ICL_HANDLE_OFFSET(length64));
- *alength = length64;
+ *alength = length;
#else /* AFS_64BIT_CLIENT */
RX_AFS_GUNLOCK();
code = StartRXAFS_FetchData(v->call, (struct AFSFid *)&avc->f.fid.Fid,
#endif /* AFS_64BIT_CLIENT */
} else
code = -1;
+
+ /* We need to cast here, in order to avoid issues if *alength is
+ * negative. Some, older, fileservers can return a negative length,
+ * which the rest of the code deals correctly with. */
+ if (code == 0 && *alength > (afs_int32) size) {
+ /* The fileserver told us it is going to send more data than we
+ * requested. It shouldn't do that, and accepting that much data
+ * can make us take up more cache space than we're supposed to,
+ * so error. */
+ code = rx_Error(v->call);
+ RX_AFS_GUNLOCK();
+ code1 = rx_EndCall(v->call, code);
+ RX_AFS_GLOCK();
+ v->call = NULL;
+ code = EIO;
+ }
+
+ if (!code && code1)
+ code = code1;
+
if (code) {
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)
struct afs_FetchOutput *tsmall)
{
afs_int32 code;
- afs_uint32 length;
+ afs_int32 length;
afs_uint32 bytesread, byteswritten;
struct fetchOps *ops = NULL;
void *rock = NULL;
- int moredata = 0;
+ afs_uint32 moredata = 0;
int offset = 0;
XSTATS_DECLS;
* adc->lock(W)
*/
code = rxfs_fetchInit(
- tc, avc, base, size, &length, &moredata, adc, fP, &ops, &rock);
+ tc, avc, base, size, &length, adc, fP, &ops, &rock);
#ifndef AFS_NOSTATS
osi_GetuTime(&xferStartTime);
}
if ( !code ) do {
- if ((avc->f.states & CForeign) && moredata && !length) {
+ if (avc->f.states & CForeign) {
code = (*ops->more)(rock, &length, &moredata);
if ( code )
break;
#ifndef AFS_NOSTATS
bytesToXfer += length;
#endif /* AFS_NOSTATS */
- while (length) {
+ while (length > 0) {
#ifdef RX_KERNEL_TRACE
afs_Trace1(afs_iclSetp, CM_TRACE_TIMESTAMP, ICL_TYPE_STRING,
"before rx_Read");