mirror of
https://git.openafs.org/openafs.git
synced 2025-01-19 15:30:14 +00:00
Windows: cm_SetupStoreBIOD compute correct scanEnd
The algorithm used to ensure "chunk size" operations attempts to enforce aligned chunks. There are two problems: 1. an aligned chunk range may extend beyond the end of the file. 2. an aligned chunk might end before the requested length of the active write. Protect against scanning beyond the end of the file and do not truncate writes. Change-Id: Ibe6caebd78f73d2c93bfef0dcebef379ca843994 Reviewed-on: http://gerrit.openafs.org/10625 Tested-by: BuildBot <buildbot@rampaginggeek.com> Reviewed-by: Jeffrey Altman <jaltman@your-file-system.com>
This commit is contained in:
parent
4f1d4b63a9
commit
fb6bc16b33
@ -1015,9 +1015,13 @@ long cm_SetupStoreBIOD(cm_scache_t *scp, osi_hyper_t *inOffsetp, long inSize,
|
|||||||
osi_hyper_t scanStart; /* where to start scan for dirty pages */
|
osi_hyper_t scanStart; /* where to start scan for dirty pages */
|
||||||
osi_hyper_t scanEnd; /* where to stop scan for dirty pages */
|
osi_hyper_t scanEnd; /* where to stop scan for dirty pages */
|
||||||
osi_hyper_t firstModOffset; /* offset of first modified page in range */
|
osi_hyper_t firstModOffset; /* offset of first modified page in range */
|
||||||
|
osi_hyper_t tblocksize;
|
||||||
long temp;
|
long temp;
|
||||||
long code;
|
long code;
|
||||||
long flags; /* flags to cm_SyncOp */
|
long flags; /* flags to cm_SyncOp */
|
||||||
|
int blockSize = cm_data.blockSize; /* need a signed version */
|
||||||
|
|
||||||
|
tblocksize = ConvertLongToLargeInteger(cm_data.buf_blockSize);
|
||||||
|
|
||||||
/* clear things out */
|
/* clear things out */
|
||||||
biop->scp = scp; /* do not hold; held by caller */
|
biop->scp = scp; /* do not hold; held by caller */
|
||||||
@ -1031,12 +1035,12 @@ long cm_SetupStoreBIOD(cm_scache_t *scp, osi_hyper_t *inOffsetp, long inSize,
|
|||||||
|
|
||||||
/* reserve a chunk's worth of buffers */
|
/* reserve a chunk's worth of buffers */
|
||||||
lock_ReleaseWrite(&scp->rw);
|
lock_ReleaseWrite(&scp->rw);
|
||||||
biop->reserved = (cm_chunkSize / cm_data.buf_blockSize);
|
biop->reserved = (cm_chunkSize / blockSize);
|
||||||
buf_ReserveBuffers(biop->reserved);
|
buf_ReserveBuffers(biop->reserved);
|
||||||
lock_ObtainWrite(&scp->rw);
|
lock_ObtainWrite(&scp->rw);
|
||||||
|
|
||||||
bufp = NULL;
|
bufp = NULL;
|
||||||
for (temp = 0; temp < inSize; temp += cm_data.buf_blockSize) {
|
for (temp = 0; temp < inSize; temp += blockSize) {
|
||||||
thyper = ConvertLongToLargeInteger(temp);
|
thyper = ConvertLongToLargeInteger(temp);
|
||||||
tbase = LargeIntegerAdd(*inOffsetp, thyper);
|
tbase = LargeIntegerAdd(*inOffsetp, thyper);
|
||||||
|
|
||||||
@ -1060,7 +1064,7 @@ long cm_SetupStoreBIOD(cm_scache_t *scp, osi_hyper_t *inOffsetp, long inSize,
|
|||||||
lock_ReleaseMutex(&bufp->mx);
|
lock_ReleaseMutex(&bufp->mx);
|
||||||
buf_Release(bufp);
|
buf_Release(bufp);
|
||||||
bufp = NULL;
|
bufp = NULL;
|
||||||
buf_UnreserveBuffers(cm_chunkSize / cm_data.buf_blockSize);
|
buf_UnreserveBuffers(cm_chunkSize / blockSize);
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1101,7 +1105,7 @@ long cm_SetupStoreBIOD(cm_scache_t *scp, osi_hyper_t *inOffsetp, long inSize,
|
|||||||
osi_QAddH((osi_queue_t **) &biop->bufListp,
|
osi_QAddH((osi_queue_t **) &biop->bufListp,
|
||||||
(osi_queue_t **) &biop->bufListEndp,
|
(osi_queue_t **) &biop->bufListEndp,
|
||||||
&qdp->q);
|
&qdp->q);
|
||||||
biop->length = cm_data.buf_blockSize;
|
biop->length = blockSize;
|
||||||
firstModOffset = bufp->offset;
|
firstModOffset = bufp->offset;
|
||||||
biop->offset = firstModOffset;
|
biop->offset = firstModOffset;
|
||||||
bufp = NULL; /* this buffer and reference added to the queue */
|
bufp = NULL; /* this buffer and reference added to the queue */
|
||||||
@ -1112,14 +1116,25 @@ long cm_SetupStoreBIOD(cm_scache_t *scp, osi_hyper_t *inOffsetp, long inSize,
|
|||||||
thyper = ConvertLongToLargeInteger(cm_chunkSize);
|
thyper = ConvertLongToLargeInteger(cm_chunkSize);
|
||||||
scanEnd = LargeIntegerAdd(scanStart, thyper);
|
scanEnd = LargeIntegerAdd(scanStart, thyper);
|
||||||
|
|
||||||
|
/* do not scan beyond the end of the file */
|
||||||
|
if (scanEnd.QuadPart > scp->length.QuadPart) {
|
||||||
|
scanEnd = scp->length;
|
||||||
|
scanEnd.LowPart &= (-blockSize);
|
||||||
|
if (scanEnd.LowPart < scp->length.LowPart)
|
||||||
|
scanEnd.LowPart += blockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do not leave out a requested portion of the range */
|
||||||
|
if (scanEnd.QuadPart < inOffsetp->QuadPart + inSize) {
|
||||||
|
scanEnd.QuadPart = inOffsetp->QuadPart + inSize;
|
||||||
|
}
|
||||||
|
|
||||||
flags = CM_SCACHESYNC_GETSTATUS
|
flags = CM_SCACHESYNC_GETSTATUS
|
||||||
| CM_SCACHESYNC_STOREDATA
|
| CM_SCACHESYNC_STOREDATA
|
||||||
| CM_SCACHESYNC_BUFLOCKED;
|
| CM_SCACHESYNC_BUFLOCKED;
|
||||||
|
|
||||||
/* start by looking backwards until scanStart */
|
/* start by looking backwards until scanStart */
|
||||||
/* hyper version of cm_data.buf_blockSize */
|
tbase = LargeIntegerSubtract(firstModOffset, tblocksize);
|
||||||
thyper = ConvertLongToLargeInteger(cm_data.buf_blockSize);
|
|
||||||
tbase = LargeIntegerSubtract(firstModOffset, thyper);
|
|
||||||
while(LargeIntegerGreaterThanOrEqualTo(tbase, scanStart)) {
|
while(LargeIntegerGreaterThanOrEqualTo(tbase, scanStart)) {
|
||||||
/* see if we can find the buffer */
|
/* see if we can find the buffer */
|
||||||
bufp = buf_Find(&scp->fid, &tbase);
|
bufp = buf_Find(&scp->fid, &tbase);
|
||||||
@ -1173,17 +1188,15 @@ long cm_SetupStoreBIOD(cm_scache_t *scp, osi_hyper_t *inOffsetp, long inSize,
|
|||||||
bufp = NULL; /* added to the queue */
|
bufp = NULL; /* added to the queue */
|
||||||
|
|
||||||
/* update biod info describing the transfer */
|
/* update biod info describing the transfer */
|
||||||
biop->offset = LargeIntegerSubtract(biop->offset, thyper);
|
biop->offset = LargeIntegerSubtract(biop->offset, tblocksize);
|
||||||
biop->length += cm_data.buf_blockSize;
|
biop->length += blockSize;
|
||||||
|
|
||||||
/* update loop pointer */
|
/* update loop pointer */
|
||||||
tbase = LargeIntegerSubtract(tbase, thyper);
|
tbase = LargeIntegerSubtract(tbase, tblocksize);
|
||||||
} /* while loop looking for pages preceding the one we found */
|
} /* while loop looking for pages preceding the one we found */
|
||||||
|
|
||||||
/* now, find later dirty, contiguous pages, and add them to the list */
|
/* now, find later dirty, contiguous pages, and add them to the list */
|
||||||
/* hyper version of cm_data.buf_blockSize */
|
tbase = LargeIntegerAdd(firstModOffset, tblocksize);
|
||||||
thyper = ConvertLongToLargeInteger(cm_data.buf_blockSize);
|
|
||||||
tbase = LargeIntegerAdd(firstModOffset, thyper);
|
|
||||||
while(LargeIntegerLessThan(tbase, scanEnd)) {
|
while(LargeIntegerLessThan(tbase, scanEnd)) {
|
||||||
/* see if we can find the buffer */
|
/* see if we can find the buffer */
|
||||||
bufp = buf_Find(&scp->fid, &tbase);
|
bufp = buf_Find(&scp->fid, &tbase);
|
||||||
@ -1237,10 +1250,10 @@ long cm_SetupStoreBIOD(cm_scache_t *scp, osi_hyper_t *inOffsetp, long inSize,
|
|||||||
bufp = NULL;
|
bufp = NULL;
|
||||||
|
|
||||||
/* update biod info describing the transfer */
|
/* update biod info describing the transfer */
|
||||||
biop->length += cm_data.buf_blockSize;
|
biop->length += blockSize;
|
||||||
|
|
||||||
/* update loop pointer */
|
/* update loop pointer */
|
||||||
tbase = LargeIntegerAdd(tbase, thyper);
|
tbase = LargeIntegerAdd(tbase, tblocksize);
|
||||||
} /* while loop looking for pages following the first page we found */
|
} /* while loop looking for pages following the first page we found */
|
||||||
|
|
||||||
/* finally, we're done */
|
/* finally, we're done */
|
||||||
|
Loading…
Reference in New Issue
Block a user