140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project/* 240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * YAFFS: Yet another FFS. A NAND-flash specific file system. 340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * 440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Copyright (C) 2002 Aleph One Ltd. 540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * for Toby Churchill Ltd and Brightstar Engineering 640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * 740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * Created by Charles Manning <charles@aleph1.co.uk> 840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * 940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * This program is free software; you can redistribute it and/or modify 1040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * it under the terms of the GNU General Public License version 2 as 1140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * published by the Free Software Foundation. 1240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * 1340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project */ 1440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 1540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectconst char *yaffs_checkptrw_c_version = 1640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project "$Id: yaffs_checkptrw.c,v 1.5 2006/10/03 10:13:03 charles Exp $"; 1740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 1840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 1940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project#include "yaffs_checkptrw.h" 2040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 2140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 2240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_CheckpointSpaceOk(yaffs_Device *dev) 2340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 2440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 2540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int blocksAvailable = dev->nErasedBlocks - dev->nReservedBlocks; 2640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 2740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project T(YAFFS_TRACE_CHECKPOINT, 2840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project (TSTR("checkpt blocks available = %d" TENDSTR), 2940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project blocksAvailable)); 3040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 3140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 3240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return (blocksAvailable <= 0) ? 0 : 1; 3340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 3440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 3540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 3640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 3740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_CheckpointErase(yaffs_Device *dev) 3840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 3940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 4040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int i; 4140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 4240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 4340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(!dev->eraseBlockInNAND) 4440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return 0; 4540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project T(YAFFS_TRACE_CHECKPOINT,(TSTR("checking blocks %d to %d"TENDSTR), 4640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->startBlock,dev->endBlock)); 4740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 4840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project for(i = dev->startBlock; i <= dev->endBlock; i++) { 4940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yaffs_BlockInfo *bi = &dev->blockInfo[i]; 5040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT){ 5140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project T(YAFFS_TRACE_CHECKPOINT,(TSTR("erasing checkpt block %d"TENDSTR),i)); 5240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(dev->eraseBlockInNAND(dev,i)){ 5340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project bi->blockState = YAFFS_BLOCK_STATE_EMPTY; 5440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->nErasedBlocks++; 5540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->nFreeChunks += dev->nChunksPerBlock; 5640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 5740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project else { 5840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->markNANDBlockBad(dev,i); 5940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project bi->blockState = YAFFS_BLOCK_STATE_DEAD; 6040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 6140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 6240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 6340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 6440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->blocksInCheckpoint = 0; 6540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 6640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return 1; 6740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 6840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 6940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 7040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_CheckpointFindNextErasedBlock(yaffs_Device *dev) 7140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 7240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int i; 7340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int blocksAvailable = dev->nErasedBlocks - dev->nReservedBlocks; 7440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 7540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(dev->checkpointNextBlock >= 0 && 7640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointNextBlock <= dev->endBlock && 7740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project blocksAvailable > 0){ 7840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 7940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project for(i = dev->checkpointNextBlock; i <= dev->endBlock; i++){ 8040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yaffs_BlockInfo *bi = &dev->blockInfo[i]; 8140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(bi->blockState == YAFFS_BLOCK_STATE_EMPTY){ 8240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointNextBlock = i + 1; 8340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointCurrentBlock = i; 8440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project T(YAFFS_TRACE_CHECKPOINT,(TSTR("allocating checkpt block %d"TENDSTR),i)); 8540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return; 8640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 8740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 8840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 8940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project T(YAFFS_TRACE_CHECKPOINT,(TSTR("out of checkpt blocks"TENDSTR))); 9040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 9140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointNextBlock = -1; 9240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointCurrentBlock = -1; 9340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 9440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 9540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic void yaffs_CheckpointFindNextCheckpointBlock(yaffs_Device *dev) 9640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 9740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int i; 9840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yaffs_ExtendedTags tags; 9940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 10040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(dev->blocksInCheckpoint < dev->checkpointMaxBlocks) 10140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project for(i = dev->checkpointNextBlock; i <= dev->endBlock; i++){ 10240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int chunk = i * dev->nChunksPerBlock; 10340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 10440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->readChunkWithTagsFromNAND(dev,chunk,NULL,&tags); 10540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 10640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(tags.sequenceNumber == YAFFS_SEQUENCE_CHECKPOINT_DATA){ 10740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project /* Right kind of block */ 10840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointNextBlock = tags.objectId; 10940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointCurrentBlock = i; 11040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointBlockList[dev->blocksInCheckpoint] = i; 11140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->blocksInCheckpoint++; 11240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project T(YAFFS_TRACE_CHECKPOINT,(TSTR("found checkpt block %d"TENDSTR),i)); 11340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return; 11440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 11540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 11640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 11740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project T(YAFFS_TRACE_CHECKPOINT,(TSTR("found no more checkpt blocks"TENDSTR))); 11840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 11940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointNextBlock = -1; 12040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointCurrentBlock = -1; 12140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 12240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 12340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 12440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting) 12540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 12640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 12740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project /* Got the functions we need? */ 12840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if (!dev->writeChunkWithTagsToNAND || 12940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project !dev->readChunkWithTagsFromNAND || 13040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project !dev->eraseBlockInNAND || 13140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project !dev->markNANDBlockBad) 13240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return 0; 13340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 13440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(forWriting && !yaffs_CheckpointSpaceOk(dev)) 13540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return 0; 13640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 13740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(!dev->checkpointBuffer) 13840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointBuffer = YMALLOC_DMA(dev->nDataBytesPerChunk); 13940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(!dev->checkpointBuffer) 14040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return 0; 14140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 14240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 14340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointPageSequence = 0; 14440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 14540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointOpenForWrite = forWriting; 14640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 14740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointByteCount = 0; 14840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointCurrentBlock = -1; 14940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointCurrentChunk = -1; 15040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointNextBlock = dev->startBlock; 15140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 15240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project /* Erase all the blocks in the checkpoint area */ 15340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(forWriting){ 15440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project memset(dev->checkpointBuffer,0,dev->nDataBytesPerChunk); 15540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointByteOffset = 0; 15640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return yaffs_CheckpointErase(dev); 15740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 15840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 15940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } else { 16040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int i; 16140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project /* Set to a value that will kick off a read */ 16240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointByteOffset = dev->nDataBytesPerChunk; 16340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project /* A checkpoint block list of 1 checkpoint block per 16 block is (hopefully) 16440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project * going to be way more than we need */ 16540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->blocksInCheckpoint = 0; 16640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointMaxBlocks = (dev->endBlock - dev->startBlock)/16 + 2; 16740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointBlockList = YMALLOC(sizeof(int) * dev->checkpointMaxBlocks); 16840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project for(i = 0; i < dev->checkpointMaxBlocks; i++) 16940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointBlockList[i] = -1; 17040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 17140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 17240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return 1; 17340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 17440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 17540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectstatic int yaffs_CheckpointFlushBuffer(yaffs_Device *dev) 17640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 17740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 17840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int chunk; 17940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 18040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yaffs_ExtendedTags tags; 18140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 18240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(dev->checkpointCurrentBlock < 0){ 18340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yaffs_CheckpointFindNextErasedBlock(dev); 18440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointCurrentChunk = 0; 18540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 18640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 18740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(dev->checkpointCurrentBlock < 0) 18840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return 0; 18940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 19040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project tags.chunkDeleted = 0; 19140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project tags.objectId = dev->checkpointNextBlock; /* Hint to next place to look */ 19240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project tags.chunkId = dev->checkpointPageSequence + 1; 19340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project tags.sequenceNumber = YAFFS_SEQUENCE_CHECKPOINT_DATA; 19440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project tags.byteCount = dev->nDataBytesPerChunk; 19540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(dev->checkpointCurrentChunk == 0){ 19640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project /* First chunk we write for the block? Set block state to 19740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project checkpoint */ 19840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yaffs_BlockInfo *bi = &dev->blockInfo[dev->checkpointCurrentBlock]; 19940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project bi->blockState = YAFFS_BLOCK_STATE_CHECKPOINT; 20040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->blocksInCheckpoint++; 20140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 20240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 20340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project chunk = dev->checkpointCurrentBlock * dev->nChunksPerBlock + dev->checkpointCurrentChunk; 20440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 20540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->writeChunkWithTagsToNAND(dev,chunk,dev->checkpointBuffer,&tags); 20640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointByteOffset = 0; 20740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointPageSequence++; 20840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointCurrentChunk++; 20940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(dev->checkpointCurrentChunk >= dev->nChunksPerBlock){ 21040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointCurrentChunk = 0; 21140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointCurrentBlock = -1; 21240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 21340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project memset(dev->checkpointBuffer,0,dev->nDataBytesPerChunk); 21440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 21540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return 1; 21640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 21740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 21840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 21940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_CheckpointWrite(yaffs_Device *dev,const void *data, int nBytes) 22040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 22140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int i=0; 22240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int ok = 1; 22340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 22440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 22540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project __u8 * dataBytes = (__u8 *)data; 22640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 22740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 22840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 22940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(!dev->checkpointBuffer) 23040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return 0; 23140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 23240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project while(i < nBytes && ok) { 23340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 23440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 23540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 23640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointBuffer[dev->checkpointByteOffset] = *dataBytes ; 23740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointByteOffset++; 23840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project i++; 23940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dataBytes++; 24040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointByteCount++; 24140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 24240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 24340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(dev->checkpointByteOffset < 0 || 24440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointByteOffset >= dev->nDataBytesPerChunk) 24540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project ok = yaffs_CheckpointFlushBuffer(dev); 24640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 24740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 24840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 24940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return i; 25040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 25140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 25240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_CheckpointRead(yaffs_Device *dev, void *data, int nBytes) 25340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 25440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int i=0; 25540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int ok = 1; 25640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yaffs_ExtendedTags tags; 25740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 25840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 25940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int chunk; 26040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 26140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project __u8 *dataBytes = (__u8 *)data; 26240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 26340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(!dev->checkpointBuffer) 26440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return 0; 26540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 26640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project while(i < nBytes && ok) { 26740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 26840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 26940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(dev->checkpointByteOffset < 0 || 27040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointByteOffset >= dev->nDataBytesPerChunk) { 27140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 27240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(dev->checkpointCurrentBlock < 0){ 27340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yaffs_CheckpointFindNextCheckpointBlock(dev); 27440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointCurrentChunk = 0; 27540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 27640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 27740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(dev->checkpointCurrentBlock < 0) 27840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project ok = 0; 27940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project else { 28040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 28140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project chunk = dev->checkpointCurrentBlock * dev->nChunksPerBlock + 28240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointCurrentChunk; 28340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 28440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project /* read in the next chunk */ 28540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project /* printf("read checkpoint page %d\n",dev->checkpointPage); */ 28640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->readChunkWithTagsFromNAND(dev, chunk, 28740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointBuffer, 28840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project &tags); 28940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 29040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(tags.chunkId != (dev->checkpointPageSequence + 1) || 29140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project tags.sequenceNumber != YAFFS_SEQUENCE_CHECKPOINT_DATA) 29240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project ok = 0; 29340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 29440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointByteOffset = 0; 29540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointPageSequence++; 29640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointCurrentChunk++; 29740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 29840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(dev->checkpointCurrentChunk >= dev->nChunksPerBlock) 29940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointCurrentBlock = -1; 30040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 30140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 30240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 30340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(ok){ 30440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project *dataBytes = dev->checkpointBuffer[dev->checkpointByteOffset]; 30540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointByteOffset++; 30640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project i++; 30740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dataBytes++; 30840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointByteCount++; 30940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 31040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 31140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 31240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return i; 31340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 31440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 31540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_CheckpointClose(yaffs_Device *dev) 31640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 31740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 31840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(dev->checkpointOpenForWrite){ 31940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(dev->checkpointByteOffset != 0) 32040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yaffs_CheckpointFlushBuffer(dev); 32140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } else { 32240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project int i; 32340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project for(i = 0; i < dev->blocksInCheckpoint && dev->checkpointBlockList[i] >= 0; i++){ 32440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project yaffs_BlockInfo *bi = &dev->blockInfo[dev->checkpointBlockList[i]]; 32540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(bi->blockState == YAFFS_BLOCK_STATE_EMPTY) 32640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project bi->blockState = YAFFS_BLOCK_STATE_CHECKPOINT; 32740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project else { 32840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project // Todo this looks odd... 32940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 33040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 33140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project YFREE(dev->checkpointBlockList); 33240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointBlockList = NULL; 33340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 33440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 33540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->nFreeChunks -= dev->blocksInCheckpoint * dev->nChunksPerBlock; 33640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->nErasedBlocks -= dev->blocksInCheckpoint; 33740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 33840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 33940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project T(YAFFS_TRACE_CHECKPOINT,(TSTR("checkpoint byte count %d" TENDSTR), 34040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointByteCount)); 34140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 34240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(dev->checkpointBuffer){ 34340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project /* free the buffer */ 34440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project YFREE(dev->checkpointBuffer); 34540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project dev->checkpointBuffer = NULL; 34640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return 1; 34740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project } 34840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project else 34940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return 0; 35040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 35140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 35240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 35340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Projectint yaffs_CheckpointInvalidateStream(yaffs_Device *dev) 35440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project{ 35540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project /* Erase the first checksum block */ 35640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 35740c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project T(YAFFS_TRACE_CHECKPOINT,(TSTR("checkpoint invalidate"TENDSTR))); 35840c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 35940c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project if(!yaffs_CheckpointSpaceOk(dev)) 36040c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return 0; 36140c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 36240c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project return yaffs_CheckpointErase(dev); 36340c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project} 36440c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 36540c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 36640c4004d07a37a9b140067f893930ce4436b9346The Android Open Source Project 367