diff options
Diffstat (limited to 'fs/jffs2/summary.c')
-rw-r--r-- | fs/jffs2/summary.c | 162 |
1 files changed, 49 insertions, 113 deletions
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c index 351ba9f8185e..ccb6803a6e41 100644 --- a/fs/jffs2/summary.c +++ b/fs/jffs2/summary.c | |||
@@ -369,22 +369,18 @@ no_mem: | |||
369 | return -ENOMEM; | 369 | return -ENOMEM; |
370 | } | 370 | } |
371 | 371 | ||
372 | static struct jffs2_raw_node_ref *alloc_ref_at(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | 372 | static struct jffs2_raw_node_ref *sum_link_node_ref(struct jffs2_sb_info *c, |
373 | uint32_t offset) | 373 | struct jffs2_eraseblock *jeb, |
374 | uint32_t ofs, uint32_t len, | ||
375 | struct jffs2_inode_cache *ic) | ||
374 | { | 376 | { |
375 | struct jffs2_raw_node_ref *ref; | ||
376 | /* If there was a gap, mark it dirty */ | 377 | /* If there was a gap, mark it dirty */ |
377 | if (offset > c->sector_size - jeb->free_size) { | 378 | if ((ofs & ~3) > c->sector_size - jeb->free_size) { |
378 | int ret = jffs2_scan_dirty_space(c, jeb, offset - (c->sector_size - jeb->free_size)); | 379 | /* Ew. Summary doesn't actually tell us explicitly about dirty space */ |
379 | if (ret) | 380 | jffs2_scan_dirty_space(c, jeb, (ofs & ~3) - (c->sector_size - jeb->free_size)); |
380 | return NULL; | ||
381 | } | 381 | } |
382 | ref = jffs2_alloc_raw_node_ref(); | ||
383 | if (!ref) | ||
384 | return NULL; | ||
385 | 382 | ||
386 | ref->flash_offset = jeb->offset + offset; | 383 | return jffs2_link_node_ref(c, jeb, jeb->offset + ofs, len, ic); |
387 | return ref; | ||
388 | } | 384 | } |
389 | 385 | ||
390 | /* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */ | 386 | /* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */ |
@@ -392,7 +388,6 @@ static struct jffs2_raw_node_ref *alloc_ref_at(struct jffs2_sb_info *c, struct j | |||
392 | static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | 388 | static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, |
393 | struct jffs2_raw_summary *summary, uint32_t *pseudo_random) | 389 | struct jffs2_raw_summary *summary, uint32_t *pseudo_random) |
394 | { | 390 | { |
395 | struct jffs2_raw_node_ref *raw; | ||
396 | struct jffs2_inode_cache *ic; | 391 | struct jffs2_inode_cache *ic; |
397 | struct jffs2_full_dirent *fd; | 392 | struct jffs2_full_dirent *fd; |
398 | void *sp; | 393 | void *sp; |
@@ -404,6 +399,11 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras | |||
404 | for (i=0; i<je32_to_cpu(summary->sum_num); i++) { | 399 | for (i=0; i<je32_to_cpu(summary->sum_num); i++) { |
405 | dbg_summary("processing summary index %d\n", i); | 400 | dbg_summary("processing summary index %d\n", i); |
406 | 401 | ||
402 | /* Make sure there's a spare ref for dirty space */ | ||
403 | err = jffs2_prealloc_raw_node_refs(c, 2); | ||
404 | if (err) | ||
405 | return err; | ||
406 | |||
407 | switch (je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) { | 407 | switch (je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) { |
408 | case JFFS2_NODETYPE_INODE: { | 408 | case JFFS2_NODETYPE_INODE: { |
409 | struct jffs2_sum_inode_flash *spi; | 409 | struct jffs2_sum_inode_flash *spi; |
@@ -415,22 +415,14 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras | |||
415 | jeb->offset + je32_to_cpu(spi->offset), | 415 | jeb->offset + je32_to_cpu(spi->offset), |
416 | jeb->offset + je32_to_cpu(spi->offset) + je32_to_cpu(spu->totlen)); | 416 | jeb->offset + je32_to_cpu(spi->offset) + je32_to_cpu(spu->totlen)); |
417 | 417 | ||
418 | raw = alloc_ref_at(c, jeb, je32_to_cpu(spi->offset)); | ||
419 | if (!raw) { | ||
420 | JFFS2_NOTICE("allocation of node reference failed\n"); | ||
421 | return -ENOMEM; | ||
422 | } | ||
423 | |||
424 | ic = jffs2_scan_make_ino_cache(c, ino); | 418 | ic = jffs2_scan_make_ino_cache(c, ino); |
425 | if (!ic) { | 419 | if (!ic) { |
426 | JFFS2_NOTICE("scan_make_ino_cache failed\n"); | 420 | JFFS2_NOTICE("scan_make_ino_cache failed\n"); |
427 | jffs2_free_raw_node_ref(raw); | ||
428 | return -ENOMEM; | 421 | return -ENOMEM; |
429 | } | 422 | } |
430 | 423 | ||
431 | raw->flash_offset |= REF_UNCHECKED; | 424 | sum_link_node_ref(c, jeb, je32_to_cpu(spi->offset) | REF_UNCHECKED, |
432 | 425 | PAD(je32_to_cpu(spi->totlen)), ic); | |
433 | jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spi->totlen)), ic); | ||
434 | 426 | ||
435 | *pseudo_random += je32_to_cpu(spi->version); | 427 | *pseudo_random += je32_to_cpu(spi->version); |
436 | 428 | ||
@@ -455,24 +447,15 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras | |||
455 | memcpy(&fd->name, spd->name, spd->nsize); | 447 | memcpy(&fd->name, spd->name, spd->nsize); |
456 | fd->name[spd->nsize] = 0; | 448 | fd->name[spd->nsize] = 0; |
457 | 449 | ||
458 | raw = alloc_ref_at(c, jeb, je32_to_cpu(spd->offset)); | ||
459 | if (!raw) { | ||
460 | jffs2_free_full_dirent(fd); | ||
461 | JFFS2_NOTICE("allocation of node reference failed\n"); | ||
462 | return -ENOMEM; | ||
463 | } | ||
464 | |||
465 | ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(spd->pino)); | 450 | ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(spd->pino)); |
466 | if (!ic) { | 451 | if (!ic) { |
467 | jffs2_free_full_dirent(fd); | 452 | jffs2_free_full_dirent(fd); |
468 | jffs2_free_raw_node_ref(raw); | ||
469 | return -ENOMEM; | 453 | return -ENOMEM; |
470 | } | 454 | } |
471 | 455 | ||
472 | raw->flash_offset |= REF_PRISTINE; | 456 | fd->raw = sum_link_node_ref(c, jeb, je32_to_cpu(spd->offset) | REF_PRISTINE, |
473 | jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spd->totlen)), ic); | 457 | PAD(je32_to_cpu(spd->totlen)), ic); |
474 | 458 | ||
475 | fd->raw = raw; | ||
476 | fd->next = NULL; | 459 | fd->next = NULL; |
477 | fd->version = je32_to_cpu(spd->version); | 460 | fd->version = je32_to_cpu(spd->version); |
478 | fd->ino = je32_to_cpu(spd->ino); | 461 | fd->ino = je32_to_cpu(spd->ino); |
@@ -497,15 +480,10 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras | |||
497 | jeb->offset + je32_to_cpu(spx->offset), | 480 | jeb->offset + je32_to_cpu(spx->offset), |
498 | jeb->offset + je32_to_cpu(spx->offset) + je32_to_cpu(spx->totlen), | 481 | jeb->offset + je32_to_cpu(spx->offset) + je32_to_cpu(spx->totlen), |
499 | je32_to_cpu(spx->xid), je32_to_cpu(spx->version)); | 482 | je32_to_cpu(spx->xid), je32_to_cpu(spx->version)); |
500 | raw = alloc_ref_at(c, jeb, je32_to_cpu(spx->offset)); | 483 | |
501 | if (!raw) { | ||
502 | JFFS2_NOTICE("allocation of node reference failed\n"); | ||
503 | return -ENOMEM; | ||
504 | } | ||
505 | xd = jffs2_setup_xattr_datum(c, je32_to_cpu(spx->xid), | 484 | xd = jffs2_setup_xattr_datum(c, je32_to_cpu(spx->xid), |
506 | je32_to_cpu(spx->version)); | 485 | je32_to_cpu(spx->version)); |
507 | if (IS_ERR(xd)) { | 486 | if (IS_ERR(xd)) { |
508 | jffs2_free_raw_node_ref(raw); | ||
509 | if (PTR_ERR(xd) == -EEXIST) { | 487 | if (PTR_ERR(xd) == -EEXIST) { |
510 | /* a newer version of xd exists */ | 488 | /* a newer version of xd exists */ |
511 | if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(spx->totlen)))) | 489 | if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(spx->totlen)))) |
@@ -516,12 +494,10 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras | |||
516 | JFFS2_NOTICE("allocation of xattr_datum failed\n"); | 494 | JFFS2_NOTICE("allocation of xattr_datum failed\n"); |
517 | return PTR_ERR(xd); | 495 | return PTR_ERR(xd); |
518 | } | 496 | } |
519 | xd->node = raw; | ||
520 | 497 | ||
521 | raw->flash_offset |= REF_UNCHECKED; | 498 | xd->node = sum_link_node_ref(c, jeb, je32_to_cpu(spx->offset) | REF_UNCHECKED, |
522 | 499 | PAD(je32_to_cpu(spx->totlen)), NULL); | |
523 | jffs2_link_node_ref(c, jeb, raw, PAD(je32_to_cpu(spx->totlen)), NULL); | 500 | /* FIXME */ xd->node->next_in_ino = (void *)xd; |
524 | /* FIXME */ raw->next_in_ino = (void *)xd; | ||
525 | 501 | ||
526 | *pseudo_random += je32_to_cpu(spx->xid); | 502 | *pseudo_random += je32_to_cpu(spx->xid); |
527 | sp += JFFS2_SUMMARY_XATTR_SIZE; | 503 | sp += JFFS2_SUMMARY_XATTR_SIZE; |
@@ -537,29 +513,21 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras | |||
537 | jeb->offset + je32_to_cpu(spr->offset), | 513 | jeb->offset + je32_to_cpu(spr->offset), |
538 | jeb->offset + je32_to_cpu(spr->offset) + PAD(sizeof(struct jffs2_raw_xref))); | 514 | jeb->offset + je32_to_cpu(spr->offset) + PAD(sizeof(struct jffs2_raw_xref))); |
539 | 515 | ||
540 | raw = alloc_ref_at(c, jeb, je32_to_cpu(spr->offset)); | ||
541 | if (!raw) { | ||
542 | JFFS2_NOTICE("allocation of node reference failed\n"); | ||
543 | return -ENOMEM; | ||
544 | } | ||
545 | ref = jffs2_alloc_xattr_ref(); | 516 | ref = jffs2_alloc_xattr_ref(); |
546 | if (!ref) { | 517 | if (!ref) { |
547 | JFFS2_NOTICE("allocation of xattr_datum failed\n"); | 518 | JFFS2_NOTICE("allocation of xattr_datum failed\n"); |
548 | jffs2_free_raw_node_ref(raw); | ||
549 | return -ENOMEM; | 519 | return -ENOMEM; |
550 | } | 520 | } |
551 | ref->ino = 0xfffffffe; | 521 | ref->ino = 0xfffffffe; |
552 | ref->xid = 0xfffffffd; | 522 | ref->xid = 0xfffffffd; |
553 | ref->node = raw; | ||
554 | ref->next = c->xref_temp; | 523 | ref->next = c->xref_temp; |
555 | c->xref_temp = ref; | 524 | c->xref_temp = ref; |
556 | 525 | ||
557 | raw->flash_offset |= REF_UNCHECKED; | 526 | ref->node = sum_link_node_ref(c, jeb, je32_to_cpu(spr->offset) | REF_UNCHECKED, |
527 | PAD(sizeof(struct jffs2_raw_xref)), NULL); | ||
528 | /* FIXME */ ref->node->next_in_ino = (void *)ref; | ||
558 | 529 | ||
559 | jffs2_link_node_ref(c, jeb, raw, PAD(sizeof(struct jffs2_raw_xref)), NULL); | 530 | *pseudo_random += ref->node->flash_offset; |
560 | /* FIXME */ raw->next_in_ino = (void *)ref; | ||
561 | |||
562 | *pseudo_random += raw->flash_offset; | ||
563 | sp += JFFS2_SUMMARY_XREF_SIZE; | 531 | sp += JFFS2_SUMMARY_XREF_SIZE; |
564 | 532 | ||
565 | break; | 533 | break; |
@@ -584,7 +552,6 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras | |||
584 | } | 552 | } |
585 | } | 553 | } |
586 | } | 554 | } |
587 | |||
588 | return 0; | 555 | return 0; |
589 | } | 556 | } |
590 | 557 | ||
@@ -594,7 +561,6 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb | |||
594 | uint32_t *pseudo_random) | 561 | uint32_t *pseudo_random) |
595 | { | 562 | { |
596 | struct jffs2_unknown_node crcnode; | 563 | struct jffs2_unknown_node crcnode; |
597 | struct jffs2_raw_node_ref *cache_ref; | ||
598 | int ret, ofs; | 564 | int ret, ofs; |
599 | uint32_t crc; | 565 | uint32_t crc; |
600 | int err; | 566 | int err; |
@@ -650,16 +616,8 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb | |||
650 | if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr))))) | 616 | if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr))))) |
651 | return err; | 617 | return err; |
652 | } else { | 618 | } else { |
653 | struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref(); | 619 | jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, |
654 | 620 | je32_to_cpu(summary->cln_mkr), NULL); | |
655 | if (!marker_ref) { | ||
656 | JFFS2_NOTICE("Failed to allocate node ref for clean marker\n"); | ||
657 | return -ENOMEM; | ||
658 | } | ||
659 | |||
660 | marker_ref->flash_offset = jeb->offset | REF_NORMAL; | ||
661 | |||
662 | jffs2_link_node_ref(c, jeb, marker_ref, je32_to_cpu(summary->cln_mkr), NULL); | ||
663 | } | 621 | } |
664 | } | 622 | } |
665 | 623 | ||
@@ -672,16 +630,11 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb | |||
672 | return ret; /* real error */ | 630 | return ret; /* real error */ |
673 | 631 | ||
674 | /* for PARANOIA_CHECK */ | 632 | /* for PARANOIA_CHECK */ |
675 | cache_ref = alloc_ref_at(c, jeb, ofs); | 633 | ret = jffs2_prealloc_raw_node_refs(c, 1); |
676 | 634 | if (ret) | |
677 | if (!cache_ref) { | 635 | return ret; |
678 | JFFS2_NOTICE("Failed to allocate node ref for cache\n"); | ||
679 | return -ENOMEM; | ||
680 | } | ||
681 | |||
682 | cache_ref->flash_offset |= REF_NORMAL; | ||
683 | 636 | ||
684 | jffs2_link_node_ref(c, jeb, cache_ref, sumsize, NULL); | 637 | jffs2_link_node_ref(c, jeb, (jeb->offset + ofs) | REF_NORMAL, sumsize, NULL); |
685 | 638 | ||
686 | if (unlikely(jeb->free_size)) { | 639 | if (unlikely(jeb->free_size)) { |
687 | JFFS2_WARNING("Free size 0x%x bytes in eraseblock @0x%08x with summary?\n", | 640 | JFFS2_WARNING("Free size 0x%x bytes in eraseblock @0x%08x with summary?\n", |
@@ -709,6 +662,7 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock | |||
709 | union jffs2_sum_mem *temp; | 662 | union jffs2_sum_mem *temp; |
710 | struct jffs2_sum_marker *sm; | 663 | struct jffs2_sum_marker *sm; |
711 | struct kvec vecs[2]; | 664 | struct kvec vecs[2]; |
665 | uint32_t sum_ofs; | ||
712 | void *wpage; | 666 | void *wpage; |
713 | int ret; | 667 | int ret; |
714 | size_t retlen; | 668 | size_t retlen; |
@@ -821,36 +775,31 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock | |||
821 | vecs[1].iov_base = c->summary->sum_buf; | 775 | vecs[1].iov_base = c->summary->sum_buf; |
822 | vecs[1].iov_len = datasize; | 776 | vecs[1].iov_len = datasize; |
823 | 777 | ||
778 | sum_ofs = jeb->offset + c->sector_size - jeb->free_size; | ||
779 | |||
824 | dbg_summary("JFFS2: writing out data to flash to pos : 0x%08x\n", | 780 | dbg_summary("JFFS2: writing out data to flash to pos : 0x%08x\n", |
825 | jeb->offset + c->sector_size - jeb->free_size); | 781 | sum_ofs); |
826 | 782 | ||
827 | spin_unlock(&c->erase_completion_lock); | 783 | ret = jffs2_flash_writev(c, vecs, 2, sum_ofs, &retlen, 0); |
828 | ret = jffs2_flash_writev(c, vecs, 2, jeb->offset + c->sector_size - | ||
829 | jeb->free_size, &retlen, 0); | ||
830 | 784 | ||
831 | if (ret || (retlen != infosize)) { | 785 | if (ret || (retlen != infosize)) { |
832 | struct jffs2_raw_node_ref *ref; | ||
833 | 786 | ||
834 | JFFS2_WARNING("Write of %u bytes at 0x%08x failed. returned %d, retlen %zd\n", | 787 | JFFS2_WARNING("Write of %u bytes at 0x%08x failed. returned %d, retlen %zd\n", |
835 | infosize, jeb->offset + c->sector_size - jeb->free_size, ret, retlen); | 788 | infosize, sum_ofs, ret, retlen); |
836 | 789 | ||
837 | /* Waste remaining space */ | 790 | /* Waste remaining space */ |
838 | ref = jffs2_alloc_raw_node_ref(); | 791 | spin_lock(&c->erase_completion_lock); |
839 | if (ref) { | 792 | jffs2_link_node_ref(c, jeb, sum_ofs | REF_OBSOLETE, infosize, NULL); |
840 | spin_lock(&c->erase_completion_lock); | 793 | spin_unlock(&c->erase_completion_lock); |
841 | |||
842 | ref->flash_offset = jeb->offset + c->sector_size - jeb->free_size; | ||
843 | ref->flash_offset |= REF_OBSOLETE; | ||
844 | |||
845 | jffs2_link_node_ref(c, jeb, ref, c->sector_size - jeb->free_size, NULL); | ||
846 | } | ||
847 | 794 | ||
848 | c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE; | 795 | c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE; |
849 | 796 | ||
850 | return 1; | 797 | return 0; |
851 | } | 798 | } |
852 | 799 | ||
853 | spin_lock(&c->erase_completion_lock); | 800 | spin_lock(&c->erase_completion_lock); |
801 | jffs2_link_node_ref(c, jeb, sum_ofs | REF_NORMAL, infosize, NULL); | ||
802 | spin_unlock(&c->erase_completion_lock); | ||
854 | 803 | ||
855 | return 0; | 804 | return 0; |
856 | } | 805 | } |
@@ -859,12 +808,15 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock | |||
859 | 808 | ||
860 | int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) | 809 | int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) |
861 | { | 810 | { |
862 | struct jffs2_raw_node_ref *summary_ref; | 811 | int datasize, infosize, padsize; |
863 | int datasize, infosize, padsize, ret; | ||
864 | struct jffs2_eraseblock *jeb; | 812 | struct jffs2_eraseblock *jeb; |
813 | int ret; | ||
865 | 814 | ||
866 | dbg_summary("called\n"); | 815 | dbg_summary("called\n"); |
867 | 816 | ||
817 | spin_unlock(&c->erase_completion_lock); | ||
818 | jffs2_prealloc_raw_node_refs(c, 1); | ||
819 | |||
868 | jeb = c->nextblock; | 820 | jeb = c->nextblock; |
869 | 821 | ||
870 | if (!c->summary->sum_num || !c->summary->sum_list_head) { | 822 | if (!c->summary->sum_num || !c->summary->sum_list_head) { |
@@ -888,22 +840,6 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) | |||
888 | } | 840 | } |
889 | 841 | ||
890 | ret = jffs2_sum_write_data(c, jeb, infosize, datasize, padsize); | 842 | ret = jffs2_sum_write_data(c, jeb, infosize, datasize, padsize); |
891 | if (ret) | ||
892 | return 0; /* can't write out summary, block is marked as NOSUM_SIZE */ | ||
893 | |||
894 | /* for ACCT_PARANOIA_CHECK */ | ||
895 | spin_unlock(&c->erase_completion_lock); | ||
896 | summary_ref = jffs2_alloc_raw_node_ref(); | ||
897 | |||
898 | if (!summary_ref) { | ||
899 | JFFS2_NOTICE("Failed to allocate node ref for summary\n"); | ||
900 | return -ENOMEM; | ||
901 | } | ||
902 | |||
903 | summary_ref->flash_offset = (jeb->offset + c->sector_size - jeb->free_size) | REF_NORMAL; | ||
904 | |||
905 | spin_lock(&c->erase_completion_lock); | 843 | spin_lock(&c->erase_completion_lock); |
906 | jffs2_link_node_ref(c, jeb, summary_ref, infosize, NULL); | 844 | return ret; |
907 | |||
908 | return 0; | ||
909 | } | 845 | } |