-
- // Sort the blocks
- // Dungy old bubble sort for now...
- {
- yaffs_BlockIndex temp;
- int i;
- int j;
-
- for(i = 0; i < nBlocksToScan; i++)
- for(j = i+1; j < nBlocksToScan; j++)
- if(blockIndex[i].seq > blockIndex[j].seq)
- {
- temp = blockIndex[j];
- blockIndex[j] = blockIndex[i];
- blockIndex[i] = temp;
- }
- }
-
-
- // Now scan the blocks looking at the data.
- startIterator = 0;
- endIterator = nBlocksToScan-1;
- T(YAFFS_TRACE_SCAN_DEBUG,(TSTR("%d blocks to be scanned" TENDSTR),nBlocksToScan));
-
-
- // 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->yst_mode = oh->yst_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->yst_uid = oh->yst_uid;
- in->yst_gid = oh->yst_gid;
- in->yst_atime = oh->yst_atime;
- in->yst_mtime = oh->yst_mtime;
- in->yst_ctime = oh->yst_ctime;
- in->yst_rdev = oh->yst_rdev;
-#endif
- in->chunkId = chunk;
-
- }
- else if(!in->valid)
- {
- // we need to load this info
-
- in->valid = 1;
- in->variantType = oh->type;
-
- in->yst_mode = oh->yst_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->yst_uid = oh->yst_uid;
- in->yst_gid = oh->yst_gid;
- in->yst_atime = oh->yst_atime;
- in->yst_mtime = oh->yst_mtime;
- in->yst_ctime = oh->yst_ctime;
- in->yst_rdev = oh->yst_rdev;
-#endif
- in->chunkId = chunk;
-
- if(oh->shadowsObject > 0)
- {
- yaffs_HandleShadowedObject(dev,oh->shadowsObject,0);
- }
-