mirror of
https://git.openafs.org/openafs.git
synced 2025-01-31 05:27:44 +00:00
DEVEL15-windows-cm-buf-misc-20080229
LICENSE MIT (1) Add an undocumented store behind mode for use in testing. Set EnableSMBAsyncStore to 2. When set all smb_WriteData calls are background writes, all calls to cm_FSync are skipped and file close operations do not block for dirty buffers to be written. This permits all writes to be performed in the buf_IncrSyncer thread. (2) Do not use I64 in osi_Log() format strings as all parameters are converted to size_t which is 32-bit on 32-bit Windows. (3) Reduce the number of times the cm_buf_t mutex is obtained, dropped, obtained, dropped in buf_IncrSyncer (4) In buf_CleanAsyncLocked, request that a full chunk be written instead of just the current buffer. cm_SetupStoreBIOD will stop at the first clean buffer. This reduces the overall number of RPCs that must be performed. (5) Define CM_BUF_VERSION_BAD and use it instead of -1. (cherry picked from commit 114de458ca7717cf0bcda90df61f24495fe8f922)
This commit is contained in:
parent
e677ed9ff1
commit
df13fd4cb0
@ -1401,7 +1401,7 @@ int afsd_InitSMB(char **reasonP, void *aMBfunc)
|
||||
code = RegQueryValueEx(parmKey, "EnableSMBAsyncStore", NULL, NULL,
|
||||
(BYTE *) &dwValue, &dummyLen);
|
||||
if (code == ERROR_SUCCESS)
|
||||
smb_AsyncStore = dwValue ? 1 : 0;
|
||||
smb_AsyncStore = dwValue == 2 ? 2 : (dwValue ? 1 : 0);
|
||||
afsi_log("EnableSMBAsyncStore = %d", smb_AsyncStore);
|
||||
|
||||
dummyLen = sizeof(DWORD);
|
||||
|
@ -200,11 +200,10 @@ void buf_IncrSyncer(long parm)
|
||||
|
||||
/* now go through our percentage of the buffers */
|
||||
for (bpp = &cm_data.buf_dirtyListp; bp = *bpp; ) {
|
||||
|
||||
/* all dirty buffers are held when they are added to the
|
||||
* dirty list. No need for an additional hold.
|
||||
*/
|
||||
|
||||
lock_ObtainMutex(&bp->mx);
|
||||
if (bp->flags & CM_BUF_DIRTY) {
|
||||
/* start cleaning the buffer; don't touch log pages since
|
||||
* the log code counts on knowing exactly who is writing
|
||||
@ -212,33 +211,27 @@ void buf_IncrSyncer(long parm)
|
||||
*/
|
||||
cm_InitReq(&req);
|
||||
req.flags |= CM_REQ_NORETRY;
|
||||
wasDirty |= buf_CleanAsync(bp, &req);
|
||||
wasDirty |= buf_CleanAsyncLocked(bp, &req);
|
||||
}
|
||||
|
||||
/* the buffer may or may not have been dirty
|
||||
* and if dirty may or may not have been cleaned
|
||||
* successfully. check the dirty flag again.
|
||||
*/
|
||||
if (!(bp->flags & CM_BUF_DIRTY)) {
|
||||
lock_ObtainMutex(&bp->mx);
|
||||
if (!(bp->flags & CM_BUF_DIRTY)) {
|
||||
/* remove the buffer from the dirty list */
|
||||
lock_ObtainWrite(&buf_globalLock);
|
||||
*bpp = bp->dirtyp;
|
||||
bp->dirtyp = NULL;
|
||||
if (cm_data.buf_dirtyListp == NULL)
|
||||
cm_data.buf_dirtyListEndp = NULL;
|
||||
buf_ReleaseLocked(bp, TRUE);
|
||||
lock_ReleaseWrite(&buf_globalLock);
|
||||
} else {
|
||||
/* advance the pointer so we don't loop forever */
|
||||
bpp = &bp->dirtyp;
|
||||
}
|
||||
lock_ReleaseMutex(&bp->mx);
|
||||
} else {
|
||||
/* advance the pointer so we don't loop forever */
|
||||
bpp = &bp->dirtyp;
|
||||
}
|
||||
if (!(bp->flags & CM_BUF_DIRTY)) {
|
||||
/* remove the buffer from the dirty list */
|
||||
lock_ObtainWrite(&buf_globalLock);
|
||||
*bpp = bp->dirtyp;
|
||||
bp->dirtyp = NULL;
|
||||
if (cm_data.buf_dirtyListp == NULL)
|
||||
cm_data.buf_dirtyListEndp = NULL;
|
||||
buf_ReleaseLocked(bp, TRUE);
|
||||
lock_ReleaseWrite(&buf_globalLock);
|
||||
} else {
|
||||
/* advance the pointer so we don't loop forever */
|
||||
bpp = &bp->dirtyp;
|
||||
}
|
||||
lock_ReleaseMutex(&bp->mx);
|
||||
} /* for loop over a bunch of buffers */
|
||||
} /* whole daemon's while loop */
|
||||
}
|
||||
@ -653,7 +646,16 @@ long buf_CleanAsyncLocked(cm_buf_t *bp, cm_req_t *reqp)
|
||||
|
||||
offset = bp->offset;
|
||||
LargeIntegerAdd(offset, ConvertLongToLargeInteger(bp->dirty_offset));
|
||||
code = (*cm_buf_opsp->Writep)(scp, &offset, bp->dirty_length, 0, bp->userp, reqp);
|
||||
code = (*cm_buf_opsp->Writep)(scp, &offset,
|
||||
#if 1
|
||||
/* we might as well try to write all of the contiguous
|
||||
* dirty buffers in one RPC
|
||||
*/
|
||||
cm_chunkSize,
|
||||
#else
|
||||
bp->dirty_length,
|
||||
#endif
|
||||
0, bp->userp, reqp);
|
||||
osi_Log3(buf_logp, "buf_CleanAsyncLocked I/O on scp 0x%p buf 0x%p, done=%d", scp, bp, code);
|
||||
|
||||
cm_ReleaseSCache(scp);
|
||||
@ -674,7 +676,7 @@ long buf_CleanAsyncLocked(cm_buf_t *bp, cm_req_t *reqp)
|
||||
bp->dirty_offset = 0;
|
||||
bp->dirty_length = 0;
|
||||
bp->error = code;
|
||||
bp->dataVersion = -1; /* bad */
|
||||
bp->dataVersion = CM_BUF_VERSION_BAD; /* bad */
|
||||
bp->dirtyCounter++;
|
||||
}
|
||||
|
||||
@ -910,7 +912,7 @@ long buf_GetNewLocked(struct cm_scache *scp, osi_hyper_t *offsetp, cm_buf_t **bu
|
||||
|
||||
/* clean up junk flags */
|
||||
bp->flags &= ~(CM_BUF_EOF | CM_BUF_ERROR);
|
||||
bp->dataVersion = -1; /* unknown so far */
|
||||
bp->dataVersion = CM_BUF_VERSION_BAD; /* unknown so far */
|
||||
|
||||
/* now hash in as our new buffer, and give it the
|
||||
* appropriate label, if requested.
|
||||
@ -1468,7 +1470,7 @@ long buf_Truncate(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp,
|
||||
bufp->flags &= ~CM_BUF_DIRTY;
|
||||
bufp->dirty_offset = 0;
|
||||
bufp->dirty_length = 0;
|
||||
bufp->dataVersion = -1; /* known bad */
|
||||
bufp->dataVersion = CM_BUF_VERSION_BAD; /* known bad */
|
||||
bufp->dirtyCounter++;
|
||||
}
|
||||
else {
|
||||
@ -1559,7 +1561,7 @@ long buf_FlushCleanPages(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
|
||||
bp->error = CM_ERROR_BADFD;
|
||||
bp->dirty_offset = 0;
|
||||
bp->dirty_length = 0;
|
||||
bp->dataVersion = -1; /* known bad */
|
||||
bp->dataVersion = CM_BUF_VERSION_BAD; /* known bad */
|
||||
bp->dirtyCounter++;
|
||||
lock_ReleaseMutex(&bp->mx);
|
||||
}
|
||||
@ -1851,7 +1853,7 @@ long buf_CleanDirtyBuffers(cm_scache_t *scp)
|
||||
bp->dirty_length = 0;
|
||||
bp->flags |= CM_BUF_ERROR;
|
||||
bp->error = VNOVNODE;
|
||||
bp->dataVersion = -1; /* bad */
|
||||
bp->dataVersion = CM_BUF_VERSION_BAD; /* bad */
|
||||
bp->dirtyCounter++;
|
||||
if (bp->flags & CM_BUF_WAITING) {
|
||||
osi_Log2(buf_logp, "BUF CleanDirtyBuffers Waking [scp 0x%x] bp 0x%x", scp, bp);
|
||||
|
@ -44,6 +44,8 @@ extern int buf_cacheType;
|
||||
|
||||
#define CM_BUF_MAGIC ('B' | 'U' <<8 | 'F'<<16 | 'F'<<24)
|
||||
|
||||
#define CM_BUF_VERSION_BAD 0xFFFFFFFFFFFFFFFF
|
||||
|
||||
/* represents a single buffer */
|
||||
typedef struct cm_buf {
|
||||
osi_queue_t q; /* queue of all zero-refcount buffers */
|
||||
|
@ -569,7 +569,7 @@ long cm_CheckFetchRange(cm_scache_t *scp, osi_hyper_t *startBasep, osi_hyper_t *
|
||||
/* We cheat slightly by not locking the bp mutex. */
|
||||
if (bp) {
|
||||
if ((bp->cmFlags & (CM_BUF_CMFETCHING | CM_BUF_CMSTORING)) == 0
|
||||
&& bp->dataVersion != scp->dataVersion)
|
||||
&& (bp->dataVersion < scp->bufDataVersionLow || bp->dataVersion > scp->dataVersion))
|
||||
stop = 1;
|
||||
buf_Release(bp);
|
||||
bp = NULL;
|
||||
@ -1377,13 +1377,13 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *userp
|
||||
* which case we just retry.
|
||||
*/
|
||||
if (bufp->dataVersion <= scp->dataVersion && bufp->dataVersion >= scp->bufDataVersionLow || biod.length == 0) {
|
||||
if ((bufp->dataVersion == -1 || bufp->dataVersion < scp->dataVersion) &&
|
||||
if ((bufp->dataVersion == CM_BUF_VERSION_BAD || bufp->dataVersion < scp->bufDataVersionLow) &&
|
||||
LargeIntegerGreaterThanOrEqualTo(bufp->offset, scp->serverLength))
|
||||
{
|
||||
osi_Log3(afsd_logp, "Bad DVs %I64d, %I64d or length 0x%x",
|
||||
bufp->dataVersion, scp->dataVersion, biod.length);
|
||||
osi_Log4(afsd_logp, "Bad DVs 0x%x != (0x%x -> 0x%x) or length 0x%x",
|
||||
bufp->dataVersion, scp->bufDataVersionLow, scp->dataVersion, biod.length);
|
||||
|
||||
if (bufp->dataVersion == -1)
|
||||
if (bufp->dataVersion == CM_BUF_VERSION_BAD)
|
||||
memset(bufp->datap, 0, cm_data.buf_blockSize);
|
||||
bufp->dataVersion = scp->dataVersion;
|
||||
}
|
||||
@ -1391,6 +1391,15 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *userp
|
||||
cm_ReleaseBIOD(&biod, 0, 0);
|
||||
lock_ObtainMutex(&scp->mx);
|
||||
return 0;
|
||||
} else if ((bufp->dataVersion == CM_BUF_VERSION_BAD || bufp->dataVersion < scp->bufDataVersionLow)
|
||||
&& (scp->mask & CM_SCACHEMASK_TRUNCPOS) &&
|
||||
LargeIntegerGreaterThanOrEqualTo(bufp->offset, scp->truncPos)) {
|
||||
memset(bufp->datap, 0, cm_data.buf_blockSize);
|
||||
bufp->dataVersion = scp->dataVersion;
|
||||
lock_ReleaseMutex(&scp->mx);
|
||||
cm_ReleaseBIOD(&biod, 0, 0);
|
||||
lock_ObtainMutex(&scp->mx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
lock_ReleaseMutex(&scp->mx);
|
||||
@ -1401,10 +1410,9 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *userp
|
||||
require_64bit_ops = 1;
|
||||
}
|
||||
|
||||
#ifdef DISKCACHE95
|
||||
DPRINTF("cm_GetBuffer: fetching data scpDV=%I64d bufDV=%I64d scp=%x bp=%x dcp=%x\n",
|
||||
scp->dataVersion, bufp->dataVersion, scp, bufp, bufp->dcp);
|
||||
#endif /* DISKCACHE95 */
|
||||
osi_Log2(afsd_logp, "cm_GetBuffer: fetching data scp %p bufp %p", scp, bufp);
|
||||
osi_Log3(afsd_logp, "cm_GetBuffer: fetching data scpDV 0x%x scpDVLow 0x%x bufDV 0x%x",
|
||||
scp->dataVersion, scp->bufDataVersionLow, bufp->dataVersion);
|
||||
|
||||
#ifdef AFS_FREELANCE_CLIENT
|
||||
|
||||
|
@ -1151,7 +1151,7 @@ cm_CheckDirOpForSingleChange(cm_dirOp_t * op)
|
||||
osi_Log0(afsd_logp, "cm_CheckDirOpForSingleChange succeeded");
|
||||
else
|
||||
osi_Log3(afsd_logp,
|
||||
"cm_CheckDirOpForSingleChange failed. code=0x%x, old dv=%I64d, new dv=%I64d",
|
||||
"cm_CheckDirOpForSingleChange failed. code=0x%x, old dv=%d, new dv=%d",
|
||||
code, op->dataVersion, op->scp->dataVersion);
|
||||
return rc;
|
||||
}
|
||||
@ -1272,7 +1272,7 @@ cm_DirOpAddBuffer(cm_dirOp_t * op, cm_buf_t * bufferp)
|
||||
CM_SCACHESYNC_BUFLOCKED);
|
||||
|
||||
if (code == 0 && bufferp->dataVersion != op->dataVersion) {
|
||||
osi_Log2(afsd_logp, "cm_DirOpAddBuffer: buffer data version mismatch. buf dv = %I64d. needs %I64d",
|
||||
osi_Log2(afsd_logp, "cm_DirOpAddBuffer: buffer data version mismatch. buf dv = %d. needs %d",
|
||||
bufferp->dataVersion, op->dataVersion);
|
||||
|
||||
cm_SyncOpDone(op->scp, bufferp,
|
||||
|
@ -1579,7 +1579,7 @@ void cm_MergeStatus(cm_scache_t *dscp,
|
||||
if (volp)
|
||||
cm_PutVolume(volp);
|
||||
}
|
||||
osi_Log3(afsd_logp, "Bad merge, scp %x, scp dv %I64d, RPC dv %I64d",
|
||||
osi_Log3(afsd_logp, "Bad merge, scp %x, scp dv %d, RPC dv %d",
|
||||
scp, scp->dataVersion, dataVersion);
|
||||
/* we have a number of data fetch/store operations running
|
||||
* concurrently, and we can tell which one executed last at the
|
||||
@ -1724,7 +1724,8 @@ void cm_MergeStatus(cm_scache_t *dscp,
|
||||
* the size of the file.
|
||||
*/
|
||||
if (((flags & CM_MERGEFLAG_STOREDATA) && dataVersion - scp->dataVersion > 1) ||
|
||||
(!(flags & CM_MERGEFLAG_STOREDATA) && scp->dataVersion != dataVersion))
|
||||
(!(flags & CM_MERGEFLAG_STOREDATA) && scp->dataVersion != dataVersion) ||
|
||||
scp->bufDataVersionLow == 0)
|
||||
scp->bufDataVersionLow = dataVersion;
|
||||
|
||||
scp->dataVersion = dataVersion;
|
||||
|
@ -6011,7 +6011,7 @@ long smb_ReceiveCoreFlush(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
|
||||
userp = smb_GetUserFromVCP(vcp, inp);
|
||||
|
||||
lock_ObtainMutex(&fidp->mx);
|
||||
if (fidp->flags & SMB_FID_OPENWRITE) {
|
||||
if ((fidp->flags & SMB_FID_OPENWRITE) && smb_AsyncStore != 2) {
|
||||
cm_scache_t * scp = fidp->scp;
|
||||
cm_HoldSCache(scp);
|
||||
lock_ReleaseMutex(&fidp->mx);
|
||||
@ -6146,9 +6146,11 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
|
||||
CompensateForSmbClientLastWriteTimeBugs(&dosTime);
|
||||
smb_UnixTimeFromDosUTime(&fidp->scp->clientModTime, dosTime);
|
||||
}
|
||||
lock_ReleaseMutex(&fidp->mx);
|
||||
code = cm_FSync(scp, userp, &req);
|
||||
lock_ObtainMutex(&fidp->mx);
|
||||
if (smb_AsyncStore != 2) {
|
||||
lock_ReleaseMutex(&fidp->mx);
|
||||
code = cm_FSync(scp, userp, &req);
|
||||
lock_ObtainMutex(&fidp->mx);
|
||||
}
|
||||
}
|
||||
else
|
||||
code = 0;
|
||||
@ -6557,7 +6559,7 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char
|
||||
* based upon cm_chunkSize but we desire cm_chunkSize to be large
|
||||
* so that we can read larger amounts of data at a time.
|
||||
*/
|
||||
if (smb_AsyncStore &&
|
||||
if (smb_AsyncStore == 1 &&
|
||||
(thyper.LowPart & ~(cm_data.buf_blockSize-1)) !=
|
||||
(offset.LowPart & ~(cm_data.buf_blockSize-1))) {
|
||||
/* they're different */
|
||||
@ -6636,7 +6638,7 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char
|
||||
ConvertLongToLargeInteger(count)),
|
||||
minLength))) {
|
||||
if (count < cm_data.buf_blockSize
|
||||
&& bufferp->dataVersion == -1)
|
||||
&& bufferp->dataVersion == CM_BUF_VERSION_BAD)
|
||||
memset(bufferp->datap, 0,
|
||||
cm_data.buf_blockSize);
|
||||
bufferp->dataVersion = scp->dataVersion;
|
||||
@ -6715,7 +6717,7 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char
|
||||
lock_ReleaseMutex(&fidp->mx);
|
||||
|
||||
if (code == 0) {
|
||||
if (smb_AsyncStore) {
|
||||
if (smb_AsyncStore > 0) {
|
||||
if (doWriteBack) {
|
||||
long code2;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user