#include <afs/param.h>
#include <afs/stds.h>
-#ifndef DJGPP
#include <windows.h>
#include <winsock2.h>
#include <nb30.h>
-#endif /* !DJGPP */
#ifdef COMMENT
#include <malloc.h>
#endif
extern osi_mutex_t cm_Freelance_Lock;
#endif
+#ifdef AFS_LARGEFILES
+/* we can access connp->serverp without holding a lock because that
+ never changes since the connection is made. */
+#define SERVERHAS64BIT(connp) (!((connp)->serverp->flags & CM_SERVERFLAG_NO64BIT))
+#define SET_SERVERHASNO64BIT(connp) (cm_SetServerNo64Bit((connp)->serverp, TRUE))
+#else
+#define SERVERHAS64BIT(connp) (FALSE)
+#define SET_SERVERHASNO64BIT(connp) (FALSE)
+#endif
+
/* functions called back from the buffer package when reading or writing data,
* or when holding or releasing a vnode pointer.
*/
AFSVolSync volSync;
AFSFid tfid;
struct rx_call *callp;
+ struct rx_connection *rxconnp;
osi_queueData_t *qdp;
cm_buf_t *bufp;
long wbytes;
char *bufferp;
cm_conn_t *connp;
- long truncPos;
+ osi_hyper_t truncPos;
cm_bulkIO_t biod; /* bulk IO descriptor */
+ int require_64bit_ops = 0;
osi_assert(userp != NULL);
* buffer, although more likely it will just return a new, empty, buffer.
*/
scp = cm_FindSCache(fidp);
- if (scp == NULL)
+ if (scp == NULL) {
return CM_ERROR_NOSUCHFILE; /* shouldn't happen */
+ }
cm_AFSFidFromFid(&tfid, fidp);
lock_ObtainMutex(&scp->mx);
-
+ if (scp->flags & CM_SCACHEFLAG_DELETED) {
+ lock_ReleaseMutex(&scp->mx);
+ cm_ReleaseSCache(scp);
+ return CM_ERROR_NOSUCHFILE;
+ }
+
code = cm_SetupStoreBIOD(scp, offsetp, length, &biod, userp, reqp);
if (code) {
osi_Log1(afsd_logp, "cm_SetupStoreBIOD code %x", code);
cm_ReleaseBIOD(&biod, 1); /* should be a NOOP */
cm_ReleaseSCache(scp);
return 0;
- }
+ }
/* Serialize StoreData RPC's; for rationale see cm_scache.c */
(void) cm_SyncOp(scp, NULL, userp, reqp, 0, CM_SCACHESYNC_STOREDATA_EXCL);
/* prepare the output status for the store */
scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
cm_StatusFromAttr(&inStatus, scp, NULL);
- truncPos = scp->length.LowPart;
+ truncPos = scp->length;
if ((scp->mask & CM_SCACHEMASK_TRUNCPOS)
- && scp->truncPos.LowPart < (unsigned long) truncPos)
- truncPos = scp->truncPos.LowPart;
+ && LargeIntegerLessThan(scp->truncPos, truncPos))
+ truncPos = scp->truncPos;
scp->mask &= ~CM_SCACHEMASK_TRUNCPOS;
/* compute how many bytes to write from this buffer */
/* otherwise write out part of buffer before EOF, but not
* more than bufferSize bytes.
*/
- nbytes = thyper.LowPart;
- if (nbytes > biod.length)
+ if (LargeIntegerGreaterThan(thyper,
+ ConvertLongToLargeInteger(biod.length))) {
nbytes = biod.length;
+ } else {
+ /* if thyper is less than or equal to biod.length, then we
+ can safely assume that the value fits in a long. */
+ nbytes = thyper.LowPart;
+ }
}
- lock_ReleaseMutex(&scp->mx);
+ if (LargeIntegerGreaterThan(LargeIntegerAdd(biod.offset,
+ ConvertLongToLargeInteger(nbytes)),
+ ConvertLongToLargeInteger(LONG_MAX)) ||
+ LargeIntegerGreaterThan(truncPos,
+ ConvertLongToLargeInteger(LONG_MAX))) {
+ require_64bit_ops = 1;
+ }
+ lock_ReleaseMutex(&scp->mx);
+
/* now we're ready to do the store operation */
do {
code = cm_Conn(&scp->fid, userp, reqp, &connp);
if (code)
continue;
-
- callp = rx_NewCall(connp->callp);
- osi_Log3(afsd_logp, "CALL StoreData vp %x, off 0x%x, size 0x%x",
- (long) scp, biod.offset.LowPart, nbytes);
+ retry:
+ rxconnp = cm_GetRxConn(connp);
+ callp = rx_NewCall(rxconnp);
+ rx_PutConnection(rxconnp);
+
+#ifdef AFS_LARGEFILES
+ if (SERVERHAS64BIT(connp)) {
+ osi_Log4(afsd_logp, "CALL StoreData64 scp 0x%p, offset 0x%x:%08x, length 0x%x",
+ scp, biod.offset.HighPart, biod.offset.LowPart, nbytes);
+
+ code = StartRXAFS_StoreData64(callp, &tfid, &inStatus,
+ biod.offset.QuadPart,
+ nbytes,
+ truncPos.QuadPart);
+ } else {
+
+ if (require_64bit_ops) {
+ osi_Log0(afsd_logp, "Skipping StoreData. The operation requires StoreData64");
+ code = CM_ERROR_TOOBIG;
+ } else {
+ osi_Log4(afsd_logp, "CALL StoreData scp 0x%p, offset 0x%x:%08x, length 0x%x",
+ scp, biod.offset.HighPart, biod.offset.LowPart, nbytes);
+
+ code = StartRXAFS_StoreData(callp, &tfid, &inStatus,
+ biod.offset.LowPart, nbytes, truncPos.LowPart);
+ }
+ }
+#else
+ osi_Log4(afsd_logp, "CALL StoreData scp 0x%p, offset 0x%x:%08x, length 0x%x",
+ scp, biod.offset.HighPart, biod.offset.LowPart, nbytes);
- lock_ObtainMutex(&connp->mx);
code = StartRXAFS_StoreData(callp, &tfid, &inStatus,
- biod.offset.LowPart, nbytes, truncPos);
+ biod.offset.LowPart, nbytes, truncPos.LowPart);
+#endif
if (code == 0) {
/* write the data from the the list of buffers */
bufp = osi_GetQData(qdp);
bufferp = bufp->datap;
wbytes = nbytes;
- if (wbytes > buf_bufferSize)
- wbytes = buf_bufferSize;
+ if (wbytes > cm_data.buf_blockSize)
+ wbytes = cm_data.buf_blockSize;
/* write out wbytes of data from bufferp */
temp = rx_Write(callp, bufferp, wbytes);
if (temp != wbytes) {
- osi_Log2(afsd_logp, "rx_Write failed %d != %d",temp,wbytes);
+ osi_Log3(afsd_logp, "rx_Write failed bp 0x%p, %d != %d",bufp,temp,wbytes);
code = -1;
break;
} else {
- osi_Log1(afsd_logp, "rx_Write succeeded %d",temp);
+ osi_Log2(afsd_logp, "rx_Write succeeded bp 0x%p, %d",bufp,temp);
}
nbytes -= wbytes;
} /* while more bytes to write */
} /* if RPC started successfully */
else {
- osi_Log1(afsd_logp, "StartRXAFS_StoreData failed (%lX)",code);
+ osi_Log2(afsd_logp, "StartRXAFS_StoreData?? scp 0x%p failed (%lX)",scp,code);
}
+
if (code == 0) {
- code = EndRXAFS_StoreData(callp, &outStatus, &volSync);
- if (code)
- osi_Log1(afsd_logp, "EndRXAFS_StoreData failed (%lX)",code);
+ if (SERVERHAS64BIT(connp)) {
+ code = EndRXAFS_StoreData64(callp, &outStatus, &volSync);
+ if (code)
+ osi_Log2(afsd_logp, "EndRXAFS_StoreData64 scp 0x%p failed (%lX)", scp, code);
+ } else {
+ code = EndRXAFS_StoreData(callp, &outStatus, &volSync);
+ if (code)
+ osi_Log2(afsd_logp, "EndRXAFS_StoreData scp 0x%p failed (%lX)",scp,code);
+ }
}
+
code = rx_EndCall(callp, code);
- lock_ReleaseMutex(&connp->mx);
- osi_Log0(afsd_logp, "CALL StoreData DONE");
+#ifdef AFS_LARGEFILES
+ if (code == RXGEN_OPCODE && SERVERHAS64BIT(connp)) {
+ SET_SERVERHASNO64BIT(connp);
+ goto retry;
+ }
+#endif
} while (cm_Analyze(connp, userp, reqp, &scp->fid, &volSync, NULL, NULL, code));
+
code = cm_MapRPCError(code, reqp);
-
+
+ if (code)
+ osi_Log2(afsd_logp, "CALL StoreData FAILURE scp 0x%p, code 0x%x", scp, code);
+ else
+ osi_Log1(afsd_logp, "CALL StoreData SUCCESS scp 0x%p", scp);
+
/* now, clean up our state */
lock_ObtainMutex(&scp->mx);
cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_STOREDATA_EXCL);
if (code == 0) {
+ osi_hyper_t t;
/* now, here's something a little tricky: in AFS 3, a dirty
* length can't be directly stored, instead, a dirty chunk is
* stored that sets the file's size (by writing and by using
* We have to turn off the length dirty bit as soon as we can,
* so that we see updates made by other machines.
*/
- if (outStatus.Length >= scp->length.LowPart)
+
+ if (SERVERHAS64BIT(connp)) {
+ t.LowPart = outStatus.Length;
+ t.HighPart = outStatus.Length_hi;
+ } else {
+ t = ConvertLongToLargeInteger(outStatus.Length);
+ }
+
+ if (LargeIntegerGreaterThanOrEqualTo(t, scp->length))
scp->mask &= ~CM_SCACHEMASK_LENGTH;
+
cm_MergeStatus(scp, &outStatus, &volSync, userp, 0);
} else {
if (code == CM_ERROR_SPACE)
AFSVolSync volSync;
AFSFid tfid;
long code;
- long truncPos;
+ osi_hyper_t truncPos;
cm_conn_t *connp;
struct rx_call *callp;
+ struct rx_connection *rxconnp;
+ int require_64bit_ops = 0;
/* Serialize StoreData RPC's; for rationale see cm_scache.c */
(void) cm_SyncOp(scp, NULL, userp, reqp, 0,
scp->mask &= ~CM_SCACHEMASK_CLIENTMODTIME;
/* calculate truncation position */
- truncPos = scp->length.LowPart;
+ truncPos = scp->length;
if ((scp->mask & CM_SCACHEMASK_TRUNCPOS)
- && scp->truncPos.LowPart < (unsigned long) truncPos)
- truncPos = scp->truncPos.LowPart;
+ && LargeIntegerLessThan(scp->truncPos, truncPos))
+ truncPos = scp->truncPos;
scp->mask &= ~CM_SCACHEMASK_TRUNCPOS;
+ if (LargeIntegerGreaterThan(truncPos,
+ ConvertLongToLargeInteger(LONG_MAX))) {
+
+ require_64bit_ops = 1;
+ }
+
lock_ReleaseMutex(&scp->mx);
cm_AFSFidFromFid(&tfid, &scp->fid);
code = cm_Conn(&scp->fid, userp, reqp, &connp);
if (code)
continue;
-
- callp = rx_NewCall(connp->callp);
- lock_ObtainMutex(&connp->mx);
+ retry:
+ rxconnp = cm_GetRxConn(connp);
+ callp = rx_NewCall(rxconnp);
+ rx_PutConnection(rxconnp);
+
+#ifdef AFS_LARGEFILES
+ if (SERVERHAS64BIT(connp)) {
+ code = StartRXAFS_StoreData64(callp, &tfid, &inStatus,
+ 0, 0, truncPos.QuadPart);
+ } else {
+ if (require_64bit_ops) {
+ code = CM_ERROR_TOOBIG;
+ } else {
+ code = StartRXAFS_StoreData(callp, &tfid, &inStatus,
+ 0, 0, truncPos.LowPart);
+ }
+ }
+#else
code = StartRXAFS_StoreData(callp, &tfid, &inStatus,
- 0, 0, truncPos);
+ 0, 0, truncPos.LowPart);
+#endif
- if (code == 0)
- code = EndRXAFS_StoreData(callp, &outStatus, &volSync);
+ if (code == 0) {
+ if (SERVERHAS64BIT(connp))
+ code = EndRXAFS_StoreData64(callp, &outStatus, &volSync);
+ else
+ code = EndRXAFS_StoreData(callp, &outStatus, &volSync);
+ }
code = rx_EndCall(callp, code);
- lock_ReleaseMutex(&connp->mx);
+#ifdef AFS_LARGEFILES
+ if (code == RXGEN_OPCODE && SERVERHAS64BIT(connp)) {
+ SET_SERVERHASNO64BIT(connp);
+ goto retry;
+ }
+#endif
} while (cm_Analyze(connp, userp, reqp, &scp->fid, &volSync, NULL, NULL, code));
code = cm_MapRPCError(code, reqp);
cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_STOREDATA_EXCL);
if (code == 0) {
+ osi_hyper_t t;
/*
* For explanation of handling of CM_SCACHEMASK_LENGTH,
* see cm_BufWrite().
*/
- if (outStatus.Length >= scp->length.LowPart)
+ if (SERVERHAS64BIT(connp)) {
+ t.HighPart = outStatus.Length_hi;
+ t.LowPart = outStatus.Length;
+ } else {
+ t = ConvertLongToLargeInteger(outStatus.Length);
+ }
+
+ if (LargeIntegerGreaterThanOrEqualTo(t, scp->length))
scp->mask &= ~CM_SCACHEMASK_LENGTH;
cm_MergeStatus(scp, &outStatus, &volSync, userp, 0);
}
long cm_BufRead(cm_buf_t *bufp, long nbytes, long *bytesReadp, cm_user_t *userp)
{
- *bytesReadp = buf_bufferSize;
+ *bytesReadp = cm_data.buf_blockSize;
/* now return a code that means that I/O is done */
return 0;
scp = parmp;
+ cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_SETSIZE);
+
lock_ReleaseMutex(&scp->mx);
/* always succeeds */
cm_BufUnstabilize
};
-int cm_InitDCache(long chunkSize, long nbuffers)
+long cm_ValidateDCache(void)
+{
+ return buf_ValidateBuffers();
+}
+
+long cm_ShutdownDCache(void)
+{
+ return 0;
+}
+
+int cm_InitDCache(int newFile, long chunkSize, afs_uint64 nbuffers)
{
lock_InitializeMutex(&cm_bufGetMutex, "buf_Get mutex");
- if (nbuffers)
- buf_nbuffers = nbuffers;
- return buf_Init(&cm_bufOps);
+ return buf_Init(newFile, &cm_bufOps, nbuffers);
}
/* check to see if we have an up-to-date buffer. The buffer must have
int code;
if (!cm_HaveCallback(scp))
return 0;
- if ((bufp->cmFlags
- & (CM_BUF_CMFETCHING | CM_BUF_CMFULLYFETCHED))
- == (CM_BUF_CMFETCHING | CM_BUF_CMFULLYFETCHED))
+ if ((bufp->cmFlags & (CM_BUF_CMFETCHING | CM_BUF_CMFULLYFETCHED)) == (CM_BUF_CMFETCHING | CM_BUF_CMFULLYFETCHED))
return 1;
if (bufp->dataVersion == scp->dataVersion)
return 1;
bp = buf_Find(scp, &tbase);
/* We cheat slightly by not locking the bp mutex. */
if (bp) {
- if ((bp->cmFlags
- & (CM_BUF_CMFETCHING | CM_BUF_CMSTORING)) == 0
+ if ((bp->cmFlags & (CM_BUF_CMFETCHING | CM_BUF_CMSTORING)) == 0
&& bp->dataVersion != scp->dataVersion)
stop = 1;
buf_Release(bp);
+ bp = NULL;
}
else
stop = 1;
if (stop)
break;
- toffset.LowPart = buf_bufferSize;
+ toffset.LowPart = cm_data.buf_blockSize;
toffset.HighPart = 0;
tbase = LargeIntegerAdd(toffset, tbase);
- length -= buf_bufferSize;
+ length -= cm_data.buf_blockSize;
}
/* if we get here, either everything is fine or stop stopped us at a
return code;
}
-void cm_BkgStore(cm_scache_t *scp, long p1, long p2, long p3, long p4,
+void cm_BkgStore(cm_scache_t *scp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_uint32 p4,
cm_user_t *userp)
{
osi_hyper_t toffset;
long length;
cm_req_t req;
+ long code;
- cm_InitReq(&req);
- req.flags |= CM_REQ_NORETRY;
+ if (scp->flags & CM_SCACHEFLAG_DELETED) {
+ osi_Log4(afsd_logp, "Skipping BKG store - Deleted scp 0x%p, offset 0x%x:%08x, length 0x%x", scp, p2, p1, p3);
+ } else {
+ cm_InitReq(&req);
+#ifdef NO_BKG_RETRIES
+ req.flags |= CM_REQ_NORETRY;
+#endif
- toffset.LowPart = p1;
- toffset.HighPart = p2;
- length = p3;
+ toffset.LowPart = p1;
+ toffset.HighPart = p2;
+ length = p3;
- osi_Log2(afsd_logp, "Starting BKG store vp 0x%x, base 0x%x", scp, p1);
+ osi_Log4(afsd_logp, "Starting BKG store scp 0x%p, offset 0x%x:%08x, length 0x%x", scp, p2, p1, p3);
- cm_BufWrite(&scp->fid, &toffset, length, /* flags */ 0, userp, &req);
+ code = cm_BufWrite(&scp->fid, &toffset, length, /* flags */ 0, userp, &req);
+ }
lock_ObtainMutex(&scp->mx);
cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_ASYNCSTORE);
lock_ReleaseMutex(&scp->mx);
}
+/* Called with scp locked */
void cm_ClearPrefetchFlag(long code, cm_scache_t *scp, osi_hyper_t *base)
{
osi_hyper_t thyper;
base.HighPart = p2;
length = p3;
- osi_Log2(afsd_logp, "Starting BKG prefetch vp 0x%x, base 0x%x", scp, p1);
+ osi_Log2(afsd_logp, "Starting BKG prefetch scp 0x%p, base 0x%x", scp, p1);
code = buf_Get(scp, &base, &bp);
if (code)
return; /* can't find something to prefetch */
- osi_Log2(afsd_logp, "BKG Prefetch request vp 0x%x, base 0x%x",
+ osi_Log2(afsd_logp, "BKG Prefetch request scp 0x%p, base 0x%x",
scp, realBase.LowPart);
cm_QueueBKGRequest(scp, cm_BkgPrefetch, realBase.LowPart,
/* reserve a chunk's worth of buffers */
lock_ReleaseMutex(&scp->mx);
- buf_ReserveBuffers(cm_chunkSize / buf_bufferSize);
+ buf_ReserveBuffers(cm_chunkSize / cm_data.buf_blockSize);
lock_ObtainMutex(&scp->mx);
bufp = NULL;
- for (temp = 0; temp < inSize; temp += buf_bufferSize, bufp = NULL) {
+ for (temp = 0; temp < inSize; temp += cm_data.buf_blockSize) {
thyper.HighPart = 0;
thyper.LowPart = temp;
tbase = LargeIntegerAdd(*inOffsetp, thyper);
if (code) {
lock_ReleaseMutex(&bufp->mx);
buf_Release(bufp);
- buf_UnreserveBuffers(cm_chunkSize / buf_bufferSize);
+ buf_UnreserveBuffers(cm_chunkSize / cm_data.buf_blockSize);
return code;
}
cm_SyncOpDone(scp, bufp, flags);
lock_ReleaseMutex(&bufp->mx);
buf_Release(bufp);
+ bufp = NULL;
}
}
osi_QAddH((osi_queue_t **) &biop->bufListp,
(osi_queue_t **) &biop->bufListEndp,
&qdp->q);
- biop->length = buf_bufferSize;
+ biop->length = cm_data.buf_blockSize;
firstModOffset = bufp->offset;
biop->offset = firstModOffset;
+ bufp = NULL; /* this buffer and reference added to the queue */
/* compute the window surrounding *inOffsetp of size cm_chunkSize */
scanStart = *inOffsetp;
| CM_SCACHESYNC_NOWAIT;
/* start by looking backwards until scanStart */
- thyper.HighPart = 0; /* hyper version of buf_bufferSize */
- thyper.LowPart = buf_bufferSize;
+ thyper.HighPart = 0; /* hyper version of cm_data.buf_blockSize */
+ thyper.LowPart = cm_data.buf_blockSize;
tbase = LargeIntegerSubtract(firstModOffset, thyper);
while(LargeIntegerGreaterThanOrEqualTo(tbase, scanStart)) {
/* see if we can find the buffer */
break;
/* try to lock it, and quit if we can't (simplifies locking) */
+ lock_ReleaseMutex(&scp->mx);
code = lock_TryMutex(&bufp->mx);
+ lock_ObtainMutex(&scp->mx);
if (code == 0) {
buf_Release(bufp);
+ bufp = NULL;
break;
}
if (code) {
lock_ReleaseMutex(&bufp->mx);
buf_Release(bufp);
+ bufp = NULL;
break;
}
cm_SyncOpDone(scp, bufp, flags);
lock_ReleaseMutex(&bufp->mx);
buf_Release(bufp);
+ bufp = NULL;
break;
}
osi_QAddT((osi_queue_t **) &biop->bufListp,
(osi_queue_t **) &biop->bufListEndp,
&qdp->q);
+ bufp = NULL; /* added to the queue */
/* update biod info describing the transfer */
biop->offset = LargeIntegerSubtract(biop->offset, thyper);
- biop->length += buf_bufferSize;
+ biop->length += cm_data.buf_blockSize;
/* update loop pointer */
tbase = LargeIntegerSubtract(tbase, thyper);
} /* while loop looking for pages preceding the one we found */
/* now, find later dirty, contiguous pages, and add them to the list */
- thyper.HighPart = 0; /* hyper version of buf_bufferSize */
- thyper.LowPart = buf_bufferSize;
+ thyper.HighPart = 0; /* hyper version of cm_data.buf_blockSize */
+ thyper.LowPart = cm_data.buf_blockSize;
tbase = LargeIntegerAdd(firstModOffset, thyper);
while(LargeIntegerLessThan(tbase, scanEnd)) {
/* see if we can find the buffer */
break;
/* try to lock it, and quit if we can't (simplifies locking) */
+ lock_ReleaseMutex(&scp->mx);
code = lock_TryMutex(&bufp->mx);
+ lock_ObtainMutex(&scp->mx);
if (code == 0) {
buf_Release(bufp);
+ bufp = NULL;
break;
}
if (code) {
lock_ReleaseMutex(&bufp->mx);
buf_Release(bufp);
+ bufp = NULL;
break;
}
cm_SyncOpDone(scp, bufp, flags);
lock_ReleaseMutex(&bufp->mx);
buf_Release(bufp);
+ bufp = NULL;
break;
}
osi_QAddH((osi_queue_t **) &biop->bufListp,
(osi_queue_t **) &biop->bufListEndp,
&qdp->q);
+ bufp = NULL;
/* update biod info describing the transfer */
- biop->length += buf_bufferSize;
+ biop->length += cm_data.buf_blockSize;
/* update loop pointer */
tbase = LargeIntegerAdd(tbase, thyper);
* sequence at a time.
*/
+ // lock_ObtainMutex(&cm_bufGetMutex);
/* first hold all buffers, since we can't hold any locks in buf_Get */
while (1) {
/* stop at chunk boundary */
- if (collected >= cm_chunkSize) break;
+ if (collected >= cm_chunkSize)
+ break;
/* see if the next page would be past EOF */
- if (LargeIntegerGreaterThanOrEqualTo(pageBase, fileSize)) break;
-
- lock_ObtainMutex(&cm_bufGetMutex);
+ if (LargeIntegerGreaterThanOrEqualTo(pageBase, fileSize))
+ break;
code = buf_Get(scp, &pageBase, &tbp);
if (code) {
- lock_ReleaseMutex(&cm_bufGetMutex);
+ //lock_ReleaseMutex(&cm_bufGetMutex);
lock_ObtainMutex(&scp->mx);
+ cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
return code;
}
buf_Release(tbp);
- lock_ReleaseMutex(&cm_bufGetMutex);
-
toffset.HighPart = 0;
- toffset.LowPart = buf_bufferSize;
+ toffset.LowPart = cm_data.buf_blockSize;
pageBase = LargeIntegerAdd(toffset, pageBase);
- collected += buf_bufferSize;
+ collected += cm_data.buf_blockSize;
}
/* reserve a chunk's worth of buffers if possible */
- reserving = buf_TryReserveBuffers(cm_chunkSize / buf_bufferSize);
+ reserving = buf_TryReserveBuffers(cm_chunkSize / cm_data.buf_blockSize);
+
+ // lock_ReleaseMutex(&cm_bufGetMutex);
pageBase = *offsetp;
collected = pageBase.LowPart & (cm_chunkSize - 1);
/* add the buffer to the list */
qdp = osi_QDAlloc();
osi_SetQData(qdp, tbp);
- osi_QAdd((osi_queue_t **)&heldBufListp, &qdp->q);
- if (!heldBufListEndp) heldBufListEndp = qdp;
+ osi_QAddH((osi_queue_t **)&heldBufListp,
+ (osi_queue_t **)&heldBufListEndp,
+ &qdp->q);
/* leave tbp held (from buf_Get) */
if (!reserving)
break;
- collected += buf_bufferSize;
+ collected += cm_data.buf_blockSize;
toffset.HighPart = 0;
- toffset.LowPart = buf_bufferSize;
+ toffset.LowPart = cm_data.buf_blockSize;
pageBase = LargeIntegerAdd(toffset, pageBase);
}
/* add the buffer to the list */
qdp = osi_QDAlloc();
osi_SetQData(qdp, tbp);
- osi_QAdd((osi_queue_t **)&biop->bufListp, &qdp->q);
- if (!biop->bufListEndp)
- biop->bufListEndp = qdp;
+ osi_QAddH((osi_queue_t **)&biop->bufListp,
+ (osi_queue_t **)&biop->bufListEndp,
+ &qdp->q);
buf_Hold(tbp);
/* from now on, a failure just stops our collection process, but
* we still do the I/O to whatever we've already managed to collect.
*/
isFirst = 0;
- collected += buf_bufferSize;
+ collected += cm_data.buf_blockSize;
}
/* now, we've held in biop->bufListp all the buffer's we're really
for (qdp = heldBufListp; qdp; qdp = tqdp) {
tqdp = (osi_queueData_t *) osi_QNext(&qdp->q);
tbp = osi_GetQData(qdp);
+ osi_QRemoveHT((osi_queue_t **) &heldBufListp,
+ (osi_queue_t **) &heldBufListEndp,
+ &qdp->q);
osi_QDFree(qdp);
buf_Release(tbp);
}
* caller requires to make any progress. Give up now.
*/
if (code && isFirst) {
- buf_UnreserveBuffers(cm_chunkSize / buf_bufferSize);
+ buf_UnreserveBuffers(cm_chunkSize / cm_data.buf_blockSize);
return code;
}
/* Give back reserved buffers */
if (biop->reserved)
- buf_UnreserveBuffers(cm_chunkSize / buf_bufferSize);
+ buf_UnreserveBuffers(cm_chunkSize / cm_data.buf_blockSize);
flags = CM_SCACHESYNC_NEEDCALLBACK;
if (isStore)
/* extract buffer and free queue data */
bufp = osi_GetQData(qdp);
+ osi_QRemoveHT((osi_queue_t **) &biop->bufListp,
+ (osi_queue_t **) &biop->bufListEndp,
+ &qdp->q);
osi_QDFree(qdp);
/* now, mark I/O as done, unlock the buffer and release it */
lock_ObtainMutex(&bufp->mx);
lock_ObtainMutex(&scp->mx);
cm_SyncOpDone(scp, bufp, flags);
- lock_ReleaseMutex(&scp->mx);
/* turn off writing and wakeup users */
if (isStore) {
if (bufp->flags & CM_BUF_WAITING) {
- osi_Wakeup((long) bufp);
+ osi_Log2(afsd_logp, "cm_ReleaseBIOD Waking [scp 0x%p] bp 0x%p", scp, bufp);
+ osi_Wakeup((LONG_PTR) bufp);
}
- bufp->flags &= ~(CM_BUF_WAITING | CM_BUF_WRITING | CM_BUF_DIRTY);
+ bufp->flags &= ~(CM_BUF_WRITING | CM_BUF_DIRTY);
}
+ lock_ReleaseMutex(&scp->mx);
lock_ReleaseMutex(&bufp->mx);
buf_Release(bufp);
+ bufp = NULL;
}
/* clean things out */
cm_req_t *reqp)
{
long code;
- long nbytes; /* bytes in transfer */
+ afs_int32 nbytes; /* bytes in transfer */
+ afs_int32 nbytes_hi = 0; /* high-order 32 bits of bytes in transfer */
+ afs_int64 length_found = 0;
long rbytes; /* bytes in rx_Read call */
long temp;
AFSFetchStatus afsStatus;
AFSCallBack callback;
AFSVolSync volSync;
char *bufferp;
- cm_buf_t *tbufp; /* buf we're filling */
+ cm_buf_t *tbufp; /* buf we're filling */
osi_queueData_t *qdp; /* q element we're scanning */
AFSFid tfid;
struct rx_call *callp;
+ struct rx_connection *rxconnp;
cm_bulkIO_t biod; /* bulk IO descriptor */
cm_conn_t *connp;
int getroot;
long t1, t2;
+ int require_64bit_ops = 0;
/* now, the buffer may or may not be filled with good data (buf_GetNew
* drops lots of locks, and may indeed return a properly initialized
// handle it differently, since it's local rather than on any
// server
- getroot = (scp==cm_rootSCachep);
+ getroot = (scp==cm_data.rootSCachep);
if (getroot)
- osi_Log1(afsd_logp,"GetBuffer returns cm_rootSCachep=%x",cm_rootSCachep);
+ osi_Log1(afsd_logp,"GetBuffer returns cm_data.rootSCachep=%x",cm_data.rootSCachep);
#endif
cm_AFSFidFromFid(&tfid, &scp->fid);
&& LargeIntegerGreaterThanOrEqualTo(bufp->offset,
scp->serverLength)) {
if (bufp->dataVersion == -1)
- memset(bufp->datap, 0, buf_bufferSize);
+ memset(bufp->datap, 0, cm_data.buf_blockSize);
bufp->dataVersion = scp->dataVersion;
}
lock_ReleaseMutex(&scp->mx);
lock_ObtainMutex(&scp->mx);
return 0;
}
-
+
lock_ReleaseMutex(&scp->mx);
+ if (LargeIntegerGreaterThan(LargeIntegerAdd(biod.offset,
+ ConvertLongToLargeInteger(biod.length)),
+ ConvertLongToLargeInteger(LONG_MAX))) {
+ require_64bit_ops = 1;
+ }
+
#ifdef DISKCACHE95
DPRINTF("cm_GetBuffer: fetching data scpDV=%d bufDV=%d scp=%x bp=%x dcp=%x\n",
scp->dataVersion, bufp->dataVersion, scp, bufp, bufp->dcp);
afsStatus.FileType = 0x2;
afsStatus.LinkCount = scp->linkCount;
afsStatus.Length = cm_fakeDirSize;
- afsStatus.DataVersion = cm_fakeDirVersion;
+ afsStatus.DataVersion = cm_data.fakeDirVersion;
afsStatus.Author = 0x1;
afsStatus.Owner = 0x0;
afsStatus.CallerAccess = 0x9;
afsStatus.ParentVnode = 0x1;
afsStatus.ParentUnique = 0x1;
afsStatus.ResidencyMask = 0;
- afsStatus.ClientModTime = FakeFreelanceModTime;
- afsStatus.ServerModTime = FakeFreelanceModTime;
+ afsStatus.ClientModTime = (afs_uint32)FakeFreelanceModTime;
+ afsStatus.ServerModTime = (afs_uint32)FakeFreelanceModTime;
afsStatus.Group = 0;
afsStatus.SyncCounter = 0;
afsStatus.dataVersionHigh = 0;
+ afsStatus.lockCount = 0;
+ afsStatus.Length_hi = 0;
+ afsStatus.errorCode = 0;
// once we're done setting up the status info,
// we just fill the buffer pages with fakedata
while (qdp) {
tbufp = osi_GetQData(qdp);
bufferp=tbufp->datap;
- memset(bufferp, 0, buf_bufferSize);
+ memset(bufferp, 0, cm_data.buf_blockSize);
t2 = cm_fakeDirSize - t1;
- if (t2>buf_bufferSize) t2=buf_bufferSize;
+ if (t2>cm_data.buf_blockSize) t2=cm_data.buf_blockSize;
if (t2 > 0) {
memcpy(bufferp, cm_FakeRootDir+t1, t2);
} else {
code = cm_Conn(&scp->fid, up, reqp, &connp);
if (code)
continue;
-
- lock_ObtainMutex(&connp->mx);
- callp = rx_NewCall(connp->callp);
- osi_Log3(afsd_logp, "CALL FetchData vp %x, off 0x%x, size 0x%x",
- (long) scp, biod.offset.LowPart, biod.length);
+ rxconnp = cm_GetRxConn(connp);
+ callp = rx_NewCall(rxconnp);
+ rx_PutConnection(rxconnp);
+
+#ifdef AFS_LARGEFILES
+ nbytes = nbytes_hi = 0;
+
+ if (SERVERHAS64BIT(connp)) {
+ osi_Log4(afsd_logp, "CALL FetchData64 scp 0x%p, off 0x%x:%08x, size 0x%x",
+ scp, biod.offset.HighPart, biod.offset.LowPart, biod.length);
+
+ code = StartRXAFS_FetchData64(callp, &tfid, biod.offset.QuadPart, biod.length);
+
+ if (code == 0) {
+ temp = rx_Read(callp, (char *) &nbytes_hi, sizeof(afs_int32));
+ if (temp == sizeof(afs_int32)) {
+ nbytes_hi = ntohl(nbytes_hi);
+ } else {
+ nbytes_hi = 0;
+ code = callp->error;
+ rx_EndCall(callp, code);
+ callp = NULL;
+ }
+ }
+ }
+
+ if (code == RXGEN_OPCODE || !SERVERHAS64BIT(connp)) {
+ if (require_64bit_ops) {
+ osi_Log0(afsd_logp, "Skipping FetchData. Operation requires FetchData64");
+ code = CM_ERROR_TOOBIG;
+ } else {
+ if (!callp) {
+ rxconnp = cm_GetRxConn(connp);
+ callp = rx_NewCall(rxconnp);
+ rx_PutConnection(rxconnp);
+ }
+
+ osi_Log3(afsd_logp, "CALL FetchData scp 0x%p, off 0x%x, size 0x%x",
+ scp, biod.offset.LowPart, biod.length);
+
+ code = StartRXAFS_FetchData(callp, &tfid, biod.offset.LowPart,
+ biod.length);
+
+ SET_SERVERHASNO64BIT(connp);
+ }
+ }
+
+ if (code == 0) {
+ temp = rx_Read(callp, (char *)&nbytes, sizeof(afs_int32));
+ if (temp == sizeof(afs_int32)) {
+ nbytes = ntohl(nbytes);
+ FillInt64(length_found, nbytes_hi, nbytes);
+ if (length_found > biod.length)
+ code = (callp->error < 0) ? callp->error : -1;
+ } else {
+ code = (callp->error < 0) ? callp->error : -1;
+ }
+ }
+ /* for the moment, nbytes_hi will always be 0 if code == 0
+ because biod.length is a 32-bit quantity. */
+#else
+ osi_Log3(afsd_logp, "CALL FetchData scp 0x%p, off 0x%x, size 0x%x",
+ scp, biod.offset.LowPart, biod.length);
code = StartRXAFS_FetchData(callp, &tfid, biod.offset.LowPart,
biod.length);
/* now copy the data out of the pipe and put it in the buffer */
- temp = rx_Read(callp, (char *)&nbytes, 4);
- if (temp == 4) {
- nbytes = ntohl(nbytes);
- if (nbytes > biod.length)
+ if (code == 0) {
+ temp = rx_Read(callp, (char *)&nbytes, sizeof(afs_int32));
+ if (temp == sizeof(afs_int32)) {
+ nbytes = ntohl(nbytes);
+ if (nbytes > biod.length)
+ code = (callp->error < 0) ? callp->error : -1;
+ }
+ else
code = (callp->error < 0) ? callp->error : -1;
}
- else
- code = (callp->error < 0) ? callp->error : -1;
+#endif
if (code == 0) {
qdp = biod.bufListEndp;
osi_assert(bufferp != NULL);
/* read rbytes of data */
- rbytes = (nbytes > buf_bufferSize? buf_bufferSize : nbytes);
+ rbytes = (nbytes > cm_data.buf_blockSize? cm_data.buf_blockSize : nbytes);
temp = rx_Read(callp, bufferp, rbytes);
if (temp < rbytes) {
code = (callp->error < 0) ? callp->error : -1;
tbufp->cmFlags |= CM_BUF_CMFULLYFETCHED;
lock_ObtainMutex(&scp->mx);
if (scp->flags & CM_SCACHEFLAG_WAITING) {
- scp->flags &= ~CM_SCACHEFLAG_WAITING;
- osi_Wakeup((long) &scp->flags);
+ osi_Log1(afsd_logp, "CM GetBuffer Waking scp 0x%p", scp);
+ osi_Wakeup((LONG_PTR) &scp->flags);
}
if (cpffp && !*cpffp && !osi_QPrev(&qdp->q)) {
*cpffp = 1;
* all of the rest of the pages.
*/
/* bytes fetched */
- rbytes = bufferp - tbufp->datap;
+ osi_assert((bufferp - tbufp->datap) < LONG_MAX);
+ rbytes = (long) (bufferp - tbufp->datap);
+
/* bytes left to zero */
- rbytes = buf_bufferSize - rbytes;
+ rbytes = cm_data.buf_blockSize - rbytes;
while(qdp) {
if (rbytes != 0)
memset(bufferp, 0, rbytes);
tbufp = osi_GetQData(qdp);
bufferp = tbufp->datap;
/* bytes to clear in this page */
- rbytes = buf_bufferSize;
+ rbytes = cm_data.buf_blockSize;
}
}
- if (code == 0)
- code = EndRXAFS_FetchData(callp, &afsStatus, &callback, &volSync);
- else
- osi_Log0(afsd_logp, "CALL EndRXAFS_FetchData skipped due to error");
- code = rx_EndCall(callp, code);
+ if (code == 0) {
+ if (SERVERHAS64BIT(connp))
+ code = EndRXAFS_FetchData64(callp, &afsStatus, &callback, &volSync);
+ else
+ code = EndRXAFS_FetchData(callp, &afsStatus, &callback, &volSync);
+ } else {
+ if (SERVERHAS64BIT(connp))
+ osi_Log1(afsd_logp, "CALL EndRXAFS_FetchData64 skipped due to error %d", code);
+ else
+ osi_Log1(afsd_logp, "CALL EndRXAFS_FetchData skipped due to error %d", code);
+ }
+
+ if (callp)
+ code = rx_EndCall(callp, code);
+
if (code == RXKADUNKNOWNKEY)
osi_Log0(afsd_logp, "CALL EndCall returns RXKADUNKNOWNKEY");
- osi_Log0(afsd_logp, "CALL FetchData DONE");
- lock_ReleaseMutex(&connp->mx);
+ osi_Log0(afsd_logp, "CALL FetchData DONE");
} while (cm_Analyze(connp, up, reqp, &scp->fid, &volSync, NULL, NULL, code));
code = cm_MapRPCError(code, reqp);
lock_ObtainMutex(&scp->mx);
+
+ cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_FETCHSTATUS);
+
/* we know that no one else has changed the buffer, since we still have
* the fetching flag on the buffers, and we have the scp locked again.
* Copy in the version # into the buffer if we got code 0 back from the
#ifdef DISKCACHE95
/* write buffer out to disk cache */
- diskcache_Update(tbufp->dcp, tbufp->datap, buf_bufferSize,
+ diskcache_Update(tbufp->dcp, tbufp->datap, cm_data.buf_blockSize,
tbufp->dataVersion);
#endif /* DISKCACHE95 */
}
if (code == 0)
cm_MergeStatus(scp, &afsStatus, &volSync, up, 0);
+
return code;
}