comparison packages/fs/yaffs/current/src/yaffs_guts.c @ 353:fa7270d25c51

Merge from upstream
author Ross Younger <wry@ecoscentric.com>
date Tue, 17 Nov 2009 10:49:51 +0000
parents yaffs_guts.c@cc31d3d1ea89 yaffs_guts.c@1c56b1df53d8
children 68aafa1d2927
comparison
equal deleted inserted replaced
339:73b6efce8c58 353:fa7270d25c51
114 static __u32 yaffs_GetChunkGroupBase(yaffs_Device *dev, yaffs_Tnode *tn, 114 static __u32 yaffs_GetChunkGroupBase(yaffs_Device *dev, yaffs_Tnode *tn,
115 unsigned pos); 115 unsigned pos);
116 static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device *dev, 116 static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device *dev,
117 yaffs_FileStructure *fStruct, 117 yaffs_FileStructure *fStruct,
118 __u32 chunkId); 118 __u32 chunkId);
119
120 119
121 /* Function to calculate chunk and offset */ 120 /* Function to calculate chunk and offset */
122 121
123 static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, int *chunkOut, 122 static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, int *chunkOut,
124 __u32 *offsetOut) 123 __u32 *offsetOut)
1326 dev->nFreeTnodes = 0; 1325 dev->nFreeTnodes = 0;
1327 dev->nTnodesCreated = 0; 1326 dev->nTnodesCreated = 0;
1328 } 1327 }
1329 1328
1330 1329
1331 void yaffs_PutLevel0Tnode(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos, 1330 void yaffs_LoadLevel0Tnode(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos,
1332 unsigned val) 1331 unsigned val)
1333 { 1332 {
1334 __u32 *map = (__u32 *)tn; 1333 __u32 *map = (__u32 *)tn;
1335 __u32 bitInMap; 1334 __u32 bitInMap;
1336 __u32 bitInWord; 1335 __u32 bitInWord;
1484 tn = yaffs_GetTnode(dev); 1483 tn = yaffs_GetTnode(dev);
1485 1484
1486 if (tn) { 1485 if (tn) {
1487 tn->internal[0] = fStruct->top; 1486 tn->internal[0] = fStruct->top;
1488 fStruct->top = tn; 1487 fStruct->top = tn;
1488 fStruct->topLevel++;
1489 } else { 1489 } else {
1490 T(YAFFS_TRACE_ERROR, 1490 T(YAFFS_TRACE_ERROR,
1491 (TSTR("yaffs: no more tnodes" TENDSTR))); 1491 (TSTR("yaffs: no more tnodes" TENDSTR)));
1492 return NULL;
1492 } 1493 }
1493 } 1494 }
1494
1495 fStruct->topLevel = requiredTallness;
1496 } 1495 }
1497 1496
1498 /* Traverse down to level 0, adding anything we need */ 1497 /* Traverse down to level 0, adding anything we need */
1499 1498
1500 l = fStruct->topLevel; 1499 l = fStruct->topLevel;
1509 1508
1510 1509
1511 if ((l > 1) && !tn->internal[x]) { 1510 if ((l > 1) && !tn->internal[x]) {
1512 /* Add missing non-level-zero tnode */ 1511 /* Add missing non-level-zero tnode */
1513 tn->internal[x] = yaffs_GetTnode(dev); 1512 tn->internal[x] = yaffs_GetTnode(dev);
1513 if(!tn->internal[x])
1514 return NULL;
1514 1515
1515 } else if (l == 1) { 1516 } else if (l == 1) {
1516 /* Looking from level 1 at level 0 */ 1517 /* Looking from level 1 at level 0 */
1517 if (passedTn) { 1518 if (passedTn) {
1518 /* If we already have one, then release it.*/ 1519 /* If we already have one, then release it.*/
1521 tn->internal[x] = passedTn; 1522 tn->internal[x] = passedTn;
1522 1523
1523 } else if (!tn->internal[x]) { 1524 } else if (!tn->internal[x]) {
1524 /* Don't have one, none passed in */ 1525 /* Don't have one, none passed in */
1525 tn->internal[x] = yaffs_GetTnode(dev); 1526 tn->internal[x] = yaffs_GetTnode(dev);
1527 if(!tn->internal[x])
1528 return NULL;
1526 } 1529 }
1527 } 1530 }
1528 1531
1529 tn = tn->internal[x]; 1532 tn = tn->internal[x];
1530 l--; 1533 l--;
1644 hitLimit = 1; 1647 hitLimit = 1;
1645 } 1648 }
1646 1649
1647 } 1650 }
1648 1651
1649 yaffs_PutLevel0Tnode(dev, tn, i, 0); 1652 yaffs_LoadLevel0Tnode(dev, tn, i, 0);
1650 } 1653 }
1651 1654
1652 } 1655 }
1653 return (i < 0) ? 1 : 0; 1656 return (i < 0) ? 1 : 0;
1654 1657
1721 /* Note this does not find the real chunk, only the chunk group. 1724 /* Note this does not find the real chunk, only the chunk group.
1722 * We make an assumption that a chunk group is not larger than 1725 * We make an assumption that a chunk group is not larger than
1723 * a block. 1726 * a block.
1724 */ 1727 */
1725 yaffs_SoftDeleteChunk(dev, theChunk); 1728 yaffs_SoftDeleteChunk(dev, theChunk);
1726 yaffs_PutLevel0Tnode(dev, tn, i, 0); 1729 yaffs_LoadLevel0Tnode(dev, tn, i, 0);
1727 } 1730 }
1728 1731
1729 } 1732 }
1730 return 1; 1733 return 1;
1731 1734
2172 yaffs_Tnode *tn = NULL; 2175 yaffs_Tnode *tn = NULL;
2173 2176
2174 if (number < 0) 2177 if (number < 0)
2175 number = yaffs_CreateNewObjectNumber(dev); 2178 number = yaffs_CreateNewObjectNumber(dev);
2176 2179
2177 theObject = yaffs_AllocateEmptyObject(dev);
2178 if (!theObject)
2179 return NULL;
2180
2181 if (type == YAFFS_OBJECT_TYPE_FILE) { 2180 if (type == YAFFS_OBJECT_TYPE_FILE) {
2182 tn = yaffs_GetTnode(dev); 2181 tn = yaffs_GetTnode(dev);
2183 if (!tn) { 2182 if (!tn)
2184 yaffs_DoGenericObjectDeletion(theObject);
2185 return NULL; 2183 return NULL;
2186 } 2184 }
2187 } 2185
2186 theObject = yaffs_AllocateEmptyObject(dev);
2187 if (!theObject){
2188 if(tn)
2189 yaffs_FreeTnode(dev,tn);
2190 return NULL;
2191 }
2192
2188 2193
2189 if (theObject) { 2194 if (theObject) {
2190 theObject->fake = 0; 2195 theObject->fake = 0;
2191 theObject->renameAllowed = 1; 2196 theObject->renameAllowed = 1;
2192 theObject->unlinkAllowed = 1; 2197 theObject->unlinkAllowed = 1;
2285 2290
2286 /* Check if the entry exists. If it does then fail the call since we don't want a dup.*/ 2291 /* Check if the entry exists. If it does then fail the call since we don't want a dup.*/
2287 if (yaffs_FindObjectByName(parent, name)) 2292 if (yaffs_FindObjectByName(parent, name))
2288 return NULL; 2293 return NULL;
2289 2294
2290 in = yaffs_CreateNewObject(dev, -1, type);
2291
2292 if (!in)
2293 return YAFFS_FAIL;
2294
2295 if (type == YAFFS_OBJECT_TYPE_SYMLINK) { 2295 if (type == YAFFS_OBJECT_TYPE_SYMLINK) {
2296 str = yaffs_CloneString(aliasString); 2296 str = yaffs_CloneString(aliasString);
2297 if (!str) { 2297 if (!str)
2298 yaffs_DoGenericObjectDeletion(in);
2299 return NULL; 2298 return NULL;
2300 } 2299 }
2301 } 2300
2301 in = yaffs_CreateNewObject(dev, -1, type);
2302
2303 if (!in){
2304 if(str)
2305 YFREE(str);
2306 return NULL;
2307 }
2308
2302 2309
2303 2310
2304 2311
2305 if (in) { 2312 if (in) {
2306 in->hdrChunk = 0; 2313 in->hdrChunk = 0;
3359 yaffs_FindChunkInGroup(dev, theChunk, tags, in->objectId, 3366 yaffs_FindChunkInGroup(dev, theChunk, tags, in->objectId,
3360 chunkInInode); 3367 chunkInInode);
3361 3368
3362 /* Delete the entry in the filestructure (if found) */ 3369 /* Delete the entry in the filestructure (if found) */
3363 if (retVal != -1) 3370 if (retVal != -1)
3364 yaffs_PutLevel0Tnode(dev, tn, chunkInInode, 0); 3371 yaffs_LoadLevel0Tnode(dev, tn, chunkInInode, 0);
3365 } 3372 }
3366 3373
3367 return retVal; 3374 return retVal;
3368 } 3375 }
3369 3376
3429 int chunkInNAND, int inScan) 3436 int chunkInNAND, int inScan)
3430 { 3437 {
3431 /* NB inScan is zero unless scanning. 3438 /* NB inScan is zero unless scanning.
3432 * For forward scanning, inScan is > 0; 3439 * For forward scanning, inScan is > 0;
3433 * for backward scanning inScan is < 0 3440 * for backward scanning inScan is < 0
3441 *
3442 * chunkInNAND = 0 is a dummy insert to make sure the tnodes are there.
3434 */ 3443 */
3435 3444
3436 yaffs_Tnode *tn; 3445 yaffs_Tnode *tn;
3437 yaffs_Device *dev = in->myDev; 3446 yaffs_Device *dev = in->myDev;
3438 int existingChunk; 3447 int existingChunk;
3460 &in->variant.fileVariant, 3469 &in->variant.fileVariant,
3461 chunkInInode, 3470 chunkInInode,
3462 NULL); 3471 NULL);
3463 if (!tn) 3472 if (!tn)
3464 return YAFFS_FAIL; 3473 return YAFFS_FAIL;
3474
3475 if(!chunkInNAND)
3476 /* Dummy insert, bail now */
3477 return YAFFS_OK;
3478
3465 3479
3466 existingChunk = yaffs_GetChunkGroupBase(dev, tn, chunkInInode); 3480 existingChunk = yaffs_GetChunkGroupBase(dev, tn, chunkInInode);
3467 3481
3468 if (inScan != 0) { 3482 if (inScan != 0) {
3469 /* If we're scanning then we need to test for duplicates 3483 /* If we're scanning then we need to test for duplicates
3541 } 3555 }
3542 3556
3543 if (existingChunk == 0) 3557 if (existingChunk == 0)
3544 in->nDataChunks++; 3558 in->nDataChunks++;
3545 3559
3546 yaffs_PutLevel0Tnode(dev, tn, chunkInInode, chunkInNAND); 3560 yaffs_LoadLevel0Tnode(dev, tn, chunkInInode, chunkInNAND);
3547 3561
3548 return YAFFS_OK; 3562 return YAFFS_OK;
3549 } 3563 }
3550 3564
3551 static int yaffs_ReadChunkDataFromObject(yaffs_Object *in, int chunkInInode, 3565 static int yaffs_ReadChunkDataFromObject(yaffs_Object *in, int chunkInInode,
3664 T(YAFFS_TRACE_ERROR, 3678 T(YAFFS_TRACE_ERROR,
3665 (TSTR("Writing %d bytes to chunk!!!!!!!!!" TENDSTR), nBytes)); 3679 (TSTR("Writing %d bytes to chunk!!!!!!!!!" TENDSTR), nBytes));
3666 YBUG(); 3680 YBUG();
3667 } 3681 }
3668 3682
3683 /*
3684 * If there isn't already a chunk there then do a dummy
3685 * insert to make sue we have the desired tnode structure.
3686 */
3687 if(prevChunkId < 1 &&
3688 yaffs_PutChunkIntoFile(in, chunkInInode, 0, 0) != YAFFS_OK)
3689 return -1;
3690
3669 newChunkId = 3691 newChunkId =
3670 yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &newTags, 3692 yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &newTags,
3671 useReserve); 3693 useReserve);
3672 3694
3673 if (newChunkId >= 0) { 3695 if (newChunkId > 0) {
3674 yaffs_PutChunkIntoFile(in, chunkInInode, newChunkId, 0); 3696 yaffs_PutChunkIntoFile(in, chunkInInode, newChunkId, 0);
3675 3697
3676 if (prevChunkId > 0) 3698 if (prevChunkId > 0)
3677 yaffs_DeleteChunk(dev, prevChunkId, 1, __LINE__); 3699 yaffs_DeleteChunk(dev, prevChunkId, 1, __LINE__);
3678 3700
5486 yaffs_DeleteObject(l); 5508 yaffs_DeleteObject(l);
5487 } 5509 }
5488 } 5510 }
5489 5511
5490 } 5512 }
5491 #endif 5513
5492 5514 /*
5493 #ifndef CONFIG_YAFFS_NO_YAFFS1 5515 * This code iterates through all the objects making sure that they are rooted.
5516 * Any unrooted objects are re-rooted in lost+found.
5517 * An object needs to be in one of:
5518 * - Directly under deleted, unlinked
5519 * - Directly or indirectly under root.
5520 *
5521 * Note:
5522 * This code assumes that we don't ever change the current relationships between
5523 * directories:
5524 * rootDir->parent == unlinkedDir->parent == deletedDir->parent == NULL
5525 * lostNfound->parent == rootDir
5526 *
5527 * This fixes the problem where directories might have inadvertently been deleted
5528 * leaving the object "hanging" without being rooted in the directory tree.
5529 */
5530
5531 static int yaffs_HasNULLParent(yaffs_Device *dev, yaffs_Object *obj)
5532 {
5533 return (obj == dev->deletedDir ||
5534 obj == dev->unlinkedDir||
5535 obj == dev->rootDir);
5536 }
5537
5538 static void yaffs_FixHangingObjects(yaffs_Device *dev)
5539 {
5540 yaffs_Object *obj;
5541 yaffs_Object *parent;
5542 int i;
5543 struct ylist_head *lh;
5544 struct ylist_head *n;
5545 int depthLimit;
5546 int hanging;
5547
5548
5549 /* Iterate through the objects in each hash entry,
5550 * looking at each object.
5551 * Make sure it is rooted.
5552 */
5553
5554 for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
5555 ylist_for_each_safe(lh, n, &dev->objectBucket[i].list) {
5556 if (lh) {
5557 obj = ylist_entry(lh, yaffs_Object, hashLink);
5558 parent= obj->parent;
5559
5560 if(yaffs_HasNULLParent(dev,obj)){
5561 /* These directories are not hanging */
5562 hanging = 0;
5563 }
5564 else if(!parent || parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
5565 hanging = 1;
5566 else if(yaffs_HasNULLParent(dev,parent))
5567 hanging = 0;
5568 else {
5569 /*
5570 * Need to follow the parent chain to see if it is hanging.
5571 */
5572 hanging = 0;
5573 depthLimit=100;
5574
5575 while(parent != dev->rootDir &&
5576 parent->parent &&
5577 parent->parent->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&
5578 depthLimit > 0){
5579 parent = parent->parent;
5580 depthLimit--;
5581 }
5582 if(parent != dev->rootDir)
5583 hanging = 1;
5584 }
5585 if(hanging){
5586 T(YAFFS_TRACE_SCAN,
5587 (TSTR("Hanging object %d moved to lost and found" TENDSTR),
5588 obj->objectId));
5589 yaffs_AddObjectToDirectory(dev->lostNFoundDir,obj);
5590 }
5591 }
5592 }
5593 }
5594 }
5595
5596
5597 /*
5598 * Delete directory contents for cleaning up lost and found.
5599 */
5600 static void yaffs_DeleteDirectoryContents(yaffs_Object *dir)
5601 {
5602 yaffs_Object *obj;
5603 struct ylist_head *lh;
5604 struct ylist_head *n;
5605
5606 if(dir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
5607 YBUG();
5608
5609 ylist_for_each_safe(lh, n, &dir->variant.directoryVariant.children) {
5610 if (lh) {
5611 obj = ylist_entry(lh, yaffs_Object, siblings);
5612 if(obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)
5613 yaffs_DeleteDirectoryContents(obj);
5614
5615 T(YAFFS_TRACE_SCAN,
5616 (TSTR("Deleting lost_found object %d" TENDSTR),
5617 obj->objectId));
5618
5619 /* Need to use UnlinkObject since Delete would not handle
5620 * hardlinked objects correctly.
5621 */
5622 yaffs_UnlinkObject(obj);
5623 }
5624 }
5625
5626 }
5627
5628 static void yaffs_EmptyLostAndFound(yaffs_Device *dev)
5629 {
5630 yaffs_DeleteDirectoryContents(dev->lostNFoundDir);
5631 }
5632
5494 static int yaffs_Scan(yaffs_Device *dev) 5633 static int yaffs_Scan(yaffs_Device *dev)
5495 { 5634 {
5496 yaffs_ExtendedTags tags; 5635 yaffs_ExtendedTags tags;
5497 int blk; 5636 int blk;
5498 int blockIterator; 5637 int blockIterator;
7463 #else 7602 #else
7464 if (!yaffs_Scan(dev)) 7603 if (!yaffs_Scan(dev))
7465 init_failed = 1; 7604 init_failed = 1;
7466 7605
7467 yaffs_StripDeletedObjects(dev); 7606 yaffs_StripDeletedObjects(dev);
7607 yaffs_FixHangingObjects(dev);
7608 if(dev->emptyLostAndFound)
7609 yaffs_EmptyLostAndFound(dev);
7468 #endif 7610 #endif
7469 }
7470 } 7611 }
7471 7612
7472 if (init_failed) { 7613 if (init_failed) {
7473 /* Clean up the mess */ 7614 /* Clean up the mess */
7474 T(YAFFS_TRACE_TRACING, 7615 T(YAFFS_TRACE_TRACING,
7488 dev->nRetiredBlocks = 0; 7629 dev->nRetiredBlocks = 0;
7489 7630
7490 yaffs_VerifyFreeChunks(dev); 7631 yaffs_VerifyFreeChunks(dev);
7491 yaffs_VerifyBlocks(dev); 7632 yaffs_VerifyBlocks(dev);
7492 7633
7634 /* Clean up any aborted checkpoint data */
7635 if(!dev->isCheckpointed && dev->blocksInCheckpoint > 0)
7636 yaffs_InvalidateCheckpoint(dev);
7493 7637
7494 T(YAFFS_TRACE_TRACING, 7638 T(YAFFS_TRACE_TRACING,
7495 (TSTR("yaffs: yaffs_GutsInitialise() done.\n" TENDSTR))); 7639 (TSTR("yaffs: yaffs_GutsInitialise() done.\n" TENDSTR)));
7496 return YAFFS_OK; 7640 return YAFFS_OK;
7497 7641