diff -r 2bb754abd467 -r 0ffb4e86fcc9 userlibandfileserver/fileserver/sfile/sf_file_cache.cpp --- a/userlibandfileserver/fileserver/sfile/sf_file_cache.cpp Mon Jun 21 17:12:14 2010 +0300 +++ b/userlibandfileserver/fileserver/sfile/sf_file_cache.cpp Thu Jul 15 20:11:42 2010 +0300 @@ -36,6 +36,9 @@ // disables flushing of stale cachelines before each write #define LAZY_WRITE +// call SetSizeL() to pre-allocate FAT clusters before flushing dirty data +#define SETSIZE_BEFORE_WRITE + enum TFileCacheFault { ECacheSettingsInitFailed, @@ -63,6 +66,7 @@ EUnexpectedReNewLFailure, EDirtyDataOwnerNull, EFlushingWithSessionNull, + EFlushingWithAllocatedRequest, }; @@ -985,7 +989,7 @@ // with any dirty data already in the file cache if (aMode & EFileWriteBuffered) { - TInt r = DoFlushDirty(aNewRequest, &aMsgRequest, ETrue); + TInt r = DoFlushDirty(aNewRequest, &aMsgRequest, EFlushAll); if (r == CFsRequest::EReqActionBusy || r != CFsRequest::EReqActionComplete) return r; } @@ -1165,7 +1169,7 @@ if ((aMode & EFileWriteBuffered) == 0 || (cachingWrites && totalLen > iCacheSize)) { - TInt r = DoFlushDirty(aNewRequest, &aMsgRequest, ETrue); + TInt r = DoFlushDirty(aNewRequest, &aMsgRequest, EFlushAll); if (r == CFsRequest::EReqActionBusy || r != CFsRequest::EReqActionComplete) return r; } @@ -1237,7 +1241,7 @@ // If there's nothing to flush then the dirty (locked) data // must belong to another drive, so there's not much we can do // but write through - TInt r = DoFlushDirty(aNewRequest, &aMsgRequest, EFalse); + TInt r = DoFlushDirty(aNewRequest, &aMsgRequest, EFlushSingle); if (r == CFsRequest::EReqActionBusy) return CFsRequest::EReqActionBusy; if (r != KErrInUse) @@ -1262,7 +1266,7 @@ // or wait if already flushing if (iFlushBusy) return CFsRequest::EReqActionBusy; - TInt r = DoFlushDirty(aNewRequest, &aMsgRequest, EFalse); + TInt r = DoFlushDirty(aNewRequest, &aMsgRequest, EFlushSingle); if (r != CFsRequest::EReqActionBusy && r != CFsRequest::EReqActionComplete) lastError = r; } @@ -1495,7 +1499,7 @@ if (cachingWrites) { - TInt r = DoFlushDirty(aNewRequest, &aMsgRequest, ETrue); + TInt r = DoFlushDirty(aNewRequest, &aMsgRequest, EFlushAll); #ifdef _DEBUG if (r == CFsRequest::EReqActionBusy) CCacheManagerFactory::CacheManager()->Stats().iWriteThroughWithDirtyDataCount++; @@ -1573,7 +1577,7 @@ CFsClientMessageRequest* newRequest = NULL; - TInt r = DoFlushDirty(newRequest, aOldRequest, ETrue); + TInt r = DoFlushDirty(newRequest, aOldRequest, EFlushAll); iLock.Signal(); @@ -1615,7 +1619,7 @@ /** CFileCache::DoFlushDirty() -@param aFlushAll. If EFalse then only a single cacheline will be flushed +@param aFlushMode. The flush mode which indicates how many cache-lines to flush. @See TFlushMode returns CFsRequest::EReqActionBusy if a flush is in progress OR cacheline already in use CFsRequest::EReqActionComplete if nothing to flush / flush completed @@ -1623,11 +1627,13 @@ or one of the system wide error codes */ -TInt CFileCache::DoFlushDirty(CFsClientMessageRequest*& aNewRequest, CFsRequest* aOldRequest, TBool aFlushAll) +TInt CFileCache::DoFlushDirty(CFsClientMessageRequest*& aNewRequest, CFsRequest* aOldRequest, TFlushMode aFlushMode) { TInt64 pos; TUint8* addr; + __ASSERT_ALWAYS(aNewRequest == NULL, Fault(EFlushingWithAllocatedRequest)); + if (iFlushBusy) return CFsRequest::EReqActionBusy; @@ -1681,10 +1687,8 @@ return r; } - // set the number of segments to flush - either all dirty data or the equivalent of one full cacheline - aNewRequest->CurrentOperation().iScratchValue0 = - (TAny*) (aFlushAll?KMaxTInt:iCacheClient->CacheLineSizeInSegments()); - + // set the flush mode + aNewRequest->CurrentOperation().iScratchValue0 = (TAny*) aFlushMode; // issue flush request r = FlushDirtySm(*aNewRequest); @@ -1701,6 +1705,11 @@ } else // CFsRequest::EReqActionComplete { + // Return any allocation failures etc to client + TInt lastError = aNewRequest->LastError(); + if (lastError != KErrNone) + r = lastError; + aNewRequest->PopOperation(); aNewRequest->Free(); aNewRequest = NULL; @@ -1778,9 +1787,6 @@ TUint8* addr; TInt segmentCount = iCacheClient->FindFirstDirtySegment(pos, addr); - // keep track of how many segments we've written - currentOperation->iScratchValue0 = (TAny*) ((TInt) currentOperation->iScratchValue0 - segmentCount); - // if no more dirty segments of if a genuine error then finish // NB if the request has been cancelled then we still need to proceed and mark all the // segments as clean, otherwise they will never get freed ! @@ -1807,6 +1813,28 @@ break; } +#ifdef SETSIZE_BEFORE_WRITE + TInt64 physicalFileSize = iFileCB->Size64(); + if ( (!iDrive->IsRugged()) && ((pos + (TInt64) len) > physicalFileSize)) + { + // Need to switch to drive thread before calling CFileCB::SetSizeL() + if (!IsDriveThread()) + { + aMsgRequest.SetState(CFsRequest::EReqStatePostInitialise); + return CFsRequest::EReqActionBusy; + } + __CACHE_PRINT2(_L("CACHEFILE: Increasing uncached size from %ld to %ld"), iFileCB->Size64(), iSize64); + TInt r; + + r = CheckDiskSpace(iSize64 - physicalFileSize, &aMsgRequest); + if(r == KErrNone) + TRAP(r, iFileCB->SetSizeL(iSize64)) + if (r == KErrNone) + { + iFileCB->SetSize64(iSize64, ETrue); // NB drive might be locked + } + } +#endif __CACHE_PRINT3(_L("CACHEFILE: FlushDirty first dirty pos %d, addr %08X count %d"), I64LOW(pos), addr, segmentCount); TInt filledSegmentCount; @@ -1900,12 +1928,18 @@ } - if (TInt(currentOperation->iScratchValue0) > 0) - currentOperation->iState = EStWriteToDisk; - else - currentOperation->iState = EStEnd; - - + switch((TFlushMode) (TInt) currentOperation->iScratchValue0) + { + case EFlushSingle: + currentOperation->iState = EStEnd; + break; + case EFlushAll: + currentOperation->iState = EStWriteToDisk; + break; + default: + ASSERT(0); + break; + } } break;