-
- // For each block.... backwards
- for(blockIterator = endIterator; blockIterator >= startIterator; blockIterator--)
- {
-
- // get the block to scan in the correct order
- blk = blockIndex[blockIterator].block;
-
-
- bi = yaffs_GetBlockInfo(dev,blk);
- state = bi->blockState;
-
- deleted = 0;
-
- if( 0 && // Disable since this is redundant.
- state == YAFFS_BLOCK_STATE_NEEDS_SCANNING)
- {
- // Let's look at the first chunk in the block
- chunk = blk * dev->nChunksPerBlock;
-
- yaffs_ReadChunkWithTagsFromNAND(dev,chunk,NULL,&tags);
-
- // Let's have a good look at this chunk...
-
- if(!tags.chunkUsed)
- {
- // An unassigned chunk in the block
- // This means that either the block is empty or
- // this is the one being allocated from
-
- // We're looking at the first chunk in the block so the block is unused
- state = YAFFS_BLOCK_STATE_EMPTY;
- dev->nErasedBlocks++;
- dev->nFreeChunks += dev->nChunksPerBlock;
- }
-
- }
-
- // For each chunk in each block that needs scanning....
- for(c = dev->nChunksPerBlock-1; c >= 0 &&
- (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING ||
- state == YAFFS_BLOCK_STATE_ALLOCATING); c--)
- {
- // Scan backwards...
- // Read the tags and decide what to do
- chunk = blk * dev->nChunksPerBlock + c;
-
- yaffs_ReadChunkWithTagsFromNAND(dev,chunk,NULL,&tags);
-
- // Let's have a good look at this chunk...
-
- if(!tags.chunkUsed)
- {
- // An unassigned chunk in the block
- // This means that either the block is empty or
- // this is the one being allocated from
-
- if(c == 0)
- {
- // We're looking at the first chunk in the block so the block is unused
- state = YAFFS_BLOCK_STATE_EMPTY;
- dev->nErasedBlocks++;
- }
- else
- {
- // this is the block being allocated from
- if(state == YAFFS_BLOCK_STATE_NEEDS_SCANNING)
- {
- T(YAFFS_TRACE_SCAN,(TSTR(" Allocating from %d %d" TENDSTR),blk,c));
- }
- state = YAFFS_BLOCK_STATE_ALLOCATING;
- dev->allocationBlock = blk;
- dev->allocationPage = c;
- dev->allocationBlockFinder = blk; // Set it to here to encourage the allocator to
- // go forth from here.
- //Yaffs2 sanity check:
- // This should be the one with the highest sequence number
- if(dev->isYaffs2 && (dev->sequenceNumber != bi->sequenceNumber))
- {
- T(YAFFS_TRACE_ALWAYS,
- (TSTR("yaffs: Allocation block %d was not highest sequence id: block seq = %d, dev seq = %d" TENDSTR),
- blk,bi->sequenceNumber,dev->sequenceNumber));
- }
- }
-
- dev->nFreeChunks ++;
- }
- else if(tags.chunkId > 0)
- {
- // chunkId > 0 so it is a data chunk...
- unsigned int endpos;
-
- __u32 chunkBase = (tags.chunkId - 1)* dev->nBytesPerChunk;
-
- yaffs_SetChunkBit(dev,blk,c);
- bi->pagesInUse++;
-
- in = yaffs_FindOrCreateObjectByNumber(dev,tags.objectId,YAFFS_OBJECT_TYPE_FILE);
- if(in->variantType == YAFFS_OBJECT_TYPE_FILE &&
- chunkBase < in->variant.fileVariant.shrinkSize)
- {
- // This has not been invalidated by a resize
- yaffs_PutChunkIntoFile(in,tags.chunkId,chunk,-1);
-
-
- // File size is calculated by looking at the data chunks if we have not
- // seen an object header yet. Stop this practice once we find an object header.
- endpos = (tags.chunkId - 1)* dev->nBytesPerChunk + tags.byteCount;
- if(!in->valid && // have not got an object header yet
- in->variant.fileVariant.scannedFileSize <endpos)
- {
- in->variant.fileVariant.scannedFileSize = endpos;
- in->variant.fileVariant.fileSize = in->variant.fileVariant.scannedFileSize;
- }
-
- }
- else
- {
- // This chunk has been invalidated by a resize, so delete
- yaffs_DeleteChunk(dev,chunk,1,__LINE__);
-
-
- }
- //T((" %d %d data %d %d\n",blk,c,tags.objectId,tags.chunkId));
- }
- else
- {
- // chunkId == 0, so it is an ObjectHeader.
- // Thus, we read in the object header and make the object
- yaffs_SetChunkBit(dev,blk,c);
- bi->pagesInUse++;
-
- oh = NULL;
- in = NULL;
-
- if(tags.extraHeaderInfoAvailable)
- {
- in = yaffs_FindOrCreateObjectByNumber(dev,tags.objectId,tags.extraObjectType);
- }
-
-
- if(!in || !in->valid)
- {
-
- // If we don't have valid info then we need to read the chunk
- // TODO In future we can probably defer reading the chunk and
- // living with invalid data until needed.
-
- yaffs_ReadChunkWithTagsFromNAND(dev,chunk,chunkData,NULL);
-
- oh = (yaffs_ObjectHeader *)chunkData;
-
- if(!in)
- in = yaffs_FindOrCreateObjectByNumber(dev,tags.objectId,oh->type);
-
- }
-
- if(!in)
- {
- // TODO Hoosterman we have a problem!
- T(YAFFS_TRACE_ERROR, (TSTR("yaffs tragedy: Could not make object for object %d at chunk %d during scan" TENDSTR),tags.objectId,chunk));
-
- }
-
- if(in->valid)
- {
- // We have already filled this one. We have a duplicate that will be discarded, but
- // we first have to suck out resize info if it is a file.
-
- if( (in->variantType == YAFFS_OBJECT_TYPE_FILE) &&
- ((oh && oh->type == YAFFS_OBJECT_TYPE_FILE) ||
- (tags.extraHeaderInfoAvailable && tags.extraObjectType == YAFFS_OBJECT_TYPE_FILE))
- )
- {
- __u32 thisSize = (oh) ? oh->fileSize : tags.extraFileLength;
- __u32 parentObjectId = (oh) ? oh->parentObjectId : tags.extraParentObjectId;
- unsigned isShrink = (oh) ? oh->isShrink : tags.extraIsShrinkHeader;
-
- // If it is deleted (unlinked at start also means deleted)
- // we treat the file size as being zeroed at this point.
- if(parentObjectId == YAFFS_OBJECTID_DELETED ||
- parentObjectId == YAFFS_OBJECTID_UNLINKED)
- {
- thisSize = 0;
- isShrink = 1;
- }
-
- if(in->variant.fileVariant.shrinkSize > thisSize)
- {
- in->variant.fileVariant.shrinkSize = thisSize;
- }
-
- if(isShrink)
- {
- bi->hasShrinkHeader = 1;
- }
-
- }
- // Use existing - destroy this one.
- yaffs_DeleteChunk(dev,chunk,1,__LINE__);
-
- }
-
- if(!in->valid &&
- (tags.objectId == YAFFS_OBJECTID_ROOT ||
- tags.objectId == YAFFS_OBJECTID_LOSTNFOUND))
- {
- // We only load some info, don't fiddle with directory structure
- in->valid = 1;
- in->variantType = oh->type;
-
- in->st_mode = oh->st_mode;
-#ifdef CONFIG_YAFFS_WINCE
- in->win_atime[0] = oh->win_atime[0];
- in->win_ctime[0] = oh->win_ctime[0];
- in->win_mtime[0] = oh->win_mtime[0];
- in->win_atime[1] = oh->win_atime[1];
- in->win_ctime[1] = oh->win_ctime[1];
- in->win_mtime[1] = oh->win_mtime[1];
-#else
- in->st_uid = oh->st_uid;
- in->st_gid = oh->st_gid;
- in->st_atime = oh->st_atime;
- in->st_mtime = oh->st_mtime;
- in->st_ctime = oh->st_ctime;
- in->st_rdev = oh->st_rdev;
-#endif
- in->chunkId = chunk;
-
- }
- else if(!in->valid)
- {
- // we need to load this info
-
- in->valid = 1;
- in->variantType = oh->type;
-
- in->st_mode = oh->st_mode;
-#ifdef CONFIG_YAFFS_WINCE
- in->win_atime[0] = oh->win_atime[0];
- in->win_ctime[0] = oh->win_ctime[0];
- in->win_mtime[0] = oh->win_mtime[0];
- in->win_atime[1] = oh->win_atime[1];
- in->win_ctime[1] = oh->win_ctime[1];
- in->win_mtime[1] = oh->win_mtime[1];
-#else
- in->st_uid = oh->st_uid;
- in->st_gid = oh->st_gid;
- in->st_atime = oh->st_atime;
- in->st_mtime = oh->st_mtime;
- in->st_ctime = oh->st_ctime;
- in->st_rdev = oh->st_rdev;
-#endif
- in->chunkId = chunk;
-
- yaffs_SetObjectName(in,oh->name);
- in->dirty = 0;
-
- // directory stuff...
- // hook up to parent
-
- parent = yaffs_FindOrCreateObjectByNumber(dev,oh->parentObjectId,YAFFS_OBJECT_TYPE_DIRECTORY);
- if(parent->variantType == YAFFS_OBJECT_TYPE_UNKNOWN)
- {
- // Set up as a directory
- parent->variantType = YAFFS_OBJECT_TYPE_DIRECTORY;
- INIT_LIST_HEAD(&parent->variant.directoryVariant.children);
- }
- else if(parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
- {
- // Hoosterman, another problem....
- // We're trying to use a non-directory as a directory
-
- T(YAFFS_TRACE_ERROR, (TSTR("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found." TENDSTR)));
- parent = dev->lostNFoundDir;
- }
-
- yaffs_AddObjectToDirectory(parent,in);
-
- if((parent == dev->deletedDir ||
- parent == dev->unlinkedDir))
- {
- in->deleted = 1; // If it is unlinked at start up then it wants deleting
- }
-
- if( oh->isShrink)
- {
- // Mark the block as having a shrinkHeader
- bi->hasShrinkHeader = 1;
- }
-
-
- // Note re hardlinks.
- // Since we might scan a hardlink before its equivalent object is scanned
- // we put them all in a list.
- // After scanning is complete, we should have all the objects, so we run through this
- // list and fix up all the chains.
-
- switch(in->variantType)
- {
- case YAFFS_OBJECT_TYPE_UNKNOWN: // Todo got a problem
- break;
- case YAFFS_OBJECT_TYPE_FILE:
-
-
- if(in->variant.fileVariant.scannedFileSize < oh->fileSize)
- {
- in->variant.fileVariant.fileSize = oh->fileSize;
- in->variant.fileVariant.scannedFileSize = in->variant.fileVariant.fileSize;
- }
-
-
-
- if(in->variant.fileVariant.shrinkSize > oh->fileSize)
- {
- in->variant.fileVariant.shrinkSize = oh->fileSize;
- }
-
-
- break;
- case YAFFS_OBJECT_TYPE_HARDLINK:
- in->variant.hardLinkVariant.equivalentObjectId = oh->equivalentObjectId;
- in->hardLinks.next = (struct list_head *)hardList;
- hardList = in;
- break;
- case YAFFS_OBJECT_TYPE_DIRECTORY: // Do nothing
- break;
- case YAFFS_OBJECT_TYPE_SPECIAL: // Do nothing
- break;
- case YAFFS_OBJECT_TYPE_SYMLINK: // Do nothing
- in->variant.symLinkVariant.alias = yaffs_CloneString(oh->alias);
- break;
- }
-
-#if 0
- if(parent == dev->deletedDir)
- {
- yaffs_DestroyObject(in);
- bi->hasShrinkHeader = 1;
- }
-#endif
- //T((" %d %d header %d \"%s\" type %d\n",blk,c,tags.objectId,oh->name,in->variantType));
- }
- }
- }
-
- if(state == YAFFS_BLOCK_STATE_NEEDS_SCANNING)
- {
- // If we got this far while scanning, then the block is fully allocated.
- state = YAFFS_BLOCK_STATE_FULL;
- }
-
- bi->blockState = state;
-
- // Now let's see if it was dirty
- if( bi->pagesInUse == 0 &&
- !bi->hasShrinkHeader &&
- bi->blockState == YAFFS_BLOCK_STATE_FULL)
- {
- yaffs_BlockBecameDirty(dev,blk);
- }
-
- }
-
- if(blockIndex)
- {
- YFREE(blockIndex);
- }
-
- // Ok, we've done all the scanning.
-
- // Fix up the hard link chains.
- // We should now have scanned all the objects, now it's time to add these
- // hardlinks.
- while(hardList)
- {
- hl = hardList;
- hardList = (yaffs_Object *)(hardList->hardLinks.next);
-
- in = yaffs_FindObjectByNumber(dev,hl->variant.hardLinkVariant.equivalentObjectId);
-
- if(in)
- {
- // Add the hardlink pointers
- hl->variant.hardLinkVariant.equivalentObject=in;
- list_add(&hl->hardLinks,&in->hardLinks);
- }
- else
- {
- //Todo Need to report/handle this better.
- // Got a problem... hardlink to a non-existant object
- hl->variant.hardLinkVariant.equivalentObject=NULL;
- INIT_LIST_HEAD(&hl->hardLinks);
-
- }
-
- }
-
- {
- struct list_head *i;
- struct list_head *n;
-
- yaffs_Object *l;
-
- // Soft delete all the unlinked files
- list_for_each_safe(i,n,&dev->unlinkedDir->variant.directoryVariant.children)
- {
- if(i)
- {
- l = list_entry(i, yaffs_Object,siblings);
- yaffs_DestroyObject(l);
- }
- }
-
- // Soft delete all the deletedDir files
- list_for_each_safe(i,n,&dev->deletedDir->variant.directoryVariant.children)
- {
- if(i)
- {
- l = list_entry(i, yaffs_Object,siblings);
- yaffs_DestroyObject(l);
-
- }
- }
- }
-
- yaffs_ReleaseTempBuffer(dev,chunkData,__LINE__);