aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2006-05-20 11:13:34 -0400
committerDavid Woodhouse <dwmw2@infradead.org>2006-05-20 11:13:34 -0400
commit9641b784ff82cf0a48a6c70ef9867f5fd728de67 (patch)
tree40d7bbc06ee5e54560ea7e7dabe75ac01a72e00c
parent6c8b44abc86a3e23dd1a22c0ee187f06bd7c7f5d (diff)
[JFFS2] Optimise reading of eraseblock summary nodes
This improves the time to mount 512MiB of NAND flash on my OLPC prototype by about 4%. We used to read the last page of the eraseblock twice -- once to find the offset of the summary node, and again to actually _read_ the summary node. Now we read the last page only once, and read more only if we need to. We also don't allocate a new buffer just for the summary code -- we use the buffer which was already allocated for the scan. Better still, if the 'buffer' for the scan is actually just a pointer directly into NOR flash, we use that too, avoiding the memcpy() which we used to do. Signed-off-by: David Woodhouse <dwmw2@infradead.org>
-rw-r--r--fs/jffs2/scan.c74
-rw-r--r--fs/jffs2/summary.c36
-rw-r--r--fs/jffs2/summary.h3
3 files changed, 64 insertions, 49 deletions
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index 352ada892f3e..2a24b44662bb 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -306,11 +306,12 @@ int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *je
306 return BLK_STATE_ALLDIRTY; 306 return BLK_STATE_ALLDIRTY;
307} 307}
308 308
309/* Called with 'buf_size == 0' if buf is in fact a pointer _directly_ into
310 the flash, XIP-style */
309static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 311static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
310 unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) { 312 unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) {
311 struct jffs2_unknown_node *node; 313 struct jffs2_unknown_node *node;
312 struct jffs2_unknown_node crcnode; 314 struct jffs2_unknown_node crcnode;
313 struct jffs2_sum_marker *sm;
314 uint32_t ofs, prevofs; 315 uint32_t ofs, prevofs;
315 uint32_t hdr_crc, buf_ofs, buf_len; 316 uint32_t hdr_crc, buf_ofs, buf_len;
316 int err; 317 int err;
@@ -344,32 +345,69 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
344#endif 345#endif
345 346
346 if (jffs2_sum_active()) { 347 if (jffs2_sum_active()) {
347 sm = kmalloc(sizeof(struct jffs2_sum_marker), GFP_KERNEL); 348 struct jffs2_sum_marker *sm;
348 if (!sm) { 349 void *sumptr = NULL;
349 return -ENOMEM; 350 uint32_t sumlen;
350 } 351
352 if (!buf_size) {
353 /* XIP case. Just look, point at the summary if it's there */
354 sm = (void *)buf + jeb->offset - sizeof(*sm);
355 if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC) {
356 sumptr = buf + je32_to_cpu(sm->offset);
357 sumlen = c->sector_size - je32_to_cpu(sm->offset);
358 }
359 } else {
360 /* If NAND flash, read a whole page of it. Else just the end */
361 if (c->wbuf_pagesize)
362 buf_len = c->wbuf_pagesize;
363 else
364 buf_len = sizeof(*sm);
365
366 /* Read as much as we want into the _end_ of the preallocated buffer */
367 err = jffs2_fill_scan_buf(c, buf + buf_size - buf_len,
368 jeb->offset + c->sector_size - buf_len,
369 buf_len);
370 if (err)
371 return err;
372
373 sm = (void *)buf + buf_size - sizeof(*sm);
374 if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC) {
375 sumlen = c->sector_size - je32_to_cpu(sm->offset);
376 sumptr = buf + buf_size - sumlen;
377
378 /* Now, make sure the summary itself is available */
379 if (sumlen > buf_size) {
380 /* Need to kmalloc for this. */
381 sumptr = kmalloc(sumlen, GFP_KERNEL);
382 if (!sumptr)
383 return -ENOMEM;
384 memcpy(sumptr + sumlen - buf_len, buf + buf_size - buf_len, buf_len);
385 }
386 if (buf_len < sumlen) {
387 /* Need to read more so that the entire summary node is present */
388 err = jffs2_fill_scan_buf(c, sumptr,
389 jeb->offset + c->sector_size - sumlen,
390 sumlen - buf_len);
391 if (err)
392 return err;
393 }
394 }
351 395
352 err = jffs2_fill_scan_buf(c, (unsigned char *) sm, jeb->offset + c->sector_size -
353 sizeof(struct jffs2_sum_marker), sizeof(struct jffs2_sum_marker));
354 if (err) {
355 kfree(sm);
356 return err;
357 } 396 }
358 397
359 if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC ) { 398 if (sumptr) {
360 err = jffs2_sum_scan_sumnode(c, jeb, je32_to_cpu(sm->offset), &pseudo_random); 399 err = jffs2_sum_scan_sumnode(c, jeb, sumptr, sumlen, &pseudo_random);
361 if (err) { 400 if (err)
362 kfree(sm);
363 return err; 401 return err;
364 } 402 if (buf_size && sumlen > buf_size)
403 kfree(sumptr);
365 } 404 }
366
367 kfree(sm);
368 } 405 }
369 406
370 buf_ofs = jeb->offset; 407 buf_ofs = jeb->offset;
371 408
372 if (!buf_size) { 409 if (!buf_size) {
410 /* This is the XIP case -- we're reading _directly_ from the flash chip */
373 buf_len = c->sector_size; 411 buf_len = c->sector_size;
374 } else { 412 } else {
375 buf_len = EMPTY_SCAN_SIZE(c->sector_size); 413 buf_len = EMPTY_SCAN_SIZE(c->sector_size);
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c
index 48293c197f13..82a3706c54d8 100644
--- a/fs/jffs2/summary.c
+++ b/fs/jffs2/summary.c
@@ -318,7 +318,6 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
318 raw = jffs2_alloc_raw_node_ref(); 318 raw = jffs2_alloc_raw_node_ref();
319 if (!raw) { 319 if (!raw) {
320 JFFS2_NOTICE("allocation of node reference failed\n"); 320 JFFS2_NOTICE("allocation of node reference failed\n");
321 kfree(summary);
322 return -ENOMEM; 321 return -ENOMEM;
323 } 322 }
324 323
@@ -326,7 +325,6 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
326 if (!ic) { 325 if (!ic) {
327 JFFS2_NOTICE("scan_make_ino_cache failed\n"); 326 JFFS2_NOTICE("scan_make_ino_cache failed\n");
328 jffs2_free_raw_node_ref(raw); 327 jffs2_free_raw_node_ref(raw);
329 kfree(summary);
330 return -ENOMEM; 328 return -ENOMEM;
331 } 329 }
332 330
@@ -358,10 +356,8 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
358 jeb->offset + je32_to_cpu(spd->offset)); 356 jeb->offset + je32_to_cpu(spd->offset));
359 357
360 fd = jffs2_alloc_full_dirent(spd->nsize+1); 358 fd = jffs2_alloc_full_dirent(spd->nsize+1);
361 if (!fd) { 359 if (!fd)
362 kfree(summary);
363 return -ENOMEM; 360 return -ENOMEM;
364 }
365 361
366 memcpy(&fd->name, spd->name, spd->nsize); 362 memcpy(&fd->name, spd->name, spd->nsize);
367 fd->name[spd->nsize] = 0; 363 fd->name[spd->nsize] = 0;
@@ -370,7 +366,6 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
370 if (!raw) { 366 if (!raw) {
371 jffs2_free_full_dirent(fd); 367 jffs2_free_full_dirent(fd);
372 JFFS2_NOTICE("allocation of node reference failed\n"); 368 JFFS2_NOTICE("allocation of node reference failed\n");
373 kfree(summary);
374 return -ENOMEM; 369 return -ENOMEM;
375 } 370 }
376 371
@@ -378,7 +373,6 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
378 if (!ic) { 373 if (!ic) {
379 jffs2_free_full_dirent(fd); 374 jffs2_free_full_dirent(fd);
380 jffs2_free_raw_node_ref(raw); 375 jffs2_free_raw_node_ref(raw);
381 kfree(summary);
382 return -ENOMEM; 376 return -ENOMEM;
383 } 377 }
384 378
@@ -411,45 +405,28 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
411 405
412 default : { 406 default : {
413 JFFS2_WARNING("Unsupported node type found in summary! Exiting..."); 407 JFFS2_WARNING("Unsupported node type found in summary! Exiting...");
414 kfree(summary);
415 return -EIO; 408 return -EIO;
416 } 409 }
417 } 410 }
418 } 411 }
419 412
420 kfree(summary);
421 return 0; 413 return 0;
422} 414}
423 415
424/* Process the summary node - called from jffs2_scan_eraseblock() */ 416/* Process the summary node - called from jffs2_scan_eraseblock() */
425
426int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 417int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
427 uint32_t ofs, uint32_t *pseudo_random) 418 struct jffs2_raw_summary *summary, uint32_t sumsize,
419 uint32_t *pseudo_random)
428{ 420{
429 struct jffs2_unknown_node crcnode; 421 struct jffs2_unknown_node crcnode;
430 struct jffs2_raw_node_ref *cache_ref; 422 struct jffs2_raw_node_ref *cache_ref;
431 struct jffs2_raw_summary *summary; 423 int ret, ofs;
432 int ret, sumsize;
433 uint32_t crc; 424 uint32_t crc;
434 425
435 sumsize = c->sector_size - ofs; 426 ofs = jeb->offset + c->sector_size - sumsize;
436 ofs += jeb->offset;
437 427
438 dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n", 428 dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n",
439 jeb->offset, ofs, sumsize); 429 jeb->offset, ofs, sumsize);
440
441 summary = kmalloc(sumsize, GFP_KERNEL);
442
443 if (!summary) {
444 return -ENOMEM;
445 }
446
447 ret = jffs2_fill_scan_buf(c, (unsigned char *)summary, ofs, sumsize);
448
449 if (ret) {
450 kfree(summary);
451 return ret;
452 }
453 430
454 /* OK, now check for node validity and CRC */ 431 /* OK, now check for node validity and CRC */
455 crcnode.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 432 crcnode.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -499,7 +476,6 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
499 476
500 if (!marker_ref) { 477 if (!marker_ref) {
501 JFFS2_NOTICE("Failed to allocate node ref for clean marker\n"); 478 JFFS2_NOTICE("Failed to allocate node ref for clean marker\n");
502 kfree(summary);
503 return -ENOMEM; 479 return -ENOMEM;
504 } 480 }
505 481
diff --git a/fs/jffs2/summary.h b/fs/jffs2/summary.h
index b7a678be1709..afff4bd551a1 100644
--- a/fs/jffs2/summary.h
+++ b/fs/jffs2/summary.h
@@ -160,7 +160,8 @@ int jffs2_sum_add_padding_mem(struct jffs2_summary *s, uint32_t size);
160int jffs2_sum_add_inode_mem(struct jffs2_summary *s, struct jffs2_raw_inode *ri, uint32_t ofs); 160int jffs2_sum_add_inode_mem(struct jffs2_summary *s, struct jffs2_raw_inode *ri, uint32_t ofs);
161int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *rd, uint32_t ofs); 161int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *rd, uint32_t ofs);
162int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 162int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
163 uint32_t ofs, uint32_t *pseudo_random); 163 struct jffs2_raw_summary *summary, uint32_t sumlen,
164 uint32_t *pseudo_random);
164 165
165#else /* SUMMARY DISABLED */ 166#else /* SUMMARY DISABLED */
166 167