public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot] [PATCH] JFFS2: accelerate scanning.
@ 2011-04-11 13:35 Leo Liu
  2011-04-13 11:31 ` Detlev Zundel
  0 siblings, 1 reply; 5+ messages in thread
From: Leo Liu @ 2011-04-11 13:35 UTC (permalink / raw)
  To: u-boot

This patch make the JFFS2 scanning faster in U-Boot.
1). if we find 1KB 0xFF data from the beginning of the erase block,skip it.
2). if the 1KB data is 0xFF after the cleanmarker, ship this erase block.

For the 16MB nor flash, the scanning time is changed from about 9s to 1s.

Signed-off-by: Leo Liu <liucai.lfn@gmail.com>
---
 fs/jffs2/jffs2_1pass.c      |   31 +++++++++++++++++++++----------
 fs/jffs2/jffs2_nand_1pass.c |    2 +-
 2 files changed, 22 insertions(+), 11 deletions(-)

diff --git a/fs/jffs2/jffs2_1pass.c b/fs/jffs2/jffs2_1pass.c
index dfb1745..f38f755 100644
--- a/fs/jffs2/jffs2_1pass.c
+++ b/fs/jffs2/jffs2_1pass.c
@@ -1441,7 +1441,7 @@ dump_dirents(struct b_lists *pL)
 }
 #endif
 
-#define DEFAULT_EMPTY_SCAN_SIZE	4096
+#define DEFAULT_EMPTY_SCAN_SIZE	1024
 
 static inline uint32_t EMPTY_SCAN_SIZE(uint32_t sector_size)
 {
@@ -1461,7 +1461,7 @@ jffs2_1pass_build_lists(struct part_info * part)
 	u32 counter4 = 0;
 	u32 counterF = 0;
 	u32 counterN = 0;
-	u32 buf_size = DEFAULT_EMPTY_SCAN_SIZE;
+	u32 buf_size = 128*1024;;
 	char *buf;
 
 	/* turn off the lcd.  Refreshing the lcd adds 50% overhead to the */
@@ -1559,14 +1559,17 @@ jffs2_1pass_build_lists(struct part_info * part)
 		/* We temporarily use 'ofs' as a pointer into the buffer/jeb */
 		ofs = 0;
 
-		/* Scan only 4KiB of 0xFF before declaring it's empty */
+		/* Scan only 1KiB of 0xFF before declaring it's empty */
 		while (ofs < EMPTY_SCAN_SIZE(part->sector_size) &&
 				*(uint32_t *)(&buf[ofs]) == 0xFFFFFFFF)
 			ofs += 4;
 
-		if (ofs == EMPTY_SCAN_SIZE(part->sector_size))
+		if (ofs == EMPTY_SCAN_SIZE(part->sector_size)) {
+			printf("Block at 0x%08x is empty (erased)\n", sector_ofs);
 			continue;
+		}
 
+		/* Now ofs is a complete physical flash offset as it always was... */
 		ofs += sector_ofs;
 		prevofs = ofs - 1;
 
@@ -1594,16 +1597,14 @@ jffs2_1pass_build_lists(struct part_info * part)
 
 			if (*(uint32_t *)(&buf[ofs-buf_ofs]) == 0xffffffff) {
 				uint32_t inbuf_ofs;
-				uint32_t empty_start, scan_end;
+				uint32_t empty_start;
 
 				empty_start = ofs;
 				ofs += 4;
-				scan_end = min_t(uint32_t, EMPTY_SCAN_SIZE(
-							part->sector_size)/8,
-							buf_len);
+				
 			more_empty:
 				inbuf_ofs = ofs - buf_ofs;
-				while (inbuf_ofs < scan_end) {
+				while (inbuf_ofs < buf_len) {
 					if (*(uint32_t *)(&buf[inbuf_ofs]) !=
 							0xffffffff)
 						goto scan_more;
@@ -1613,6 +1614,12 @@ jffs2_1pass_build_lists(struct part_info * part)
 				}
 				/* Ran off end. */
 
+				/* If we're only checking the beginning of a block with a cleanmarker,
+				   bail now */
+				if((buf_ofs == sector_ofs) && 
+					(node ==(struct jffs2_unknown_node *)&buf[ofs-buf_ofs])) 
+					break;
+	
 				/* See how much more there is to read in this
 				 * eraseblock...
 				 */
@@ -1627,12 +1634,12 @@ jffs2_1pass_build_lists(struct part_info * part)
 					 */
 					break;
 				}
-				scan_end = buf_len;
 				get_fl_mem((u32)part->offset + ofs, buf_len,
 					   buf);
 				buf_ofs = ofs;
 				goto more_empty;
 			}
+			
 			if (node->magic != JFFS2_MAGIC_BITMASK ||
 					!hdr_crc(node)) {
 				ofs += 4;
@@ -1650,6 +1657,8 @@ jffs2_1pass_build_lists(struct part_info * part)
 			case JFFS2_NODETYPE_INODE:
 				if (buf_ofs + buf_len < ofs + sizeof(struct
 							jffs2_raw_inode)) {
+					buf_len = min_t(uint32_t, buf_size, sector_ofs
+							+ part->sector_size - ofs);

 					get_fl_mem((u32)part->offset + ofs,
 						   buf_len, buf);
 					buf_ofs = ofs;
@@ -1671,6 +1680,8 @@ jffs2_1pass_build_lists(struct part_info * part)
 							((struct
 							 jffs2_raw_dirent *)
 							node)->nsize) {
+					buf_len = min_t(uint32_t, buf_size, sector_ofs
+							+ part->sector_size - ofs);

 					get_fl_mem((u32)part->offset + ofs,
 						   buf_len, buf);
 					buf_ofs = ofs;
diff --git a/fs/jffs2/jffs2_nand_1pass.c b/fs/jffs2/jffs2_nand_1pass.c
index e3bc536..16bb2e9 100644
--- a/fs/jffs2/jffs2_nand_1pass.c
+++ b/fs/jffs2/jffs2_nand_1pass.c
@@ -833,7 +833,7 @@ jffs2_1pass_build_lists(struct part_info * part)
 			return 0;
 
 		ofs = 0;
-		/* Scan only 4KiB of 0xFF before declaring it's empty */
+		/* Scan only 1KiB of 0xFF before declaring it's empty */
 		while (ofs < EMPTY_SCAN_SIZE && *(uint32_t *)(&buf[ofs]) == 0xFFFFFFFF)
 			ofs += 4;
 		if (ofs == EMPTY_SCAN_SIZE)
-- 
1.7.3.1.msysgit.0

^ permalink raw reply related	[flat|nested] 5+ messages in thread
* [U-Boot] [PATCH] JFFS2: accelerate scanning.
@ 2011-04-13 13:39 Baidu Liu
  2011-04-13 14:27 ` Detlev Zundel
  0 siblings, 1 reply; 5+ messages in thread
From: Baidu Liu @ 2011-04-13 13:39 UTC (permalink / raw)
  To: u-boot

Hi, Detlev

2011/4/13 Detlev Zundel <dzu@denx.de>:
> Hi Leo,
>
>> This patch make the JFFS2 scanning faster in U-Boot.
>> 1). if we find 1KB 0xFF data from the beginning of the erase block,skip it.
>> 2). if the 1KB data is 0xFF after the cleanmarker, ship this erase block.
>
> Ship it to where? ;)  Typo, should be skip.
>
Skip to the next erase block

>> For the 16MB nor flash, the scanning time is changed from about 9s to 1s.
>>
>> Signed-off-by: Leo Liu <liucai.lfn@gmail.com>
>
> checkpatch says:
>
> total: 7 errors, 9 warnings, 103 lines checked
>
> NOTE: whitespace errors detected, you may wish to use scripts/cleanpatch or
>      scripts/cleanfile
>
> Is there a corresponding thing in the Linux kernel?
>
>> ---
>>  fs/jffs2/jffs2_1pass.c      |   31 +++++++++++++++++++++----------
>>  fs/jffs2/jffs2_nand_1pass.c |    2 +-
>>  2 files changed, 22 insertions(+), 11 deletions(-)
>>
>> diff --git a/fs/jffs2/jffs2_1pass.c b/fs/jffs2/jffs2_1pass.c
>> index dfb1745..f38f755 100644
>> --- a/fs/jffs2/jffs2_1pass.c
>> +++ b/fs/jffs2/jffs2_1pass.c
>> @@ -1441,7 +1441,7 @@ dump_dirents(struct b_lists *pL)
>>  }
>>  #endif
>>
>> -#define DEFAULT_EMPTY_SCAN_SIZE      4096
>> +#define DEFAULT_EMPTY_SCAN_SIZE      1024
>
> Hm, this is not mentioned in the commit log.  So is this detection
> already there and you simply decrease the amount of empty space you are
> looking for?
>

1KB FF is enough to get the conclusion that the erase block is empty.
I refer kenel to do this change

>>
>>  static inline uint32_t EMPTY_SCAN_SIZE(uint32_t sector_size)
>>  {
>> @@ -1461,7 +1461,7 @@ jffs2_1pass_build_lists(struct part_info * part)
>>       u32 counter4 = 0;
>>       u32 counterF = 0;
>>       u32 counterN = 0;
>> -     u32 buf_size = DEFAULT_EMPTY_SCAN_SIZE;
>> +     u32 buf_size = 128*1024;;
>
> This is a 128k buffer size which previously was a 4k buffer.  Why is
> this change needed? Where does the size come from?
>
I refer the kenel jffs2 to do this change. we read 128 KB or size of a
erase block if the block size is less than 128 KB.

>>       char *buf;
>>
>>       /* turn off the lcd.  Refreshing the lcd adds 50% overhead to the */
>> @@ -1559,14 +1559,17 @@ jffs2_1pass_build_lists(struct part_info * part)
>>               /* We temporarily use 'ofs' as a pointer into the buffer/jeb */
>>               ofs = 0;
>>
>> -             /* Scan only 4KiB of 0xFF before declaring it's empty */
>> +             /* Scan only 1KiB of 0xFF before declaring it's empty */
>
> Change the comment to refer to the macro so we don't need to change it
> every time the macro changes.

Ok, i will do the change in the next patch

>
>>               while (ofs < EMPTY_SCAN_SIZE(part->sector_size) &&
>>                               *(uint32_t *)(&buf[ofs]) == 0xFFFFFFFF)
>>                       ofs += 4;
>>
>> -             if (ofs == EMPTY_SCAN_SIZE(part->sector_size))
>> +             if (ofs == EMPTY_SCAN_SIZE(part->sector_size)) {
>> +                     printf("Block at 0x%08x is empty (erased)\n", sector_ofs);
>
> Hm, you add this output so lets consider what it says - wouldn't it be
> better to say "is considered to be empty"?  After all, we only infer the
> emptiness in the code.
>
Yes, thanks. You description is better.

>>                       continue;
>> +             }
>>
>> +             /* Now ofs is a complete physical flash offset as it always was... */
>>               ofs += sector_ofs;
>>               prevofs = ofs - 1;
>>
>> @@ -1594,16 +1597,14 @@ jffs2_1pass_build_lists(struct part_info * part)
>>
>>                       if (*(uint32_t *)(&buf[ofs-buf_ofs]) == 0xffffffff) {
>>                               uint32_t inbuf_ofs;
>> -                             uint32_t empty_start, scan_end;
>> +                             uint32_t empty_start;
>>
>>                               empty_start = ofs;
>>                               ofs += 4;
>> -                             scan_end = min_t(uint32_t, EMPTY_SCAN_SIZE(
>> -                                                     part->sector_size)/8,
>> -                                                     buf_len);
>> +
>>                       more_empty:
>>                               inbuf_ofs = ofs - buf_ofs;
>> -                             while (inbuf_ofs < scan_end) {
>> +                             while (inbuf_ofs < buf_len) {
>>                                       if (*(uint32_t *)(&buf[inbuf_ofs]) !=
>>                                                       0xffffffff)
>>                                               goto scan_more;
>> @@ -1613,6 +1614,12 @@ jffs2_1pass_build_lists(struct part_info * part)
>>                               }
>>                               /* Ran off end. */
>>
>> +                             /* If we're only checking the beginning of a block with a cleanmarker,
>> +                                bail now */
>> +                             if((buf_ofs == sector_ofs) &&
>> +                                     (node ==(struct jffs2_unknown_node *)&buf[ofs-buf_ofs]))
>> +                                     break;
>> +
It is wrong here. I test in my board today. I will send a new patch to
correct this.

>>                               /* See how much more there is to read in this
>>                                * eraseblock...
>>                                */
>> @@ -1627,12 +1634,12 @@ jffs2_1pass_build_lists(struct part_info * part)
>>                                        */
>>                                       break;
>>                               }
>> -                             scan_end = buf_len;
>>                               get_fl_mem((u32)part->offset + ofs, buf_len,
>>                                          buf);
>>                               buf_ofs = ofs;
>>                               goto more_empty;
>>                       }
>> +
>>                       if (node->magic != JFFS2_MAGIC_BITMASK ||
>>                                       !hdr_crc(node)) {
>>                               ofs += 4;
>> @@ -1650,6 +1657,8 @@ jffs2_1pass_build_lists(struct part_info * part)
>>                       case JFFS2_NODETYPE_INODE:
>>                               if (buf_ofs + buf_len < ofs + sizeof(struct
>>                                                       jffs2_raw_inode)) {
>> +                                     buf_len = min_t(uint32_t, buf_size, sector_ofs
>> +                                                     + part->sector_size - ofs);
>>
>>                                       get_fl_mem((u32)part->offset + ofs,
>>                                                  buf_len, buf);
>>                                       buf_ofs = ofs;
>> @@ -1671,6 +1680,8 @@ jffs2_1pass_build_lists(struct part_info * part)
>>                                                       ((struct
>>                                                        jffs2_raw_dirent *)
>>                                                       node)->nsize) {
>> +                                     buf_len = min_t(uint32_t, buf_size, sector_ofs
>> +                                                     + part->sector_size - ofs);
>>
>>                                       get_fl_mem((u32)part->offset + ofs,
>>                                                  buf_len, buf);
>>                                       buf_ofs = ofs;
>> diff --git a/fs/jffs2/jffs2_nand_1pass.c b/fs/jffs2/jffs2_nand_1pass.c
>> index e3bc536..16bb2e9 100644
>> --- a/fs/jffs2/jffs2_nand_1pass.c
>> +++ b/fs/jffs2/jffs2_nand_1pass.c
>> @@ -833,7 +833,7 @@ jffs2_1pass_build_lists(struct part_info * part)
>>                       return 0;
>>
>>               ofs = 0;
>> -             /* Scan only 4KiB of 0xFF before declaring it's empty */
>> +             /* Scan only 1KiB of 0xFF before declaring it's empty */
>>               while (ofs < EMPTY_SCAN_SIZE && *(uint32_t *)(&buf[ofs]) == 0xFFFFFFFF)
>>                       ofs += 4;
>>               if (ofs == EMPTY_SCAN_SIZE)
>
> On a whole - is this optimization safe with regard to uncompressed files
> containing only 0xFFs?
>
Yes, I think it is ok. Most of the change is porting from kernel JFFS2.
We can see in the kernel we mount a 16MB , we need about 0.09s, but in
uboot, we need 9s


I wil send a new patch soon. Thanks

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2011-04-13 14:40 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-04-11 13:35 [U-Boot] [PATCH] JFFS2: accelerate scanning Leo Liu
2011-04-13 11:31 ` Detlev Zundel
  -- strict thread matches above, loose matches on Subject: below --
2011-04-13 13:39 Baidu Liu
2011-04-13 14:27 ` Detlev Zundel
2011-04-13 14:40   ` Joakim Tjernlund

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox