39#undef HALARC_ALIGNMENT
41#define HALARC_ALIGNMENT DMA_ALLGN
42#define BCACHE_MAGIC_NUM 20132016
43#define BCACHE_STATCK_SIZE 0x3000
44#define ASYNC_EVENT_BIT 0x01
47#define D(args) printf args
67 PRINTK(
"Bcache information:\n");
70 PRINTK(
"index, switch, hit\n");
75 PRINTK(
"Bcache hasn't started\n");
79#ifdef LOSCFG_FS_FAT_CACHE_SYNC_THREAD
87 if ((dirtyRatio !=
g_dirtyRatio) && (dirtyRatio <= 100)) {
99 INT32 ret = VFS_ERROR;
102 if ((prio == 0) || (prio >= OS_TASK_PRIORITY_LOWEST)) {
124 PRINT_ERR(
"%s %d, mutex lock fail!\n", __FUNCTION__, __LINE__);
131 PRINT_ERR(
"%s %d, mutex unlock fail!\n", __FUNCTION__, __LINE__);
141 struct rb_node *node = bc->
rbRoot.rb_node;
143 for (; node != NULL; node = (block->
num < num) ? node->rb_right : node->rb_left) {
145 if (block->
num == num) {
154 struct rb_node *node = bc->
rbRoot.rb_node;
155 struct rb_node **link = NULL;
159 rb_link_node(&block->
rbNode, NULL, &bc->
rbRoot.rb_node);
161 for (; node != NULL; link = (b->
num > block->
num) ? &node->rb_left : &node->rb_right, node = *link) {
163 if (b->
num == block->
num) {
164 PRINT_ERR(
"RbAddBlock fail, b->num = %llu, block->num = %llu\n", b->
num, block->
num);
196 while ((i & 1) == 0) {
214 *start = BCACHE_MAGIC_NUM;
216 for (i = 0; i < len; i++) {
217 for (j = 0; j < UNSIGNED_INTEGER_BITS; j++) {
219 tmp = tmp >> UNINT_MAX_SHIFT_BITS;
223 if (val && (*start == BCACHE_MAGIC_NUM)) {
224 *start = (i << UNINT_LOG2_SHIFT) + j;
226 }
else if (val && (*start != BCACHE_MAGIC_NUM)) {
230 *end = (i << UNINT_LOG2_SHIFT) + j;
235 if (*start == BCACHE_MAGIC_NUM) {
240 *end = len << UNINT_LOG2_SHIFT;
251 PRINT_ERR(
"BlockRead, brread_fn error, ret = %d\n", ret);
268 UINT32 i, n, f, sectorPos, val, start, pos, currentSize;
277 for (i = 0; i < flagUse; i++) {
278 flag &= block->
flag[i];
281 if (flag == UINT_MAX) {
290 for (i = 0, sectorPos = 0; i < flagUse; i++) {
291 val = block->
flag[i];
293 for (f = 0, bits = UNSIGNED_INTEGER_BITS; bits > 0; val = ~(val << n), f++, bits = bits - (
INT32)n) {
295 n = UNSIGNED_INTEGER_BITS;
300 if (((f % EVEN_JUDGED) != 0) || (n == 0)) {
303 if (sectorPos > ((i + 1) << UNINT_LOG2_SHIFT)) {
304 start = sectorPos - n;
305 currentSize = (((i + 1) << UNINT_LOG2_SHIFT) - start) * bc->
sectorSize;
307 start = sectorPos - n;
315 if (sectorPos > ((i + 1) << UNINT_LOG2_SHIFT)) {
316 sectorPos = (i + 1) << UNINT_LOG2_SHIFT;
326 UINT32 start, num, i, j, k;
329 PRINT_ERR(
"BcacheSetFlag sectorSize is equal to zero! \n");
336 i = start / UNSIGNED_INTEGER_BITS;
337 j = start % UNSIGNED_INTEGER_BITS;
338 for (k = 0; k < num; k++) {
339 block->
flag[i] |= 1u << (UNINT_MAX_SHIFT_BITS - j);
341 if (j == UNSIGNED_INTEGER_BITS) {
354 D((
"bcache writing block = %llu\n", block->
num));
374 PRINT_ERR(
"BcacheSyncBlock fail, ret = %d, len = %u, block->num = %llu, start = %u\n",
375 ret, len, block->
num, start);
386 if (temp->
num > block->
num) {
441 if (base->
used == FALSE) {
497 PRINT_ERR(
"WriteMergedBlocks bwriteFun failed ret %d\n", ret);
515 INT32 mergedBlock = 0;
519 while (cur <= bc->wEnd) {
524 if (last && (last->
num + 1 != cur->
num)) {
533 if (mergedBlock > 0) {
569 if (last == NULL || last->
readBuff) {
574 if (prefer > bc->
wEnd) {
580 prefer->
used = FALSE;
605 D((
"bcache cache sync\n"));
613 PRINT_ERR(
"BcacheSync error, ret = %d\n", ret);
625 (VOID)memset_s(block->
flag,
sizeof(block->
flag), 0,
sizeof(block->
flag));
651 D((
"bcache block = %llu found in cache\n", num));
654 PRINTK(
", [HIT], %llu, %u\n", num, index);
658 if (first != block) {
663 if ((bc->
prereadFun != NULL) && (readData == TRUE) && (block->
pgHit == 1)) {
671 D((
"bcache block = %llu NOT found in cache\n", num));
683 PRINTK(
", [MISS], %llu, %u\n", num, index);
688 if (readData == TRUE) {
689 D((
"bcache reading block = %llu\n", block->
num));
721 UINT8 *blockMem = NULL;
722 UINT8 *dataMem = NULL;
732 PRINT_ERR(
"GetValLog2(%u) return 0.\n", blockSize);
736 bc->
rbRoot.rb_node = NULL;
748 dataMem += ALIGN_DISP((
UINTPTR)dataMem);
757 for (i = 0; i < blockNum; i++) {
759 block->
data = dataMem;
760 block->
readBuff = (i < CONFIG_FS_FAT_READ_NUMS) ? TRUE : FALSE;
762 if (i == CONFIG_FS_FAT_READ_NUMS) {
779 struct block_operations *bops = (
struct block_operations *)((
struct drv_data *)priv->
data)->ops;
781 INT32 ret = bops->read(priv, buf, pos, len);
782 if (ret != (
INT32)len) {
783 PRINT_ERR(
"%s failure\n", __FUNCTION__);
791 struct block_operations *bops = (
struct block_operations *)((
struct drv_data *)priv->
data)->ops;
792 INT32 ret = bops->write(priv, buf, pos, len);
793 if (ret != (
INT32)len) {
794 PRINT_ERR(
"%s failure\n", __FUNCTION__);
819 bc->
bcacheMutex.attr.type = PTHREAD_MUTEX_RECURSIVE;
827 UINT8 *tempBuf = buf;
834 PRINTK(
"bcache read:\n");
837 if (bc == NULL || buf == NULL || len == NULL) {
883 tempBuf += currentSize;
895 const UINT8 *tempBuf = buf;
902 PRINTK(
"bcache write:\n");
909 D((
"bcache write len = %u pos = %llu bnum = %llu\n", *len, pos, num));
926 (VOID *)tempBuf, currentSize) != EOK) {
934 if ((pos == 0) && (currentSize == bc->
blockSize)) {
935 (
void)memset_s(block->
flag,
sizeof(block->
flag), 0xFF,
sizeof(block->
flag));
942 tempBuf += currentSize;
958#ifdef LOSCFG_FS_FAT_CACHE
965 PRINT_ERR(
"%s %d, mutex lock fail!\n", __FUNCTION__, __LINE__);
974 PRINT_ERR(
"%s %d, mutex unlock fail!\n", __FUNCTION__, __LINE__);
991#ifdef LOSCFG_FS_FAT_CACHE
999 PRINT_ERR(
"%s %d, mutex lock fail!\n", __FUNCTION__, __LINE__);
1008 PRINT_ERR(
"%s %d, mutex unlock fail!\n", __FUNCTION__, __LINE__);
1023#ifdef LOSCFG_FS_FAT_CACHE_SYNC_THREAD
1045 appTask.
pcName =
"bcache_sync_task";
1048 appTask.
uwResved = LOS_TASK_STATUS_DETACHED;
1050 if (ret != ENOERR) {
1051 PRINT_ERR(
"Bcache sync task create failed in %s, %d\n", __FUNCTION__, __LINE__);
1059 PRINT_ERR(
"Bcache sync task delete failed in %s, %d\n", __FUNCTION__, __LINE__);
1069 struct Vnode *blkDriver = devNode;
1070 UINT8 *bcacheMem = NULL;
1071 UINT8 *rwBuffer = NULL;
1072 UINT32 blockSize, memSize;
1074 if ((blkDriver == NULL) || (sectorSize * sectorPerBlock * blockNum == 0) || (blockCount == 0)) {
1078 blockSize = sectorSize * sectorPerBlock;
1082 memSize = ((
sizeof(
OsBcacheBlock) + blockSize) * blockNum) + DMA_ALLGN;
1085 if (bcache == NULL) {
1086 PRINT_ERR(
"bcache_init : malloc %u Bytes failed!\n",
sizeof(
OsBcache));
1091 if (bcacheMem == NULL) {
1092 PRINT_ERR(
"bcache_init : malloc %u Bytes failed!\n", memSize);
1093 goto ERROR_OUT_WITH_BCACHE;
1097 if (rwBuffer == NULL) {
1098 PRINT_ERR(
"bcache_init : malloc %u Bytes failed!\n", blockSize);
1099 goto ERROR_OUT_WITH_MEM;
1108 goto ERROR_OUT_WITH_BUFFER;
1113ERROR_OUT_WITH_BUFFER:
1117ERROR_OUT_WITH_BCACHE:
1124 if (bcache != NULL) {
1143 LOS_WAITMODE_OR | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER);
1144 if (ret != ASYNC_EVENT_BIT) {
1145 PRINT_ERR(
"The event read in %s, %d is error!!!\n", __FUNCTION__, __LINE__);
1149 for (i = 1; i <= PREREAD_BLOCK_NUM; i++) {
1156 if (ret != ENOERR) {
1157 PRINT_ERR(
"read block %llu error : %d!\n", bc->
curBlockNum, ret);
1163 if (block != NULL) {
1178 if (ret != ENOERR) {
1179 PRINT_ERR(
"Write event failed in %s, %d\n", __FUNCTION__, __LINE__);
1190 if (ret != ENOERR) {
1191 PRINT_ERR(
"Async event init failed in %s, %d\n", __FUNCTION__, __LINE__);
1198 appTask.
pcName =
"bcache_async_task";
1201 appTask.
uwResved = LOS_TASK_STATUS_DETACHED;
1203 if (ret != ENOERR) {
1204 PRINT_ERR(
"Bcache async task create failed in %s, %d\n", __FUNCTION__, __LINE__);
1216 if (ret != ENOERR) {
1217 PRINT_ERR(
"Bcache async task delete failed in %s, %d\n", __FUNCTION__, __LINE__);
1221 if (ret != ENOERR) {
1222 PRINT_ERR(
"Async event destroy failed in %s, %d\n", __FUNCTION__, __LINE__);
INT32 BlockCacheDrvCreate(VOID *handle, UINT8 *memStart, UINT32 memSize, UINT32 blockSize, OsBcache *bc)
初始化块设备
static UINT32 GetValLog2(UINT32 val)
static VOID BcacheSetFlag(const OsBcache *bc, OsBcacheBlock *block, UINT32 pos, UINT32 size)
static VOID MergeSyncBlocks(OsBcache *bc, OsBcacheBlock *start)
VOID ResumeAsyncPreread(OsBcache *arg1, const OsBcacheBlock *arg2)
OsBcache * BlockCacheInit(struct Vnode *devNode, UINT32 sectorSize, UINT32 sectorPerBlock, UINT32 blockNum, UINT64 blockCount)
static void DelBlock(OsBcache *bc, OsBcacheBlock *block)
volatile UINT32 g_hitTimes[CONFIG_FS_FAT_BLOCK_NUMS]
INT32 BlockCacheWrite(OsBcache *bc, const UINT8 *buf, UINT32 *len, UINT64 sector)
写块设备缓存
static UINT64 GetMinWriteNum(OsBcache *bc)
VOID LOS_SetSyncThreadInterval(UINT32 interval)
设置同步间隔,5秒
INT32 BcacheClearCache(OsBcache *bc)
static INT32 BcacheSyncBlock(OsBcache *bc, OsBcacheBlock *block)
volatile UINT8 * g_memStart
VOID BlockCacheDeinit(OsBcache *bcache)
static VOID ListMoveBlockToHead(OsBcache *bc, OsBcacheBlock *block)
删除红黑树块
INT32 LOS_SetSyncThreadPrio(UINT32 prio, const CHAR *name)
设置同步任务优先级,10
static OsBcacheBlock * GetBaseBlock(OsBcache *bc)
INT32 BlockCacheSync(OsBcache *bc)
块缓存同步
static VOID BlockInit(OsBcache *bc, OsBcacheBlock *block, UINT64 num)
volatile UINT32 g_dataSize
static INT32 BcacheInitCache(OsBcache *bc, UINT8 *memStart, UINT32 memSize, UINT32 blockSize)
块设备缓存初始化
INT32 BcacheGetDirtyRatio(INT32 id)
static OsBcacheBlock * AllocNewBlock(OsBcache *bc, BOOL read, UINT64 num)
VOID BcacheSyncThreadInit(OsBcache *bc, INT32 id)
块缓存同步任务初始化,开了个内核任务.
static VOID BcacheAsyncPrereadThread(VOID *arg)
INT32 LOS_GetDirtyRatioByName(const CHAR *name)
static VOID WriteMergedBlocks(OsBcache *bc, OsBcacheBlock *begin, int blocks)
INT32 BlockCacheRead(OsBcache *bc, UINT8 *buf, UINT32 *len, UINT64 sector, BOOL useRead)
读块设备缓存
static OsBcacheBlock * GetSlowBlock(OsBcache *bc, BOOL read)
static BOOL BlockAllDirty(const OsBcache *bc, OsBcacheBlock *block)
static INT32 DrvBwrite(struct Vnode *priv, const UINT8 *buf, UINT32 len, UINT64 pos)
写块设备数据
static void NumListAdd(OsBcache *bc, OsBcacheBlock *block)
volatile UINT32 g_blockNum
static VOID FreeBlock(OsBcache *bc, OsBcacheBlock *block)
释放块
volatile UINT32 g_switchTimes[CONFIG_FS_FAT_BLOCK_NUMS]
static INT32 BcacheSync(OsBcache *bc)
VOID BcacheAnalyse(UINT32 level)
static INT32 BlockRead(OsBcache *bc, OsBcacheBlock *block, UINT8 *buf)
static VOID RbAddBlock(OsBcache *bc, OsBcacheBlock *block)
添加缓存块
UINT32 BcacheAsyncPrereadInit(OsBcache *bc)
VOID BcacheSyncThreadDeinit(const OsBcache *bc)
static INT32 BcacheGetBlock(OsBcache *bc, UINT64 num, BOOL readData, OsBcacheBlock **dblock)
UINT32 BcacheAsyncPrereadDeinit(OsBcache *bc)
static INT32 BcacheGetFlag(OsBcache *bc, OsBcacheBlock *block)
VOID LOS_SetDirtyRatioThreshold(UINT32 dirtyRatio)
static void AddBlock(OsBcache *bc, OsBcacheBlock *block)
static INT32 FindFlagPos(const UINT32 *arr, UINT32 len, UINT32 *p1, UINT32 *p2)
static VOID RbDelBlock(OsBcache *bc, OsBcacheBlock *block)
删除红黑树块
static OsBcacheBlock * RbFindBlock(const OsBcache *bc, UINT64 num)
红黑树找块
static VOID BcacheSyncThread(UINT32 id)
INT32 LOS_BcacheSyncByName(const CHAR *name)
static INT32 DrvBread(struct Vnode *priv, UINT8 *buf, UINT32 len, UINT64 pos)
读块设备数据
UINT32 GetFatBlockNums(VOID)
los_disk * get_disk(INT32 id)
Find disk driver.
INT32 los_get_diskid_byname(const CHAR *diskName)
get the INUSED disk id.
LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventDestroy(PEVENT_CB_S eventCB)
销毁指定的事件控制块
LITE_OS_SEC_TEXT UINT32 LOS_EventRead(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout)
读取指定事件类型,超时时间为相对时间:单位为Tick
LITE_OS_SEC_TEXT UINT32 LOS_EventWrite(PEVENT_CB_S eventCB, UINT32 events)
写指定的事件类型
LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventInit(PEVENT_CB_S eventCB)
初始化一个事件控制块
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListInit(LOS_DL_LIST *list)
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListTailInsert(LOS_DL_LIST *list, LOS_DL_LIST *node)
Insert a node to the tail of a doubly linked list.
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelete(LOS_DL_LIST *node)
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListAdd(LOS_DL_LIST *list, LOS_DL_LIST *node)
Insert a new node to a doubly linked list.
LITE_OS_SEC_ALW_INLINE STATIC INLINE BOOL LOS_ListEmpty(LOS_DL_LIST *list)
Identify whether a specified doubly linked list is empty. | 判断链表是否为空
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskDelete(UINT32 taskID)
Delete a task.
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskPriSet(UINT32 taskID, UINT16 taskPrio)
设置指定任务的优先级
struct tagTskInitParam TSK_INIT_PARAM_S
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreate(UINT32 *taskID, TSK_INIT_PARAM_S *initParam)
创建任务,并使该任务进入ready状态,如果就绪队列中没有更高优先级的任务,则运行该任务
VOID *(* TSK_ENTRY_FUNC)(UINTPTR param1, UINTPTR param2, UINTPTR param3, UINTPTR param4)
Define the type of a task entrance function.
STATIC INLINE LosTaskCB * OsCurrTaskGet(VOID)
void * zalloc(size_t size)
void * memalign(size_t boundary, size_t size)
void free(void *ptr)
释放ptr所指向的内存空间
int pthread_mutex_lock(pthread_mutex_t *mutex)
互斥锁加锁操作
int pthread_mutex_destroy(pthread_mutex_t *mutex)
销毁互斥锁
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexAttr)
初始化互斥锁。 如果 mutexAttr 为 NULL,则使用默认属性。
int pthread_mutex_unlock(pthread_mutex_t *mutex)
解锁互斥锁
struct pthread_mutex disk_mutex
struct LOS_DL_LIST * pstPrev
struct LOS_DL_LIST * pstNext
UINT32 flag[BCACHE_BLOCK_FLAGS]
vnode并不包含文件名,因为 vnode和文件名是 1:N 的关系
pthread_mutex_t bcacheMutex
BcachePrereadFun prereadFun
TSK_ENTRY_FUNC pfnTaskEntry
ARG_NUM_3 ARG_NUM_1 ARG_NUM_2 ARG_NUM_2 ARG_NUM_3 ARG_NUM_1 ARG_NUM_4 ARG_NUM_2 ARG_NUM_2 ARG_NUM_5 ARG_NUM_2 void
INT32 LOS_CopyToKernel(VOID *dest, UINT32 max, const VOID *src, UINT32 count)
将用户空间的数据拷贝到内核空间
INT32 LOS_CopyFromKernel(VOID *dest, UINT32 max, const VOID *src, UINT32 count)
将内核数据拷贝到用户空间