-static int yaffs_ReadCheckpointObjects(yaffs_Device *dev)
-{
- yaffs_Object *obj;
- yaffs_CheckpointObject cp;
- int ok = 1;
- int done = 0;
- yaffs_Object *hardList = NULL;
-
- while(ok && !done) {
- ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp));
- if(cp.structType != sizeof(cp)) {
- T(YAFFS_TRACE_CHECKPOINT,(TSTR("struct size %d instead of %d ok %d"TENDSTR),
- cp.structType,sizeof(cp),ok));
- ok = 0;
- }
-
- T(YAFFS_TRACE_CHECKPOINT,(TSTR("Checkpoint read object %d parent %d type %d chunk %d " TENDSTR),
- cp.objectId,cp.parentId,cp.variantType,cp.hdrChunk));
-
- if(ok && cp.objectId == ~0)
- done = 1;
- else if(ok){
- obj = yaffs_FindOrCreateObjectByNumber(dev,cp.objectId, cp.variantType);
- if(obj) {
- yaffs_CheckpointObjectToObject(obj,&cp);
- if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) {
- ok = yaffs_ReadCheckpointTnodes(obj);
- } else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
- obj->hardLinks.next =
- (struct ylist_head *)
- hardList;
- hardList = obj;
- }
-
- }
- }
- }
-
- if(ok)
- yaffs_HardlinkFixup(dev,hardList);
-
- return ok ? 1 : 0;
-}
-
-static int yaffs_WriteCheckpointSum(yaffs_Device *dev)
-{
- __u32 checkpointSum;
- int ok;
-
- yaffs_GetCheckpointSum(dev,&checkpointSum);
-
- ok = (yaffs_CheckpointWrite(dev,&checkpointSum,sizeof(checkpointSum)) == sizeof(checkpointSum));
-
- if(!ok)
- return 0;
-
- return 1;
-}
-
-static int yaffs_ReadCheckpointSum(yaffs_Device *dev)
-{
- __u32 checkpointSum0;
- __u32 checkpointSum1;
- int ok;
-
- yaffs_GetCheckpointSum(dev,&checkpointSum0);
-
- ok = (yaffs_CheckpointRead(dev,&checkpointSum1,sizeof(checkpointSum1)) == sizeof(checkpointSum1));
-
- if(!ok)
- return 0;
-
- if(checkpointSum0 != checkpointSum1)
- return 0;
-
- return 1;
-}
-
-
-static int yaffs_WriteCheckpointData(yaffs_Device *dev)
-{
-
- int ok = 1;
-
- if(dev->skipCheckpointWrite || !dev->isYaffs2){
- T(YAFFS_TRACE_CHECKPOINT,(TSTR("skipping checkpoint write" TENDSTR)));
- ok = 0;
- }
-
- if(ok)
- ok = yaffs_CheckpointOpen(dev,1);
-
- if(ok){
- T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint validity" TENDSTR)));
- ok = yaffs_WriteCheckpointValidityMarker(dev,1);
- }
- if(ok){
- T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint device" TENDSTR)));
- ok = yaffs_WriteCheckpointDevice(dev);
- }
- if(ok){
- T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint objects" TENDSTR)));
- ok = yaffs_WriteCheckpointObjects(dev);
- }
- if(ok){
- T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint validity" TENDSTR)));
- ok = yaffs_WriteCheckpointValidityMarker(dev,0);
- }
-
- if(ok){
- ok = yaffs_WriteCheckpointSum(dev);
- }
-
-
- if(!yaffs_CheckpointClose(dev))
- ok = 0;
-
- if(ok)
- dev->isCheckpointed = 1;
- else
- dev->isCheckpointed = 0;
-
- return dev->isCheckpointed;
-}
-
-static int yaffs_ReadCheckpointData(yaffs_Device *dev)
-{
- int ok = 1;
-
- if(dev->skipCheckpointRead || !dev->isYaffs2){
- T(YAFFS_TRACE_CHECKPOINT,(TSTR("skipping checkpoint read" TENDSTR)));
- ok = 0;
- }
-
- if(ok)
- ok = yaffs_CheckpointOpen(dev,0); /* open for read */
-
- if(ok){
- T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint validity" TENDSTR)));
- ok = yaffs_ReadCheckpointValidityMarker(dev,1);
- }
- if(ok){
- T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint device" TENDSTR)));
- ok = yaffs_ReadCheckpointDevice(dev);
- }
- if(ok){
- T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint objects" TENDSTR)));
- ok = yaffs_ReadCheckpointObjects(dev);
- }
- if(ok){
- T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint validity" TENDSTR)));
- ok = yaffs_ReadCheckpointValidityMarker(dev,0);
- }
-
- if(ok){
- ok = yaffs_ReadCheckpointSum(dev);
- T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint checksum %d" TENDSTR),ok));
- }
-
- if(!yaffs_CheckpointClose(dev))
- ok = 0;
-
- if(ok)
- dev->isCheckpointed = 1;
- else
- dev->isCheckpointed = 0;
-
- return ok ? 1 : 0;
-
-}
-
-static void yaffs_InvalidateCheckpoint(yaffs_Device *dev)
-{
- if(dev->isCheckpointed ||
- dev->blocksInCheckpoint > 0){
- dev->isCheckpointed = 0;
- yaffs_CheckpointInvalidateStream(dev);
- if(dev->superBlock && dev->markSuperBlockDirty)
- dev->markSuperBlockDirty(dev->superBlock);
- }
-}
-
-
-int yaffs_CheckpointSave(yaffs_Device *dev)
-{
-
- T(YAFFS_TRACE_CHECKPOINT,(TSTR("save entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
-
- yaffs_VerifyObjects(dev);
- yaffs_VerifyBlocks(dev);
- yaffs_VerifyFreeChunks(dev);
-
- if(!dev->isCheckpointed) {
- yaffs_InvalidateCheckpoint(dev);
- yaffs_WriteCheckpointData(dev);
- }
-
- T(YAFFS_TRACE_ALWAYS,(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);
-
- if(dev->isCheckpointed){
- yaffs_VerifyObjects(dev);
- yaffs_VerifyBlocks(dev);
- yaffs_VerifyFreeChunks(dev);
- }
-
- T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
-
- return retval;
-}
-
-/*--------------------- File read/write ------------------------
- * Read and write have very similar structures.
- * In general the read/write has three parts to it
- * An incomplete chunk to start with (if the read/write is not chunk-aligned)
- * Some complete chunks
- * An incomplete chunk to end off with
- *
- * Curve-balls: the first chunk might also be the last chunk.
- */
-
-int yaffs_ReadDataFromFile(yaffs_Object * in, __u8 * buffer, loff_t offset,
- int nBytes)
-{
-
- int chunk;
- __u32 start;
- int nToCopy;
- int n = nBytes;
- int nDone = 0;
- yaffs_ChunkCache *cache;
-
- yaffs_Device *dev;
-
- dev = in->myDev;
-
- while (n > 0) {
- //chunk = offset / dev->nDataBytesPerChunk + 1;
- //start = offset % dev->nDataBytesPerChunk;
- yaffs_AddrToChunk(dev,offset,&chunk,&start);
- chunk++;
-
- /* OK now check for the curveball where the start and end are in
- * the same chunk.
- */
- if ((start + n) < dev->nDataBytesPerChunk) {
- nToCopy = n;
- } else {
- nToCopy = dev->nDataBytesPerChunk - start;
- }
-
- cache = yaffs_FindChunkCache(in, chunk);
-
- /* If the chunk is already in the cache or it is less than a whole chunk
- * or we're using inband tags then use the cache (if there is caching)
- * else bypass the cache.
- */
- if (cache || nToCopy != dev->nDataBytesPerChunk || dev->inbandTags) {
- if (dev->nShortOpCaches > 0) {
-
- /* If we can't find the data in the cache, then load it up. */
-
- if (!cache) {
- cache = yaffs_GrabChunkCache(in->myDev);
- cache->object = in;
- cache->chunkId = chunk;
- cache->dirty = 0;
- cache->locked = 0;
- yaffs_ReadChunkDataFromObject(in, chunk,
- cache->
- data);
- cache->nBytes = 0;
- }
-
- yaffs_UseChunkCache(dev, cache, 0);
-
- cache->locked = 1;
-
-#ifdef CONFIG_YAFFS_WINCE
- yfsd_UnlockYAFFS(TRUE);
-#endif
- memcpy(buffer, &cache->data[start], nToCopy);
-
-#ifdef CONFIG_YAFFS_WINCE
- yfsd_LockYAFFS(TRUE);
-#endif
- cache->locked = 0;
- } else {
- /* Read into the local buffer then copy..*/
-
- __u8 *localBuffer =
- yaffs_GetTempBuffer(dev, __LINE__);
- yaffs_ReadChunkDataFromObject(in, chunk,
- localBuffer);
-#ifdef CONFIG_YAFFS_WINCE
- yfsd_UnlockYAFFS(TRUE);
-#endif
- memcpy(buffer, &localBuffer[start], nToCopy);
-
-#ifdef CONFIG_YAFFS_WINCE
- yfsd_LockYAFFS(TRUE);
-#endif
- yaffs_ReleaseTempBuffer(dev, localBuffer,
- __LINE__);
- }
-
- } else {
-#ifdef CONFIG_YAFFS_WINCE
- __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__);
-
- /* Under WinCE can't do direct transfer. Need to use a local buffer.
- * This is because we otherwise screw up WinCE's memory mapper
- */
- yaffs_ReadChunkDataFromObject(in, chunk, localBuffer);
-
-#ifdef CONFIG_YAFFS_WINCE
- yfsd_UnlockYAFFS(TRUE);
-#endif
- memcpy(buffer, localBuffer, dev->nDataBytesPerChunk);
-
-#ifdef CONFIG_YAFFS_WINCE
- yfsd_LockYAFFS(TRUE);
- yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__);
-#endif
-
-#else
- /* A full chunk. Read directly into the supplied buffer. */
- yaffs_ReadChunkDataFromObject(in, chunk, buffer);
-#endif
- }
-
- n -= nToCopy;
- offset += nToCopy;
- buffer += nToCopy;
- nDone += nToCopy;
-
- }
-
- return nDone;
-}
-
-int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset,
- int nBytes, int writeThrough)
-{
-
- int chunk;
- __u32 start;
- int nToCopy;
- int n = nBytes;
- int nDone = 0;
- int nToWriteBack;
- int startOfWrite = offset;
- int chunkWritten = 0;
- __u32 nBytesRead;
- __u32 chunkStart;
-
- yaffs_Device *dev;
-
- dev = in->myDev;
-
- while (n > 0 && chunkWritten >= 0) {
- //chunk = offset / dev->nDataBytesPerChunk + 1;
- //start = offset % dev->nDataBytesPerChunk;
- yaffs_AddrToChunk(dev,offset,&chunk,&start);
-
- if(chunk * dev->nDataBytesPerChunk + start != offset ||
- start >= dev->nDataBytesPerChunk){
- T(YAFFS_TRACE_ERROR,(TSTR("AddrToChunk of offset %d gives chunk %d start %d"TENDSTR),
- (int)offset, chunk,start));
- }
- chunk++;
-
- /* OK now check for the curveball where the start and end are in
- * the same chunk.
- */