[PATCH] remove support for virtual blocks

Jörn Engel joern at wohnheim.fh-wedel.de
Tue Aug 30 06:27:39 EDT 2005


On Tue, 30 August 2005 11:56:10 +0200, Jörn Engel wrote:
> 
> You cannot kmalloc() more than 128k in a chunk.  Depending on your
> system, you could vmalloc() more.
> 
> It's not the eraseblock size that matters, it's the number of erase
> blocks.  One struct jffs2_eraseblock is needed for each and right now,
> they are put into a large array, allocated by kmalloc().  This array
> hits the ceiling at 128k.
> 
> What we have to do is allocate the memory in smaller chunks and put
> some effort into organizing it.  A slab cache would be the best idea.

Zhao asked me to write some documentation on the 1:1 problem and
possible solutions to it.  He's right, I should have done that long
ago.


	The problem

As explained above, there is a size limit to kmalloc().  Therefore,
JFFS2 in its original design cannot support flashes with more than
131072 / sizeof(struct jffs2_eraseblock) blocks.

In the current implementation, JFFS2 attempts to "solve" this problem
by creating virtual erase blocks.  If one struct takes 68 bytes, JFFS2
could support a maximum of 1927 blocks.  For a 2048 block device, it
will simply combine two physical blocks into one virtual, giving a
total of 1024 virtual blocks.  This is below the limit and everything
appeared to be well.

But it isn't.  The problem is that sizeof(struct jffs2_eraseblock) is
not a god-given constant but changes depending on your architecture
(bigger for 64bit machines, smaller for 32bit), patches you may have
applied (erase count and summary both add fields to the struct) and
possibly other things as well.  Thus, the number of blocks that JFFS2
can support it not fixed.

Since the maximum number of blocks is not fixed, it depends on your
architecture, kernel, etc. whether you have virtual blocks on your
system or you don't.  A kernel update could turn virtual mapping on or
off for your system.

One example of how this hurts you is this:

+----------------+----------------+
|node node node node node node ...|
+----------------+----------------+

You have two physical blocks combined into a virtual one.  Notice how
the fourth node is partially in one physical block and partially in
the other.  Now imagine your last kernel update shrunk struct
jffs2_eraseblock, so that you don't need virtual blocks anymore:

+----------------+----------------+
|node node node n|ode node node...|
+----------------+----------------+

The fourth node is divided into two parts.  Either one of them will
have CRC errors, thus it will be treated as garbage and removed.  Wave
your data a last goodbye, it will be gone once GC handles either of
those blocks.


	The solution

Quite a few things are possible now.  But any real fix for this design
problem will require a fixed amount of physical blocks to be part of a
virtual block.  No matter what else changes, the number of physical
blocks per virtual one *must not*.

Imo, the best number of physical blocks per virtual one to pick is one
(1).  Any higher number will limit scalability towards small flashes.
JFFS2 requires 5 erase blocks in _addition_ to whatever is occupied by
data.  With a 2:1 mapping, devices smaller than 12 physical blocks
wouldn't work with JFFS2 at all.

The rest is code and implementation details.

Jörn

-- 
I've never met a human being who would want to read 17,000 pages of
documentation, and if there was, I'd kill him to get him out of the
gene pool.
-- Joseph Costello




More information about the linux-mtd mailing list