Re: [Yaffs] Why does YAFFS skip the first block?

Top Page
Attachments:
Message as email
+ (text/plain)
Delete this message
Reply to this message
Author: Charles Manning
Date:  
To: Peter Barada
CC: yaffs
New-Topics: Re: [Yaffs] Why does YAFFS skip the first block?
Subject: Re: [Yaffs] Why does YAFFS skip the first block?

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

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

While the loss of a single block is not significant for NAND systems it is
significant for many NOR systems. YAFFS is a NAND system, but there have
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 days.

-- 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, 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.



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

>
> > > 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).


This is mentioned in yaffs_fs.c.

The mkyaffsimage output is fine, so long as you write it into flash starting
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 -= 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.



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

In what way don't they match?

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


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