*/
const char *yaffs_guts_c_version =
- "$Id: yaffs_guts.c,v 1.33 2006-05-17 09:20:26 charles Exp $";
+ "$Id: yaffs_guts.c,v 1.35 2006-06-05 04:10:49 charles Exp $";
#include "yportenv.h"
#include "yaffs_tagsvalidity.h"
#include "yaffs_tagscompat.h"
+#ifndef CONFIG_YAFFS_OWN_SORT
+#include "yaffs_qsort.h"
+#endif
#include "yaffs_nand.h"
#include "yaffs_checkptrw.h"
}
+/*
+ * Determine if we have a managed buffer.
+ */
+int yaffs_IsManagedTempBuffer(yaffs_Device * dev, const __u8 * buffer)
+{
+ int i;
+ for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
+ if (dev->tempBuffer[i].buffer == buffer)
+ return 1;
+
+ }
+
+ for (i = 0; i < dev->nShortOpCaches; i++) {
+ if( dev->srCache[i].data == buffer )
+ return 1;
+
+ }
+
+ if (buffer == dev->checkpointBuffer)
+ return 1;
+
+ T(YAFFS_TRACE_ALWAYS,
+ (TSTR("yaffs: unmaged buffer detected.\n" TENDSTR)));
+ return 0;
+}
+
/*
* Chunk bitmap manipulations
*/
#endif
obj = yaffs_FindObjectByName(oldDir, oldName);
+ /* Check new name to long. */
+ if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK &&
+ yaffs_strlen(newName) > YAFFS_MAX_ALIAS_LENGTH)
+ /* ENAMETOOLONG */
+ return YAFFS_FAIL;
+ else if (obj->variantType != YAFFS_OBJECT_TYPE_SYMLINK &&
+ yaffs_strlen(newName) > YAFFS_MAX_NAME_LENGTH)
+ /* ENAMETOOLONG */
+ return YAFFS_FAIL;
if (obj && obj->renameAllowed) {
int aggressive;
int gcOk = YAFFS_OK;
int maxTries = 0;
+
+ int checkpointBlockAdjust;
if (dev->isDoingGC) {
/* Bail out so we don't get recursive gc */
do {
maxTries++;
- if (dev->nErasedBlocks < dev->nReservedBlocks) {
+
+ checkpointBlockAdjust = (dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint);
+ if(checkpointBlockAdjust < 0)
+ checkpointBlockAdjust = 0;
+
+ if (dev->nErasedBlocks < (dev->nReservedBlocks + checkpointBlockAdjust)) {
/* We need a block soon...*/
aggressive = 1;
} else {
{
int i;
yaffs_Device *dev = in->myDev;
+ int ok = 1;
+ int nTnodeBytes = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
if (tn) {
if (level > 0) {
- for (i = 0; i < YAFFS_NTNODES_INTERNAL; i++){
+ for (i = 0; i < YAFFS_NTNODES_INTERNAL && ok; i++){
if (tn->internal[i]) {
- yaffs_CheckpointTnodeWorker(in,
+ ok = yaffs_CheckpointTnodeWorker(in,
tn->internal[i],
level - 1,
(chunkOffset<<YAFFS_TNODES_INTERNAL_BITS) + i);
} else if (level == 0) {
__u32 baseOffset = chunkOffset << YAFFS_TNODES_LEVEL0_BITS;
/* printf("write tnode at %d\n",baseOffset); */
- yaffs_CheckpointWrite(dev,&baseOffset,sizeof(baseOffset));
- yaffs_CheckpointWrite(dev,tn,(dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8);
+ ok = (yaffs_CheckpointWrite(dev,&baseOffset,sizeof(baseOffset)) == sizeof(baseOffset));
+ if(ok)
+ ok = (yaffs_CheckpointWrite(dev,tn,nTnodeBytes) == nTnodeBytes);
}
}
- return 1;
+ return ok;
}
if(ok && cp.objectId == ~0)
done = 1;
- else {
- /* printf("Read object %d type %d\n",cp.objectId,cp.variantType); */
+ else if(ok){
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("Read object %d parent %d type %d" TENDSTR),
+ cp.objectId,cp.parentId,cp.variantType));
obj = yaffs_FindOrCreateObjectByNumber(dev,cp.objectId, cp.variantType);
if(obj) {
yaffs_CheckpointObjectToObject(obj,&cp);
if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) {
- yaffs_ReadCheckpointTnodes(obj);
+ ok = yaffs_ReadCheckpointTnodes(obj);
} else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
obj->hardLinks.next =
(struct list_head *)
if(ok)
ok = yaffs_WriteCheckpointValidityMarker(dev,0);
- yaffs_CheckpointClose(dev);
-
-// if(dev->checkpointBytes)
+ if(!yaffs_CheckpointClose(dev))
+ ok = 0;
+
+ if(ok)
dev->isCheckpointed = 1;
-// else
- //dev->isCheckpointed = 0;
+ else
+ dev->isCheckpointed = 0;
return dev->isCheckpointed;
}
- yaffs_CheckpointClose(dev);
+ if(!yaffs_CheckpointClose(dev))
+ ok = 0;
-// if(ok)
+ if(ok)
dev->isCheckpointed = 1;
-// else
-// dev->isCheckpointed = 0;
+ else
+ dev->isCheckpointed = 0;
return ok ? 1 : 0;
static void yaffs_InvalidateCheckpoint(yaffs_Device *dev)
{
- if(dev->isCheckpointed){
+ if(dev->isCheckpointed ||
+ dev->blocksInCheckpoint > 0){
dev->isCheckpointed = 0;
yaffs_CheckpointInvalidateStream(dev);
if(dev->superBlock && dev->markSuperBlockDirty)
int yaffs_CheckpointSave(yaffs_Device *dev)
{
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("save entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
+
if(!dev->isCheckpointed)
yaffs_WriteCheckpointData(dev);
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("save exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
+
return dev->isCheckpointed;
}
int yaffs_CheckpointRestore(yaffs_Device *dev)
{
+ int retval;
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
+
+ retval = yaffs_ReadCheckpointData(dev);
+
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
- return yaffs_ReadCheckpointData(dev);
+ return retval;
}
/*--------------------- File read/write ------------------------
+static int ybicmp(const void *a, const void *b){
+ register int aseq = ((yaffs_BlockIndex *)a)->seq;
+ register int bseq = ((yaffs_BlockIndex *)b)->seq;
+ register int ablock = ((yaffs_BlockIndex *)a)->block;
+ register int bblock = ((yaffs_BlockIndex *)b)->block;
+ if( aseq == bseq )
+ return ablock - bblock;
+ else
+ return aseq - bseq;
+
+}
+
static int yaffs_Scan(yaffs_Device * dev)
{
yaffs_ExtendedTags tags;
yaffs_BlockIndex *blockIndex = NULL;
+ if (dev->isYaffs2) {
+ T(YAFFS_TRACE_SCAN,
+ (TSTR("yaffs_Scan is not for YAFFS2!" TENDSTR)));
+ return YAFFS_FAIL;
+ }
+
+ //TODO Throw all the yaffs2 stuuf out of yaffs_Scan since it is only for yaffs1 format.
+
T(YAFFS_TRACE_SCAN,
(TSTR("yaffs_Scan starts intstartblk %d intendblk %d..." TENDSTR),
dev->internalStartBlock, dev->internalEndBlock));
yaffs_BlockIndex *blockIndex = NULL;
+ int altBlockIndex = 0;
if (!dev->isYaffs2) {
T(YAFFS_TRACE_SCAN,
("yaffs_ScanBackwards starts intstartblk %d intendblk %d..."
TENDSTR), dev->internalStartBlock, dev->internalEndBlock));
- chunkData = yaffs_GetTempBuffer(dev, __LINE__);
dev->sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER;
blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex));
+
+ if(!blockIndex) {
+ blockIndex = YMALLOC_ALT(nBlocks * sizeof(yaffs_BlockIndex));
+ altBlockIndex = 1;
+ }
+
+ if(!blockIndex) {
+ T(YAFFS_TRACE_SCAN,
+ (TSTR("yaffs_Scan() could not allocate block index!" TENDSTR)));
+ return YAFFS_FAIL;
+ }
+
+ chunkData = yaffs_GetTempBuffer(dev, __LINE__);
/* Scan all the blocks to determine their state */
for (blk = dev->internalStartBlock; blk <= dev->internalEndBlock; blk++) {
}
}
- /*
- * Sort the blocks
- * Dungy old bubble sort for now...
- */
+ T(YAFFS_TRACE_SCAN,
+ (TSTR("%d blocks to be sorted..." TENDSTR), nBlocksToScan));
+
+
+
+ YYIELD();
+
+ /* Sort the blocks */
+#ifndef CONFIG_YAFFS_USE_OWN_SORT
+ {
+ /* Use qsort now. */
+ qsort(blockIndex, nBlocksToScan, sizeof(yaffs_BlockIndex), ybicmp);
+ }
+#else
{
+ /* Dungy old bubble sort... */
+
yaffs_BlockIndex temp;
int i;
int j;
blockIndex[i] = temp;
}
}
+#endif
+
+ YYIELD();
+
+ T(YAFFS_TRACE_SCAN, (TSTR("...done" TENDSTR)));
/* Now scan the blocks looking at the data. */
startIterator = 0;
/* For each block.... backwards */
for (blockIterator = endIterator; blockIterator >= startIterator;
blockIterator--) {
+ /* Cooperative multitasking! This loop can run for so
+ long that watchdog timers expire. */
+ YYIELD();
/* get the block to scan in the correct order */
blk = blockIndex[blockIterator].block;
}
- if (blockIndex) {
+ if (altBlockIndex)
+ YFREE_ALT(blockIndex);
+ else
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
for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
dev->tempBuffer[i].line = 0; /* not in use */
dev->tempBuffer[i].buffer =
- YMALLOC(dev->nBytesPerChunk);
+ YMALLOC_DMA(dev->nBytesPerChunk);
}
}
dev->srCache[i].object = NULL;
dev->srCache[i].lastUse = 0;
dev->srCache[i].dirty = 0;
- dev->srCache[i].data = YMALLOC(dev->nBytesPerChunk);
+ dev->srCache[i].data = YMALLOC_DMA(dev->nBytesPerChunk);
}
dev->srLastUse = 0;
}