- // Sort the blocks
- // Dungy old bubble sort for now...
- if(dev->isYaffs2)
- {
- 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.
- if(dev->isYaffs2)
- {
- startIterator = 0;
- endIterator = nBlocksToScan-1;
- T(YAFFS_TRACE_SCAN_DEBUG,(TSTR("%d blocks to be scanned" TENDSTR),nBlocksToScan));
- }
- else
- {
- startIterator = dev->internalStartBlock;
- endIterator = dev->internalEndBlock;
- }
-
- // For each block....
- for(blockIterator = startIterator; blockIterator <= endIterator; blockIterator++)
- {
-
- if(dev->isYaffs2)
- {
- // get the block to scan in the correct order
- blk = blockIndex[blockIterator].block;
- }
- else
- {
- blk = blockIterator;
- }
-
-
- bi = yaffs_GetBlockInfo(dev,blk);
- state = bi->blockState;
-
- deleted = 0;
-
- // For each chunk in each block that needs scanning....
- for(c = 0; c < dev->nChunksPerBlock &&
- state == YAFFS_BLOCK_STATE_NEEDS_SCANNING; c++)
- {
- // 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(!dev->isYaffs2 && tags.chunkDeleted)
- {
- // YAFFS1 only...
- // A deleted chunk
- deleted++;
- dev->nFreeChunks ++;
- //T((" %d %d deleted\n",blk,c));
- }
- else 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
- 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 += (dev->nChunksPerBlock - c);
- }
- else if(tags.chunkId > 0)
- {
- // chunkId > 0 so it is a data chunk...
- unsigned int endpos;
-
- yaffs_SetChunkBit(dev,blk,c);
- bi->pagesInUse++;
-
- in = yaffs_FindOrCreateObjectByNumber(dev,tags.objectId,YAFFS_OBJECT_TYPE_FILE);
- // PutChunkIntoFile checks for a clash (two data chunks with
- // the same chunkId).
- yaffs_PutChunkIntoFile(in,tags.chunkId,chunk,1);
- endpos = (tags.chunkId - 1)* dev->nBytesPerChunk + tags.byteCount;
- if(in->variantType == YAFFS_OBJECT_TYPE_FILE && in->variant.fileVariant.scannedFileSize <endpos)
- {
- in->variant.fileVariant.scannedFileSize = endpos;
- if(!dev->useHeaderFileSize)
- {
- in->variant.fileVariant.fileSize = in->variant.fileVariant.scannedFileSize;
- }
-
- }
- //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++;
-
- yaffs_ReadChunkWithTagsFromNAND(dev,chunk,chunkData,NULL);
-
- oh = (yaffs_ObjectHeader *)chunkData;
-
- in = yaffs_FindObjectByNumber(dev,tags.objectId);
- if(in && in->variantType != oh->type)
- {
- // This should not happen, but somehow
- // Wev'e ended up with an objectId that has been reused but not yet
- // deleted, and worse still it has changed type. Delete the old object.
-
- yaffs_DestroyObject(in);
-
- in = 0;
- }
-
- in = yaffs_FindOrCreateObjectByNumber(dev,tags.objectId,oh->type);
-
- if(oh->shadowsObject > 0)
- {
- yaffs_HandleShadowedObject(dev,oh->shadowsObject,0);
- }
-
- if(in->valid)
- {
- // We have already filled this one. We have a duplicate and need to resolve it.
-
- unsigned existingSerial = in->serial;
- unsigned newSerial = tags.serialNumber;
-
- if( dev->isYaffs2 ||
- ((existingSerial+1) & 3) == newSerial)
- {
- // Use new one - destroy the exisiting one
- yaffs_DeleteChunk(dev,in->chunkId,1,__LINE__);
- in->valid = 0;
- }
- else
- {
- // 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;
-
- 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