diff options
Diffstat (limited to 'fs/jffs2/scan.c')
-rw-r--r-- | fs/jffs2/scan.c | 85 |
1 files changed, 56 insertions, 29 deletions
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 5847e76ce16c..40d62d057aa4 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c | |||
@@ -437,11 +437,12 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock | |||
437 | } | 437 | } |
438 | #endif | 438 | #endif |
439 | 439 | ||
440 | /* Called with 'buf_size == 0' if buf is in fact a pointer _directly_ into | ||
441 | the flash, XIP-style */ | ||
440 | static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | 442 | static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, |
441 | unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) { | 443 | unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) { |
442 | struct jffs2_unknown_node *node; | 444 | struct jffs2_unknown_node *node; |
443 | struct jffs2_unknown_node crcnode; | 445 | struct jffs2_unknown_node crcnode; |
444 | struct jffs2_sum_marker *sm; | ||
445 | uint32_t ofs, prevofs; | 446 | uint32_t ofs, prevofs; |
446 | uint32_t hdr_crc, buf_ofs, buf_len; | 447 | uint32_t hdr_crc, buf_ofs, buf_len; |
447 | int err; | 448 | int err; |
@@ -475,44 +476,70 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo | |||
475 | #endif | 476 | #endif |
476 | 477 | ||
477 | if (jffs2_sum_active()) { | 478 | if (jffs2_sum_active()) { |
478 | sm = kmalloc(sizeof(struct jffs2_sum_marker), GFP_KERNEL); | 479 | struct jffs2_sum_marker *sm; |
479 | if (!sm) { | 480 | void *sumptr = NULL; |
480 | return -ENOMEM; | 481 | uint32_t sumlen; |
481 | } | 482 | |
483 | if (!buf_size) { | ||
484 | /* XIP case. Just look, point at the summary if it's there */ | ||
485 | sm = (void *)buf + jeb->offset - sizeof(*sm); | ||
486 | if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC) { | ||
487 | sumptr = buf + je32_to_cpu(sm->offset); | ||
488 | sumlen = c->sector_size - je32_to_cpu(sm->offset); | ||
489 | } | ||
490 | } else { | ||
491 | /* If NAND flash, read a whole page of it. Else just the end */ | ||
492 | if (c->wbuf_pagesize) | ||
493 | buf_len = c->wbuf_pagesize; | ||
494 | else | ||
495 | buf_len = sizeof(*sm); | ||
496 | |||
497 | /* Read as much as we want into the _end_ of the preallocated buffer */ | ||
498 | err = jffs2_fill_scan_buf(c, buf + buf_size - buf_len, | ||
499 | jeb->offset + c->sector_size - buf_len, | ||
500 | buf_len); | ||
501 | if (err) | ||
502 | return err; | ||
503 | |||
504 | sm = (void *)buf + buf_size - sizeof(*sm); | ||
505 | if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC) { | ||
506 | sumlen = c->sector_size - je32_to_cpu(sm->offset); | ||
507 | sumptr = buf + buf_size - sumlen; | ||
508 | |||
509 | /* Now, make sure the summary itself is available */ | ||
510 | if (sumlen > buf_size) { | ||
511 | /* Need to kmalloc for this. */ | ||
512 | sumptr = kmalloc(sumlen, GFP_KERNEL); | ||
513 | if (!sumptr) | ||
514 | return -ENOMEM; | ||
515 | memcpy(sumptr + sumlen - buf_len, buf + buf_size - buf_len, buf_len); | ||
516 | } | ||
517 | if (buf_len < sumlen) { | ||
518 | /* Need to read more so that the entire summary node is present */ | ||
519 | err = jffs2_fill_scan_buf(c, sumptr, | ||
520 | jeb->offset + c->sector_size - sumlen, | ||
521 | sumlen - buf_len); | ||
522 | if (err) | ||
523 | return err; | ||
524 | } | ||
525 | } | ||
482 | 526 | ||
483 | err = jffs2_fill_scan_buf(c, (unsigned char *) sm, jeb->offset + c->sector_size - | ||
484 | sizeof(struct jffs2_sum_marker), sizeof(struct jffs2_sum_marker)); | ||
485 | if (err) { | ||
486 | kfree(sm); | ||
487 | return err; | ||
488 | } | 527 | } |
489 | 528 | ||
490 | if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC ) { | 529 | if (sumptr) { |
491 | err = jffs2_sum_scan_sumnode(c, jeb, je32_to_cpu(sm->offset), &pseudo_random); | 530 | err = jffs2_sum_scan_sumnode(c, jeb, sumptr, sumlen, &pseudo_random); |
492 | if (err) { | 531 | if (err) |
493 | kfree(sm); | ||
494 | return err; | 532 | return err; |
495 | } | 533 | if (buf_size && sumlen > buf_size) |
534 | kfree(sumptr); | ||
496 | } | 535 | } |
497 | |||
498 | kfree(sm); | ||
499 | |||
500 | ofs = jeb->offset; | ||
501 | prevofs = jeb->offset - 1; | ||
502 | } | 536 | } |
503 | 537 | ||
504 | buf_ofs = jeb->offset; | 538 | buf_ofs = jeb->offset; |
505 | 539 | ||
506 | if (!buf_size) { | 540 | if (!buf_size) { |
541 | /* This is the XIP case -- we're reading _directly_ from the flash chip */ | ||
507 | buf_len = c->sector_size; | 542 | buf_len = c->sector_size; |
508 | |||
509 | if (jffs2_sum_active()) { | ||
510 | /* must reread because of summary test */ | ||
511 | err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len); | ||
512 | if (err) | ||
513 | return err; | ||
514 | } | ||
515 | |||
516 | } else { | 543 | } else { |
517 | buf_len = EMPTY_SCAN_SIZE(c->sector_size); | 544 | buf_len = EMPTY_SCAN_SIZE(c->sector_size); |
518 | err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len); | 545 | err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len); |