Re: [Yaffs] How to trigger garbage collection on read?

Top Page
Attachments:
Message as email
+ (text/plain)
Delete this message
Reply to this message
Author: Charles Manning
Date:  
To: yaffs, Peter Barada
Subject: Re: [Yaffs] How to trigger garbage collection on read?
On Tuesday 17 January 2012 12:39:43 Charles Manning wrote:
> Hello Peter
>
> On Tuesday 17 January 2012 08:13:21 Peter Barada wrote:
> > I need to modify YAFFS to trigger garbage collection on a block that has
> > too many page reads between erases.
> >
> > This is due to the characterisation of the Micron NAND
> > (MTMT29C4G48MAPLCJI6) I'm using where it can only have ~20K reads
> > between erasures to maintain UBER below 10E-14. The NAND itself has an
> > internal 4-bit ECC engine, but I can't extract any useful information
> > from the ECC due to the lack of bit error counts (i.e. the chip can only
> > tell me that a read required some level of correction but not the amount
> > of correction, and worse the rate of corrections indicated by the chip
> > is too high to employ effective strike counting).
>
> Oh how these silicon vendors seem to take glee in causing us pain!
>
> > So I need to track the page reads in a block and if they reach a limit
> > then cause the block to be garbage collected (i.e. copy out all the
> > useful data and erase the block).
>
> You just need to run the block through the garbage collector.
>
> But first the block needs to be in FULL state. Now that is most likely the
> case, but it is possible to contrive some cases where this might not be
> (eg. write a couple of pages then read just those pages a million times).
>
> That can be achieved by some code in the spirit of
>
>  if(block state == ALLOCATING)
>     yaffs_skip_rest_of_block(dev);

>
>
> 2. Then I think it will be ok to just call yaffs_gc_block() while locked.
>
>     yaffs_gc_block(dev, block_i_want_to_refresh, 1);

>
>
> -or- cleverer
>
> Or you could just set dev->gc_block = block_i_want_to_refresh and the
> garbage collector will pick it up and sort it out in the next gc.
>
> Of course that has the potential problem of two blocks needing refreshing
> and one interrupting the other.
>
> Perhaps the two ideas can be melded as follows:
>
>     if(block state == ALLOCATING)
>     yaffs_skip_rest_of_block(dev);

>
>     if(dev->gc_block)
>         yaffs_gc_block(dev, block_i_want_to_refresh, 1);
>     else
>        dev->gc_block = block_i_want_to_refesh;

>
> - or - cleverist
>
> Add a list of blocks needing refresh to dev and in yaffs_check_gc() add a
> new clause for getting a new gc block
>
>                 if (dev->gc_block < 1 && refresh list not empty) {
>                         dev->gc_block = grab first in list;
>                         dev->gc_chunk = 0;
>                         dev->n_clean_ups = 0;
>                 }

>
> > Any help is appreciated!
>
> Hope that helps....
>
> Charles
>


Hi Peter

I was wondering how you got on with the block refreshing.

Last night I was thinking about something unrelated and suddenly realised that
I think there might be a corner case where data written in a certain pattern
could come back from the dead if you just do what I suggest above.

Consider the following sequence:
* create file
* write 3MB
* truncate to 1MB
* seek to 3MB
* write 1MB of data

That should now give you a file that is 4MB in size, but only has valid data
in the first and last MB. The 2MB in the middle is a "hole" that should be
read as zeros.

YAFFS2 handles this by creating a shrink header to mark the beginning of the
hole.

If you run the garbage collector on the block containing the shrink header
(thus deleting the shrink header) and then do an unclean shut down, the
scanner will no longer know that there is a hole there and any remaining
chunks in that hole will come back to life.

This should only be an issue if you do weird things as shown above.

yaffs mitigates against this by only garbage collecting a block with shrink
headers if they meet certain criteria. See yaffs_block_ok_for_gc().

Thus I think the best approach for doing the refreshing is to introduce a new
mechanism for the handling of prioritised blocks that allows multiple blocks
to be held for refreshing. If you need a block refreshed then just add it to
the list and the gc mechanism will handle it when appropriate.

Does that sound valuable?

Charles