10d163575Sopenharmony_ci/* 20d163575Sopenharmony_ci * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. 30d163575Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. 40d163575Sopenharmony_ci * 50d163575Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification, 60d163575Sopenharmony_ci * are permitted provided that the following conditions are met: 70d163575Sopenharmony_ci * 80d163575Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, this list of 90d163575Sopenharmony_ci * conditions and the following disclaimer. 100d163575Sopenharmony_ci * 110d163575Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, this list 120d163575Sopenharmony_ci * of conditions and the following disclaimer in the documentation and/or other materials 130d163575Sopenharmony_ci * provided with the distribution. 140d163575Sopenharmony_ci * 150d163575Sopenharmony_ci * 3. Neither the name of the copyright holder nor the names of its contributors may be used 160d163575Sopenharmony_ci * to endorse or promote products derived from this software without specific prior written 170d163575Sopenharmony_ci * permission. 180d163575Sopenharmony_ci * 190d163575Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 200d163575Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 210d163575Sopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 220d163575Sopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 230d163575Sopenharmony_ci * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 240d163575Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 250d163575Sopenharmony_ci * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 260d163575Sopenharmony_ci * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 270d163575Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 280d163575Sopenharmony_ci * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 290d163575Sopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 300d163575Sopenharmony_ci */ 310d163575Sopenharmony_ci 320d163575Sopenharmony_ci#include "bcache.h" 330d163575Sopenharmony_ci#include "assert.h" 340d163575Sopenharmony_ci#include "stdlib.h" 350d163575Sopenharmony_ci#include "linux/delay.h" 360d163575Sopenharmony_ci#include "disk_pri.h" 370d163575Sopenharmony_ci#include "user_copy.h" 380d163575Sopenharmony_ci 390d163575Sopenharmony_ci#undef HALARC_ALIGNMENT 400d163575Sopenharmony_ci#define DMA_ALLGN 64 410d163575Sopenharmony_ci#define HALARC_ALIGNMENT DMA_ALLGN 420d163575Sopenharmony_ci#define BCACHE_MAGIC_NUM 20132016 430d163575Sopenharmony_ci#define BCACHE_STATCK_SIZE 0x3000 440d163575Sopenharmony_ci#define ASYNC_EVENT_BIT 0x01 450d163575Sopenharmony_ci 460d163575Sopenharmony_ci#ifdef DEBUG 470d163575Sopenharmony_ci#define D(args) printf args 480d163575Sopenharmony_ci#else 490d163575Sopenharmony_ci#define D(args) 500d163575Sopenharmony_ci#endif 510d163575Sopenharmony_ci 520d163575Sopenharmony_ci#ifdef BCACHE_ANALYSE 530d163575Sopenharmony_ciUINT32 g_memSize; 540d163575Sopenharmony_civolatile UINT32 g_blockNum; 550d163575Sopenharmony_civolatile UINT32 g_dataSize; 560d163575Sopenharmony_civolatile UINT8 *g_memStart; 570d163575Sopenharmony_civolatile UINT32 g_switchTimes[CONFIG_FS_FAT_BLOCK_NUMS] = { 0 }; 580d163575Sopenharmony_civolatile UINT32 g_hitTimes[CONFIG_FS_FAT_BLOCK_NUMS] = { 0 }; 590d163575Sopenharmony_ci#endif 600d163575Sopenharmony_ci 610d163575Sopenharmony_ciVOID BcacheAnalyse(UINT32 level) 620d163575Sopenharmony_ci{ 630d163575Sopenharmony_ci (VOID)level; 640d163575Sopenharmony_ci#ifdef BCACHE_ANALYSE 650d163575Sopenharmony_ci int i; 660d163575Sopenharmony_ci 670d163575Sopenharmony_ci PRINTK("Bcache information:\n"); 680d163575Sopenharmony_ci PRINTK(" mem: %u\n", g_memSize); 690d163575Sopenharmony_ci PRINTK(" block number: %u\n", g_blockNum); 700d163575Sopenharmony_ci PRINTK("index, switch, hit\n"); 710d163575Sopenharmony_ci for (i = 0; i < g_blockNum; i++) { 720d163575Sopenharmony_ci PRINTK("%5d, %6d, %3d\n", i, g_switchTimes[i], g_hitTimes[i]); 730d163575Sopenharmony_ci } 740d163575Sopenharmony_ci#else 750d163575Sopenharmony_ci PRINTK("Bcache hasn't started\n"); 760d163575Sopenharmony_ci#endif 770d163575Sopenharmony_ci} 780d163575Sopenharmony_ci 790d163575Sopenharmony_ci#ifdef LOSCFG_FS_FAT_CACHE_SYNC_THREAD 800d163575Sopenharmony_ci 810d163575Sopenharmony_ciUINT32 g_syncThreadPrio = CONFIG_FS_FAT_SYNC_THREAD_PRIO; 820d163575Sopenharmony_ciUINT32 g_dirtyRatio = CONFIG_FS_FAT_DIRTY_RATIO; 830d163575Sopenharmony_ciUINT32 g_syncInterval = CONFIG_FS_FAT_SYNC_INTERVAL; 840d163575Sopenharmony_ci 850d163575Sopenharmony_ciVOID LOS_SetDirtyRatioThreshold(UINT32 dirtyRatio) 860d163575Sopenharmony_ci{ 870d163575Sopenharmony_ci if ((dirtyRatio != g_dirtyRatio) && (dirtyRatio <= 100)) { /* The ratio cannot exceed 100% */ 880d163575Sopenharmony_ci g_dirtyRatio = dirtyRatio; 890d163575Sopenharmony_ci } 900d163575Sopenharmony_ci} 910d163575Sopenharmony_ci 920d163575Sopenharmony_ciVOID LOS_SetSyncThreadInterval(UINT32 interval) 930d163575Sopenharmony_ci{ 940d163575Sopenharmony_ci g_syncInterval = interval; 950d163575Sopenharmony_ci} 960d163575Sopenharmony_ci 970d163575Sopenharmony_ciINT32 LOS_SetSyncThreadPrio(UINT32 prio, const CHAR *name) 980d163575Sopenharmony_ci{ 990d163575Sopenharmony_ci INT32 ret = VFS_ERROR; 1000d163575Sopenharmony_ci INT32 diskID; 1010d163575Sopenharmony_ci los_disk *disk = NULL; 1020d163575Sopenharmony_ci if ((prio == 0) || (prio >= OS_TASK_PRIORITY_LOWEST)) { /* The priority can not be zero */ 1030d163575Sopenharmony_ci return ret; 1040d163575Sopenharmony_ci } 1050d163575Sopenharmony_ci 1060d163575Sopenharmony_ci g_syncThreadPrio = prio; 1070d163575Sopenharmony_ci 1080d163575Sopenharmony_ci /* 1090d163575Sopenharmony_ci * If the name is NULL, it only sets the value of a global variable, 1100d163575Sopenharmony_ci * and takes effect the next time the thread is created. 1110d163575Sopenharmony_ci */ 1120d163575Sopenharmony_ci if (name == NULL) { 1130d163575Sopenharmony_ci return ENOERR; 1140d163575Sopenharmony_ci } 1150d163575Sopenharmony_ci 1160d163575Sopenharmony_ci /* If the name is not NULL, it shall return an error if can't find the disk corresponding to name. */ 1170d163575Sopenharmony_ci diskID = los_get_diskid_byname(name); 1180d163575Sopenharmony_ci disk = get_disk(diskID); 1190d163575Sopenharmony_ci if (disk == NULL) { 1200d163575Sopenharmony_ci return ret; 1210d163575Sopenharmony_ci } 1220d163575Sopenharmony_ci 1230d163575Sopenharmony_ci if (pthread_mutex_lock(&disk->disk_mutex) != ENOERR) { 1240d163575Sopenharmony_ci PRINT_ERR("%s %d, mutex lock fail!\n", __FUNCTION__, __LINE__); 1250d163575Sopenharmony_ci return ret; 1260d163575Sopenharmony_ci } 1270d163575Sopenharmony_ci if ((disk->disk_status == STAT_INUSED) && (disk->bcache != NULL)) { 1280d163575Sopenharmony_ci ret = LOS_TaskPriSet(disk->bcache->syncTaskId, prio); 1290d163575Sopenharmony_ci } 1300d163575Sopenharmony_ci if (pthread_mutex_unlock(&disk->disk_mutex) != ENOERR) { 1310d163575Sopenharmony_ci PRINT_ERR("%s %d, mutex unlock fail!\n", __FUNCTION__, __LINE__); 1320d163575Sopenharmony_ci return VFS_ERROR; 1330d163575Sopenharmony_ci } 1340d163575Sopenharmony_ci return ret; 1350d163575Sopenharmony_ci} 1360d163575Sopenharmony_ci#endif 1370d163575Sopenharmony_ci 1380d163575Sopenharmony_cistatic OsBcacheBlock *RbFindBlock(const OsBcache *bc, UINT64 num) 1390d163575Sopenharmony_ci{ 1400d163575Sopenharmony_ci OsBcacheBlock *block = NULL; 1410d163575Sopenharmony_ci struct rb_node *node = bc->rbRoot.rb_node; 1420d163575Sopenharmony_ci 1430d163575Sopenharmony_ci for (; node != NULL; node = (block->num < num) ? node->rb_right : node->rb_left) { 1440d163575Sopenharmony_ci block = rb_entry(node, OsBcacheBlock, rbNode); 1450d163575Sopenharmony_ci if (block->num == num) { 1460d163575Sopenharmony_ci return block; 1470d163575Sopenharmony_ci } 1480d163575Sopenharmony_ci } 1490d163575Sopenharmony_ci return NULL; 1500d163575Sopenharmony_ci} 1510d163575Sopenharmony_ci 1520d163575Sopenharmony_cistatic VOID RbAddBlock(OsBcache *bc, OsBcacheBlock *block) 1530d163575Sopenharmony_ci{ 1540d163575Sopenharmony_ci struct rb_node *node = bc->rbRoot.rb_node; 1550d163575Sopenharmony_ci struct rb_node **link = NULL; 1560d163575Sopenharmony_ci OsBcacheBlock *b = NULL; 1570d163575Sopenharmony_ci 1580d163575Sopenharmony_ci if (node == NULL) { 1590d163575Sopenharmony_ci rb_link_node(&block->rbNode, NULL, &bc->rbRoot.rb_node); 1600d163575Sopenharmony_ci } else { 1610d163575Sopenharmony_ci for (; node != NULL; link = (b->num > block->num) ? &node->rb_left : &node->rb_right, node = *link) { 1620d163575Sopenharmony_ci b = rb_entry(node, OsBcacheBlock, rbNode); 1630d163575Sopenharmony_ci if (b->num == block->num) { 1640d163575Sopenharmony_ci PRINT_ERR("RbAddBlock fail, b->num = %llu, block->num = %llu\n", b->num, block->num); 1650d163575Sopenharmony_ci return; 1660d163575Sopenharmony_ci } 1670d163575Sopenharmony_ci } 1680d163575Sopenharmony_ci rb_link_node(&block->rbNode, &b->rbNode, link); 1690d163575Sopenharmony_ci } 1700d163575Sopenharmony_ci rb_insert_color(&block->rbNode, &bc->rbRoot); 1710d163575Sopenharmony_ci} 1720d163575Sopenharmony_ci 1730d163575Sopenharmony_cistatic inline VOID RbDelBlock(OsBcache *bc, OsBcacheBlock *block) 1740d163575Sopenharmony_ci{ 1750d163575Sopenharmony_ci rb_erase(&block->rbNode, &bc->rbRoot); 1760d163575Sopenharmony_ci} 1770d163575Sopenharmony_ci 1780d163575Sopenharmony_cistatic inline VOID ListMoveBlockToHead(OsBcache *bc, OsBcacheBlock *block) 1790d163575Sopenharmony_ci{ 1800d163575Sopenharmony_ci LOS_ListDelete(&block->listNode); 1810d163575Sopenharmony_ci LOS_ListAdd(&bc->listHead, &block->listNode); 1820d163575Sopenharmony_ci} 1830d163575Sopenharmony_ci 1840d163575Sopenharmony_cistatic inline VOID FreeBlock(OsBcache *bc, OsBcacheBlock *block) 1850d163575Sopenharmony_ci{ 1860d163575Sopenharmony_ci block->used = FALSE; 1870d163575Sopenharmony_ci LOS_ListAdd(&bc->freeListHead, &block->listNode); 1880d163575Sopenharmony_ci} 1890d163575Sopenharmony_ci 1900d163575Sopenharmony_cistatic UINT32 GetValLog2(UINT32 val) 1910d163575Sopenharmony_ci{ 1920d163575Sopenharmony_ci UINT32 i, log2; 1930d163575Sopenharmony_ci 1940d163575Sopenharmony_ci i = val; 1950d163575Sopenharmony_ci log2 = 0; 1960d163575Sopenharmony_ci while ((i & 1) == 0) { /* Check if the last bit is 1 */ 1970d163575Sopenharmony_ci i >>= 1; 1980d163575Sopenharmony_ci log2++; 1990d163575Sopenharmony_ci } 2000d163575Sopenharmony_ci if (i != 1) { /* Not the power of 2 */ 2010d163575Sopenharmony_ci return 0; 2020d163575Sopenharmony_ci } 2030d163575Sopenharmony_ci 2040d163575Sopenharmony_ci return log2; 2050d163575Sopenharmony_ci} 2060d163575Sopenharmony_ci 2070d163575Sopenharmony_cistatic INT32 FindFlagPos(const UINT32 *arr, UINT32 len, UINT32 *p1, UINT32 *p2) 2080d163575Sopenharmony_ci{ 2090d163575Sopenharmony_ci UINT32 *start = p1; 2100d163575Sopenharmony_ci UINT32 *end = p2; 2110d163575Sopenharmony_ci UINT32 i, j, tmp; 2120d163575Sopenharmony_ci UINT32 val = 1; 2130d163575Sopenharmony_ci 2140d163575Sopenharmony_ci *start = BCACHE_MAGIC_NUM; 2150d163575Sopenharmony_ci *end = 0; 2160d163575Sopenharmony_ci for (i = 0; i < len; i++) { 2170d163575Sopenharmony_ci for (j = 0; j < UNSIGNED_INTEGER_BITS; j++) { 2180d163575Sopenharmony_ci tmp = arr[i] << j; 2190d163575Sopenharmony_ci tmp = tmp >> UNINT_MAX_SHIFT_BITS; 2200d163575Sopenharmony_ci if (tmp != val) { 2210d163575Sopenharmony_ci continue; 2220d163575Sopenharmony_ci } 2230d163575Sopenharmony_ci if (val && (*start == BCACHE_MAGIC_NUM)) { 2240d163575Sopenharmony_ci *start = (i << UNINT_LOG2_SHIFT) + j; 2250d163575Sopenharmony_ci val = 1 - val; /* Control parity by 0 and 1 */ 2260d163575Sopenharmony_ci } else if (val && (*start != BCACHE_MAGIC_NUM)) { 2270d163575Sopenharmony_ci *start = 0; 2280d163575Sopenharmony_ci return VFS_ERROR; 2290d163575Sopenharmony_ci } else { 2300d163575Sopenharmony_ci *end = (i << UNINT_LOG2_SHIFT) + j; 2310d163575Sopenharmony_ci val = 1 - val; /* Control parity by 0 and 1 */ 2320d163575Sopenharmony_ci } 2330d163575Sopenharmony_ci } 2340d163575Sopenharmony_ci } 2350d163575Sopenharmony_ci if (*start == BCACHE_MAGIC_NUM) { 2360d163575Sopenharmony_ci *start = 0; 2370d163575Sopenharmony_ci return VFS_ERROR; 2380d163575Sopenharmony_ci } 2390d163575Sopenharmony_ci if (*end == 0) { 2400d163575Sopenharmony_ci *end = len << UNINT_LOG2_SHIFT; 2410d163575Sopenharmony_ci } 2420d163575Sopenharmony_ci 2430d163575Sopenharmony_ci return ENOERR; 2440d163575Sopenharmony_ci} 2450d163575Sopenharmony_ci 2460d163575Sopenharmony_cistatic INT32 BlockRead(OsBcache *bc, OsBcacheBlock *block, UINT8 *buf) 2470d163575Sopenharmony_ci{ 2480d163575Sopenharmony_ci INT32 ret = bc->breadFun(bc->priv, buf, bc->sectorPerBlock, 2490d163575Sopenharmony_ci (block->num) << GetValLog2(bc->sectorPerBlock)); 2500d163575Sopenharmony_ci if (ret) { 2510d163575Sopenharmony_ci PRINT_ERR("BlockRead, brread_fn error, ret = %d\n", ret); 2520d163575Sopenharmony_ci if (block->modified == FALSE) { 2530d163575Sopenharmony_ci if (block->listNode.pstNext != NULL) { 2540d163575Sopenharmony_ci LOS_ListDelete(&block->listNode); /* list del block */ 2550d163575Sopenharmony_ci RbDelBlock(bc, block); 2560d163575Sopenharmony_ci } 2570d163575Sopenharmony_ci FreeBlock(bc, block); 2580d163575Sopenharmony_ci } 2590d163575Sopenharmony_ci return ret; 2600d163575Sopenharmony_ci } 2610d163575Sopenharmony_ci 2620d163575Sopenharmony_ci block->readFlag = TRUE; 2630d163575Sopenharmony_ci return ENOERR; 2640d163575Sopenharmony_ci} 2650d163575Sopenharmony_ci 2660d163575Sopenharmony_cistatic INT32 BcacheGetFlag(OsBcache *bc, OsBcacheBlock *block) 2670d163575Sopenharmony_ci{ 2680d163575Sopenharmony_ci UINT32 i, n, f, sectorPos, val, start, pos, currentSize; 2690d163575Sopenharmony_ci UINT32 flagUse = bc->sectorPerBlock >> UNINT_LOG2_SHIFT; 2700d163575Sopenharmony_ci UINT32 flag = UINT_MAX; 2710d163575Sopenharmony_ci INT32 ret, bits; 2720d163575Sopenharmony_ci 2730d163575Sopenharmony_ci if (block->readFlag == TRUE) { 2740d163575Sopenharmony_ci return ENOERR; 2750d163575Sopenharmony_ci } 2760d163575Sopenharmony_ci 2770d163575Sopenharmony_ci for (i = 0; i < flagUse; i++) { 2780d163575Sopenharmony_ci flag &= block->flag[i]; 2790d163575Sopenharmony_ci } 2800d163575Sopenharmony_ci 2810d163575Sopenharmony_ci if (flag == UINT_MAX) { 2820d163575Sopenharmony_ci return ENOERR; 2830d163575Sopenharmony_ci } 2840d163575Sopenharmony_ci 2850d163575Sopenharmony_ci ret = BlockRead(bc, block, bc->rwBuffer); 2860d163575Sopenharmony_ci if (ret != ENOERR) { 2870d163575Sopenharmony_ci return ret; 2880d163575Sopenharmony_ci } 2890d163575Sopenharmony_ci 2900d163575Sopenharmony_ci for (i = 0, sectorPos = 0; i < flagUse; i++) { 2910d163575Sopenharmony_ci val = block->flag[i]; 2920d163575Sopenharmony_ci /* use unsigned integer for bit map */ 2930d163575Sopenharmony_ci for (f = 0, bits = UNSIGNED_INTEGER_BITS; bits > 0; val = ~(val << n), f++, bits = bits - (INT32)n) { 2940d163575Sopenharmony_ci if (val == 0) { 2950d163575Sopenharmony_ci n = UNSIGNED_INTEGER_BITS; 2960d163575Sopenharmony_ci } else { 2970d163575Sopenharmony_ci n = (UINT32)CLZ(val); 2980d163575Sopenharmony_ci } 2990d163575Sopenharmony_ci sectorPos += n; 3000d163575Sopenharmony_ci if (((f % EVEN_JUDGED) != 0) || (n == 0)) { /* Number of leading zeros of n is zero */ 3010d163575Sopenharmony_ci goto LOOP; 3020d163575Sopenharmony_ci } 3030d163575Sopenharmony_ci if (sectorPos > ((i + 1) << UNINT_LOG2_SHIFT)) { 3040d163575Sopenharmony_ci start = sectorPos - n; 3050d163575Sopenharmony_ci currentSize = (((i + 1) << UNINT_LOG2_SHIFT) - start) * bc->sectorSize; 3060d163575Sopenharmony_ci } else { 3070d163575Sopenharmony_ci start = sectorPos - n; 3080d163575Sopenharmony_ci currentSize = n * bc->sectorSize; 3090d163575Sopenharmony_ci } 3100d163575Sopenharmony_ci pos = start * bc->sectorSize; 3110d163575Sopenharmony_ci if (memcpy_s(block->data + pos, bc->blockSize - pos, bc->rwBuffer + pos, currentSize) != EOK) { 3120d163575Sopenharmony_ci return VFS_ERROR; 3130d163575Sopenharmony_ci } 3140d163575Sopenharmony_ciLOOP: 3150d163575Sopenharmony_ci if (sectorPos > ((i + 1) << UNINT_LOG2_SHIFT)) { 3160d163575Sopenharmony_ci sectorPos = (i + 1) << UNINT_LOG2_SHIFT; 3170d163575Sopenharmony_ci } 3180d163575Sopenharmony_ci } 3190d163575Sopenharmony_ci } 3200d163575Sopenharmony_ci 3210d163575Sopenharmony_ci return ENOERR; 3220d163575Sopenharmony_ci} 3230d163575Sopenharmony_ci 3240d163575Sopenharmony_cistatic VOID BcacheSetFlag(const OsBcache *bc, OsBcacheBlock *block, UINT32 pos, UINT32 size) 3250d163575Sopenharmony_ci{ 3260d163575Sopenharmony_ci UINT32 start, num, i, j, k; 3270d163575Sopenharmony_ci 3280d163575Sopenharmony_ci if (bc->sectorSize == 0) { 3290d163575Sopenharmony_ci PRINT_ERR("BcacheSetFlag sectorSize is equal to zero! \n"); 3300d163575Sopenharmony_ci return; 3310d163575Sopenharmony_ci } 3320d163575Sopenharmony_ci 3330d163575Sopenharmony_ci start = pos / bc->sectorSize; 3340d163575Sopenharmony_ci num = size / bc->sectorSize; 3350d163575Sopenharmony_ci 3360d163575Sopenharmony_ci i = start / UNSIGNED_INTEGER_BITS; 3370d163575Sopenharmony_ci j = start % UNSIGNED_INTEGER_BITS; 3380d163575Sopenharmony_ci for (k = 0; k < num; k++) { 3390d163575Sopenharmony_ci block->flag[i] |= 1u << (UNINT_MAX_SHIFT_BITS - j); 3400d163575Sopenharmony_ci j++; 3410d163575Sopenharmony_ci if (j == UNSIGNED_INTEGER_BITS) { 3420d163575Sopenharmony_ci j = 0; 3430d163575Sopenharmony_ci i++; 3440d163575Sopenharmony_ci } 3450d163575Sopenharmony_ci } 3460d163575Sopenharmony_ci} 3470d163575Sopenharmony_ci 3480d163575Sopenharmony_cistatic INT32 BcacheSyncBlock(OsBcache *bc, OsBcacheBlock *block) 3490d163575Sopenharmony_ci{ 3500d163575Sopenharmony_ci INT32 ret = ENOERR; 3510d163575Sopenharmony_ci UINT32 len, start, end; 3520d163575Sopenharmony_ci 3530d163575Sopenharmony_ci if (block->modified == TRUE) { 3540d163575Sopenharmony_ci D(("bcache writing block = %llu\n", block->num)); 3550d163575Sopenharmony_ci 3560d163575Sopenharmony_ci ret = FindFlagPos(block->flag, bc->sectorPerBlock >> UNINT_LOG2_SHIFT, &start, &end); 3570d163575Sopenharmony_ci if (ret == ENOERR) { 3580d163575Sopenharmony_ci len = end - start; 3590d163575Sopenharmony_ci } else { 3600d163575Sopenharmony_ci ret = BcacheGetFlag(bc, block); 3610d163575Sopenharmony_ci if (ret != ENOERR) { 3620d163575Sopenharmony_ci return ret; 3630d163575Sopenharmony_ci } 3640d163575Sopenharmony_ci 3650d163575Sopenharmony_ci len = bc->sectorPerBlock; 3660d163575Sopenharmony_ci } 3670d163575Sopenharmony_ci 3680d163575Sopenharmony_ci ret = bc->bwriteFun(bc->priv, (const UINT8 *)(block->data + (start * bc->sectorSize)), 3690d163575Sopenharmony_ci len, (block->num * bc->sectorPerBlock) + start); 3700d163575Sopenharmony_ci if (ret == ENOERR) { 3710d163575Sopenharmony_ci block->modified = FALSE; 3720d163575Sopenharmony_ci bc->modifiedBlock--; 3730d163575Sopenharmony_ci } else { 3740d163575Sopenharmony_ci PRINT_ERR("BcacheSyncBlock fail, ret = %d, len = %u, block->num = %llu, start = %u\n", 3750d163575Sopenharmony_ci ret, len, block->num, start); 3760d163575Sopenharmony_ci } 3770d163575Sopenharmony_ci } 3780d163575Sopenharmony_ci return ret; 3790d163575Sopenharmony_ci} 3800d163575Sopenharmony_ci 3810d163575Sopenharmony_cistatic void NumListAdd(OsBcache *bc, OsBcacheBlock *block) 3820d163575Sopenharmony_ci{ 3830d163575Sopenharmony_ci OsBcacheBlock *temp = NULL; 3840d163575Sopenharmony_ci 3850d163575Sopenharmony_ci LOS_DL_LIST_FOR_EACH_ENTRY(temp, &bc->numHead, OsBcacheBlock, numNode) { 3860d163575Sopenharmony_ci if (temp->num > block->num) { 3870d163575Sopenharmony_ci LOS_ListTailInsert(&temp->numNode, &block->numNode); 3880d163575Sopenharmony_ci return; 3890d163575Sopenharmony_ci } 3900d163575Sopenharmony_ci } 3910d163575Sopenharmony_ci 3920d163575Sopenharmony_ci LOS_ListTailInsert(&bc->numHead, &block->numNode); 3930d163575Sopenharmony_ci} 3940d163575Sopenharmony_ci 3950d163575Sopenharmony_cistatic void AddBlock(OsBcache *bc, OsBcacheBlock *block) 3960d163575Sopenharmony_ci{ 3970d163575Sopenharmony_ci RbAddBlock(bc, block); 3980d163575Sopenharmony_ci NumListAdd(bc, block); 3990d163575Sopenharmony_ci bc->sumNum += block->num; 4000d163575Sopenharmony_ci bc->nBlock++; 4010d163575Sopenharmony_ci LOS_ListAdd(&bc->listHead, &block->listNode); 4020d163575Sopenharmony_ci} 4030d163575Sopenharmony_ci 4040d163575Sopenharmony_cistatic void DelBlock(OsBcache *bc, OsBcacheBlock *block) 4050d163575Sopenharmony_ci{ 4060d163575Sopenharmony_ci LOS_ListDelete(&block->listNode); /* lru list del */ 4070d163575Sopenharmony_ci LOS_ListDelete(&block->numNode); /* num list del */ 4080d163575Sopenharmony_ci bc->sumNum -= block->num; 4090d163575Sopenharmony_ci bc->nBlock--; 4100d163575Sopenharmony_ci RbDelBlock(bc, block); /* rb tree del */ 4110d163575Sopenharmony_ci FreeBlock(bc, block); /* free list add */ 4120d163575Sopenharmony_ci} 4130d163575Sopenharmony_ci 4140d163575Sopenharmony_cistatic BOOL BlockAllDirty(const OsBcache *bc, OsBcacheBlock *block) 4150d163575Sopenharmony_ci{ 4160d163575Sopenharmony_ci UINT32 start = 0; 4170d163575Sopenharmony_ci UINT32 end = 0; 4180d163575Sopenharmony_ci UINT32 len = bc->sectorPerBlock >> UNINT_LOG2_SHIFT; 4190d163575Sopenharmony_ci 4200d163575Sopenharmony_ci if (block->modified == TRUE) { 4210d163575Sopenharmony_ci if (block->allDirty) { 4220d163575Sopenharmony_ci return TRUE; 4230d163575Sopenharmony_ci } 4240d163575Sopenharmony_ci 4250d163575Sopenharmony_ci if (FindFlagPos(block->flag, len, &start, &end) == ENOERR) { 4260d163575Sopenharmony_ci if ((end - start) == bc->sectorPerBlock) { 4270d163575Sopenharmony_ci block->allDirty = TRUE; 4280d163575Sopenharmony_ci return TRUE; 4290d163575Sopenharmony_ci } 4300d163575Sopenharmony_ci } 4310d163575Sopenharmony_ci } 4320d163575Sopenharmony_ci 4330d163575Sopenharmony_ci return FALSE; 4340d163575Sopenharmony_ci} 4350d163575Sopenharmony_ci 4360d163575Sopenharmony_cistatic OsBcacheBlock *GetBaseBlock(OsBcache *bc) 4370d163575Sopenharmony_ci{ 4380d163575Sopenharmony_ci OsBcacheBlock *base = bc->wStart; 4390d163575Sopenharmony_ci OsBcacheBlock *end = bc->wEnd; 4400d163575Sopenharmony_ci while (base < end) { 4410d163575Sopenharmony_ci if (base->used == FALSE) { 4420d163575Sopenharmony_ci base->used = TRUE; 4430d163575Sopenharmony_ci LOS_ListDelete(&base->listNode); 4440d163575Sopenharmony_ci return base; 4450d163575Sopenharmony_ci } 4460d163575Sopenharmony_ci base++; 4470d163575Sopenharmony_ci } 4480d163575Sopenharmony_ci 4490d163575Sopenharmony_ci return NULL; 4500d163575Sopenharmony_ci} 4510d163575Sopenharmony_ci 4520d163575Sopenharmony_ci/* try get free block first, if failed free a useless block */ 4530d163575Sopenharmony_cistatic OsBcacheBlock *GetSlowBlock(OsBcache *bc, BOOL read) 4540d163575Sopenharmony_ci{ 4550d163575Sopenharmony_ci LOS_DL_LIST *node = NULL; 4560d163575Sopenharmony_ci OsBcacheBlock *block = NULL; 4570d163575Sopenharmony_ci 4580d163575Sopenharmony_ci LOS_DL_LIST_FOR_EACH_ENTRY(block, &bc->freeListHead, OsBcacheBlock, listNode) { 4590d163575Sopenharmony_ci if (block->readBuff == read) { 4600d163575Sopenharmony_ci block->used = TRUE; 4610d163575Sopenharmony_ci LOS_ListDelete(&block->listNode); 4620d163575Sopenharmony_ci return block; /* get free one */ 4630d163575Sopenharmony_ci } 4640d163575Sopenharmony_ci } 4650d163575Sopenharmony_ci 4660d163575Sopenharmony_ci node = bc->listHead.pstPrev; 4670d163575Sopenharmony_ci while (node != &bc->listHead) { 4680d163575Sopenharmony_ci block = LOS_DL_LIST_ENTRY(node, OsBcacheBlock, listNode); 4690d163575Sopenharmony_ci node = block->listNode.pstPrev; 4700d163575Sopenharmony_ci 4710d163575Sopenharmony_ci if (block->readBuff == read) { 4720d163575Sopenharmony_ci if (block->modified == TRUE) { 4730d163575Sopenharmony_ci BcacheSyncBlock(bc, block); 4740d163575Sopenharmony_ci } 4750d163575Sopenharmony_ci 4760d163575Sopenharmony_ci DelBlock(bc, block); 4770d163575Sopenharmony_ci block->used = TRUE; 4780d163575Sopenharmony_ci LOS_ListDelete(&block->listNode); 4790d163575Sopenharmony_ci return block; /* get used one */ 4800d163575Sopenharmony_ci } 4810d163575Sopenharmony_ci } 4820d163575Sopenharmony_ci 4830d163575Sopenharmony_ci return NULL; 4840d163575Sopenharmony_ci} 4850d163575Sopenharmony_ci 4860d163575Sopenharmony_ci/* flush combined blocks */ 4870d163575Sopenharmony_cistatic VOID WriteMergedBlocks(OsBcache *bc, OsBcacheBlock *begin, int blocks) 4880d163575Sopenharmony_ci{ 4890d163575Sopenharmony_ci INT32 ret; 4900d163575Sopenharmony_ci OsBcacheBlock *cur = NULL; 4910d163575Sopenharmony_ci OsBcacheBlock *next = NULL; 4920d163575Sopenharmony_ci UINT32 len = blocks * bc->sectorPerBlock; 4930d163575Sopenharmony_ci UINT64 pos = begin->num * bc->sectorPerBlock; 4940d163575Sopenharmony_ci 4950d163575Sopenharmony_ci ret = bc->bwriteFun(bc->priv, (const UINT8 *)begin->data, len, pos); 4960d163575Sopenharmony_ci if (ret != ENOERR) { 4970d163575Sopenharmony_ci PRINT_ERR("WriteMergedBlocks bwriteFun failed ret %d\n", ret); 4980d163575Sopenharmony_ci return; 4990d163575Sopenharmony_ci } 5000d163575Sopenharmony_ci 5010d163575Sopenharmony_ci bc->modifiedBlock -= blocks; 5020d163575Sopenharmony_ci cur = begin; 5030d163575Sopenharmony_ci while (blocks > 0) { 5040d163575Sopenharmony_ci next = LOS_DL_LIST_ENTRY(cur->numNode.pstNext, OsBcacheBlock, numNode); 5050d163575Sopenharmony_ci DelBlock(bc, cur); 5060d163575Sopenharmony_ci cur->modified = FALSE; 5070d163575Sopenharmony_ci blocks--; 5080d163575Sopenharmony_ci cur = next; 5090d163575Sopenharmony_ci } 5100d163575Sopenharmony_ci} 5110d163575Sopenharmony_ci 5120d163575Sopenharmony_ci/* find continue blocks and flush them */ 5130d163575Sopenharmony_cistatic VOID MergeSyncBlocks(OsBcache *bc, OsBcacheBlock *start) 5140d163575Sopenharmony_ci{ 5150d163575Sopenharmony_ci INT32 mergedBlock = 0; 5160d163575Sopenharmony_ci OsBcacheBlock *cur = start; 5170d163575Sopenharmony_ci OsBcacheBlock *last = NULL; 5180d163575Sopenharmony_ci 5190d163575Sopenharmony_ci while (cur <= bc->wEnd) { 5200d163575Sopenharmony_ci if (!cur->used || !BlockAllDirty(bc, cur)) { 5210d163575Sopenharmony_ci break; 5220d163575Sopenharmony_ci } 5230d163575Sopenharmony_ci 5240d163575Sopenharmony_ci if (last && (last->num + 1 != cur->num)) { 5250d163575Sopenharmony_ci break; 5260d163575Sopenharmony_ci } 5270d163575Sopenharmony_ci 5280d163575Sopenharmony_ci mergedBlock++; 5290d163575Sopenharmony_ci last = cur; 5300d163575Sopenharmony_ci cur++; 5310d163575Sopenharmony_ci } 5320d163575Sopenharmony_ci 5330d163575Sopenharmony_ci if (mergedBlock > 0) { 5340d163575Sopenharmony_ci WriteMergedBlocks(bc, start, mergedBlock); 5350d163575Sopenharmony_ci } 5360d163575Sopenharmony_ci} 5370d163575Sopenharmony_ci 5380d163575Sopenharmony_ci/* get the min write block num of block cache buffer */ 5390d163575Sopenharmony_cistatic inline UINT64 GetMinWriteNum(OsBcache *bc) 5400d163575Sopenharmony_ci{ 5410d163575Sopenharmony_ci UINT64 ret = 0; 5420d163575Sopenharmony_ci OsBcacheBlock *block = NULL; 5430d163575Sopenharmony_ci 5440d163575Sopenharmony_ci LOS_DL_LIST_FOR_EACH_ENTRY(block, &bc->numHead, OsBcacheBlock, numNode) { 5450d163575Sopenharmony_ci if (!block->readBuff) { 5460d163575Sopenharmony_ci ret = block->num; 5470d163575Sopenharmony_ci break; 5480d163575Sopenharmony_ci } 5490d163575Sopenharmony_ci } 5500d163575Sopenharmony_ci 5510d163575Sopenharmony_ci return ret; 5520d163575Sopenharmony_ci} 5530d163575Sopenharmony_ci 5540d163575Sopenharmony_cistatic OsBcacheBlock *AllocNewBlock(OsBcache *bc, BOOL read, UINT64 num) 5550d163575Sopenharmony_ci{ 5560d163575Sopenharmony_ci OsBcacheBlock *last = NULL; 5570d163575Sopenharmony_ci OsBcacheBlock *prefer = NULL; 5580d163575Sopenharmony_ci 5590d163575Sopenharmony_ci if (read) { /* read */ 5600d163575Sopenharmony_ci return GetSlowBlock(bc, TRUE); 5610d163575Sopenharmony_ci } 5620d163575Sopenharmony_ci 5630d163575Sopenharmony_ci /* fallback, this may happen when the block previously flushed, use read buffer */ 5640d163575Sopenharmony_ci if (bc->nBlock && num < GetMinWriteNum(bc)) { 5650d163575Sopenharmony_ci return GetSlowBlock(bc, TRUE); 5660d163575Sopenharmony_ci } 5670d163575Sopenharmony_ci 5680d163575Sopenharmony_ci last = RbFindBlock(bc, num - 1); /* num=0 is ok */ 5690d163575Sopenharmony_ci if (last == NULL || last->readBuff) { 5700d163575Sopenharmony_ci return GetBaseBlock(bc); /* new block */ 5710d163575Sopenharmony_ci } 5720d163575Sopenharmony_ci 5730d163575Sopenharmony_ci prefer = last + 1; 5740d163575Sopenharmony_ci if (prefer > bc->wEnd) { 5750d163575Sopenharmony_ci prefer = bc->wStart; 5760d163575Sopenharmony_ci } 5770d163575Sopenharmony_ci 5780d163575Sopenharmony_ci /* this is a sync thread synced block! */ 5790d163575Sopenharmony_ci if (prefer->used && !prefer->modified) { 5800d163575Sopenharmony_ci prefer->used = FALSE; 5810d163575Sopenharmony_ci DelBlock(bc, prefer); 5820d163575Sopenharmony_ci } 5830d163575Sopenharmony_ci 5840d163575Sopenharmony_ci if (prefer->used) { /* do not combine with next check */ 5850d163575Sopenharmony_ci MergeSyncBlocks(bc, prefer); /* prefer->used may be changed here */ 5860d163575Sopenharmony_ci } 5870d163575Sopenharmony_ci 5880d163575Sopenharmony_ci if (prefer->used) { 5890d163575Sopenharmony_ci BcacheSyncBlock(bc, prefer); 5900d163575Sopenharmony_ci DelBlock(bc, prefer); 5910d163575Sopenharmony_ci } 5920d163575Sopenharmony_ci 5930d163575Sopenharmony_ci prefer->used = TRUE; 5940d163575Sopenharmony_ci LOS_ListDelete(&prefer->listNode); /* del from free list */ 5950d163575Sopenharmony_ci 5960d163575Sopenharmony_ci return prefer; 5970d163575Sopenharmony_ci} 5980d163575Sopenharmony_ci 5990d163575Sopenharmony_cistatic INT32 BcacheSync(OsBcache *bc) 6000d163575Sopenharmony_ci{ 6010d163575Sopenharmony_ci LOS_DL_LIST *node = NULL; 6020d163575Sopenharmony_ci OsBcacheBlock *block = NULL; 6030d163575Sopenharmony_ci INT32 ret = ENOERR; 6040d163575Sopenharmony_ci 6050d163575Sopenharmony_ci D(("bcache cache sync\n")); 6060d163575Sopenharmony_ci 6070d163575Sopenharmony_ci (VOID)pthread_mutex_lock(&bc->bcacheMutex); 6080d163575Sopenharmony_ci node = bc->listHead.pstPrev; 6090d163575Sopenharmony_ci while (&bc->listHead != node) { 6100d163575Sopenharmony_ci block = LOS_DL_LIST_ENTRY(node, OsBcacheBlock, listNode); 6110d163575Sopenharmony_ci ret = BcacheSyncBlock(bc, block); 6120d163575Sopenharmony_ci if (ret != ENOERR) { 6130d163575Sopenharmony_ci PRINT_ERR("BcacheSync error, ret = %d\n", ret); 6140d163575Sopenharmony_ci break; 6150d163575Sopenharmony_ci } 6160d163575Sopenharmony_ci node = node->pstPrev; 6170d163575Sopenharmony_ci } 6180d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&bc->bcacheMutex); 6190d163575Sopenharmony_ci 6200d163575Sopenharmony_ci return ret; 6210d163575Sopenharmony_ci} 6220d163575Sopenharmony_ci 6230d163575Sopenharmony_cistatic VOID BlockInit(OsBcache *bc, OsBcacheBlock *block, UINT64 num) 6240d163575Sopenharmony_ci{ 6250d163575Sopenharmony_ci (VOID)memset_s(block->flag, sizeof(block->flag), 0, sizeof(block->flag)); 6260d163575Sopenharmony_ci block->num = num; 6270d163575Sopenharmony_ci block->readFlag = FALSE; 6280d163575Sopenharmony_ci if (block->modified == TRUE) { 6290d163575Sopenharmony_ci block->modified = FALSE; 6300d163575Sopenharmony_ci bc->modifiedBlock--; 6310d163575Sopenharmony_ci } 6320d163575Sopenharmony_ci block->allDirty = FALSE; 6330d163575Sopenharmony_ci} 6340d163575Sopenharmony_ci 6350d163575Sopenharmony_cistatic INT32 BcacheGetBlock(OsBcache *bc, UINT64 num, BOOL readData, OsBcacheBlock **dblock) 6360d163575Sopenharmony_ci{ 6370d163575Sopenharmony_ci INT32 ret; 6380d163575Sopenharmony_ci OsBcacheBlock *block = NULL; 6390d163575Sopenharmony_ci OsBcacheBlock *first = NULL; 6400d163575Sopenharmony_ci 6410d163575Sopenharmony_ci /* 6420d163575Sopenharmony_ci * First check if the most recently used block is the requested block, 6430d163575Sopenharmony_ci * this can improve performance when using byte access functions. 6440d163575Sopenharmony_ci */ 6450d163575Sopenharmony_ci if (LOS_ListEmpty(&bc->listHead) == FALSE) { 6460d163575Sopenharmony_ci first = LOS_DL_LIST_ENTRY(bc->listHead.pstNext, OsBcacheBlock, listNode); 6470d163575Sopenharmony_ci block = (first->num == num) ? first : RbFindBlock(bc, num); 6480d163575Sopenharmony_ci } 6490d163575Sopenharmony_ci 6500d163575Sopenharmony_ci if (block != NULL) { 6510d163575Sopenharmony_ci D(("bcache block = %llu found in cache\n", num)); 6520d163575Sopenharmony_ci#ifdef BCACHE_ANALYSE 6530d163575Sopenharmony_ci UINT32 index = ((UINT32)(block->data - g_memStart)) / g_dataSize; 6540d163575Sopenharmony_ci PRINTK(", [HIT], %llu, %u\n", num, index); 6550d163575Sopenharmony_ci g_hitTimes[index]++; 6560d163575Sopenharmony_ci#endif 6570d163575Sopenharmony_ci 6580d163575Sopenharmony_ci if (first != block) { 6590d163575Sopenharmony_ci ListMoveBlockToHead(bc, block); 6600d163575Sopenharmony_ci } 6610d163575Sopenharmony_ci *dblock = block; 6620d163575Sopenharmony_ci 6630d163575Sopenharmony_ci if ((bc->prereadFun != NULL) && (readData == TRUE) && (block->pgHit == 1)) { 6640d163575Sopenharmony_ci block->pgHit = 0; 6650d163575Sopenharmony_ci bc->prereadFun(bc, block); 6660d163575Sopenharmony_ci } 6670d163575Sopenharmony_ci 6680d163575Sopenharmony_ci return ENOERR; 6690d163575Sopenharmony_ci } 6700d163575Sopenharmony_ci 6710d163575Sopenharmony_ci D(("bcache block = %llu NOT found in cache\n", num)); 6720d163575Sopenharmony_ci 6730d163575Sopenharmony_ci block = AllocNewBlock(bc, readData, num); 6740d163575Sopenharmony_ci if (block == NULL) { 6750d163575Sopenharmony_ci block = GetSlowBlock(bc, readData); 6760d163575Sopenharmony_ci } 6770d163575Sopenharmony_ci 6780d163575Sopenharmony_ci if (block == NULL) { 6790d163575Sopenharmony_ci return -ENOMEM; 6800d163575Sopenharmony_ci } 6810d163575Sopenharmony_ci#ifdef BCACHE_ANALYSE 6820d163575Sopenharmony_ci UINT32 index = ((UINT32)(block->data - g_memStart)) / g_dataSize; 6830d163575Sopenharmony_ci PRINTK(", [MISS], %llu, %u\n", num, index); 6840d163575Sopenharmony_ci g_switchTimes[index]++; 6850d163575Sopenharmony_ci#endif 6860d163575Sopenharmony_ci BlockInit(bc, block, num); 6870d163575Sopenharmony_ci 6880d163575Sopenharmony_ci if (readData == TRUE) { 6890d163575Sopenharmony_ci D(("bcache reading block = %llu\n", block->num)); 6900d163575Sopenharmony_ci 6910d163575Sopenharmony_ci ret = BlockRead(bc, block, block->data); 6920d163575Sopenharmony_ci if (ret != ENOERR) { 6930d163575Sopenharmony_ci return ret; 6940d163575Sopenharmony_ci } 6950d163575Sopenharmony_ci if (bc->prereadFun != NULL) { 6960d163575Sopenharmony_ci bc->prereadFun(bc, block); 6970d163575Sopenharmony_ci } 6980d163575Sopenharmony_ci } 6990d163575Sopenharmony_ci 7000d163575Sopenharmony_ci AddBlock(bc, block); 7010d163575Sopenharmony_ci 7020d163575Sopenharmony_ci *dblock = block; 7030d163575Sopenharmony_ci return ENOERR; 7040d163575Sopenharmony_ci} 7050d163575Sopenharmony_ci 7060d163575Sopenharmony_ciINT32 BcacheClearCache(OsBcache *bc) 7070d163575Sopenharmony_ci{ 7080d163575Sopenharmony_ci OsBcacheBlock *block = NULL; 7090d163575Sopenharmony_ci OsBcacheBlock *next = NULL; 7100d163575Sopenharmony_ci LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(block, next, &bc->listHead, OsBcacheBlock, listNode) { 7110d163575Sopenharmony_ci DelBlock(bc, block); 7120d163575Sopenharmony_ci } 7130d163575Sopenharmony_ci return 0; 7140d163575Sopenharmony_ci} 7150d163575Sopenharmony_ci 7160d163575Sopenharmony_cistatic INT32 BcacheInitCache(OsBcache *bc, 7170d163575Sopenharmony_ci UINT8 *memStart, 7180d163575Sopenharmony_ci UINT32 memSize, 7190d163575Sopenharmony_ci UINT32 blockSize) 7200d163575Sopenharmony_ci{ 7210d163575Sopenharmony_ci UINT8 *blockMem = NULL; 7220d163575Sopenharmony_ci UINT8 *dataMem = NULL; 7230d163575Sopenharmony_ci OsBcacheBlock *block = NULL; 7240d163575Sopenharmony_ci UINT32 blockNum, i; 7250d163575Sopenharmony_ci 7260d163575Sopenharmony_ci LOS_ListInit(&bc->listHead); 7270d163575Sopenharmony_ci LOS_ListInit(&bc->numHead); 7280d163575Sopenharmony_ci bc->sumNum = 0; 7290d163575Sopenharmony_ci bc->nBlock = 0; 7300d163575Sopenharmony_ci 7310d163575Sopenharmony_ci if (!GetValLog2(blockSize)) { 7320d163575Sopenharmony_ci PRINT_ERR("GetValLog2(%u) return 0.\n", blockSize); 7330d163575Sopenharmony_ci return -EINVAL; 7340d163575Sopenharmony_ci } 7350d163575Sopenharmony_ci 7360d163575Sopenharmony_ci bc->rbRoot.rb_node = NULL; 7370d163575Sopenharmony_ci bc->memStart = memStart; 7380d163575Sopenharmony_ci bc->blockSize = blockSize; 7390d163575Sopenharmony_ci bc->blockSizeLog2 = GetValLog2(blockSize); 7400d163575Sopenharmony_ci bc->modifiedBlock = 0; 7410d163575Sopenharmony_ci 7420d163575Sopenharmony_ci /* init block memory pool */ 7430d163575Sopenharmony_ci LOS_ListInit(&bc->freeListHead); 7440d163575Sopenharmony_ci 7450d163575Sopenharmony_ci blockNum = (memSize - DMA_ALLGN) / (sizeof(OsBcacheBlock) + bc->blockSize); 7460d163575Sopenharmony_ci blockMem = bc->memStart; 7470d163575Sopenharmony_ci dataMem = blockMem + (sizeof(OsBcacheBlock) * blockNum); 7480d163575Sopenharmony_ci dataMem += ALIGN_DISP((UINTPTR)dataMem); 7490d163575Sopenharmony_ci 7500d163575Sopenharmony_ci#ifdef BCACHE_ANALYSE 7510d163575Sopenharmony_ci g_memSize = memSize; 7520d163575Sopenharmony_ci g_blockNum = blockNum; 7530d163575Sopenharmony_ci g_dataSize = bc->blockSize; 7540d163575Sopenharmony_ci g_memStart = dataMem; 7550d163575Sopenharmony_ci#endif 7560d163575Sopenharmony_ci 7570d163575Sopenharmony_ci for (i = 0; i < blockNum; i++) { 7580d163575Sopenharmony_ci block = (OsBcacheBlock *)(VOID *)blockMem; 7590d163575Sopenharmony_ci block->data = dataMem; 7600d163575Sopenharmony_ci block->readBuff = (i < CONFIG_FS_FAT_READ_NUMS) ? TRUE : FALSE; 7610d163575Sopenharmony_ci 7620d163575Sopenharmony_ci if (i == CONFIG_FS_FAT_READ_NUMS) { 7630d163575Sopenharmony_ci bc->wStart = block; 7640d163575Sopenharmony_ci } 7650d163575Sopenharmony_ci 7660d163575Sopenharmony_ci LOS_ListTailInsert(&bc->freeListHead, &block->listNode); 7670d163575Sopenharmony_ci 7680d163575Sopenharmony_ci blockMem += sizeof(OsBcacheBlock); 7690d163575Sopenharmony_ci dataMem += bc->blockSize; 7700d163575Sopenharmony_ci } 7710d163575Sopenharmony_ci 7720d163575Sopenharmony_ci bc->wEnd = block; 7730d163575Sopenharmony_ci 7740d163575Sopenharmony_ci return ENOERR; 7750d163575Sopenharmony_ci} 7760d163575Sopenharmony_ci 7770d163575Sopenharmony_cistatic INT32 DrvBread(struct Vnode *priv, UINT8 *buf, UINT32 len, UINT64 pos) 7780d163575Sopenharmony_ci{ 7790d163575Sopenharmony_ci struct block_operations *bops = (struct block_operations *)((struct drv_data *)priv->data)->ops; 7800d163575Sopenharmony_ci 7810d163575Sopenharmony_ci INT32 ret = bops->read(priv, buf, pos, len); 7820d163575Sopenharmony_ci if (ret != (INT32)len) { 7830d163575Sopenharmony_ci PRINT_ERR("%s failure\n", __FUNCTION__); 7840d163575Sopenharmony_ci return ret; 7850d163575Sopenharmony_ci } 7860d163575Sopenharmony_ci return ENOERR; 7870d163575Sopenharmony_ci} 7880d163575Sopenharmony_ci 7890d163575Sopenharmony_cistatic INT32 DrvBwrite(struct Vnode *priv, const UINT8 *buf, UINT32 len, UINT64 pos) 7900d163575Sopenharmony_ci{ 7910d163575Sopenharmony_ci struct block_operations *bops = (struct block_operations *)((struct drv_data *)priv->data)->ops; 7920d163575Sopenharmony_ci INT32 ret = bops->write(priv, buf, pos, len); 7930d163575Sopenharmony_ci if (ret != (INT32)len) { 7940d163575Sopenharmony_ci PRINT_ERR("%s failure\n", __FUNCTION__); 7950d163575Sopenharmony_ci return ret; 7960d163575Sopenharmony_ci } 7970d163575Sopenharmony_ci return ENOERR; 7980d163575Sopenharmony_ci} 7990d163575Sopenharmony_ci 8000d163575Sopenharmony_ciINT32 BlockCacheDrvCreate(VOID *handle, 8010d163575Sopenharmony_ci UINT8 *memStart, 8020d163575Sopenharmony_ci UINT32 memSize, 8030d163575Sopenharmony_ci UINT32 blockSize, 8040d163575Sopenharmony_ci OsBcache *bc) 8050d163575Sopenharmony_ci{ 8060d163575Sopenharmony_ci INT32 ret; 8070d163575Sopenharmony_ci bc->priv = handle; 8080d163575Sopenharmony_ci bc->breadFun = DrvBread; 8090d163575Sopenharmony_ci bc->bwriteFun = DrvBwrite; 8100d163575Sopenharmony_ci 8110d163575Sopenharmony_ci ret = BcacheInitCache(bc, memStart, memSize, blockSize); 8120d163575Sopenharmony_ci if (ret != ENOERR) { 8130d163575Sopenharmony_ci return ret; 8140d163575Sopenharmony_ci } 8150d163575Sopenharmony_ci 8160d163575Sopenharmony_ci if (pthread_mutex_init(&bc->bcacheMutex, NULL) != ENOERR) { 8170d163575Sopenharmony_ci return VFS_ERROR; 8180d163575Sopenharmony_ci } 8190d163575Sopenharmony_ci bc->bcacheMutex.attr.type = PTHREAD_MUTEX_RECURSIVE; 8200d163575Sopenharmony_ci 8210d163575Sopenharmony_ci return ENOERR; 8220d163575Sopenharmony_ci} 8230d163575Sopenharmony_ci 8240d163575Sopenharmony_ciINT32 BlockCacheRead(OsBcache *bc, UINT8 *buf, UINT32 *len, UINT64 sector, BOOL useRead) 8250d163575Sopenharmony_ci{ 8260d163575Sopenharmony_ci OsBcacheBlock *block = NULL; 8270d163575Sopenharmony_ci UINT8 *tempBuf = buf; 8280d163575Sopenharmony_ci UINT32 size; 8290d163575Sopenharmony_ci UINT32 currentSize; 8300d163575Sopenharmony_ci INT32 ret = ENOERR; 8310d163575Sopenharmony_ci UINT64 pos; 8320d163575Sopenharmony_ci UINT64 num; 8330d163575Sopenharmony_ci#ifdef BCACHE_ANALYSE 8340d163575Sopenharmony_ci PRINTK("bcache read:\n"); 8350d163575Sopenharmony_ci#endif 8360d163575Sopenharmony_ci 8370d163575Sopenharmony_ci if (bc == NULL || buf == NULL || len == NULL) { 8380d163575Sopenharmony_ci return -EPERM; 8390d163575Sopenharmony_ci } 8400d163575Sopenharmony_ci 8410d163575Sopenharmony_ci size = *len; 8420d163575Sopenharmony_ci pos = sector * bc->sectorSize; 8430d163575Sopenharmony_ci num = pos >> bc->blockSizeLog2; 8440d163575Sopenharmony_ci pos = pos & (bc->blockSize - 1); 8450d163575Sopenharmony_ci 8460d163575Sopenharmony_ci while (size > 0) { 8470d163575Sopenharmony_ci if ((size + pos) > bc->blockSize) { 8480d163575Sopenharmony_ci currentSize = bc->blockSize - (UINT32)pos; 8490d163575Sopenharmony_ci } else { 8500d163575Sopenharmony_ci currentSize = size; 8510d163575Sopenharmony_ci } 8520d163575Sopenharmony_ci 8530d163575Sopenharmony_ci (VOID)pthread_mutex_lock(&bc->bcacheMutex); 8540d163575Sopenharmony_ci 8550d163575Sopenharmony_ci /* useRead should be FALSE when reading large contiguous data */ 8560d163575Sopenharmony_ci ret = BcacheGetBlock(bc, num, useRead, &block); 8570d163575Sopenharmony_ci if (ret != ENOERR) { 8580d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&bc->bcacheMutex); 8590d163575Sopenharmony_ci break; 8600d163575Sopenharmony_ci } 8610d163575Sopenharmony_ci 8620d163575Sopenharmony_ci if ((block->readFlag == FALSE) && (block->modified == TRUE)) { 8630d163575Sopenharmony_ci ret = BcacheGetFlag(bc, block); 8640d163575Sopenharmony_ci if (ret != ENOERR) { 8650d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&bc->bcacheMutex); 8660d163575Sopenharmony_ci return ret; 8670d163575Sopenharmony_ci } 8680d163575Sopenharmony_ci } else if ((block->readFlag == FALSE) && (block->modified == FALSE)) { 8690d163575Sopenharmony_ci ret = BlockRead(bc, block, block->data); 8700d163575Sopenharmony_ci if (ret != ENOERR) { 8710d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&bc->bcacheMutex); 8720d163575Sopenharmony_ci return ret; 8730d163575Sopenharmony_ci } 8740d163575Sopenharmony_ci } 8750d163575Sopenharmony_ci 8760d163575Sopenharmony_ci if (LOS_CopyFromKernel((VOID *)tempBuf, size, (VOID *)(block->data + pos), currentSize) != EOK) { 8770d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&bc->bcacheMutex); 8780d163575Sopenharmony_ci return VFS_ERROR; 8790d163575Sopenharmony_ci } 8800d163575Sopenharmony_ci 8810d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&bc->bcacheMutex); 8820d163575Sopenharmony_ci 8830d163575Sopenharmony_ci tempBuf += currentSize; 8840d163575Sopenharmony_ci size -= currentSize; 8850d163575Sopenharmony_ci pos = 0; 8860d163575Sopenharmony_ci num++; 8870d163575Sopenharmony_ci } 8880d163575Sopenharmony_ci *len -= size; 8890d163575Sopenharmony_ci return ret; 8900d163575Sopenharmony_ci} 8910d163575Sopenharmony_ci 8920d163575Sopenharmony_ciINT32 BlockCacheWrite(OsBcache *bc, const UINT8 *buf, UINT32 *len, UINT64 sector) 8930d163575Sopenharmony_ci{ 8940d163575Sopenharmony_ci OsBcacheBlock *block = NULL; 8950d163575Sopenharmony_ci const UINT8 *tempBuf = buf; 8960d163575Sopenharmony_ci UINT32 size = *len; 8970d163575Sopenharmony_ci INT32 ret = ENOERR; 8980d163575Sopenharmony_ci UINT32 currentSize; 8990d163575Sopenharmony_ci UINT64 pos; 9000d163575Sopenharmony_ci UINT64 num; 9010d163575Sopenharmony_ci#ifdef BCACHE_ANALYSE 9020d163575Sopenharmony_ci PRINTK("bcache write:\n"); 9030d163575Sopenharmony_ci#endif 9040d163575Sopenharmony_ci 9050d163575Sopenharmony_ci pos = sector * bc->sectorSize; 9060d163575Sopenharmony_ci num = pos >> bc->blockSizeLog2; 9070d163575Sopenharmony_ci pos = pos & (bc->blockSize - 1); 9080d163575Sopenharmony_ci 9090d163575Sopenharmony_ci D(("bcache write len = %u pos = %llu bnum = %llu\n", *len, pos, num)); 9100d163575Sopenharmony_ci 9110d163575Sopenharmony_ci while (size > 0) { 9120d163575Sopenharmony_ci if ((size + pos) > bc->blockSize) { 9130d163575Sopenharmony_ci currentSize = bc->blockSize - (UINT32)pos; 9140d163575Sopenharmony_ci } else { 9150d163575Sopenharmony_ci currentSize = size; 9160d163575Sopenharmony_ci } 9170d163575Sopenharmony_ci 9180d163575Sopenharmony_ci (VOID)pthread_mutex_lock(&bc->bcacheMutex); 9190d163575Sopenharmony_ci ret = BcacheGetBlock(bc, num, FALSE, &block); 9200d163575Sopenharmony_ci if (ret != ENOERR) { 9210d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&bc->bcacheMutex); 9220d163575Sopenharmony_ci break; 9230d163575Sopenharmony_ci } 9240d163575Sopenharmony_ci 9250d163575Sopenharmony_ci if (LOS_CopyToKernel((VOID *)(block->data + pos), bc->blockSize - (UINT32)pos, 9260d163575Sopenharmony_ci (VOID *)tempBuf, currentSize) != EOK) { 9270d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&bc->bcacheMutex); 9280d163575Sopenharmony_ci return VFS_ERROR; 9290d163575Sopenharmony_ci } 9300d163575Sopenharmony_ci if (block->modified == FALSE) { 9310d163575Sopenharmony_ci block->modified = TRUE; 9320d163575Sopenharmony_ci bc->modifiedBlock++; 9330d163575Sopenharmony_ci } 9340d163575Sopenharmony_ci if ((pos == 0) && (currentSize == bc->blockSize)) { 9350d163575Sopenharmony_ci (void)memset_s(block->flag, sizeof(block->flag), 0xFF, sizeof(block->flag)); 9360d163575Sopenharmony_ci block->allDirty = TRUE; 9370d163575Sopenharmony_ci } else { 9380d163575Sopenharmony_ci BcacheSetFlag(bc, block, (UINT32)pos, currentSize); 9390d163575Sopenharmony_ci } 9400d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&bc->bcacheMutex); 9410d163575Sopenharmony_ci 9420d163575Sopenharmony_ci tempBuf += currentSize; 9430d163575Sopenharmony_ci size -= currentSize; 9440d163575Sopenharmony_ci pos = 0; 9450d163575Sopenharmony_ci num++; 9460d163575Sopenharmony_ci } 9470d163575Sopenharmony_ci *len -= size; 9480d163575Sopenharmony_ci return ret; 9490d163575Sopenharmony_ci} 9500d163575Sopenharmony_ci 9510d163575Sopenharmony_ciINT32 BlockCacheSync(OsBcache *bc) 9520d163575Sopenharmony_ci{ 9530d163575Sopenharmony_ci return BcacheSync(bc); 9540d163575Sopenharmony_ci} 9550d163575Sopenharmony_ci 9560d163575Sopenharmony_ciINT32 OsSdSync(INT32 id) 9570d163575Sopenharmony_ci{ 9580d163575Sopenharmony_ci#ifdef LOSCFG_FS_FAT_CACHE 9590d163575Sopenharmony_ci INT32 ret; 9600d163575Sopenharmony_ci los_disk *disk = get_disk(id); 9610d163575Sopenharmony_ci if ((disk == NULL) || (disk->disk_status == STAT_UNUSED)) { 9620d163575Sopenharmony_ci return VFS_ERROR; 9630d163575Sopenharmony_ci } 9640d163575Sopenharmony_ci if (pthread_mutex_lock(&disk->disk_mutex) != ENOERR) { 9650d163575Sopenharmony_ci PRINT_ERR("%s %d, mutex lock fail!\n", __FUNCTION__, __LINE__); 9660d163575Sopenharmony_ci return VFS_ERROR; 9670d163575Sopenharmony_ci } 9680d163575Sopenharmony_ci if ((disk->disk_status == STAT_INUSED) && (disk->bcache != NULL)) { 9690d163575Sopenharmony_ci ret = BcacheSync(disk->bcache); 9700d163575Sopenharmony_ci } else { 9710d163575Sopenharmony_ci ret = VFS_ERROR; 9720d163575Sopenharmony_ci } 9730d163575Sopenharmony_ci if (pthread_mutex_unlock(&disk->disk_mutex) != ENOERR) { 9740d163575Sopenharmony_ci PRINT_ERR("%s %d, mutex unlock fail!\n", __FUNCTION__, __LINE__); 9750d163575Sopenharmony_ci return VFS_ERROR; 9760d163575Sopenharmony_ci } 9770d163575Sopenharmony_ci return ret; 9780d163575Sopenharmony_ci#else 9790d163575Sopenharmony_ci return VFS_ERROR; 9800d163575Sopenharmony_ci#endif 9810d163575Sopenharmony_ci} 9820d163575Sopenharmony_ci 9830d163575Sopenharmony_ciINT32 LOS_BcacheSyncByName(const CHAR *name) 9840d163575Sopenharmony_ci{ 9850d163575Sopenharmony_ci INT32 diskID = los_get_diskid_byname(name); 9860d163575Sopenharmony_ci return OsSdSync(diskID); 9870d163575Sopenharmony_ci} 9880d163575Sopenharmony_ci 9890d163575Sopenharmony_ciINT32 BcacheGetDirtyRatio(INT32 id) 9900d163575Sopenharmony_ci{ 9910d163575Sopenharmony_ci#ifdef LOSCFG_FS_FAT_CACHE 9920d163575Sopenharmony_ci INT32 ret; 9930d163575Sopenharmony_ci los_disk *disk = get_disk(id); 9940d163575Sopenharmony_ci if (disk == NULL) { 9950d163575Sopenharmony_ci return VFS_ERROR; 9960d163575Sopenharmony_ci } 9970d163575Sopenharmony_ci 9980d163575Sopenharmony_ci if (pthread_mutex_lock(&disk->disk_mutex) != ENOERR) { 9990d163575Sopenharmony_ci PRINT_ERR("%s %d, mutex lock fail!\n", __FUNCTION__, __LINE__); 10000d163575Sopenharmony_ci return VFS_ERROR; 10010d163575Sopenharmony_ci } 10020d163575Sopenharmony_ci if ((disk->disk_status == STAT_INUSED) && (disk->bcache != NULL)) { 10030d163575Sopenharmony_ci ret = (INT32)((disk->bcache->modifiedBlock * PERCENTAGE) / GetFatBlockNums()); 10040d163575Sopenharmony_ci } else { 10050d163575Sopenharmony_ci ret = VFS_ERROR; 10060d163575Sopenharmony_ci } 10070d163575Sopenharmony_ci if (pthread_mutex_unlock(&disk->disk_mutex) != ENOERR) { 10080d163575Sopenharmony_ci PRINT_ERR("%s %d, mutex unlock fail!\n", __FUNCTION__, __LINE__); 10090d163575Sopenharmony_ci return VFS_ERROR; 10100d163575Sopenharmony_ci } 10110d163575Sopenharmony_ci return ret; 10120d163575Sopenharmony_ci#else 10130d163575Sopenharmony_ci return VFS_ERROR; 10140d163575Sopenharmony_ci#endif 10150d163575Sopenharmony_ci} 10160d163575Sopenharmony_ci 10170d163575Sopenharmony_ciINT32 LOS_GetDirtyRatioByName(const CHAR *name) 10180d163575Sopenharmony_ci{ 10190d163575Sopenharmony_ci INT32 diskID = los_get_diskid_byname(name); 10200d163575Sopenharmony_ci return BcacheGetDirtyRatio(diskID); 10210d163575Sopenharmony_ci} 10220d163575Sopenharmony_ci 10230d163575Sopenharmony_ci#ifdef LOSCFG_FS_FAT_CACHE_SYNC_THREAD 10240d163575Sopenharmony_cistatic VOID BcacheSyncThread(UINT32 id) 10250d163575Sopenharmony_ci{ 10260d163575Sopenharmony_ci INT32 diskID = (INT32)id; 10270d163575Sopenharmony_ci INT32 dirtyRatio; 10280d163575Sopenharmony_ci while (1) { 10290d163575Sopenharmony_ci dirtyRatio = BcacheGetDirtyRatio(diskID); 10300d163575Sopenharmony_ci if (dirtyRatio > (INT32)g_dirtyRatio) { 10310d163575Sopenharmony_ci (VOID)OsSdSync(diskID); 10320d163575Sopenharmony_ci } 10330d163575Sopenharmony_ci msleep(g_syncInterval); 10340d163575Sopenharmony_ci } 10350d163575Sopenharmony_ci} 10360d163575Sopenharmony_ci 10370d163575Sopenharmony_ciVOID BcacheSyncThreadInit(OsBcache *bc, INT32 id) 10380d163575Sopenharmony_ci{ 10390d163575Sopenharmony_ci UINT32 ret; 10400d163575Sopenharmony_ci TSK_INIT_PARAM_S appTask; 10410d163575Sopenharmony_ci 10420d163575Sopenharmony_ci (VOID)memset_s(&appTask, sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S)); 10430d163575Sopenharmony_ci appTask.pfnTaskEntry = (TSK_ENTRY_FUNC)BcacheSyncThread; 10440d163575Sopenharmony_ci appTask.uwStackSize = BCACHE_STATCK_SIZE; 10450d163575Sopenharmony_ci appTask.pcName = "bcache_sync_task"; 10460d163575Sopenharmony_ci appTask.usTaskPrio = g_syncThreadPrio; 10470d163575Sopenharmony_ci appTask.auwArgs[0] = (UINTPTR)id; 10480d163575Sopenharmony_ci appTask.uwResved = LOS_TASK_STATUS_DETACHED; 10490d163575Sopenharmony_ci ret = LOS_TaskCreate(&bc->syncTaskId, &appTask); 10500d163575Sopenharmony_ci if (ret != ENOERR) { 10510d163575Sopenharmony_ci PRINT_ERR("Bcache sync task create failed in %s, %d\n", __FUNCTION__, __LINE__); 10520d163575Sopenharmony_ci } 10530d163575Sopenharmony_ci} 10540d163575Sopenharmony_ci 10550d163575Sopenharmony_ciVOID BcacheSyncThreadDeinit(const OsBcache *bc) 10560d163575Sopenharmony_ci{ 10570d163575Sopenharmony_ci if (bc != NULL) { 10580d163575Sopenharmony_ci if (LOS_TaskDelete(bc->syncTaskId) != ENOERR) { 10590d163575Sopenharmony_ci PRINT_ERR("Bcache sync task delete failed in %s, %d\n", __FUNCTION__, __LINE__); 10600d163575Sopenharmony_ci } 10610d163575Sopenharmony_ci } 10620d163575Sopenharmony_ci} 10630d163575Sopenharmony_ci#endif 10640d163575Sopenharmony_ci 10650d163575Sopenharmony_ciOsBcache *BlockCacheInit(struct Vnode *devNode, UINT32 sectorSize, UINT32 sectorPerBlock, 10660d163575Sopenharmony_ci UINT32 blockNum, UINT64 blockCount) 10670d163575Sopenharmony_ci{ 10680d163575Sopenharmony_ci OsBcache *bcache = NULL; 10690d163575Sopenharmony_ci struct Vnode *blkDriver = devNode; 10700d163575Sopenharmony_ci UINT8 *bcacheMem = NULL; 10710d163575Sopenharmony_ci UINT8 *rwBuffer = NULL; 10720d163575Sopenharmony_ci UINT32 blockSize, memSize; 10730d163575Sopenharmony_ci 10740d163575Sopenharmony_ci if ((blkDriver == NULL) || (sectorSize * sectorPerBlock * blockNum == 0) || (blockCount == 0)) { 10750d163575Sopenharmony_ci return NULL; 10760d163575Sopenharmony_ci } 10770d163575Sopenharmony_ci 10780d163575Sopenharmony_ci blockSize = sectorSize * sectorPerBlock; 10790d163575Sopenharmony_ci if ((((UINT64)(sizeof(OsBcacheBlock) + blockSize) * blockNum) + DMA_ALLGN) > UINT_MAX) { 10800d163575Sopenharmony_ci return NULL; 10810d163575Sopenharmony_ci } 10820d163575Sopenharmony_ci memSize = ((sizeof(OsBcacheBlock) + blockSize) * blockNum) + DMA_ALLGN; 10830d163575Sopenharmony_ci 10840d163575Sopenharmony_ci bcache = (OsBcache *)zalloc(sizeof(OsBcache)); 10850d163575Sopenharmony_ci if (bcache == NULL) { 10860d163575Sopenharmony_ci PRINT_ERR("bcache_init : malloc %u Bytes failed!\n", sizeof(OsBcache)); 10870d163575Sopenharmony_ci return NULL; 10880d163575Sopenharmony_ci } 10890d163575Sopenharmony_ci 10900d163575Sopenharmony_ci bcacheMem = (UINT8 *)zalloc(memSize); 10910d163575Sopenharmony_ci if (bcacheMem == NULL) { 10920d163575Sopenharmony_ci PRINT_ERR("bcache_init : malloc %u Bytes failed!\n", memSize); 10930d163575Sopenharmony_ci goto ERROR_OUT_WITH_BCACHE; 10940d163575Sopenharmony_ci } 10950d163575Sopenharmony_ci 10960d163575Sopenharmony_ci rwBuffer = (UINT8 *)memalign(DMA_ALLGN, blockSize); 10970d163575Sopenharmony_ci if (rwBuffer == NULL) { 10980d163575Sopenharmony_ci PRINT_ERR("bcache_init : malloc %u Bytes failed!\n", blockSize); 10990d163575Sopenharmony_ci goto ERROR_OUT_WITH_MEM; 11000d163575Sopenharmony_ci } 11010d163575Sopenharmony_ci 11020d163575Sopenharmony_ci bcache->rwBuffer = rwBuffer; 11030d163575Sopenharmony_ci bcache->sectorSize = sectorSize; 11040d163575Sopenharmony_ci bcache->sectorPerBlock = sectorPerBlock; 11050d163575Sopenharmony_ci bcache->blockCount = blockCount; 11060d163575Sopenharmony_ci 11070d163575Sopenharmony_ci if (BlockCacheDrvCreate(blkDriver, bcacheMem, memSize, blockSize, bcache) != ENOERR) { 11080d163575Sopenharmony_ci goto ERROR_OUT_WITH_BUFFER; 11090d163575Sopenharmony_ci } 11100d163575Sopenharmony_ci 11110d163575Sopenharmony_ci return bcache; 11120d163575Sopenharmony_ci 11130d163575Sopenharmony_ciERROR_OUT_WITH_BUFFER: 11140d163575Sopenharmony_ci free(rwBuffer); 11150d163575Sopenharmony_ciERROR_OUT_WITH_MEM: 11160d163575Sopenharmony_ci free(bcacheMem); 11170d163575Sopenharmony_ciERROR_OUT_WITH_BCACHE: 11180d163575Sopenharmony_ci free(bcache); 11190d163575Sopenharmony_ci return NULL; 11200d163575Sopenharmony_ci} 11210d163575Sopenharmony_ci 11220d163575Sopenharmony_ciVOID BlockCacheDeinit(OsBcache *bcache) 11230d163575Sopenharmony_ci{ 11240d163575Sopenharmony_ci if (bcache != NULL) { 11250d163575Sopenharmony_ci (VOID)pthread_mutex_destroy(&bcache->bcacheMutex); 11260d163575Sopenharmony_ci free(bcache->memStart); 11270d163575Sopenharmony_ci bcache->memStart = NULL; 11280d163575Sopenharmony_ci free(bcache->rwBuffer); 11290d163575Sopenharmony_ci bcache->rwBuffer = NULL; 11300d163575Sopenharmony_ci free(bcache); 11310d163575Sopenharmony_ci } 11320d163575Sopenharmony_ci} 11330d163575Sopenharmony_ci 11340d163575Sopenharmony_cistatic VOID BcacheAsyncPrereadThread(VOID *arg) 11350d163575Sopenharmony_ci{ 11360d163575Sopenharmony_ci OsBcache *bc = (OsBcache *)arg; 11370d163575Sopenharmony_ci OsBcacheBlock *block = NULL; 11380d163575Sopenharmony_ci INT32 ret; 11390d163575Sopenharmony_ci UINT32 i; 11400d163575Sopenharmony_ci 11410d163575Sopenharmony_ci for (;;) { 11420d163575Sopenharmony_ci ret = (INT32)LOS_EventRead(&bc->bcacheEvent, PREREAD_EVENT_MASK, 11430d163575Sopenharmony_ci LOS_WAITMODE_OR | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER); 11440d163575Sopenharmony_ci if (ret != ASYNC_EVENT_BIT) { 11450d163575Sopenharmony_ci PRINT_ERR("The event read in %s, %d is error!!!\n", __FUNCTION__, __LINE__); 11460d163575Sopenharmony_ci continue; 11470d163575Sopenharmony_ci } 11480d163575Sopenharmony_ci 11490d163575Sopenharmony_ci for (i = 1; i <= PREREAD_BLOCK_NUM; i++) { 11500d163575Sopenharmony_ci if ((bc->curBlockNum + i) >= bc->blockCount) { 11510d163575Sopenharmony_ci break; 11520d163575Sopenharmony_ci } 11530d163575Sopenharmony_ci 11540d163575Sopenharmony_ci (VOID)pthread_mutex_lock(&bc->bcacheMutex); 11550d163575Sopenharmony_ci ret = BcacheGetBlock(bc, bc->curBlockNum + i, TRUE, &block); 11560d163575Sopenharmony_ci if (ret != ENOERR) { 11570d163575Sopenharmony_ci PRINT_ERR("read block %llu error : %d!\n", bc->curBlockNum, ret); 11580d163575Sopenharmony_ci } 11590d163575Sopenharmony_ci 11600d163575Sopenharmony_ci (VOID)pthread_mutex_unlock(&bc->bcacheMutex); 11610d163575Sopenharmony_ci } 11620d163575Sopenharmony_ci 11630d163575Sopenharmony_ci if (block != NULL) { 11640d163575Sopenharmony_ci block->pgHit = 1; /* preread complete */ 11650d163575Sopenharmony_ci } 11660d163575Sopenharmony_ci } 11670d163575Sopenharmony_ci} 11680d163575Sopenharmony_ci 11690d163575Sopenharmony_ciVOID ResumeAsyncPreread(OsBcache *arg1, const OsBcacheBlock *arg2) 11700d163575Sopenharmony_ci{ 11710d163575Sopenharmony_ci UINT32 ret; 11720d163575Sopenharmony_ci OsBcache *bc = arg1; 11730d163575Sopenharmony_ci const OsBcacheBlock *block = arg2; 11740d163575Sopenharmony_ci 11750d163575Sopenharmony_ci if (OsCurrTaskGet()->taskID != bc->prereadTaskId) { 11760d163575Sopenharmony_ci bc->curBlockNum = block->num; 11770d163575Sopenharmony_ci ret = LOS_EventWrite(&bc->bcacheEvent, ASYNC_EVENT_BIT); 11780d163575Sopenharmony_ci if (ret != ENOERR) { 11790d163575Sopenharmony_ci PRINT_ERR("Write event failed in %s, %d\n", __FUNCTION__, __LINE__); 11800d163575Sopenharmony_ci } 11810d163575Sopenharmony_ci } 11820d163575Sopenharmony_ci} 11830d163575Sopenharmony_ci 11840d163575Sopenharmony_ciUINT32 BcacheAsyncPrereadInit(OsBcache *bc) 11850d163575Sopenharmony_ci{ 11860d163575Sopenharmony_ci UINT32 ret; 11870d163575Sopenharmony_ci TSK_INIT_PARAM_S appTask; 11880d163575Sopenharmony_ci 11890d163575Sopenharmony_ci ret = LOS_EventInit(&bc->bcacheEvent); 11900d163575Sopenharmony_ci if (ret != ENOERR) { 11910d163575Sopenharmony_ci PRINT_ERR("Async event init failed in %s, %d\n", __FUNCTION__, __LINE__); 11920d163575Sopenharmony_ci return ret; 11930d163575Sopenharmony_ci } 11940d163575Sopenharmony_ci 11950d163575Sopenharmony_ci (VOID)memset_s(&appTask, sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S)); 11960d163575Sopenharmony_ci appTask.pfnTaskEntry = (TSK_ENTRY_FUNC)BcacheAsyncPrereadThread; 11970d163575Sopenharmony_ci appTask.uwStackSize = BCACHE_STATCK_SIZE; 11980d163575Sopenharmony_ci appTask.pcName = "bcache_async_task"; 11990d163575Sopenharmony_ci appTask.usTaskPrio = BCACHE_PREREAD_PRIO; 12000d163575Sopenharmony_ci appTask.auwArgs[0] = (UINTPTR)bc; 12010d163575Sopenharmony_ci appTask.uwResved = LOS_TASK_STATUS_DETACHED; 12020d163575Sopenharmony_ci ret = LOS_TaskCreate(&bc->prereadTaskId, &appTask); 12030d163575Sopenharmony_ci if (ret != ENOERR) { 12040d163575Sopenharmony_ci PRINT_ERR("Bcache async task create failed in %s, %d\n", __FUNCTION__, __LINE__); 12050d163575Sopenharmony_ci } 12060d163575Sopenharmony_ci 12070d163575Sopenharmony_ci return ret; 12080d163575Sopenharmony_ci} 12090d163575Sopenharmony_ci 12100d163575Sopenharmony_ciUINT32 BcacheAsyncPrereadDeinit(OsBcache *bc) 12110d163575Sopenharmony_ci{ 12120d163575Sopenharmony_ci UINT32 ret = LOS_NOK; 12130d163575Sopenharmony_ci 12140d163575Sopenharmony_ci if (bc != NULL) { 12150d163575Sopenharmony_ci ret = LOS_TaskDelete(bc->prereadTaskId); 12160d163575Sopenharmony_ci if (ret != ENOERR) { 12170d163575Sopenharmony_ci PRINT_ERR("Bcache async task delete failed in %s, %d\n", __FUNCTION__, __LINE__); 12180d163575Sopenharmony_ci } 12190d163575Sopenharmony_ci 12200d163575Sopenharmony_ci ret = LOS_EventDestroy(&bc->bcacheEvent); 12210d163575Sopenharmony_ci if (ret != ENOERR) { 12220d163575Sopenharmony_ci PRINT_ERR("Async event destroy failed in %s, %d\n", __FUNCTION__, __LINE__); 12230d163575Sopenharmony_ci return ret; 12240d163575Sopenharmony_ci } 12250d163575Sopenharmony_ci } 12260d163575Sopenharmony_ci 12270d163575Sopenharmony_ci return ret; 12280d163575Sopenharmony_ci} 1229