new write cache, flush dirty pages. fix by rodries.

This commit is contained in:
tantricity 2009-05-30 06:52:18 +00:00
parent 7d8f5f3194
commit 7262354c49
3 changed files with 116 additions and 19 deletions

View File

@ -108,6 +108,35 @@ static u32 accessTime(){
return accessCounter; return accessCounter;
} }
static void FlushAndInvalidateCachePage(CACHE* cache,unsigned int page) {
if(cache->cacheEntries[page].dirty == true) {
// Write the page back to disc
_FAT_disc_writeSectors (cache->disc, cache->cacheEntries[page].sector, cache->cacheEntries[page].count, cache->cacheEntries[page].cache);
}
//Invalidate
cache->cacheEntries[page].sector = CACHE_FREE;
cache->cacheEntries[page].last_access = 0;
cache->cacheEntries[page].count = 0;
cache->cacheEntries[page].dirty = false;
}
void InvalidateCachePagesSharingSectors(CACHE* cache, sec_t sector, sec_t numSectors, unsigned int valid_page) {
return;
unsigned int i;
if(cache==NULL)return;
CACHE_ENTRY* cacheEntries = cache->cacheEntries;
unsigned int numberOfPages = cache->numberOfPages;
for (i = 0; i < numberOfPages ; i++) {
if(i==valid_page) continue;
if ( ( cacheEntries[i].sector > sector+numSectors ) ||
( cacheEntries[i].sector+cacheEntries[i].count < sector ) ) continue;
FlushAndInvalidateCachePage(cache,i);
}
}
/* /*
Retrieve a sector's page from the cache. If it is not found in the cache, Retrieve a sector's page from the cache. If it is not found in the cache,
load it into the cache and return the page it was loaded to. load it into the cache and return the page it was loaded to.
@ -144,7 +173,7 @@ static unsigned int _FAT_cache_getSector (CACHE* cache, sec_t sector, void* buff
} }
cacheEntries[oldUsed].dirty = false; cacheEntries[oldUsed].dirty = false;
} }
InvalidateCachePagesSharingSectors(cache,sector,sectorsPerPage,oldUsed);
// Load the new sector into the cache // Load the new sector into the cache
if (!_FAT_disc_readSectors (cache->disc, sector, sectorsPerPage, cacheEntries[oldUsed].cache)) { if (!_FAT_disc_readSectors (cache->disc, sector, sectorsPerPage, cacheEntries[oldUsed].cache)) {
return false; return false;
@ -203,13 +232,13 @@ bool _FAT_cache_getSectors (CACHE* cache, sec_t sector, sec_t numSectors, void*
cacheEntries[oldUsed].dirty = false; cacheEntries[oldUsed].dirty = false;
} }
cacheEntries[oldUsed].sector = sector;
cacheEntries[oldUsed].count = cache->sectorsPerPage; cacheEntries[oldUsed].count = cache->sectorsPerPage;
InvalidateCachePagesSharingSectors(cache,cacheEntries[oldUsed].sector,cacheEntries[oldUsed].count,oldUsed);
if (!_FAT_disc_readSectors (cache->disc, sector, cacheEntries[oldUsed].count, cacheEntries[oldUsed].cache)) { if (!_FAT_disc_readSectors (cache->disc, sector, cacheEntries[oldUsed].count, cacheEntries[oldUsed].cache)) {
return false; return false;
} }
cacheEntries[oldUsed].sector = sector;
// Increment the usage count, don't reset it // Increment the usage count, don't reset it
// This creates a paging policy of least used PAGE, not sector // This creates a paging policy of least used PAGE, not sector
cacheEntries[oldUsed].last_access = accessTime(); cacheEntries[oldUsed].last_access = accessTime();
@ -344,6 +373,74 @@ bool _FAT_cache_eraseWritePartialSector (CACHE* cache, const void* buffer, sec_t
return false; return false;
} }
bool _FAT_cache_writeSectors (CACHE* cache, sec_t sector, sec_t numSectors, const void* buffer) {
unsigned int i;
CACHE_ENTRY* cacheEntries = cache->cacheEntries;
unsigned int numberOfPages = cache->numberOfPages;
sec_t sec;
sec_t secs_to_write;
unsigned int oldUsed = 0;
unsigned int oldAccess = cacheEntries[0].last_access;
while(numSectors>0)
{
i=0;
while (i < numberOfPages ) {
if ( (sector>=cacheEntries[i].sector && sector < cacheEntries[i].sector+cacheEntries[i].count) ||
(sector == cacheEntries[i].sector+cacheEntries[i].count && cacheEntries[i].count < cache->sectorsPerPage)) {
sec=sector-cacheEntries[i].sector;
secs_to_write=cache->sectorsPerPage-sec;
if(secs_to_write>numSectors)secs_to_write=numSectors;
memcpy(cacheEntries[i].cache + (sec*BYTES_PER_READ), buffer, secs_to_write*BYTES_PER_READ);
cacheEntries[i].last_access = accessTime();
cacheEntries[i].dirty = true;
cacheEntries[i].count = sec + secs_to_write;
numSectors=numSectors-secs_to_write;
if(numSectors==0) return true;
buffer+=secs_to_write*BYTES_PER_READ;
sector+=secs_to_write;
i=-1; // recheck all pages again
oldUsed = 0;
oldAccess = cacheEntries[0].last_access;
}
else // While searching for the desired sector, also search for the least recently used page
if ( (cacheEntries[i].sector == CACHE_FREE) || (cacheEntries[i].last_access < oldAccess) ) {
oldUsed = i;
oldAccess = cacheEntries[i].last_access;
}
i++;
}
// If it didn't, replace the least recently used cache page with the desired sector
if ((cacheEntries[oldUsed].sector != CACHE_FREE) && (cacheEntries[oldUsed].dirty == true)) {
// Write the page back to disc if it has been written to
if (!_FAT_disc_writeSectors (cache->disc, cacheEntries[oldUsed].sector, cacheEntries[oldUsed].count, cacheEntries[oldUsed].cache)) {
return false;
}
cacheEntries[oldUsed].dirty = false;
}
secs_to_write=numSectors;
if(secs_to_write>cache->sectorsPerPage)secs_to_write=cache->sectorsPerPage;
cacheEntries[oldUsed].sector = sector;
cacheEntries[oldUsed].count = secs_to_write;
memcpy(cacheEntries[oldUsed].cache, buffer, secs_to_write*BYTES_PER_READ);
buffer+=secs_to_write*BYTES_PER_READ;
sector+=secs_to_write;
numSectors=numSectors-secs_to_write;
// Increment the usage count, don't reset it
// This creates a paging policy of least used PAGE, not sector
cacheEntries[oldUsed].last_access = accessTime();
cacheEntries[oldUsed].dirty = true;
if(numSectors==0) return true;
oldUsed = 0;
oldAccess = cacheEntries[0].last_access;
}
return false;
}
/* /*
Flushes all dirty pages to disc, clearing the dirty flag. Flushes all dirty pages to disc, clearing the dirty flag.

View File

@ -109,6 +109,8 @@ static inline bool _FAT_cache_writeSector (CACHE* cache, const void* buffer, sec
return _FAT_cache_writePartialSector (cache, buffer, sector, 0, BYTES_PER_READ); return _FAT_cache_writePartialSector (cache, buffer, sector, 0, BYTES_PER_READ);
} }
bool _FAT_cache_writeSectors (CACHE* cache, sec_t sector, sec_t numSectors, const void* buffer);
/* /*
Write any dirty sectors back to disc and clear out the contents of the cache Write any dirty sectors back to disc and clear out the contents of the cache
*/ */

View File

@ -522,6 +522,7 @@ static bool _FAT_file_extend_r (struct _reent *r, FILE_STRUCT* file) {
uint8_t zeroBuffer [BYTES_PER_READ] = {0}; uint8_t zeroBuffer [BYTES_PER_READ] = {0};
uint32_t remain; uint32_t remain;
uint32_t tempNextCluster; uint32_t tempNextCluster;
unsigned int sector;
position.byte = file->filesize % BYTES_PER_READ; position.byte = file->filesize % BYTES_PER_READ;
position.sector = (file->filesize % partition->bytesPerCluster) / BYTES_PER_READ; position.sector = (file->filesize % partition->bytesPerCluster) / BYTES_PER_READ;
@ -571,8 +572,8 @@ static bool _FAT_file_extend_r (struct _reent *r, FILE_STRUCT* file) {
position.cluster = tempNextCluster; position.cluster = tempNextCluster;
} }
_FAT_disc_writeSectors (partition->disc, sector = _FAT_fat_clusterToSector (partition, position.cluster) + position.sector;
_FAT_fat_clusterToSector (partition, position.cluster) + position.sector, 1, zeroBuffer); _FAT_cache_writeSectors (cache, sector, 1, zeroBuffer);
remain -= BYTES_PER_READ; remain -= BYTES_PER_READ;
position.sector ++; position.sector ++;
@ -730,7 +731,7 @@ ssize_t _FAT_write_r (struct _reent *r, int fd, const char *ptr, size_t len) {
} }
if ((tempVar > 0) && flagNoError) { if ((tempVar > 0) && flagNoError) {
if (!_FAT_disc_writeSectors (partition->disc, if (!_FAT_cache_writeSectors (cache,
_FAT_fat_clusterToSector (partition, position.cluster) + position.sector, tempVar, ptr)) _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, tempVar, ptr))
{ {
flagNoError = false; flagNoError = false;
@ -784,8 +785,8 @@ ssize_t _FAT_write_r (struct _reent *r, int fd, const char *ptr, size_t len) {
#endif #endif
(chunkSize + partition->bytesPerCluster <= remain)); (chunkSize + partition->bytesPerCluster <= remain));
if ( !_FAT_disc_writeSectors (partition->disc, _FAT_fat_clusterToSector(partition, position.cluster), if ( !_FAT_cache_writeSectors (cache,
chunkSize / BYTES_PER_READ, ptr)) _FAT_fat_clusterToSector(partition, position.cluster), chunkSize / BYTES_PER_READ, ptr))
{ {
flagNoError = false; flagNoError = false;
r->_errno = EIO; r->_errno = EIO;
@ -806,8 +807,7 @@ ssize_t _FAT_write_r (struct _reent *r, int fd, const char *ptr, size_t len) {
// Write remaining sectors // Write remaining sectors
tempVar = remain / BYTES_PER_READ; // Number of sectors left tempVar = remain / BYTES_PER_READ; // Number of sectors left
if ((tempVar > 0) && flagNoError) { if ((tempVar > 0) && flagNoError) {
if (!_FAT_disc_writeSectors (partition->disc, _FAT_fat_clusterToSector (partition, position.cluster), if (!_FAT_cache_writeSectors (cache, _FAT_fat_clusterToSector (partition, position.cluster), tempVar, ptr))
tempVar, ptr))
{ {
flagNoError = false; flagNoError = false;
r->_errno = EIO; r->_errno = EIO;
@ -849,8 +849,6 @@ ssize_t _FAT_write_r (struct _reent *r, int fd, const char *ptr, size_t len) {
file->filesize = file->currentPosition; file->filesize = file->currentPosition;
} }
} }
_FAT_syncToDisc(file);
_FAT_unlock(&partition->lock); _FAT_unlock(&partition->lock);
return len; return len;