2 * YAFFS: Yet another FFS. A NAND-flash specific file system.
4 * Copyright (C) 2002 Aleph One Ltd.
5 * for Toby Churchill Ltd and Brightstar Engineering
7 * Created by Charles Manning <charles@aleph1.co.uk>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
15 const char *yaffs_checkptrw_c_version =
16 "$Id: yaffs_checkptrw.c,v 1.1 2006-05-08 10:13:34 charles Exp $";
19 #include "yaffs_checkptrw.h"
22 int yaffs_CheckpointSpaceOk(yaffs_Device *dev)
25 T(YAFFS_TRACE_CHECKPOINT,(TSTR("checkpt blocks %d %d %d %d" TENDSTR),
26 dev->checkpointStartBlock, dev->checkpointEndBlock,
27 dev->startBlock,dev->endBlock));
29 if(dev->checkpointStartBlock >= dev->checkpointEndBlock)
32 if(dev->checkpointStartBlock >= dev->startBlock &&
33 dev->checkpointStartBlock <= dev->endBlock)
36 if(dev->checkpointEndBlock >= dev->startBlock &&
37 dev->checkpointEndBlock <= dev->endBlock)
43 int yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting)
47 /* Got the functions we need? */
48 if (!dev->writeChunkWithTagsToNAND ||
49 !dev->readChunkWithTagsFromNAND ||
50 !dev->eraseBlockInNAND)
53 /* Got a valid checkpoint data region? */
54 if(!yaffs_CheckpointSpaceOk(dev))
57 if(!dev->checkpointBuffer)
58 dev->checkpointBuffer = YMALLOC(dev->nBytesPerChunk);
59 if(!dev->checkpointBuffer)
62 dev->checkpointPage = dev->checkpointStartBlock * dev->nChunksPerBlock;
64 dev->checkpointOpenForWrite = forWriting;
66 dev->checkpointByteCount = 0;
68 /* Erase all the blocks in the checkpoint area */
70 T(YAFFS_TRACE_CHECKPOINT,(TSTR("erasing checkpt data"TENDSTR)));
71 for( i = dev->checkpointStartBlock; i <= dev->checkpointEndBlock; i++)
72 dev->eraseBlockInNAND(dev,i);
74 dev->checkpointByteOffset = 0;
76 memset(dev->checkpointBuffer,0,dev->nBytesPerChunk);
79 /* Set to a value that will kick off a read */
80 dev->checkpointByteOffset = dev->nBytesPerChunk;
86 static int yaffs_CheckpointFlushBuffer(yaffs_Device *dev)
91 yaffs_BlockState state;
94 yaffs_ExtendedTags tags;
95 tags.chunkDeleted = 0;
96 tags.objectId = YAFFS_OBJECTID_CHECKPOINT_DATA;
97 tags.chunkId = dev->checkpointPage + 1;
98 tags.sequenceNumber = 1;
99 tags.byteCount = dev->nBytesPerChunk;
101 /* printf("write checkpoint page %d\n",dev->checkpointPage); */
103 if(dev->checkpointPage%dev->nChunksPerBlock == 0){
104 /* Start of a new block, do a block validity check */
105 blockNo = dev->checkpointPage/dev->nChunksPerBlock;
107 while(blockNo <= dev->checkpointEndBlock && !goodBlockFound){
108 dev->queryNANDBlock(dev,blockNo,&state,&tags);
109 if(state != YAFFS_BLOCK_STATE_DEAD)
113 dev->checkpointPage += dev->nChunksPerBlock;
121 dev->writeChunkWithTagsToNAND(dev, dev->checkpointPage,
122 dev->checkpointBuffer,&tags);
123 dev->checkpointByteOffset = 0;
124 dev->checkpointPage++;
125 memset(dev->checkpointBuffer,0,dev->nBytesPerChunk);
130 int yaffs_CheckpointWrite(yaffs_Device *dev,const void *data, int nBytes)
136 __u8 * dataBytes = (__u8 *)data;
140 if(!dev->checkpointBuffer)
143 while(i < nBytes && ok) {
147 dev->checkpointBuffer[dev->checkpointByteOffset] = *dataBytes ;
148 dev->checkpointByteOffset++;
151 dev->checkpointByteCount++;
154 if(dev->checkpointByteOffset < 0 ||
155 dev->checkpointByteOffset >= dev->nBytesPerChunk)
156 ok = yaffs_CheckpointFlushBuffer(dev);
163 int yaffs_CheckpointRead(yaffs_Device *dev, void *data, int nBytes)
167 yaffs_ExtendedTags tags;
168 yaffs_BlockState state;
172 __u8 *dataBytes = (__u8 *)data;
174 if(!dev->checkpointBuffer)
177 while(i < nBytes && ok) {
178 if(dev->checkpointByteOffset < 0 ||
179 dev->checkpointByteOffset >= dev->nBytesPerChunk) {
180 if(dev->checkpointPage%dev->nChunksPerBlock == 0){
181 /* Start of a new block, do a block validity check */
182 blockNo = dev->checkpointPage/dev->nChunksPerBlock;
184 while(blockNo <= dev->checkpointEndBlock && !goodBlockFound){
185 dev->queryNANDBlock(dev,blockNo,&state,&tags);
186 if(state != YAFFS_BLOCK_STATE_DEAD)
190 dev->checkpointPage += dev->nChunksPerBlock;
199 /* read in the next chunk */
200 /* printf("read checkpoint page %d\n",dev->checkpointPage); */
201 dev->readChunkWithTagsFromNAND(dev, dev->checkpointPage,
202 dev->checkpointBuffer,
205 if(tags.objectId != YAFFS_OBJECTID_CHECKPOINT_DATA ||
206 tags.chunkId != (dev->checkpointPage + 1))
209 dev->checkpointByteOffset = 0;
210 dev->checkpointPage++;
214 *dataBytes = dev->checkpointBuffer[dev->checkpointByteOffset];
215 dev->checkpointByteOffset++;
218 dev->checkpointByteCount++;
225 int yaffs_CheckpointClose(yaffs_Device *dev)
228 if(dev->checkpointOpenForWrite){
229 if(dev->checkpointByteOffset != 0)
230 yaffs_CheckpointFlushBuffer(dev);
233 T(YAFFS_TRACE_CHECKPOINT,(TSTR("checkpoint byte count %d" TENDSTR),
234 dev->checkpointByteCount));
236 if(dev->checkpointBuffer){
237 /* flush the buffer */
238 YFREE(dev->checkpointBuffer);
239 dev->checkpointBuffer = NULL;
247 int yaffs_CheckpointInvalidateStream(yaffs_Device *dev)
249 /* Erase the first checksum block */
251 T(YAFFS_TRACE_CHECKPOINT,(TSTR("checkpoint invalidate"TENDSTR)));
253 if(!yaffs_CheckpointSpaceOk(dev))
256 if(dev->eraseBlockInNAND){
257 T(YAFFS_TRACE_CHECKPOINT,(TSTR("erasing checkpt data"TENDSTR)));
259 return dev->eraseBlockInNAND(dev, dev->checkpointStartBlock);