[Yaffs] Why does YAFFS skip the first block?

Charles Manning manningc2@actrix.gen.nz
Wed Jun 22 05:55:23 BST 2005


I have thought of a very simple way to add the mapping stuff so that it i=
s=20
done completely internally to YAFFS, in a very non-obtrusive way (ie. I d=
on't=20
want to do something that potentially hurts what is already there). YAFFS=
=20
would then be able to accept and use block zero, but would work completel=
y=20
transparently if a non-zero starting block was used.

I think Frank's main point is that doing the work around (for YAFFS) requ=
ires=20
hacking the mtd access stuff. ie., It seems nuts to go hack somewhere els=
e to=20
fdo a YAFFS workaround. For the most part, people  using YAFFS on NOR hav=
e=20
done this with RTOSs, and had to write their own flash access functions s=
o it=20
was not a big deal.

While the loss of a single block is not significant for NAND systems it i=
s=20
significant for many NOR systems. YAFFS is a NAND system, but there have=20
already been some hacks done to make YAFFS NOR friendlier.

I consider my arm twisted and will do/test this in the next couple of day=
s.

-- Charles


On Wednesday 22 June 2005 16:09, you wrote:
> 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,  a=
nd
> > > > it is pretty straight forward. You just need to tell YAFFS some l=
ies!
> > > >
> > > > 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 =3D physical block 0.
> > > >
> > > > eg.
> > > > int (*writeChunkToNAND)(struct yaffs_DeviceStruct *dev,int
> > > > chunkInNAND, const __u8 *data, yaffs_Spare *spare)
> > > > {
> > > >       chunkInNAND -=3D 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 de=
vice
> > > > start and end blocks accordingly. If you have, say, 32 physical
> > > > blocks numbered from 0 to 31, then just set up startBlock=3D1 and
> > > > endBlock =3D32;
> > > >
> > > > There is no chunk or block info imprinted in the actual YAFFS dat=
a,
> > > > 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 dis=
rupt
> > 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 regio=
ns
> > 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 c=
hunk
> > zero, the search code  would report "it is in chunk zero" which the r=
est
> > 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.


The main offendiung function is yaffs_FindChunkInGroup() that looks at=20
theChunk. If theChunk was passed in as zero, then it means "chunk does no=
t=20
exist".

>
> > > I *could* do the remap in the access functions, but it *assumes som=
e
> > > 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 tha=
t
> 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 visibl=
e
> and usable...
>
> > Any offset is fine so long as there is no logical (ie from YAFFS's po=
int
> > 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 m=
ake
> > 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).

This is mentioned in yaffs_fs.c.

The mkyaffsimage output is fine, so long as you write it into flash start=
ing=20
at startBlock.



>
> > 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 -=3D 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 dow=
n
> this path should be able to tell you that.


The mkyaffsimage output is completely location independent, but it is=20
expected to be used with mkyaffs (which loads starting at block one). If =
you=20
take the image and load it into flash at block 1 you'll be OK.

In what way don't they match?=20

AFAIK,
1) yaffs_fs.c uses startBlock of 1
2) mkyaffs loads from block 1
3) yaffs_guts says block zero is not permitted.


<snip>

> 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 lowe=
r
> layer is clean with regard to the usable start of flash...

The main offender is how the tnodes work and FindChunkInFile which assume=
s=20
that the chunk does not exist if the chunkId is zero.







More information about the yaffs mailing list