*** empty log message ***
authorcharles <charles>
Tue, 16 Sep 2003 06:48:38 +0000 (06:48 +0000)
committercharles <charles>
Tue, 16 Sep 2003 06:48:38 +0000 (06:48 +0000)
Documentation/yaffs2.html
yaffs_guts.c

index 9014465ba399097aa8fa7a64ff0a9899e63e64bd..8dd694f38bc99573b98b63cc822722b1c67d2277 100644 (file)
@@ -7,7 +7,7 @@
        <META NAME="AUTHOR" CONTENT=" ">
        <META NAME="CREATED" CONTENT="20021004;15061000">
        <META NAME="CHANGEDBY" CONTENT=" ">
-       <META NAME="CHANGED" CONTENT="20021206;6000500">
+       <META NAME="CHANGED" CONTENT="20030906;14584300">
 </HEAD>
 <BODY>
 <H1>YAFFS2</H1>
@@ -54,19 +54,59 @@ can't use the &quot;discarded&quot; flags in YAFFS2.</P>
        <LI><P>Since there is no deletion, a resize (shrinking) of a file
        will still have valid data chunks past the end of file on the NAND.
        However, we write a new ObjectHeader at the time of the resize,
-       therefore this shows the shrunken file size.</P>
+       therefore this shows the shrunken file size. The ObjectHeader also
+       carries information to say that this is a shrink, for some special
+       handling in the garbage collector.</P>
 </UL>
+<P><BR><BR>
+</P>
 <P>This changes erasure slightly:</P>
 <UL>
        <LI><P>During garbage collection we can't just look at chunk state
        flags, instead we must read the tags of each chunk to determine
        which object's chunk count we must decrement. This step must also be
-       performed when a block is erased (as part of deletion).</P>
+       performed when a block is erased (as part of deletion). This is
+       already done in YAFFS by<I> soft deletion.</I></P>
 </UL>
 <P>This makes erasure &amp; garbage collection more expensive (by
 adding reads), but remember that ion YAFFS2 we don't need to do page
 deletions which are much more expensive operations. Thus, all-up
 YAFFS2 wins.</P>
+<H4>Resize Handling</H4>
+<P>In YAFFS, soft deletion is ued for everything but resizing
+(shrinking) a file which has some particularly ugly cases that can
+complicate garbage collection.</P>
+<P>As mentioned before, we write a new ObjectHeader to indicate the
+shrinking.  However, it is important that this ObjectHeader does not
+get destroyed (erased) before the data chunks that were discarded
+during the shrink are destroyed (erased). If this precaution is not
+taken then it is possible that the deleted chunks might be brought
+back to life.</P>
+<P>The modification to the garbage collector is as follows:</P>
+<UL>
+       <LI><P>The block info flags are expanded as follows:</P>
+       <LI><P>containsShrinkObjectHeader: Indicates that one or more of the
+       chunks in the block are object headers to indicate a file shrink.</P>
+       <LI><P>containsShrinkDataChunks: Indicates that one or more of the
+       chunks in the block are data chunks discarded by a file shrink.</P>
+</UL>
+<UL>
+       <LI><P>Before we allow a block with containsShrinkObjectHeader set
+       to be erased (garbage collected), we must first ensure that all the
+       earlier blocks (ie according to the block sequence number) that have
+       containsShrinkDataChunks set are erased (garbage collected) which
+       ensures that the shrunk data chunks are deleted. The mechanisms to
+       do this are as follows:</P>
+       <LI><P>If the garbage collector attempts to select a block with
+       containsShrinkObjectHeader set, we check that the above criterion in
+       met before selecting the block.</P>
+       <LI><P>Periodically select the oldest block with
+       containsShrinkDataChunks for garbage collection.</P>
+</UL>
+<P><BR><BR>
+</P>
+<P><BR><BR>
+</P>
 <H4>Tag structure</H4>
 <P>Each chunk in YAFFS2 has the following information:</P>
 <TABLE WIDTH=100% BORDER=1 CELLPADDING=4 CELLSPACING=3>
@@ -757,12 +797,12 @@ particular:</P>
        <LI><P>Newer, larger, NAND with 2kB pages can be used in chunks of
        2kB. Keeping the relationship of one chunk per page improves
        robustness and performance (rather than say trying to &quot;fake&quot;
-       512byte  pages). A block comprises 64x2kB pages.</P>
+       512byte pages). A block comprises 64x2kB pages.</P>
        <LI><P>Some devices have 512byte pages, but are arranged as multiple
        &quot;bit planes&quot; which can be programmed and erased in
        parallel. For example, the Samsung K9K1G08U0M can support 4
        simultaneous operations. YAFFS2 can exploit this by using 2kB chunks
-        by using  groups of 4 pages - one on each bitplane. Virtual blocks
+       by using groups of 4 pages - one on each bitplane. Virtual blocks
        would be built which comprise 32x2kB chunks.</P>
 </UL>
 <P>To this end, yaffs_guts is being re-crafted to support arbitrary
@@ -781,7 +821,7 @@ to be changed:</P>
 </UL>
 <P>Some of these differences can be absorbed in the yaffs_mtd layer.
 Some will need to be handles inside the mtd itself.</P>
-<P>$Id: yaffs2.html,v 1.2 2003-01-14 23:15:41 charles Exp $</P>
+<P>$Id: yaffs2.html,v 1.3 2003-09-16 06:48:38 charles Exp $</P>
 <P><BR><BR>
 </P>
 <P><BR><BR>
index 365fa69636622e601a951a111d0b313808721863..5218aeab3391faef20b9d85dbbf0800f29e0332f 100644 (file)
@@ -14,7 +14,7 @@
  */
  //yaffs_guts.c
 
-const char *yaffs_guts_c_version="$Id: yaffs_guts.c,v 1.29 2003-08-29 17:53:05 aleph1 Exp $";
+const char *yaffs_guts_c_version="$Id: yaffs_guts.c,v 1.30 2003-09-16 06:48:38 charles Exp $";
 
 #include "yportenv.h"
 
@@ -1156,6 +1156,8 @@ static int yaffs_SoftDeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level
                        {
                            if(tn->level0[i])
                        {
+                                       // Note this does not find the real chunk, only the chunk group.
+                                       // We make an assumption that a chunk group is niot larger than a block.
                                        theChunk =  (tn->level0[i] << in->myDev->chunkGroupBits);
                                        T(YAFFS_TRACE_SCAN,(TSTR("soft delete tch %d cgb %d chunk %d" TENDSTR),
                                                tn->level0[i],in->myDev->chunkGroupBits,theChunk));
@@ -2864,10 +2866,13 @@ static void yaffs_DeleteChunk(yaffs_Device *dev,int chunkId,int markNAND)
        {
                yaffs_SpareInitialise(&spare);
 
+#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
+
                 //read data before write, to ensure correct ecc 
-                //and transitions are guaranteed 1->0
+                //if we're using MTD verification under Linux
                 yaffs_ReadChunkFromNAND(dev,chunkId,NULL,&spare,0);
-       
+#endif
+
                spare.pageStatus = 0; // To mark it as deleted.
 
        
@@ -4670,8 +4675,7 @@ int yaffs_GutsInitialise(yaffs_Device *dev)
        int extraBits;
        int nBlocks;
 
-       if(     dev->nBytesPerChunk != YAFFS_BYTES_PER_CHUNK ||
-       
+       if(     dev->nBytesPerChunk != YAFFS_BYTES_PER_CHUNK || 
                dev->nChunksPerBlock < 2 ||
                dev->nReservedBlocks < 2 ||
                dev->startBlock <= 0 ||
@@ -4738,7 +4742,18 @@ int yaffs_GutsInitialise(yaffs_Device *dev)
        {
                dev->chunkGroupBits = bits - 16;
        }
+       
        dev->chunkGroupSize = 1 << dev->chunkGroupBits;
+
+       if(dev->nChunksPerBlock < dev->chunkGroupSize)
+       {
+               // We have a problem because the soft delete won't work if
+               // the chunk group size > chunks per block.
+               // This can be remedied by using larger "virtual blocks".
+               
+               return YAFFS_FAIL;
+       }
+