[Yaffs] Why does YAFFS skip the first block?
Peter Barada
Peter.B@LogicPD.com
Wed Jun 22 05:09:51 BST 2005
On Wed, 2005-06-22 at 13:06 +1200, Charles Manning wrote:
> On Wednesday 22 June 2005 12:13, Peter Barada wrote:
> <snip>
> > > All is not lost though, there is a way to use that block zero, and it is
> > > pretty straight forward. You just need to tell YAFFS some lies!
> > >
> > > All yaffs flash calls go through a few access functions.
> > > All you need to do is to do a mapping in these functions so that yaffs
> > > block 1 = physical block 0.
> > >
> > > eg.
> > > int (*writeChunkToNAND)(struct yaffs_DeviceStruct *dev,int chunkInNAND,
> > > const __u8 *data, yaffs_Spare *spare)
> > > {
> > > chunkInNAND -= dev->nChunksPerBlock;
> > >
> > > ..... // rest of stuff
> > > }
> > >
> > > int (*eraseBlockInNAND)(struct yaffs_DeviceStruct *dev,int blockInNAND)
> > > {
> > > blockInNAND--;
> > > ...// rest of stuff
> > > }
> > >
> > > Now you must need to keep the illusion going by setting up the device
> > > start and end blocks accordingly. If you have, say, 32 physical blocks
> > > numbered from 0 to 31, then just set up startBlock=1 and endBlock =32;
> > >
> > > There is no chunk or block info imprinted in the actual YAFFS data, so no
> > > changes are needed to mkyaffsimage etc to make this work.
> >
> > Ugh, that sounds like a *total* hack.
>
> So what? It is very simple, works fine, is efficient and does not disrupt
> stable code.
Yes it is a *simple* hack, but it builds on other "lies"(your words) in
the definition of YAFFS, i.e. that it *never* uses any data below the
first 'block' of flash. For NAND devices where block sizes are small
compared to the number of blocks, then this is no problem. In the case
where there are 4 8-bit flash parts, each with a 64k block size on a 32-
bit bus, you're talking about a 256K block size in 16M of memory which
is pretty darn large.
> As it is, you're already pulling nastier hacks to emulate spare regions etc
> to make NOR look like NAND.
That is because I want to use YAFFS on a NOR device because my hardware
has NOR devices. Of course I have to pull a hack. At least its a
*very* clean hack and hides itself from any layers above it.
> >Is there anything wrong with
> > allowing dev->startBlock to be zero instead of 1?
>
> This would not work for various things.
> For example when YAFFS goes to look for the chunkId of the chunk in chunk
> zero, the search code would report "it is in chunk zero" which the rest of
> yaffs interprets as "it does not exist". So anything you write to chunk zero
> is written into a black hole.
Can you give me a pointer to function/line where this test is? Perhaps
fixing YAFFS to handle block zero is better than forcing a 'hack' at a
lower layer.
> >
> > I *could* do the remap in the access functions, but it *assumes some
> > magical offset that requires a comment of:
> >
> > /* This is a total hack since YAFFS refuses to use block zero */
>
> Hack, maybe. Total hack, I think, is stating it a bit strongly.
Yes, "total" hack was a bit strong, but after using mkyaffsimage to
create a image that I put into flash, and finding that I couldn't find
some partial bits of it(and a bunch of objects end up in lost+found that
can't even be opened), I may have expressed my frustration a bit strong.
You can see where that comes from when 85% of the flash image is visible
and usable...
> Any offset is fine so long as there is no logical (ie from YAFFS's point of
> view) chunk zero any more. Just using a one block offset is the simplest
> case. Counting from one instead of zero is hardly going to make most
> programmers spill their cup of tea.
No, they won't spill their tea, but if you have 16MB of flash hooked up
that the minimum erase size is 256K, then that one lost block is
*really* aggrevating, especially since yaffs_mtdif.c doesn't mention
that block zero is ignored(and an offset should be applied).
> You can just use fixed constants in your mapping: Offset by one block. Since
> dev->nChunksPerBlock holds the number of chunks per block that is all you
> need to offset by for the reading/writing of a block.
>
> This means, all up, you need to add three lines of code:
>
> blockId--; // add to the erase function
>
> chunkId -= dev->nChunksPerBlock; // add to read/write functions
>
> And change two lines where you set the start and end blocks.
>
> Changing five lines of code is hardly a large effort. Much less than, say,
> writing an email.
Only after its taken a long day of yanking your hair out to understand
the problem. No offense, but yaffs_fs.c, yaffs_mdtif.c and
mkyaffsimage.c don't match as they exist now, and the documentation
doesn't mention that the image created by mkyaffsimage.c should be
offset by a flash block so that it all works. Anyone who's marched down
this path should be able to tell you that.
> >
> > Is there anything *actually* wrong with using block zero? If what you
> > say is true for NAND, then you don't even bother using the one
> > guaranteed good block in the device...
>
> There is nothing technically wrong with using block zero from a memory/NAND
> perspective. At the end of the day, file system integrity is governed by the
> performance of the worst block and not the best block. Block zero is only
> guaranteed good at the time of shipping and can go bad with time. Also,
> many/most systems use block zero for some other purpose (eg. boot data or bad
> block marker). Thus, relying on chunk zero being good is pointless.
I'm already trying to use MTD underneath YAFFS, so this should be
*completely* hidden from YAFFS point of view. I.E. the start of flash
has a boot-loader in it and I'm using the following 15MB of a 16MB flash
space, so I've partitioned the flash with 1MB for the base, and 15MB for
YAFFS which YAFFS "conveniently" skips the first 256K space or 1.7% of
the usable space(before you remove from use the reserved blocks).
> Yaffs needs some chunk/block Id for "does not exist". As I mentioned before,
> this could have been 0xFFFFFFFF/-1, but there are places (eg. Tnodes) where
> YAFFS uses 16 bit values. Using 0xFFFFFFFF as an invalid marker gets to be a
> headache when using 16 and 32 bits because we'd have to look at special
> cases. Zero is way easier.
>
> Now this mapping stuff could be done in YAFFS so that YAFFS would be able to
> start at block zero, but this has not yet risen to the top of the important
> things to do pile, mainly because the workaround is trivial (which implies,
> of course that fixing it in YAFFS is trivial too :-)).
Tell me where the code is that assumes block zero is "does not exist",
and I'll be glad to create/test(using LTP fs tests) a patch so the lower
layer is clean with regard to the usable start of flash...
--
Peter Barada <Peter.B@LogicPD.com>
More information about the yaffs
mailing list