00001
00006 #include "uffs/uffs_public.h"
00007 #include "uffs/uffs_os.h"
00008 #include "uffs/ubuffer.h"
00009 #include "uffs/uffs_config.h"
00010
00011 #include <string.h>
00012
00013 #define PFX "tree:"
00014
00015 static void uffs_InsertToFileEntry(uffs_Device *dev, TreeNode *node);
00016 static void uffs_InsertToDirEntry(uffs_Device *dev, TreeNode *node);
00017 static void uffs_InsertToDataEntry(uffs_Device *dev, TreeNode *node);
00018
00019
00024 URET uffs_InitTreeBuf(uffs_Device *dev)
00025 {
00026 int size;
00027 int nums;
00028 struct ubufm *dis;
00029 int i;
00030
00031 size = sizeof(TreeNode);
00032 nums = dev->par.end - dev->par.start + 1;
00033 dis = &(dev->tree.dis);
00034
00035 dis->node_size = size;
00036 dis->node_nums = nums;
00037 dis->node_pool = uffs_MemAlloc(dev, size * nums);
00038
00039 if(dis->node_pool == NULL) {
00040 uffs_Perror(UFFS_ERR_SERIOUS, PFX"fail to allocate memory for tree, %d*%d\n", size, nums);
00041 memset(dis, 0, sizeof(struct ubufm));
00042 return U_FAIL;
00043 }
00044
00045 uBufInit(dis);
00046 dev->tree.erased = NULL;
00047 dev->tree.erased_tail = NULL;
00048 dev->tree.erasedCount = 0;
00049 dev->tree.bad = NULL;
00050 dev->tree.badCount = 0;
00051
00052 for(i = 0; i < DIR_NODE_ENTRY_LEN; i++) {
00053 dev->tree.dirEntry[i] = EMPTY_NODE;
00054 }
00055
00056 for(i = 0; i < FILE_NODE_ENTRY_LEN; i++) {
00057 dev->tree.fileEntry[i] = EMPTY_NODE;
00058 }
00059
00060 for(i = 0; i < DATA_NODE_ENTRY_LEN; i++) {
00061 dev->tree.dataEntry[i] = EMPTY_NODE;
00062 }
00063
00064 dev->tree.maxSerialNo = ROOT_DIR_ID;
00065
00066 return U_SUCC;
00067 }
00072 URET uffs_ReleaseTreeBuf(uffs_Device *dev)
00073 {
00074 struct ubufm *dis;
00075
00076 dis = &(dev->tree.dis);
00077 if(dis->node_pool) {
00078 uffs_MemFree(dev, dis->node_pool);
00079 }
00080 memset(dis, 0, sizeof(struct ubufm));
00081
00082 return U_SUCC;
00083 }
00084
00085 static u16 _GetBlockFromNode(u8 type, TreeNode *node)
00086 {
00087 switch(type){
00088 case UFFS_TYPE_DIR:
00089 return node->u.dir.block;
00090 case UFFS_TYPE_FILE:
00091 return node->u.file.block;
00092 case UFFS_TYPE_DATA:
00093 return node->u.data.block;
00094 }
00095 uffs_Perror(UFFS_ERR_SERIOUS, PFX"unkown type, X-block\n");
00096 return UFFS_INVALID_BLOCK;
00097 }
00098
00099 static u16 _GetFatherFromNode(u8 type, TreeNode *node)
00100 {
00101 switch(type){
00102 case UFFS_TYPE_DIR:
00103 return node->u.dir.father;
00104 case UFFS_TYPE_FILE:
00105 return node->u.file.father;
00106 case UFFS_TYPE_DATA:
00107 return node->u.data.father;
00108 }
00109 uffs_Perror(UFFS_ERR_SERIOUS, PFX"unkown type, X-father\n");
00110 return UFFS_INVALID_SERIAL;
00111 }
00112
00113
00114 static u16 _GetSerialFromNode(u8 type, TreeNode *node)
00115 {
00116 switch(type){
00117 case UFFS_TYPE_DIR:
00118 return node->u.dir.serial;
00119 case UFFS_TYPE_FILE:
00120 return node->u.file.serial;
00121 case UFFS_TYPE_DATA:
00122 return node->u.data.serial;
00123 }
00124 uffs_Perror(UFFS_ERR_SERIOUS, PFX"unkown type, X-serial\n");
00125 return UFFS_INVALID_SERIAL;
00126 }
00127
00134 void uffs_InsertNodeToTree(uffs_Device *dev, u8 type, TreeNode *node)
00135 {
00136 switch(type){
00137 case UFFS_TYPE_DIR:
00138 uffs_InsertToDirEntry(dev, node);
00139 break;
00140 case UFFS_TYPE_FILE:
00141 uffs_InsertToFileEntry(dev, node);
00142 break;
00143 case UFFS_TYPE_DATA:
00144 uffs_InsertToDataEntry(dev, node);
00145 break;
00146 default:
00147 uffs_Perror(UFFS_ERR_SERIOUS, PFX"unkown type, can't insert to tree\n");
00148 break;
00149 }
00150 }
00151
00159 TreeNode * uffs_FindFromTree(uffs_Device *dev, u8 type, u16 father, u16 serial)
00160 {
00161 switch(type){
00162 case UFFS_TYPE_DIR:
00163 return uffs_FindDirNodeFromTree(dev, serial);
00164 case UFFS_TYPE_FILE:
00165 return uffs_FindFileNodeFromTree(dev, serial);
00166 case UFFS_TYPE_DATA:
00167 return uffs_FindDataNode(dev, father, serial);
00168 }
00169 uffs_Perror(UFFS_ERR_SERIOUS, PFX"unkown type, can't find node\n");
00170 return NULL;
00171 }
00172
00173 static URET _BuildValidTreeNode(uffs_Device *dev,
00174 TreeNode *node,
00175 uffs_blockInfo *bc)
00176 {
00177 uffs_Tags *tag;
00178 TreeNode *node_alt;
00179 u16 block, father, serial, block_alt, block_save;
00180 uffs_blockInfo *bc_alt;
00181 u8 type;
00182 UBOOL needToInsertToTree = U_FALSE;
00183 u16 page;
00184
00185 page = uffs_FindFirstValidPage(dev, bc);
00186 if(page == UFFS_INVALID_PAGE) {
00187
00188 uffs_Perror(UFFS_ERR_NORMAL, PFX"all pages in block %d are invalid, will be erased now!\n", bc->blockNum);
00189
00190 dev->ops->EraseBlock(dev, bc->blockNum);
00191 uffs_ExpireBlockInfo(dev, bc, UFFS_ALL_PAGES);
00192
00193
00194 uffs_InsertToErasedListTail(dev, node);
00195 return U_SUCC;
00196 }
00197
00198 page = uffs_FindBestPageInBlock(dev, bc, page);
00199 tag = &(bc->spares[page].tag);
00200 block = bc->blockNum;
00201 father = tag->father;
00202 serial = tag->serial;
00203 type = tag->type;
00204
00205
00206
00207
00208 node_alt = uffs_FindFromTree(dev, type, father, serial);
00209
00210 if(node_alt != NULL) {
00211
00212 block_alt = _GetBlockFromNode(type, node_alt);
00213 if(block_alt == INVALID_UFFS_SERIAL) {
00214 uffs_Perror(UFFS_ERR_SERIOUS, PFX"invalid block ?\n");
00215 return U_FAIL;
00216 }
00217
00218 bc_alt = uffs_GetBlockInfo(dev, block_alt);
00219 if(bc_alt == NULL) {
00220 uffs_Perror(UFFS_ERR_SERIOUS, PFX"can't get block info \n");
00221 return U_FAIL;
00222 }
00223 uffs_LoadBlockInfo(dev, bc_alt, 0);
00224 if(uffs_IsSrcNewerThanObj(
00225 tag->blockTimeStamp,
00226 bc_alt->spares[0].tag.blockTimeStamp) == U_TRUE) {
00227
00228
00229 dev->ops->EraseBlock(dev, block);
00230 uffs_ExpireBlockInfo(dev, bc, UFFS_ALL_PAGES);
00231 node->u.list.block = block;
00232 uffs_InsertToErasedListTail(dev, node);
00233 uffs_PutBlockInfo(dev, bc_alt);
00234
00235 return U_SUCC;
00236 }
00237 else {
00238
00239
00240
00241 block_save = _GetBlockFromNode(type, node_alt);
00242 dev->ops->EraseBlock(dev, block_save);
00243 uffs_ExpireBlockInfo(dev, bc_alt, UFFS_ALL_PAGES);
00244 node->u.list.block = block_save;
00245 uffs_InsertToErasedListTail(dev, node);
00246 uffs_PutBlockInfo(dev, bc_alt);
00247
00248 node = node_alt;
00249 needToInsertToTree = U_FALSE;
00250 }
00251 }
00252 else {
00253 needToInsertToTree = U_TRUE;
00254 }
00255
00256 switch(type) {
00257 case UFFS_TYPE_DIR:
00258 node->u.dir.block = bc->blockNum;
00259 node->u.dir.checkSum = tag->dataSum;
00260 node->u.dir.father = tag->father;
00261 node->u.dir.serial = tag->serial;
00262
00263
00264 break;
00265 case UFFS_TYPE_FILE:
00266 node->u.file.block = bc->blockNum;
00267 node->u.file.checkSum = tag->dataSum;
00268 node->u.file.father = tag->father;
00269 node->u.file.serial = tag->serial;
00270 node->u.file.len = uffs_GetBlockFileDataLength(dev, bc, UFFS_TYPE_FILE);
00271 break;
00272 case UFFS_TYPE_DATA:
00273 node->u.data.block = bc->blockNum;
00274 node->u.data.father = tag->father;
00275 node->u.data.serial = tag->serial;
00276 if(tag->serial == 1) {
00277 tag->serial = tag->serial;
00278 }
00279 node->u.data.len = uffs_GetBlockFileDataLength(dev, bc, UFFS_TYPE_DATA);
00280 break;
00281 }
00282
00283 if(needToInsertToTree == U_TRUE) {
00284 uffs_InsertNodeToTree(dev, type, node);
00285 }
00286
00287 return U_SUCC;
00288 }
00289
00290 static URET _BuildTreeStepOne(uffs_Device *dev)
00291 {
00292 int block_lt;
00293 uffs_blockInfo *bc;
00294 TreeNode *node;
00295 struct uffs_treeSt *tree;
00296 struct ubufm *dis;
00297 URET ret = U_SUCC;
00298
00299 tree = &(dev->tree);
00300 dis = &(tree->dis);
00301
00302 tree->bad = NULL;
00303 tree->badCount = 0;
00304 tree->erased = NULL;
00305 tree->erased_tail = NULL;
00306 tree->erasedCount = 0;
00307
00308 uffs_Perror(UFFS_ERR_NOISY, PFX"build tree step one\n");
00309
00310
00311 for(block_lt = dev->par.start; block_lt <= dev->par.end; block_lt++) {
00312 bc = uffs_GetBlockInfo(dev, block_lt);
00313
00314 if(bc == NULL) {
00315 uffs_Perror(UFFS_ERR_SERIOUS, PFX"step one:fail to get block info\n");
00316 ret = U_FAIL;
00317 break;
00318 }
00319 node = (TreeNode *)uBufGet(dis);
00320 if(node == NULL) {
00321 uffs_Perror(UFFS_ERR_SERIOUS, PFX"insufficient tree node!\n");
00322 ret = U_FAIL;
00323 break;
00324 }
00325
00326 if(dev->flash->IsBlockBad(dev, bc) == U_TRUE) {
00327 node->u.list.block = block_lt;
00328 uffs_InsertToBadBlockList(dev, node);
00329 }
00330 else if(uffs_IsPageErased(dev, bc, 0) == U_TRUE) {
00331
00332 node->u.list.block = block_lt;
00333 uffs_InsertToErasedListTail(dev, node);
00334 }
00335 else {
00336
00337 ret = _BuildValidTreeNode(dev, node, bc);
00338
00339 if(ret == U_FAIL) break;
00340 }
00341 uffs_PutBlockInfo(dev, bc);
00342 }
00343
00344 if(ret == U_FAIL) uffs_PutBlockInfo(dev, bc);
00345
00346 return ret;
00347 }
00348
00349 static URET _BuildTreeStepTwo(uffs_Device *dev)
00350 {
00351
00352 u32 startCount = 0;
00353 u32 endPoint;
00354 TreeNode *node;
00355
00356 uffs_Perror(UFFS_ERR_NOISY, PFX"build tree step two\n");
00357
00358 endPoint = uffs_GetCurDateTime() % dev->tree.erasedCount;
00359 while(startCount < endPoint) {
00360 node = uffs_GetErased(dev);
00361 if(node == NULL) {
00362 uffs_Perror(UFFS_ERR_SERIOUS, PFX"No erased block ?\n");
00363 return U_FAIL;
00364 }
00365 uffs_InsertToErasedListTail(dev, node);
00366 startCount++;
00367 }
00368 return U_SUCC;
00369 }
00370
00371 TreeNode * uffs_FindFileNodeFromTree(uffs_Device *dev, u16 serial)
00372 {
00373 int hash;
00374 u16 x;
00375 TreeNode *node;
00376 struct uffs_treeSt *tree = &(dev->tree);
00377
00378 hash = serial & FILE_NODE_HASH_MASK;
00379 x = tree->fileEntry[hash];
00380 while(x != EMPTY_NODE) {
00381 node = FROM_IDX(x, &(tree->dis));
00382 if(node->u.file.serial == serial) {
00383 return node;
00384 }
00385 else {
00386 x = node->hashNext;
00387 }
00388 }
00389 return NULL;
00390 }
00391
00392 TreeNode * uffs_FindFileNodeFromTreeWithFather(uffs_Device *dev, u16 father)
00393 {
00394 int hash;
00395 u16 x;
00396 TreeNode *node;
00397 struct uffs_treeSt *tree = &(dev->tree);
00398
00399 for (hash = 0; hash < FILE_NODE_ENTRY_LEN; hash++) {
00400 x = tree->fileEntry[hash];
00401 while(x != EMPTY_NODE) {
00402 node = FROM_IDX(x, &(tree->dis));
00403 if(node->u.file.father == father) {
00404 return node;
00405 }
00406 else {
00407 x = node->hashNext;
00408 }
00409 }
00410 }
00411 return NULL;
00412 }
00413
00414 TreeNode * uffs_FindDirNodeFromTree(uffs_Device *dev, u16 serial)
00415 {
00416 int hash;
00417 u16 x;
00418 TreeNode *node;
00419 struct uffs_treeSt *tree = &(dev->tree);
00420
00421 hash = serial & DIR_NODE_HASH_MASK;
00422 x = tree->dirEntry[hash];
00423 while(x != EMPTY_NODE) {
00424 node = FROM_IDX(x, &(tree->dis));
00425 if(node->u.dir.serial == serial) {
00426 return node;
00427 }
00428 else {
00429 x = node->hashNext;
00430 }
00431 }
00432 return NULL;
00433 }
00434
00435 TreeNode * uffs_FindDirNodeFromTreeWithFather(uffs_Device *dev, u16 father)
00436 {
00437 int hash;
00438 u16 x;
00439 TreeNode *node;
00440 struct uffs_treeSt *tree = &(dev->tree);
00441
00442 for (hash = 0; hash < DIR_NODE_ENTRY_LEN; hash++) {
00443 x = tree->dirEntry[hash];
00444 while(x != EMPTY_NODE) {
00445 node = FROM_IDX(x, &(tree->dis));
00446 if(node->u.dir.father == father) {
00447 return node;
00448 }
00449 else {
00450 x = node->hashNext;
00451 }
00452 }
00453 }
00454
00455 return NULL;
00456 }
00457
00458 TreeNode * uffs_FindFileNodeByName(uffs_Device *dev, const char *name, u32 len, u16 sum, u16 father)
00459 {
00460 int i;
00461 u16 x;
00462 TreeNode *node;
00463 struct uffs_treeSt *tree = &(dev->tree);
00464
00465 for(i = 0; i < FILE_NODE_ENTRY_LEN; i++) {
00466 x = tree->fileEntry[i];
00467 while(x != EMPTY_NODE) {
00468 node = FROM_IDX(x, &(tree->dis));
00469 if(node->u.file.checkSum == sum && node->u.file.father == father) {
00470
00471 if(uffs_CompareFileNameWithTreeNode(dev, name, len, sum, node, UFFS_TYPE_FILE) == U_TRUE) {
00472
00473 return node;
00474 }
00475 }
00476 x = node->hashNext;
00477 }
00478 }
00479 return NULL;
00480 }
00481
00482 TreeNode * uffs_FindDataNode(uffs_Device *dev, u16 father, u16 serial)
00483 {
00484 int hash;
00485 TreeNode *node;
00486 struct uffs_treeSt *tree = &(dev->tree);
00487 u16 x;
00488
00489 hash = GET_DATA_HASH(father, serial);
00490 x = tree->dataEntry[hash];
00491 while(x != EMPTY_NODE) {
00492 node = FROM_IDX(x, &(tree->dis));
00493
00494 if(node->u.data.father == father &&
00495 node->u.data.serial == serial)
00496 return node;
00497
00498 x = node->hashNext;
00499 }
00500 return NULL;
00501 }
00502
00503 TreeNode * uffs_FindDirNodeByBlock(uffs_Device *dev, u16 block)
00504 {
00505 int hash;
00506 TreeNode *node;
00507 struct uffs_treeSt *tree = &(dev->tree);
00508 u16 x;
00509
00510 for(hash = 0; hash < DIR_NODE_ENTRY_LEN; hash++) {
00511 x = tree->dirEntry[hash];
00512 while(x != EMPTY_NODE) {
00513 node = FROM_IDX(x, &(tree->dis));
00514 if(node->u.dir.block == block)
00515 return node;
00516 x = node->hashNext;
00517 }
00518 }
00519 return NULL;
00520 }
00521
00522 TreeNode * uffs_FindErasedNodeByBlock(uffs_Device *dev, u16 block)
00523 {
00524 TreeNode *node;
00525 node = dev->tree.erased;
00526 while(node) {
00527 if(node->u.list.block == block) return node;
00528 node = node->u.list.next;
00529 }
00530
00531 return NULL;
00532 }
00533
00534 TreeNode * uffs_FindBadNodeByBlock(uffs_Device *dev, u16 block)
00535 {
00536 TreeNode *node;
00537 node = dev->tree.bad;
00538 while(node) {
00539 if(node->u.list.block == block) return node;
00540 node = node->u.list.next;
00541 }
00542
00543 return NULL;
00544 }
00545
00546 TreeNode * uffs_FindFileNodeByBlock(uffs_Device *dev, u16 block)
00547 {
00548 int hash;
00549 TreeNode *node;
00550 struct uffs_treeSt *tree = &(dev->tree);
00551 u16 x;
00552
00553 for(hash = 0; hash < FILE_NODE_ENTRY_LEN; hash++) {
00554 x = tree->fileEntry[hash];
00555 while(x != EMPTY_NODE) {
00556 node = FROM_IDX(x, &(tree->dis));
00557 if(node->u.file.block == block)
00558 return node;
00559 x = node->hashNext;
00560 }
00561 }
00562 return NULL;
00563 }
00564
00565 TreeNode * uffs_FindDataNodeByBlock(uffs_Device *dev, u16 block)
00566 {
00567 int hash;
00568 TreeNode *node;
00569 struct uffs_treeSt *tree = &(dev->tree);
00570 u16 x;
00571
00572 for(hash = 0; hash < DATA_NODE_ENTRY_LEN; hash++) {
00573 x = tree->dataEntry[hash];
00574 while(x != EMPTY_NODE) {
00575 node = FROM_IDX(x, &(tree->dis));
00576 if(node->u.data.block == block)
00577 return node;
00578 x = node->hashNext;
00579 }
00580 }
00581 return NULL;
00582 }
00583
00584 TreeNode * uffs_FindNodeByBlock(uffs_Device *dev, u16 block, int *region)
00585 {
00586 TreeNode *node = NULL;
00587 if(*region & SEARCH_REGION_DATA) {
00588 node = uffs_FindDataNodeByBlock(dev, block);
00589 if(node) {
00590 *region &= SEARCH_REGION_DATA;
00591 return node;
00592 }
00593 }
00594 if(*region & SEARCH_REGION_FILE) {
00595 node = uffs_FindFileNodeByBlock(dev, block);
00596 if(node) {
00597 *region &= SEARCH_REGION_FILE;
00598 return node;
00599 }
00600 }
00601 if(*region & SEARCH_REGION_DIR) {
00602 node = uffs_FindDirNodeByBlock(dev, block);
00603 if(node) {
00604 *region &= SEARCH_REGION_DIR;
00605 return node;
00606 }
00607 }
00608 if(*region & SEARCH_REGION_ERASED) {
00609 node = uffs_FindErasedNodeByBlock(dev, block);
00610 if(node) {
00611 *region &= SEARCH_REGION_ERASED;
00612 return node;
00613 }
00614 }
00615 if(*region & SEARCH_REGION_BAD) {
00616 node = uffs_FindBadNodeByBlock(dev, block);
00617 if(node) {
00618 *region &= SEARCH_REGION_BAD;
00619 return node;
00620 }
00621 }
00622 return node;
00623 }
00624
00625 TreeNode * uffs_FindDirNodeByName(uffs_Device *dev, const char *name, u32 len, u16 sum, u16 father)
00626 {
00627 int i;
00628 u16 x;
00629 TreeNode *node;
00630 struct uffs_treeSt *tree = &(dev->tree);
00631
00632 for(i = 0; i < DIR_NODE_ENTRY_LEN; i++) {
00633 x = tree->dirEntry[i];
00634 while(x != EMPTY_NODE) {
00635 node = FROM_IDX(x, &(tree->dis));
00636 if(node->u.dir.checkSum == sum && node->u.dir.father == father) {
00637
00638 if(uffs_CompareFileNameWithTreeNode(dev, name, len, sum, node, UFFS_TYPE_DIR) == U_TRUE) {
00639
00640 return node;
00641 }
00642 }
00643 x = node->hashNext;
00644 }
00645 }
00646 return NULL;
00647
00648 }
00649
00650 UBOOL uffs_CompareFileName(const char *src, int src_len, const char *des)
00651 {
00652 while(src_len-- > 0) {
00653 if(*src++ != *des++) return U_FALSE;
00654 }
00655 return U_TRUE;
00656 }
00657
00658 UBOOL uffs_CompareFileNameWithTreeNode(uffs_Device *dev, const char *name, u32 len, u16 sum, TreeNode *node, int type)
00659 {
00660 u16 page;
00661 uffs_blockInfo *bc;
00662 uffs_Tags *tag;
00663 URET ret = U_FAIL;
00664 uffs_fileInfo fi;
00665 u16 block;
00666
00667 if (type == UFFS_TYPE_DIR)
00668 block = node->u.dir.block;
00669 else
00670 block = node->u.file.block;
00671
00672 bc = uffs_GetBlockInfo(dev, block);
00673
00674 if(bc == NULL) {
00675 uffs_Perror(UFFS_ERR_SERIOUS, PFX"can't get block info %d\n", block);
00676 return U_FALSE;
00677 }
00678
00679
00680 uffs_LoadBlockInfo(dev, bc, UFFS_ALL_PAGES);
00681 page = uffs_FindBestPageInBlock(dev, bc, 0);
00682
00683 tag = &(bc->spares[page].tag);
00684 if(tag->dataSum != sum) {
00685 uffs_Perror(UFFS_ERR_NORMAL, PFX"the obj's sum in tag is different with given sum!\n");
00686 uffs_PutBlockInfo(dev, bc);
00687 return U_FALSE;
00688 }
00689
00690 ret = dev->ops->ReadPageData(dev, block, page, (u8 *)(&fi), 0, sizeof(uffs_fileInfo));
00691 if(ret == U_FAIL) {
00692 uffs_PutBlockInfo(dev, bc);
00693 uffs_Perror(UFFS_ERR_SERIOUS, PFX"I/O error ?\n");
00694 return U_FALSE;
00695 }
00696
00697 if(fi.name_len == len) {
00698 if(uffs_CompareFileName(fi.name, fi.name_len, name) == U_TRUE) {
00699 uffs_PutBlockInfo(dev, bc);
00700 return U_TRUE;
00701 }
00702 }
00703
00704 uffs_PutBlockInfo(dev, bc);
00705 return U_FALSE;
00706 }
00707
00708
00709
00710 static URET _BuildTreeStepThree(uffs_Device *dev)
00711 {
00712 int i;
00713 u16 x;
00714 TreeNode *work;
00715 TreeNode *node;
00716 struct uffs_treeSt *tree;
00717 struct ubufm *dis;
00718 u16 blockSave;
00719
00720 TreeNode *cache = NULL;
00721 u16 cacheSerial = INVALID_UFFS_SERIAL;
00722
00723
00724
00725
00726
00727 tree = &(dev->tree);
00728 dis = &(tree->dis);
00729
00730 uffs_Perror(UFFS_ERR_NOISY, PFX"build tree step three\n");
00731
00732 for(i = 0; i < DATA_NODE_ENTRY_LEN; i++) {
00733 x = tree->dataEntry[i];
00734 while(x != EMPTY_NODE) {
00735 work = FROM_IDX(x, dis);
00736 if(work->u.data.father == cacheSerial) {
00737 node = cache;
00738 }
00739 else {
00740 node = uffs_FindFileNodeFromTree(dev, work->u.data.father);
00741 cache = node;
00742 cacheSerial = work->u.data.father;
00743 }
00744 if(node == NULL) {
00745 x = work->hashNext;
00746
00747
00748 uffs_Perror(UFFS_ERR_NORMAL, PFX"find a orphan data block:%d, father:%d, serial:%d, will be erased!\n",
00749 work->u.data.block, work->u.data.father, work->u.data.serial);
00750 uffs_BreakFromEntry(dev, UFFS_TYPE_DATA, work);
00751 blockSave = work->u.data.block;
00752 work->u.list.block = blockSave;
00753 dev->ops->EraseBlock(dev, blockSave);
00754 uffs_InsertToErasedListTail(dev, work);
00755 }
00756 else {
00757 node->u.file.len += work->u.data.len;
00758 x = work->hashNext;
00759 }
00760 }
00761 }
00762
00763 return U_SUCC;
00764 }
00765
00770 URET uffs_BuildTree(uffs_Device *dev)
00771 {
00772 URET ret;
00773
00774
00775
00776
00777 ret = _BuildTreeStepOne(dev);
00778 if(ret != U_SUCC) {
00779 uffs_Perror(UFFS_ERR_SERIOUS, PFX"build tree step one fail!\n");
00780 return ret;
00781 }
00782
00783
00784
00785 ret = _BuildTreeStepTwo(dev);
00786 if(ret != U_SUCC) {
00787 uffs_Perror(UFFS_ERR_SERIOUS, PFX"build tree step two fail!\n");
00788 return ret;
00789 }
00790
00791
00792
00793 ret = _BuildTreeStepThree(dev);
00794 if(ret != U_SUCC) {
00795 uffs_Perror(UFFS_ERR_SERIOUS, PFX"build tree step three fail!\n");
00796 return ret;
00797 }
00798
00799 return U_SUCC;
00800 }
00801
00807 u16 uffs_FindFreeFsnSerial(uffs_Device *dev)
00808 {
00809 u16 i;
00810 TreeNode *node;
00811
00812
00813
00814
00815 for(i = ROOT_DIR_ID + 1; i < MAX_UFFS_SERIAL; i++) {
00816 node = uffs_FindDirNodeFromTree(dev, i);
00817 if(node == NULL) {
00818 node = uffs_FindFileNodeFromTree(dev, i);
00819 if(node == NULL) return i;
00820 }
00821 }
00822 return INVALID_UFFS_SERIAL;
00823 }
00824
00825 TreeNode * uffs_GetErased(uffs_Device *dev)
00826 {
00827 TreeNode *node = NULL;
00828 if(dev->tree.erased) {
00829 node = dev->tree.erased;
00830 dev->tree.erased->u.list.prev = NULL;
00831 dev->tree.erased = dev->tree.erased->u.list.next;
00832 if(dev->tree.erased == NULL) dev->tree.erased_tail = NULL;
00833 }
00834 dev->tree.erasedCount--;
00835
00836 return node;
00837 }
00838
00839 static void _InsertToEntry(uffs_Device *dev, u16 *entry, int hash, TreeNode *node)
00840 {
00841 struct uffs_treeSt *tree = &(dev->tree);
00842
00843 node->hashNext = entry[hash];
00844 #ifdef TREE_NODE_USE_DOUBLE_LINK
00845 node->hashPrev = EMPTY_NODE;
00846 if(entry[hash] != EMPTY_NODE) {
00847 FROM_IDX(entry[hash], &(tree->dis))->hashPrev = TO_IDX(node, &(tree->dis));
00848 }
00849 #endif
00850 entry[hash] = TO_IDX(node, &(tree->dis));
00851 }
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872 #ifndef TREE_NODE_USE_DOUBLE_LINK
00873 TreeNode * _FindPrevNodeFromEntry(uffs_Device *dev, u16 start, u16 find)
00874 {
00875 TreeNode *work;
00876 while (start != EMPTY_NODE) {
00877 work = FROM_IDX(start, &(dev->tree.dis));
00878 if (work->hashNext == find) {
00879 return work;
00880 }
00881 }
00882 return NULL;
00883 }
00884 #endif
00885
00889 void uffs_BreakFromEntry(uffs_Device *dev, u8 type, TreeNode *node)
00890 {
00891 u16 *entry;
00892 int hash;
00893 TreeNode *work;
00894
00895 switch(type) {
00896 case UFFS_TYPE_DIR:
00897 hash = GET_DIR_HASH(node->u.dir.serial);
00898 entry = &(dev->tree.dirEntry[hash]);
00899 break;
00900 case UFFS_TYPE_FILE:
00901 hash = GET_FILE_HASH(node->u.file.serial);
00902 entry = &(dev->tree.fileEntry[hash]);
00903 break;
00904 case UFFS_TYPE_DATA:
00905 hash = GET_DATA_HASH(node->u.data.father, node->u.data.serial);
00906 entry = &(dev->tree.dataEntry[hash]);
00907 break;
00908 default:
00909 uffs_Perror(UFFS_ERR_SERIOUS, PFX"unknown type when break...\n");
00910 return;
00911 }
00912 #ifdef TREE_NODE_USE_DOUBLE_LINK
00913 if(node->hashPrev != EMPTY_NODE) {
00914 work = FROM_IDX(node->hashPrev, &(dev->tree.dis));
00915 work->hashNext = node->hashNext;
00916 }
00917 if(node->hashNext != EMPTY_NODE) {
00918 work = FROM_IDX(node->hashNext, &(dev->tree.dis));
00919 work->hashPrev = node->hashPrev;
00920 }
00921 #else
00922 if ((work = _FindPrevNodeFromEntry(dev, *entry, TO_IDX(node, &(dev->tree.dis)))) != NULL) {
00923 work->hashNext = node->hashNext;
00924 }
00925 #endif
00926
00927 if(*entry == TO_IDX(node, &(dev->tree.dis))) {
00928 *entry = node->hashNext;
00929 }
00930 }
00931
00932 static void uffs_InsertToFileEntry(uffs_Device *dev, TreeNode *node)
00933 {
00934 _InsertToEntry(dev, dev->tree.fileEntry, GET_FILE_HASH(node->u.file.serial), node);
00935 }
00936
00937 static void uffs_InsertToDirEntry(uffs_Device *dev, TreeNode *node)
00938 {
00939 _InsertToEntry(dev, dev->tree.dirEntry, GET_DIR_HASH(node->u.dir.serial), node);
00940 }
00941
00942 static void uffs_InsertToDataEntry(uffs_Device *dev, TreeNode *node)
00943 {
00944 _InsertToEntry(dev, dev->tree.dataEntry, GET_DATA_HASH(node->u.data.father, node->u.data.serial), node);
00945 }
00946
00947 void uffs_InsertToErasedListHead(uffs_Device *dev, TreeNode *node)
00948 {
00949 struct uffs_treeSt *tree;
00950 tree = &(dev->tree);
00951
00952 node->u.list.next = tree->erased;
00953 node->u.list.prev = NULL;
00954 if(tree->erased) {
00955 tree->erased->u.list.prev = node;
00956 }
00957
00958 tree->erased = node;
00959 if(node->u.list.next == tree->erased_tail) {
00960 tree->erased_tail = node;
00961 }
00962 tree->erasedCount++;
00963 }
00964
00965 void uffs_InsertToErasedListTail(uffs_Device *dev, TreeNode *node)
00966 {
00967 struct uffs_treeSt *tree;
00968 tree = &(dev->tree);
00969
00970 node->u.list.next = NULL;
00971 node->u.list.prev = tree->erased_tail;
00972 if(tree->erased_tail) {
00973 tree->erased_tail->u.list.next = node;
00974 }
00975
00976 tree->erased_tail = node;
00977 if(tree->erased == NULL) {
00978 tree->erased = node;
00979 }
00980 tree->erasedCount++;
00981 }
00982
00983 void uffs_InsertToBadBlockList(uffs_Device *dev, TreeNode *node)
00984 {
00985 struct uffs_treeSt *tree;
00986 tree = &(dev->tree);
00987 node->u.list.prev = NULL;
00988 node->u.list.next = tree->bad;
00989 if(tree->bad) {
00990 tree->bad->u.list.prev = node;
00991 }
00992 tree->bad = node;
00993 tree->badCount++;
00994 }
00995
00999 void uffs_SetTreeNodeBlock(u8 type, TreeNode *node, u16 block)
01000 {
01001 switch(type) {
01002 case UFFS_TYPE_FILE:
01003 node->u.file.block = block;
01004 break;
01005 case UFFS_TYPE_DIR:
01006 node->u.dir.block = block;
01007 break;
01008 case UFFS_TYPE_DATA:
01009 node->u.data.block = block;
01010 break;
01011 }
01012 }
01013