From: Jeffrey Altman Date: Thu, 9 Aug 2007 06:33:56 +0000 (+0000) Subject: DEVEL15-windows-dirty-buffer-optimization-20070808 X-Git-Tag: openafs-devel-1_5_22~7 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=5e92758f2685fb6d8af4b80689a724d66404cc2e;p=packages%2Fo%2Fopenafs.git DEVEL15-windows-dirty-buffer-optimization-20070808 when storing dirty buffers only store the bytes that are dirty increase the default chunksize from 128KB to 1MB remove OVERLAPPED field from cm_buf_t. It was unused. add a dummy pointer in order to ensure data structure compatibility between the checked and release builds. (cherry picked from commit 377689b39a1821eb268b25cebc9e6cb1ccc0d88a) --- diff --git a/src/WINNT/afsd/cm_buf.c b/src/WINNT/afsd/cm_buf.c index 6c3b3390f..b8fb5972a 100644 --- a/src/WINNT/afsd/cm_buf.c +++ b/src/WINNT/afsd/cm_buf.c @@ -593,6 +593,7 @@ long buf_CleanAsyncLocked(cm_buf_t *bp, cm_req_t *reqp) long code = 0; long isdirty = 0; cm_scache_t * scp = NULL; + osi_hyper_t offset; osi_assert(bp->magic == CM_BUF_MAGIC); @@ -603,9 +604,10 @@ long buf_CleanAsyncLocked(cm_buf_t *bp, cm_req_t *reqp) scp = cm_FindSCache(&bp->fid); if (scp) { osi_Log2(buf_logp, "buf_CleanAsyncLocked starts I/O on scp 0x%p buf 0x%p", scp, bp); - code = (*cm_buf_opsp->Writep)(scp, &bp->offset, - cm_data.buf_blockSize, 0, bp->userp, - reqp); + + offset = bp->offset; + LargeIntegerAdd(offset, ConvertLongToLargeInteger(bp->dirty_offset)); + code = (*cm_buf_opsp->Writep)(scp, &offset, bp->dirty_length, 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); @@ -623,6 +625,8 @@ long buf_CleanAsyncLocked(cm_buf_t *bp, cm_req_t *reqp) if (code == CM_ERROR_NOSUCHFILE){ bp->flags &= ~CM_BUF_DIRTY; bp->flags |= CM_BUF_ERROR; + bp->dirty_offset = 0; + bp->dirty_length = 0; bp->error = CM_ERROR_NOSUCHFILE; bp->dataVersion = -1; /* bad */ bp->dirtyCounter++; @@ -1034,12 +1038,6 @@ long buf_Get(struct cm_scache *scp, osi_hyper_t *offsetp, cm_buf_t **bufpp) /* load the page; freshly created pages should be idle */ osi_assert(!(bp->flags & (CM_BUF_READING | CM_BUF_WRITING))); - /* setup offset, event */ -#ifndef DJGPP /* doesn't seem to be used */ - bp->over.Offset = bp->offset.LowPart; - bp->over.OffsetHigh = bp->offset.HighPart; -#endif /* !DJGPP */ - /* start the I/O; may drop lock */ bp->flags |= CM_BUF_READING; code = (*cm_buf_opsp->Readp)(bp, cm_data.buf_blockSize, &tcount, NULL); @@ -1174,42 +1172,62 @@ void buf_CleanWait(cm_scache_t * scp, cm_buf_t *bp) * * The buffer must be locked before calling this routine. */ -void buf_SetDirty(cm_buf_t *bp) +void buf_SetDirty(cm_buf_t *bp, afs_uint32 offset, afs_uint32 length) { osi_assert(bp->magic == CM_BUF_MAGIC); osi_assert(bp->refCount > 0); - + + lock_ObtainWrite(&buf_globalLock); if (bp->flags & CM_BUF_DIRTY) { + osi_Log1(buf_logp, "buf_SetDirty 0x%p already dirty", bp); + + if (bp->dirty_offset <= offset) { + if (bp->dirty_offset + bp->dirty_length >= offset + length) { + /* dirty_length remains the same */ + } else { + bp->dirty_length = offset + length - bp->dirty_offset; + } + } else /* bp->dirty_offset > offset */ { + if (bp->dirty_offset + bp->dirty_length >= offset + length) { + bp->dirty_length = bp->dirty_offset + bp->dirty_length - offset; + } else { + bp->dirty_length = length; + } + bp->dirty_offset = offset; + } } else { osi_Log1(buf_logp, "buf_SetDirty 0x%p", bp); - } - /* set dirty bit */ - bp->flags |= CM_BUF_DIRTY; - /* and turn off EOF flag, since it has associated data now */ - bp->flags &= ~CM_BUF_EOF; + /* set dirty bit */ + bp->flags |= CM_BUF_DIRTY; - /* and add to the dirty list. - * we obtain a hold on the buffer for as long as it remains - * in the list. buffers are only removed from the list by - * the buf_IncrSyncer function regardless of when else the - * dirty flag might be cleared. - * - * This should never happen but just in case there is a bug - * elsewhere, never add to the dirty list if the buffer is - * already there. - */ - lock_ObtainWrite(&buf_globalLock); - if (bp->dirtyp == NULL && cm_data.buf_dirtyListEndp != bp) { - buf_HoldLocked(bp); - if (!cm_data.buf_dirtyListp) { - cm_data.buf_dirtyListp = cm_data.buf_dirtyListEndp = bp; - } else { - cm_data.buf_dirtyListEndp->dirtyp = bp; - cm_data.buf_dirtyListEndp = bp; - } - bp->dirtyp = NULL; + /* and turn off EOF flag, since it has associated data now */ + bp->flags &= ~CM_BUF_EOF; + + bp->dirty_offset = offset; + bp->dirty_length = length; + + /* and add to the dirty list. + * we obtain a hold on the buffer for as long as it remains + * in the list. buffers are only removed from the list by + * the buf_IncrSyncer function regardless of when else the + * dirty flag might be cleared. + * + * This should never happen but just in case there is a bug + * elsewhere, never add to the dirty list if the buffer is + * already there. + */ + if (bp->dirtyp == NULL && cm_data.buf_dirtyListEndp != bp) { + buf_HoldLocked(bp); + if (!cm_data.buf_dirtyListp) { + cm_data.buf_dirtyListp = cm_data.buf_dirtyListEndp = bp; + } else { + cm_data.buf_dirtyListEndp->dirtyp = bp; + cm_data.buf_dirtyListEndp = bp; + } + bp->dirtyp = NULL; + } } lock_ReleaseWrite(&buf_globalLock); } @@ -1392,6 +1410,8 @@ long buf_Truncate(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp, if (LargeIntegerLessThanOrEqualTo(*sizep, bufp->offset)) { /* truncating the entire page */ bufp->flags &= ~CM_BUF_DIRTY; + bufp->dirty_offset = 0; + bufp->dirty_length = 0; bufp->dataVersion = -1; /* known bad */ bufp->dirtyCounter++; } @@ -1730,8 +1750,11 @@ long buf_DirtyBuffersExist(cm_fid_t *fidp) { cm_buf_t *bp; afs_uint32 bcount = 0; + afs_uint32 i; - for (bp = cm_data.buf_allp; bp; bp=bp->allp, bcount++) { + i = BUF_FILEHASH(fidp); + + for (bp = cm_data.buf_fileHashTablepp[i]; bp; bp=bp->allp, bcount++) { if (!cm_FidCmp(fidp, &bp->fid) && (bp->flags & CM_BUF_DIRTY)) return 1; } @@ -1751,6 +1774,8 @@ long buf_CleanDirtyBuffers(cm_scache_t *scp) lock_ObtainMutex(&bp->mx); bp->cmFlags &= ~CM_BUF_CMSTORING; bp->flags &= ~CM_BUF_DIRTY; + bp->dirty_offset = 0; + bp->dirty_length = 0; bp->flags |= CM_BUF_ERROR; bp->error = VNOVNODE; bp->dataVersion = -1; /* bad */ diff --git a/src/WINNT/afsd/cm_buf.h b/src/WINNT/afsd/cm_buf.h index 7156a499d..7eeff95ac 100644 --- a/src/WINNT/afsd/cm_buf.h +++ b/src/WINNT/afsd/cm_buf.h @@ -72,28 +72,31 @@ typedef struct cm_buf { long dirtyCounter; /* bumped at each dirty->clean transition */ osi_hyper_t offset; /* offset */ cm_fid_t fid; /* file ID */ -#ifdef DEBUG - cm_scache_t *scp; /* for debugging, the scache object belonging to */ - /* the fid at the time of fid assignment. */ -#endif long flags; /* flags we're using */ char *datap; /* data in this buffer */ unsigned long error; /* last error code, if CM_BUF_ERROR is set */ cm_user_t *userp; /* user who wrote to the buffer last */ -#ifndef DJGPP - OVERLAPPED over; /* overlapped structure for I/O */ -#endif /* fields added for the CM; locked by scp->mx */ long dataVersion; /* data version of this page */ long cmFlags; /* flags for cm */ + + /* syncop state */ + afs_uint32 waitCount; /* number of threads waiting */ + afs_uint32 waitRequests; /* num of thread wait requests */ + + afs_uint32 dirty_offset; /* offset from beginning of buffer containing dirty bytes */ + afs_uint32 dirty_length; /* number of dirty bytes within the buffer */ + #ifdef DISKCACHE95 cm_diskcache_t *dcp; /* diskcache structure */ #endif /* DISKCACHE95 */ - - /* syncop state */ - afs_uint32 waitCount; /* number of threads waiting */ - afs_uint32 waitRequests; /* num of thread wait requests */ +#ifdef DEBUG + cm_scache_t *scp; /* for debugging, the scache object belonging to */ + /* the fid at the time of fid assignment. */ +#else + void * dummy; +#endif } cm_buf_t; /* values for cmFlags */ @@ -163,7 +166,7 @@ extern long buf_CleanAsync(cm_buf_t *, cm_req_t *); extern void buf_CleanWait(cm_scache_t *, cm_buf_t *); -extern void buf_SetDirty(cm_buf_t *); +extern void buf_SetDirty(cm_buf_t *, afs_uint32 offset, afs_uint32 length); extern long buf_CleanAndReset(void); diff --git a/src/WINNT/afsd/cm_config.h b/src/WINNT/afsd/cm_config.h index 0cc0578b1..f2a11e85c 100644 --- a/src/WINNT/afsd/cm_config.h +++ b/src/WINNT/afsd/cm_config.h @@ -13,7 +13,7 @@ #define CM_CONFIGDEFAULT_CACHESIZE 98304 #define CM_CONFIGDEFAULT_BLOCKSIZE 4096 #define CM_CONFIGDEFAULT_STATS 10000 -#define CM_CONFIGDEFAULT_CHUNKSIZE 17 +#define CM_CONFIGDEFAULT_CHUNKSIZE 20 #define CM_CONFIGDEFAULT_DAEMONS 2 #define CM_CONFIGDEFAULT_SVTHREADS 25 #define CM_CONFIGDEFAULT_TRACEBUFSIZE 5000 diff --git a/src/WINNT/afsd/cm_dcache.c b/src/WINNT/afsd/cm_dcache.c index d6bf95e16..e44bd9935 100644 --- a/src/WINNT/afsd/cm_dcache.c +++ b/src/WINNT/afsd/cm_dcache.c @@ -1254,8 +1254,10 @@ void cm_ReleaseBIOD(cm_bulkIO_t *biop, int isStore, int failed) } if (failed) bufp->flags &= ~CM_BUF_WRITING; - else + else { bufp->flags &= ~(CM_BUF_WRITING | CM_BUF_DIRTY); + bufp->dirty_offset = bufp->dirty_length = 0; + } } lock_ReleaseMutex(&scp->mx); diff --git a/src/WINNT/afsd/cm_scache.c b/src/WINNT/afsd/cm_scache.c index eb8b5b3c4..7cbdb7476 100644 --- a/src/WINNT/afsd/cm_scache.c +++ b/src/WINNT/afsd/cm_scache.c @@ -107,6 +107,8 @@ long cm_RecycleSCache(cm_scache_t *scp, afs_int32 flags) lock_ObtainMutex(&bufp->mx); bufp->cmFlags &= ~CM_BUF_CMSTORING; bufp->flags &= ~CM_BUF_DIRTY; + bufp->dirty_offset = 0; + bufp->dirty_length = 0; bufp->flags |= CM_BUF_ERROR; bufp->error = VNOVNODE; bufp->dataVersion = -1; /* bad */ @@ -127,6 +129,8 @@ long cm_RecycleSCache(cm_scache_t *scp, afs_int32 flags) lock_ObtainMutex(&bufp->mx); bufp->cmFlags &= ~CM_BUF_CMFETCHING; bufp->flags &= ~CM_BUF_DIRTY; + bufp->dirty_offset = 0; + bufp->dirty_length = 0; bufp->flags |= CM_BUF_ERROR; bufp->error = VNOVNODE; bufp->dataVersion = -1; /* bad */ diff --git a/src/WINNT/afsd/rawops.c b/src/WINNT/afsd/rawops.c index d33fcd063..21b77d82d 100644 --- a/src/WINNT/afsd/rawops.c +++ b/src/WINNT/afsd/rawops.c @@ -155,11 +155,11 @@ long WriteData(cm_scache_t *scp, osi_hyper_t offset, long count, char *op, long written = 0; osi_hyper_t fileLength; /* file's length at start of write */ osi_hyper_t minLength; /* don't read past this */ - long nbytes; /* # of bytes to transfer this iteration */ + afs_uint32 nbytes; /* # of bytes to transfer this iteration */ cm_buf_t *bufferp; osi_hyper_t thyper; /* hyper tmp variable */ osi_hyper_t bufferOffset; - long bufIndex; /* index in buffer where our data is */ + 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 */ @@ -333,7 +333,7 @@ long WriteData(cm_scache_t *scp, osi_hyper_t offset, long count, char *op, else #endif /* DJGPP */ memcpy(bufferp->datap + bufIndex, op, nbytes); - buf_SetDirty(bufferp); + buf_SetDirty(bufferp, bufIndex, nbytes); /* and record the last writer */ if (bufferp->userp != userp) { diff --git a/src/WINNT/afsd/smb.c b/src/WINNT/afsd/smb.c index 80a07e678..121388f2a 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -6417,11 +6417,11 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op, cm_scache_t *scp; osi_hyper_t fileLength; /* file's length at start of write */ osi_hyper_t minLength; /* don't read past this */ - long nbytes; /* # of bytes to transfer this iteration */ + afs_uint32 nbytes; /* # of bytes to transfer this iteration */ cm_buf_t *bufferp; osi_hyper_t thyper; /* hyper tmp variable */ osi_hyper_t bufferOffset; - long bufIndex; /* index in buffer where our data is */ + 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 */ @@ -6608,7 +6608,7 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op, else #endif /* DJGPP */ memcpy(bufferp->datap + bufIndex, op, nbytes); - buf_SetDirty(bufferp); + buf_SetDirty(bufferp, bufIndex, nbytes); /* and record the last writer */ if (bufferp->userp != userp) {