Skip to contentSkip to conversation

block2mtd oops in erase function.

PATCH In review Felix Fietkau 3 participants 12 messages Feb 19, 2007 – Feb 21, 2007 1 message not in the archive

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 block2mtd oops in erase function.

Hi, I have a small fix for a crash that happened when I was using jffs2 in combination with block2mtd.c

In the erase function when checking the block to see if it's already erased, the limit is to be set to the page_address(page) + PAGE_SIZE, but because the variable has the type (ulong *), it gets set to PAGE_SIZE*sizeof(ulong), which makes the kernel oops when the page is very close to the end of RAM.

drivers/mtd/devices/block2mtd.c renamed from drivers/mtd/devices/block2mtd.c.old +1 -1
@@ -111,7 +111,7 @@
 		if (IS_ERR(page))
 			return PTR_ERR(page);
 
-		max = (u_long*)page_address(page) + PAGE_SIZE;
+		max = (u_long*) ((u8 *) page_address(page) + PAGE_SIZE);
 		for (p=(u_long*)page_address(page); p<max; p++)
 			if (*p != -1UL) {
 				lock_page(page);
maintainer
#1 lore raw
Quoted 9 lines · Felix Fietkau

Hi, I have a small fix for a crash that happened when I was using jffs2 in combination with block2mtd.c

In the erase function when checking the block to see if it's already erased, the limit is to be set to the page_address(page) + PAGE_SIZE, but because the variable has the type (ulong *), it gets set to PAGE_SIZE*sizeof(ulong), which makes the kernel oops when the page is very close to the end of RAM.

Good catch! What a twisted little piece of code you've found.

drivers/mtd/devices/block2mtd.c line 117

Quoted 13 lines
drivers/mtd/devices/block2mtd.c renamed from drivers/mtd/devices/block2mtd.c.old +1 -1
@@ -111,7 +111,7 @@
 		if (IS_ERR(page))
 			return PTR_ERR(page);
 
-		max = (u_long*)page_address(page) + PAGE_SIZE;
+		max = (u_long*) ((u8 *) page_address(page) + PAGE_SIZE);
 		for (p=(u_long*)page_address(page); p<max; p++)
 			if (*p != -1UL) {
 				lock_page(page);

The proper fix would be to remove the cast instead of adding yet another. I wonder when those got added.

Jörn

Signature · 3 lines
He who knows others is wise.
He who knows himself is enlightened.
-- Lao Tsu
maintainer
#2 lore raw
Quoted 3 lines · Jörn Engel

The proper fix would be to remove the cast instead of adding yet another. I wonder when those got added.

On December 21st 2004 by none other than me. How embarrassing!
http://lists.infradead.org/pipermail/linux-mtd/2004-December/011236.html

Can you test this patch?

drivers/mtd/devices/block2mtd.c +2 -2
index f9f2ce7..6a9fb80 100644
@@ -111,8 +111,8 @@ static int _block2mtd_erase(struct block
 		if (IS_ERR(page))
 			return PTR_ERR(page);
 
-		max = (u_long*)page_address(page) + PAGE_SIZE;
-		for (p=(u_long*)page_address(page); p<max; p++)
+		max = page_address(page) + PAGE_SIZE;
+		for (p=page_address(page); p<max; p++)
 			if (*p != -1UL) {
 				lock_page(page);
 				memset(page_address(page), 0xff, PAGE_SIZE);

Jörn

Signature · 3 lines
"[One] doesn't need to know [...] how to cause a headache in order
to take an aspirin."
-- Scott Culp, Manager of the Microsoft Security Response Center, 2001
maintainer
#4 lore raw
Quoted 10 lines · Felix Fietkau

drivers/mtd/devices/block2mtd.c

Quoted 7 lines · Jörn Engel

On December 21st 2004 by none other than me. How embarrassing!
http://lists.infradead.org/pipermail/linux-mtd/2004-December/011236.html

Can you test this patch?

drivers/mtd/devices/block2mtd.c +0 -0
[...]

Works :)

Cool! Would you mind also trying two more patches? One of them just removes a compile warning if CONFIG_MODULE=n, the other rips out the readahead code, which should give a nice performance boost on USB sticks, MMC/SD, etc. Mounting JFFS2 in particular should be faster.

Jörn

Signature · 2 lines
It does not matter how slowly you go, so long as you do not stop.
-- Confucius
#5 lore raw
Quoted 4 lines · Jörn Engel

Cool! Would you mind also trying two more patches? One of them just removes a compile warning if CONFIG_MODULE=n, the other rips out the readahead code, which should give a nice performance boost on USB sticks, MMC/SD, etc. Mounting JFFS2 in particular should be faster.

I'm using jffs2 on block2mtd. I'd be happy to test any patches you have.

The readahead-disable one in particular is interesting - i ended up patching the source to get rid of the warning about readahead past end-of-disk. And mounting jffs2-on-block2mtd-on-ide-flash is quite slow.

Jason

---
 drivers/mtd/devices/block2mtd.c |    1 -
 1 file changed, 1 deletion(-)
drivers/mtd/devices/block2mtd.c +0 -1
Index: linux-2.6.20-rc5-uml/drivers/mtd/devices/block2mtd.c
===================================================================
@@ -63,7 +63,6 @@
 	for (i = 0; i < PAGE_READAHEAD; i++) {
 		pagei = index + i;
 		if (pagei > end_index) {
-			INFO("Overrun end of disk in cache readahead\n");
 			break;
 		}
 		page = radix_tree_lookup(&mapping->page_tree, pagei);
maintainer
#6 lore raw
Quoted 2 lines · Jason Lunz

I'm using jffs2 on block2mtd. I'd be happy to test any patches you have.

Is it ok if I just pass this URL?
http://kernel.org/git/?p=linux/kernel/git/joern/misc.git

The top three patches are test-worthy.

Quoted 3 lines

The readahead-disable one in particular is interesting - i ended up patching the source to get rid of the warning about readahead past end-of-disk. And mounting jffs2-on-block2mtd-on-ide-flash is quite slow.

If it works for you and improves mount time, that would be good results.

Jörn

Signature · 4 lines
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
maintainer
#8 lore raw
In reply to a message not in the archive
Quoted 7 lines · Jason Lunz
Quoted 4 lines · Jörn Engel

Is it ok if I just pass this URL?
http://kernel.org/git/?p=linux/kernel/git/joern/misc.git

The top three patches are test-worthy.

I'm running with all three. everything seems fine.

Great!

Quoted 1 line

Mount time of a ~56M jffs2 partition went from ~72s to ~54s.

Ouch! While this is a significant improvement, 54s is still quite bad. The 512MiB partition on the OLPC is mounting in ~3.4s with JFFS2 and ~60ms with LogFS. Imo 3.4s is already bad, and 54s is way beyond.

Now where is time lost? One candidate is erase block summary, enabling it usually gives roughly a 6x performance improvement. That would get you down to ~9s.

Another next thing I suspect is the erase size. The default is 4KiB, which is rather small. Can you try setting it to 64KiB or maybe even 128KiB?

Instead of passing "block2mtd=/dev/foo", you can pass "block2mtd=/dev/foo,64KiB" if my memory doesn't fail me.

Changing the erase size to a multiple of the previous erase size should be fine with JFFS2 (a smaller erase size could lead to data loss), but you likely won't get better performance unless you recreate the filesystem. Maybe something like

$ mount /dev/mtdX /mnt -t jffs2
$ (cd /mnt && tar cvpf /tmp/foo.tgz .)
$ umount /mnt
$ flash_eraseall /dev/mtdX
$ mount /dev/mtdX /mnt -t jffs2
$ (cd /mnt && tar vpf /tmp/foo.tgz)
$ umount /dev/mtdX

Unless you are happy with the current mount time, of course. Noone is forcing you to change anything.

Jörn

Signature · 2 lines
Do not stop an army on its way home.
-- Sun Tzu
#9 lore raw
Quoted 9 lines · Jörn Engel
Quoted 1 line

Mount time of a ~56M jffs2 partition went from ~72s to ~54s.

Ouch! While this is a significant improvement, 54s is still quite bad. The 512MiB partition on the OLPC is mounting in ~3.4s with JFFS2 and ~60ms with LogFS. Imo 3.4s is already bad, and 54s is way beyond.

Now where is time lost? One candidate is erase block summary, enabling it usually gives roughly a 6x performance improvement. That would get you down to ~9s.

How do I do that?

Quoted 3 lines

Another next thing I suspect is the erase size. The default is 4KiB, which is rather small. Can you try setting it to 64KiB or maybe even 128KiB?

Those timings are already using a 128k erase size.

A raw read of the underlying block device takes 54s, so jffs2 isn't adding any significant overhead anymore. It was when readahead was in use.

The only way to increase performance at this point is to make it so that jffs2 doesn't need to read the entire device at mount time. Is this what erase block summaries do?

Signature · 2 lines
Jason Lunz | Senior Developer | Reflex Security, Inc.
[email protected]
maintainer
#10 lore raw
Quoted 4 lines · Jason Lunz

A raw read of the underlying block device takes 54s, so jffs2 isn't adding any significant overhead anymore. It was when readahead was in use.

That is a bit surprising. JFFS2 has some optimizations to skip empty blocks after some bytes. This is where readahead really hurt - JFFS2 would skip and readahead would read the skipped data anyway. Now I can see that JFFS2 has some overhead over plain reading the device, but it is unusual that overhead and optimizations cancel each other out so perfectly.

Quoted 3 lines

The only way to increase performance at this point is to make it so that jffs2 doesn't need to read the entire device at mount time. Is this what erase block summaries do?

Yes. The idea is to only read the summary at the end of an erase block. If the summary does not exist, it will fall back to linear scanning of the block, afaik.

If you enable CONFIG_JFFS2_SUMMARY, it should work for you. Of course, your filesystem needs the summary, so you either have to do the backup&restore procedure or apply sumtool (is that its name?) to your images.

Jörn

Signature · 2 lines
Joern's library part 3:
http://inst.eecs.berkeley.edu/~cs152/fa05/handouts/clark-test.pdf
#11 lore raw
Quoted 4 lines · Jörn Engel

If you enable CONFIG_JFFS2_SUMMARY, it should work for you. Of course, your filesystem needs the summary, so you either have to do the backup&restore procedure or apply sumtool (is that its name?) to your images.

I thought I'd enabled CONFIG_JFFS2_SUMMARY, but it turns out not. I've enabled it now, but I still don't seem to see any speedup.

I'm unclear on how to make the filesystem use it. I create the jffs2 filesystem by simply doing:

flash_eraseall -j /dev/mtd0
mount -t jffs2 mtd0 /state

Will this create a summary automatically, or is there an extra step I need to take?

...ah, it seems removing the -j does the trick. If I don't use it, mount goes from >50s to <4s.

thanks!

Jason

maintainer
#12 lore raw
Quoted 3 lines · Jason Lunz

...ah, it seems removing the -j does the trick. If I don't use it, mount goes from >50s to <4s.

That's sounds better. Thank you for testing the patches.

Jörn

Signature · 2 lines
Time? What's that? Time is only worth what you do with it.
-- Theo de Raadt