#include <osi.h>
#include "afsd.h"
-#define CM_BUF_SIZE 4096
-long buf_bufferSize = CM_BUF_SIZE;
-
-long ReadData(cm_scache_t *scp, osi_hyper_t offset, long count, char *op,
- cm_user_t *userp, long *readp)
+/*
+ * called with scp->rw lock held exclusive
+ */
+afs_int32
+raw_ReadData( cm_scache_t *scp, osi_hyper_t *offsetp,
+ afs_uint32 length, char *bufferp, afs_uint32 *readp,
+ cm_user_t *userp, cm_req_t *reqp)
{
- //osi_hyper_t offset;
long code;
- cm_buf_t *bufferp;
+ cm_buf_t *bufp = NULL;
osi_hyper_t fileLength;
osi_hyper_t thyper;
osi_hyper_t lastByte;
osi_hyper_t bufferOffset;
long bufIndex, nbytes;
int sequential = 0;
- cm_req_t req;
-
- cm_InitReq(&req);
-
- bufferp = NULL;
-
- lock_ObtainWrite(&scp->rw);
/* start by looking up the file's end */
- code = cm_SyncOp(scp, NULL, userp, &req, 0,
+ code = cm_SyncOp(scp, NULL, userp, reqp, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
if (code)
goto done;
/* now we have the entry locked, look up the length */
fileLength = scp->length;
- /* adjust count down so that it won't go past EOF */
- thyper.LowPart = count;
+ /* adjust length down so that it won't go past EOF */
+ thyper.LowPart = length;
thyper.HighPart = 0;
- thyper = LargeIntegerAdd(offset, thyper); /* where read should end */
+ thyper = LargeIntegerAdd(*offsetp, thyper); /* where read should end */
lastByte = thyper;
if (LargeIntegerGreaterThan(thyper, fileLength)) {
/* we'd read past EOF, so just stop at fileLength bytes.
* Start by computing how many bytes remain in the file.
*/
- thyper = LargeIntegerSubtract(fileLength, offset);
+ thyper = LargeIntegerSubtract(fileLength, *offsetp);
/* if we are past EOF, read 0 bytes */
if (LargeIntegerLessThanZero(thyper))
- count = 0;
+ length = 0;
else
- count = thyper.LowPart;
+ length = thyper.LowPart;
}
- *readp = count;
+ *readp = length;
/* now, copy the data one buffer at a time,
* until we've filled the request packet
*/
while (1) {
/* if we've copied all the data requested, we're done */
- if (count <= 0) break;
+ if (length <= 0) break;
/* otherwise, load up a buffer of data */
- thyper.HighPart = offset.HighPart;
- thyper.LowPart = offset.LowPart & ~(buf_bufferSize-1);
- if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
+ thyper.HighPart = offsetp->HighPart;
+ thyper.LowPart = offsetp->LowPart & ~(cm_data.blockSize-1);
+ if (!bufp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
/* wrong buffer */
- if (bufferp) {
- buf_Release(bufferp);
- bufferp = NULL;
+ if (bufp) {
+ buf_Release(bufp);
+ bufp = NULL;
}
lock_ReleaseWrite(&scp->rw);
- code = buf_Get(scp, &thyper, &req, &bufferp);
+ code = buf_Get(scp, &thyper, reqp, &bufp);
lock_ObtainWrite(&scp->rw);
if (code) goto done;
/* now get the data in the cache */
while (1) {
- code = cm_SyncOp(scp, bufferp, userp, &req, 0,
- CM_SCACHESYNC_NEEDCALLBACK
- | CM_SCACHESYNC_READ);
+ code = cm_SyncOp(scp, bufp, userp, reqp, 0,
+ CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);
if (code)
goto done;
- cm_SyncOpDone(scp, bufferp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);
+ cm_SyncOpDone(scp, bufp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);
- if (cm_HaveBuffer(scp, bufferp, 0)) break;
+ if (cm_HaveBuffer(scp, bufp, 0)) break;
/* otherwise, load the buffer and try again */
- code = cm_GetBuffer(scp, bufferp, NULL, userp, &req);
+ code = cm_GetBuffer(scp, bufp, NULL, userp, reqp);
if (code) break;
}
if (code) {
- buf_Release(bufferp);
- bufferp = NULL;
+ buf_Release(bufp);
+ bufp = NULL;
goto done;
}
} /* if (wrong buffer) ... */
/* now we have the right buffer loaded. Copy out the
* data from here to the user's buffer.
*/
- bufIndex = offset.LowPart & (buf_bufferSize - 1);
+ bufIndex = offsetp->LowPart & (cm_data.blockSize - 1);
/* and figure out how many bytes we want from this buffer */
- nbytes = buf_bufferSize - bufIndex; /* what remains in buffer */
- if (nbytes > count) nbytes = count; /* don't go past EOF */
+ nbytes = cm_data.blockSize - bufIndex; /* what remains in buffer */
+ if (nbytes > length) nbytes = length; /* don't go past EOF */
/* now copy the data */
- memcpy(op, bufferp->datap + bufIndex, nbytes);
+ memcpy(bufferp, bufp->datap + bufIndex, nbytes);
- /* adjust counters, pointers, etc. */
- op += nbytes;
- count -= nbytes;
+ /* adjust lengthers, pointers, etc. */
+ bufferp += nbytes;
+ length -= nbytes;
thyper.LowPart = nbytes;
thyper.HighPart = 0;
- offset = LargeIntegerAdd(thyper, offset);
+ *offsetp = LargeIntegerAdd(thyper, *offsetp);
} /* while 1 */
done:
- lock_ReleaseWrite(&scp->rw);
- //lock_ReleaseMutex(&fidp->mx);
- if (bufferp)
- buf_Release(bufferp);
+ if (bufp)
+ buf_Release(bufp);
if (code == 0 && sequential)
- cm_ConsiderPrefetch(scp, &lastByte, *readp, userp, &req);
+ cm_ConsiderPrefetch(scp, &lastByte, *readp, userp, reqp);
return code;
}
-long WriteData(cm_scache_t *scp, osi_hyper_t offset, long count, char *op,
- cm_user_t *userp, long *writtenp)
+/*
+ * called with scp->rw lock held exclusive
+ */
+
+afs_uint32
+raw_WriteData( cm_scache_t *scp, osi_hyper_t *offsetp, afs_uint32 length, char *bufferp,
+ cm_user_t *userp, cm_req_t *reqp, afs_uint32 *writtenp)
{
long code = 0;
long written = 0;
osi_hyper_t fileLength; /* file's length at start of write */
osi_hyper_t minLength; /* don't read past this */
afs_uint32 nbytes; /* # of bytes to transfer this iteration */
- cm_buf_t *bufferp;
+ cm_buf_t *bufp = NULL;
osi_hyper_t thyper; /* hyper tmp variable */
osi_hyper_t bufferOffset;
afs_uint32 bufIndex; /* index in buffer where our data is */
- int doWriteBack;
- osi_hyper_t writeBackOffset;/* offset of region to write back when
- * I/O is done */
+ int doWriteBack = 0;
+ osi_hyper_t writeBackOffset;/* offset of region to write back when I/O is done */
+ afs_uint32 writeBackLength;
DWORD filter = 0;
- cm_req_t req;
-
- cm_InitReq(&req);
-
- bufferp = NULL;
- doWriteBack = 0;
-
- lock_ObtainWrite(&scp->rw);
/* start by looking up the file's end */
- code = cm_SyncOp(scp, NULL, userp, &req, 0,
+ code = cm_SyncOp(scp, NULL, userp, reqp, 0,
CM_SCACHESYNC_NEEDCALLBACK
| CM_SCACHESYNC_SETSTATUS
| CM_SCACHESYNC_GETSTATUS);
cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_SETSTATUS | CM_SCACHESYNC_GETSTATUS);
-#if 0
- /* make sure we have a writable FD */
- if (!(fidp->flags & SMB_FID_OPENWRITE)) {
- code = CM_ERROR_BADFDOP;
- goto done;
- }
-#endif
-
/* now we have the entry locked, look up the length */
fileLength = scp->length;
minLength = fileLength;
minLength = scp->serverLength;
/* adjust file length if we extend past EOF */
- thyper.LowPart = count;
+ thyper.LowPart = length;
thyper.HighPart = 0;
- thyper = LargeIntegerAdd(offset, thyper); /* where write should end */
+ thyper = LargeIntegerAdd(*offsetp, thyper); /* where write should end */
if (LargeIntegerGreaterThan(thyper, fileLength)) {
/* we'd write past EOF, so extend the file */
scp->mask |= CM_SCACHEMASK_LENGTH;
} else
filter |= FILE_NOTIFY_CHANGE_LAST_WRITE;
- /* now, if the new position (thyper) and the old (offset) are in
- * different storeback windows, remember to store back the previous
- * storeback window when we're done with the write.
- */
- if ((thyper.LowPart & (-cm_chunkSize)) !=
- (offset.LowPart & (-cm_chunkSize))) {
- /* they're different */
- doWriteBack = 1;
- writeBackOffset.HighPart = offset.HighPart;
- writeBackOffset.LowPart = offset.LowPart & (-cm_chunkSize);
- }
-
- *writtenp = count;
+ doWriteBack = 1;
+ writeBackOffset = *offsetp;
+ writeBackLength = length;
/* now, copy the data one buffer at a time, until we've filled the
* request packet */
while (1) {
/* if we've copied all the data requested, we're done */
- if (count <= 0) break;
-
- /* handle over quota or out of space */
- if (scp->flags & (CM_SCACHEFLAG_OVERQUOTA | CM_SCACHEFLAG_OUTOFSPACE)) {
- *writtenp = written;
- break;
- }
+ if (length <= 0) break;
/* otherwise, load up a buffer of data */
- thyper.HighPart = offset.HighPart;
- thyper.LowPart = offset.LowPart & ~(buf_bufferSize-1);
- if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
+ thyper.HighPart = offsetp->HighPart;
+ thyper.LowPart = offsetp->LowPart & ~(cm_data.blockSize-1);
+ if (!bufp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
/* wrong buffer */
- if (bufferp) {
- lock_ReleaseMutex(&bufferp->mx);
- buf_Release(bufferp);
- bufferp = NULL;
+ if (bufp) {
+ lock_ReleaseMutex(&bufp->mx);
+ buf_Release(bufp);
+ bufp = NULL;
}
lock_ReleaseWrite(&scp->rw);
- code = buf_Get(scp, &thyper, &req, &bufferp);
+ code = buf_Get(scp, &thyper, reqp, &bufp);
+ if (bufp)
+ lock_ObtainMutex(&bufp->mx);
- lock_ObtainMutex(&bufferp->mx);
lock_ObtainWrite(&scp->rw);
if (code)
goto done;
/* now get the data in the cache */
while (1) {
- code = cm_SyncOp(scp, bufferp, userp, &req, 0,
+ code = cm_SyncOp(scp, bufp, userp, reqp, 0,
CM_SCACHESYNC_NEEDCALLBACK
| CM_SCACHESYNC_WRITE
| CM_SCACHESYNC_BUFLOCKED);
if (code)
goto done;
- cm_SyncOpDone(scp, bufferp,
+ cm_SyncOpDone(scp, bufp,
CM_SCACHESYNC_NEEDCALLBACK
| CM_SCACHESYNC_WRITE
| CM_SCACHESYNC_BUFLOCKED);
* the latter has already been updated by this
* call.
*/
- if (LargeIntegerGreaterThanOrEqualTo(bufferp->offset, minLength) ||
- LargeIntegerEqualTo(offset, bufferp->offset) &&
- (count >= buf_bufferSize ||
- LargeIntegerGreaterThanOrEqualTo(LargeIntegerAdd(offset, ConvertLongToLargeInteger(count)), minLength))) {
- if (count < buf_bufferSize
- && bufferp->dataVersion == CM_BUF_VERSION_BAD)
- memset(bufferp->datap, 0,
- buf_bufferSize);
- bufferp->dataVersion = scp->dataVersion;
+ if (LargeIntegerGreaterThanOrEqualTo(bufp->offset, minLength) ||
+ LargeIntegerEqualTo(*offsetp, bufp->offset) &&
+ (length >= cm_data.blockSize ||
+ LargeIntegerGreaterThanOrEqualTo(LargeIntegerAdd(*offsetp, ConvertLongToLargeInteger(length)), minLength))) {
+ if (length < cm_data.blockSize
+ && bufp->dataVersion == CM_BUF_VERSION_BAD)
+ memset(bufp->datap, 0,
+ cm_data.blockSize);
+ bufp->dataVersion = scp->dataVersion;
}
- if (cm_HaveBuffer(scp, bufferp, 1)) break;
+ if (cm_HaveBuffer(scp, bufp, 1)) break;
/* otherwise, load the buffer and try again */
- lock_ReleaseMutex(&bufferp->mx);
- code = cm_GetBuffer(scp, bufferp, NULL, userp,
- &req);
+ lock_ReleaseMutex(&bufp->mx);
+ code = cm_GetBuffer(scp, bufp, NULL, userp, reqp);
lock_ReleaseWrite(&scp->rw);
- lock_ObtainMutex(&bufferp->mx);
+ lock_ObtainMutex(&bufp->mx);
lock_ObtainWrite(&scp->rw);
if (code)
break;
}
if (code) {
- lock_ReleaseMutex(&bufferp->mx);
- buf_Release(bufferp);
- bufferp = NULL;
+ lock_ReleaseMutex(&bufp->mx);
+ buf_Release(bufp);
+ bufp = NULL;
goto done;
}
} /* if (wrong buffer) ... */
/* now we have the right buffer loaded. Copy out the
* data from here to the user's buffer.
*/
- bufIndex = offset.LowPart & (buf_bufferSize - 1);
+ bufIndex = offsetp->LowPart & (cm_data.blockSize - 1);
/* and figure out how many bytes we want from this buffer */
- nbytes = buf_bufferSize - bufIndex; /* what remains in buffer */
- if (nbytes > count)
- nbytes = count; /* don't go past end of request */
+ nbytes = cm_data.blockSize - bufIndex; /* what remains in buffer */
+ if (nbytes > length)
+ nbytes = length; /* don't go past end of request */
/* now copy the data */
- memcpy(bufferp->datap + bufIndex, op, nbytes);
- buf_SetDirty(bufferp, &req, bufIndex, nbytes, userp);
+ memcpy(bufp->datap + bufIndex, bufferp, nbytes);
+ buf_SetDirty(bufp, reqp, bufIndex, nbytes, userp);
- /* adjust counters, pointers, etc. */
- op += nbytes;
- count -= nbytes;
+ /* adjust lengthers, pointers, etc. */
+ bufferp += nbytes;
+ length -= nbytes;
written += nbytes;
thyper.LowPart = nbytes;
thyper.HighPart = 0;
- offset = LargeIntegerAdd(thyper, offset);
+ *offsetp = LargeIntegerAdd(thyper, *offsetp);
} /* while 1 */
done:
- lock_ReleaseWrite(&scp->rw);
- if (bufferp) {
- lock_ReleaseMutex(&bufferp->mx);
- buf_Release(bufferp);
+ if (writtenp)
+ *writtenp = written;
+
+ if (bufp) {
+ lock_ReleaseMutex(&bufp->mx);
+ buf_Release(bufp);
}
if (code == 0 && doWriteBack) {
- lock_ObtainWrite(&scp->rw);
- code = cm_SyncOp(scp, NULL, userp, &req, 0, CM_SCACHESYNC_ASYNCSTORE);
- lock_ReleaseWrite(&scp->rw);
+ code = cm_SyncOp(scp, NULL, userp, reqp, 0, CM_SCACHESYNC_ASYNCSTORE);
if (code == 0)
cm_QueueBKGRequest(scp, cm_BkgStore, writeBackOffset.LowPart,
- writeBackOffset.HighPart, cm_chunkSize, 0, userp, &req);
+ writeBackOffset.HighPart, writeBackLength, 0, userp, reqp);
}
/* cm_SyncOpDone is called when cm_BkgStore completes */