From beca52b61b3efd061dfff4e65407aa746c955f3d Mon Sep 17 00:00:00 2001 From: Far Date: Wed, 14 Apr 2021 10:31:05 +0800 Subject: [PATCH] Feature: Fatfs scandir format and mmcblk read/write optimization 1. Bcache block with high mem address is after lower mem address in RCU list when initing bcache. 2. Format will clear the bcache before writing the FAT. 3. The fatfs_readdir use the bcache writing block to reduce the chance of data switching out 4. Add performance analysing macron switch Change-Id: I8fbc48418509d2e660d725d2c265266e931c26f8 --- fs/fat/os_adapt/fatfs.c | 5 ++- fs/include/disk.h | 30 ++++++++++++++- fs/vfs/bcache/src/bcache.c | 69 ++++++++++++++++++++++++++++++++-- fs/vfs/disk/disk.c | 33 ++++++++++++++-- fs/vfs/include/bcache/bcache.h | 5 ++- kernel/common/los_rootfs.c | 3 +- 6 files changed, 131 insertions(+), 14 deletions(-) diff --git a/fs/fat/os_adapt/fatfs.c b/fs/fat/os_adapt/fatfs.c index 933b169f..a8aba58c 100755 --- a/fs/fat/os_adapt/fatfs.c +++ b/fs/fat/os_adapt/fatfs.c @@ -1372,7 +1372,8 @@ int fatfs_readdir(struct Vnode *vp, struct fs_dirent_s *idir) DEF_NAMBUF; INIT_NAMBUF(fs); for (i = 0; i < idir->read_cnt; i++) { - result = dir_read(dp, 0); + /* using dir_read_massive to promote performance */ + result = dir_read_massive(dp, 0); if (result == FR_NO_FILE) { break; } else if (result != FR_OK) { @@ -1596,7 +1597,7 @@ static int fatfs_set_part_info(los_part *part) return -ENOMEM; } (void)memset_s(buf, disk->sector_size, 0, disk->sector_size); - ret = los_disk_read(part->disk_id, buf, 0, 1); + ret = los_disk_read(part->disk_id, buf, 0, 1, TRUE); /* TRUE when not reading large data */ if (ret < 0) { free(buf); return -EIO; diff --git a/fs/include/disk.h b/fs/include/disk.h index d4362be4..b9d64f45 100644 --- a/fs/include/disk.h +++ b/fs/include/disk.h @@ -303,6 +303,7 @@ INT32 los_disk_deinit(INT32 diskID); * @param buf [OUT] Type #VOID * memory which used to store read data. * @param sector [IN] Type #UINT64 expected start sector number to read. * @param count [IN] Type #UINT32 expected sector count to read. + * @param useRead [IN] Type #BOOL set FALSE to use the write block for optimization * * @retval #0 Read success. * @retval #-1 Read failed. @@ -312,7 +313,7 @@ INT32 los_disk_deinit(INT32 diskID); * @see los_disk_write * */ -INT32 los_disk_read(INT32 drvID, VOID *buf, UINT64 sector, UINT32 count); +INT32 los_disk_read(INT32 drvID, VOID *buf, UINT64 sector, UINT32 count, BOOL useRead); /** * @ingroup disk @@ -438,6 +439,7 @@ INT32 los_disk_set_bcache(INT32 drvID, UINT32 sectorPerBlock, UINT32 blockNum); * @param buf [OUT] Type #VOID * memory which used to store the data to be read. * @param sector [IN] Type #UINT64 start sector number of chosen partition. * @param count [IN] Type #UINT32 the expected sector count for reading. + * @param useRead [IN] Type #BOOL FALSE when reading large contiguous data, TRUE for other situations * * @retval #0 Read success. * @retval #-1 Read failed. @@ -447,7 +449,7 @@ INT32 los_disk_set_bcache(INT32 drvID, UINT32 sectorPerBlock, UINT32 blockNum); * @see los_part_read * */ -INT32 los_part_read(INT32 pt, VOID *buf, UINT64 sector, UINT32 count); +INT32 los_part_read(INT32 pt, VOID *buf, UINT64 sector, UINT32 count, BOOL useRead); /** * @ingroup disk @@ -477,6 +479,30 @@ INT32 los_part_read(INT32 pt, VOID *buf, UINT64 sector, UINT32 count); */ INT32 los_part_write(INT32 pt, const VOID *buf, UINT64 sector, UINT32 count); +/** + * @ingroup disk + * @brief Clear the bcache data + * + * @par Description: + * Flush the data and mark the block as unused. + * + * @attention + * + * + * @param drvID [IN] Type #INT32 disk id + * + * @retval #0 Write success. + * @retval #-1 Write failed. + * + * @par Dependency: + * + * @see los_part_read + * + */ +INT32 los_disk_cache_clear(INT32 drvID); + /** * @ingroup disk * @brief Get information of chosen partition. diff --git a/fs/vfs/bcache/src/bcache.c b/fs/vfs/bcache/src/bcache.c index a28fe701..b04b0057 100644 --- a/fs/vfs/bcache/src/bcache.c +++ b/fs/vfs/bcache/src/bcache.c @@ -45,11 +45,38 @@ #define ASYNC_EVENT_BIT 0x01 #ifdef DEBUG -#define D(args) printf(args) +#define D(args) printf args #else #define D(args) #endif +#ifdef BCACHE_ANALYSE +UINT32 g_memSize; +volatile UINT32 g_blockNum; +volatile UINT32 g_dataSize; +volatile UINT8 *g_memStart; +volatile UINT32 g_switchTimes[CONFIG_FS_FAT_BLOCK_NUMS] = { 0 }; +volatile UINT32 g_hitTimes[CONFIG_FS_FAT_BLOCK_NUMS] = { 0 }; +#endif + +VOID BcacheAnalyse(UINT32 level) +{ + (VOID)level; +#ifdef BCACHE_ANALYSE + int i; + + PRINTK("Bcache information:\n"); + PRINTK(" mem: %u\n", g_memSize); + PRINTK(" block number: %u\n", g_blockNum); + PRINTK("index, switch, hit\n"); + for (i = 0; i < g_blockNum; i++) { + PRINTK("%5d, %6d, %3d\n", i, g_switchTimes[i], g_hitTimes[i]); + } +#else + PRINTK("Bcache hasn't started\n"); +#endif +} + #ifdef LOSCFG_FS_FAT_CACHE_SYNC_THREAD UINT32 g_syncThreadPrio = CONFIG_FS_FAT_SYNC_THREAD_PRIO; @@ -623,6 +650,11 @@ static INT32 BcacheGetBlock(OsBcache *bc, UINT64 num, BOOL readData, OsBcacheBlo if (block != NULL) { D(("bcache block = %llu found in cache\n", num)); +#ifdef BCACHE_ANALYSE + UINT32 index = ((UINT32)(block->data - g_memStart)) / g_dataSize; + PRINTK(", [HIT], %llu, %u\n", num, index); + g_hitTimes[index]++; +#endif if (first != block) { ListMoveBlockToHead(bc, block); @@ -647,6 +679,11 @@ static INT32 BcacheGetBlock(OsBcache *bc, UINT64 num, BOOL readData, OsBcacheBlo if (block == NULL) { return -ENOMEM; } +#ifdef BCACHE_ANALYSE + UINT32 index = ((UINT32)(block->data - g_memStart)) / g_dataSize; + PRINTK(", [MISS], %llu, %u\n", num, index); + g_switchTimes[index]++; +#endif BlockInit(bc, block, num); if (readData == TRUE) { @@ -667,6 +704,16 @@ static INT32 BcacheGetBlock(OsBcache *bc, UINT64 num, BOOL readData, OsBcacheBlo return ENOERR; } +INT32 BcacheClearCache(OsBcache *bc) +{ + OsBcacheBlock *block = NULL; + OsBcacheBlock *next = NULL; + LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(block, next, &bc->listHead, OsBcacheBlock, listNode) { + DelBlock(bc, block); + } + return 0; +} + static INT32 BcacheInitCache(OsBcache *bc, UINT8 *memStart, UINT32 memSize, @@ -701,6 +748,13 @@ static INT32 BcacheInitCache(OsBcache *bc, dataMem = blockMem + (sizeof(OsBcacheBlock) * blockNum); dataMem += ALIGN_DISP((UINTPTR)dataMem); +#ifdef BCACHE_ANALYSE + g_memSize = memSize; + g_blockNum = blockNum; + g_dataSize = bc->blockSize; + g_memStart = dataMem; +#endif + for (i = 0; i < blockNum; i++) { block = (OsBcacheBlock *)(VOID *)blockMem; block->data = dataMem; @@ -710,7 +764,7 @@ static INT32 BcacheInitCache(OsBcache *bc, bc->wStart = block; } - LOS_ListAdd(&bc->freeListHead, &block->listNode); + LOS_ListTailInsert(&bc->freeListHead, &block->listNode); blockMem += sizeof(OsBcacheBlock); dataMem += bc->blockSize; @@ -768,7 +822,7 @@ INT32 BlockCacheDrvCreate(VOID *handle, return ENOERR; } -INT32 BlockCacheRead(OsBcache *bc, UINT8 *buf, UINT32 *len, UINT64 sector) +INT32 BlockCacheRead(OsBcache *bc, UINT8 *buf, UINT32 *len, UINT64 sector, BOOL useRead) { OsBcacheBlock *block = NULL; UINT8 *tempBuf = buf; @@ -777,6 +831,9 @@ INT32 BlockCacheRead(OsBcache *bc, UINT8 *buf, UINT32 *len, UINT64 sector) INT32 ret = ENOERR; UINT64 pos; UINT64 num; +#ifdef BCACHE_ANALYSE + PRINTK("bcache read:\n"); +#endif if (bc == NULL || buf == NULL || len == NULL) { return -EPERM; @@ -796,7 +853,8 @@ INT32 BlockCacheRead(OsBcache *bc, UINT8 *buf, UINT32 *len, UINT64 sector) (VOID)pthread_mutex_lock(&bc->bcacheMutex); - ret = BcacheGetBlock(bc, num, TRUE, &block); + /* useRead should be FALSE when reading large contiguous data */ + ret = BcacheGetBlock(bc, num, useRead, &block); if (ret != ENOERR) { (VOID)pthread_mutex_unlock(&bc->bcacheMutex); break; @@ -841,6 +899,9 @@ INT32 BlockCacheWrite(OsBcache *bc, const UINT8 *buf, UINT32 *len, UINT64 sector UINT32 currentSize; UINT64 pos; UINT64 num; +#ifdef BCACHE_ANALYSE + PRINTK("bcache write:\n"); +#endif pos = sector * bc->sectorSize; num = pos >> bc->blockSizeLog2; diff --git a/fs/vfs/disk/disk.c b/fs/vfs/disk/disk.c index 433dd5ea..e7dfe5bd 100755 --- a/fs/vfs/disk/disk.c +++ b/fs/vfs/disk/disk.c @@ -798,7 +798,7 @@ INT32 DiskPartitionRegister(los_disk *disk) return ENOERR; } -INT32 los_disk_read(INT32 drvID, VOID *buf, UINT64 sector, UINT32 count) +INT32 los_disk_read(INT32 drvID, VOID *buf, UINT64 sector, UINT32 count, BOOL useRead) { #ifdef LOSCFG_FS_FAT_CACHE UINT32 len; @@ -830,7 +830,8 @@ INT32 los_disk_read(INT32 drvID, VOID *buf, UINT64 sector, UINT32 count) goto ERROR_HANDLE; } len = disk->bcache->sectorSize * count; - result = BlockCacheRead(disk->bcache, (UINT8 *)buf, &len, sector); + /* useRead should be FALSE when reading large contiguous data */ + result = BlockCacheRead(disk->bcache, (UINT8 *)buf, &len, sector, useRead); if (result != ENOERR) { PRINT_ERR("los_disk_read read err = %d, sector = %llu, len = %u\n", result, sector, len); } @@ -975,7 +976,7 @@ ERROR_HANDLE: return VFS_ERROR; } -INT32 los_part_read(INT32 pt, VOID *buf, UINT64 sector, UINT32 count) +INT32 los_part_read(INT32 pt, VOID *buf, UINT64 sector, UINT32 count, BOOL useRead) { const los_part *part = get_part(pt); los_disk *disk = NULL; @@ -1017,7 +1018,8 @@ INT32 los_part_read(INT32 pt, VOID *buf, UINT64 sector, UINT32 count) goto ERROR_HANDLE; } - ret = los_disk_read((INT32)part->disk_id, buf, sector, count); + /* useRead should be FALSE when reading large contiguous data */ + ret = los_disk_read((INT32)part->disk_id, buf, sector, count, useRead); if (ret < 0) { goto ERROR_HANDLE; } @@ -1148,6 +1150,29 @@ ERROR_HANDLE: return VFS_ERROR; } +INT32 los_disk_cache_clear(INT32 drvID) +{ + INT32 result; + los_disk *disk = NULL; + + result = OsSdSync(drvID); + if (result != 0) { + PRINTK("[ERROR]disk cache clear failed!n"); + return result; + } + + disk = get_disk(drvID); + if (disk == NULL) { + return -1; + } + + DISK_LOCK(&disk->disk_mutex); + result = BcacheClearCache(disk->bcache); + DISK_UNLOCK(&disk->disk_mutex); + + return result; +} + #ifdef LOSCFG_FS_FAT_CACHE static VOID DiskCacheThreadInit(UINT32 diskID, OsBcache *bc) { diff --git a/fs/vfs/include/bcache/bcache.h b/fs/vfs/include/bcache/bcache.h index 8fc3efd9..24bf96c0 100644 --- a/fs/vfs/include/bcache/bcache.h +++ b/fs/vfs/include/bcache/bcache.h @@ -131,6 +131,7 @@ typedef struct tagOsBcache { * @param len [IN] number of bytes to read * @param num [IN] starting block number * @param pos [IN] starting position inside starting block + * @param useRead [IN] whether use the read block or write block * * @attention *