diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-06-03 18:59:32 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-06-03 18:59:32 -0400 |
| commit | 3af91a1256b628d55913324d27fe747c69566749 (patch) | |
| tree | cdbb84d4cce611ba722699d989bf1fecb73a69f1 | |
| parent | 9a44fde3435e0c6012cbc9122497bbbd3338434a (diff) | |
| parent | 098011940a2549ae7182db4bf101c3e3d2b4e6df (diff) | |
Merge branch 'linux-next' of git://git.infradead.org/ubifs-2.6
* 'linux-next' of git://git.infradead.org/ubifs-2.6:
UBIFS: fix-up free space earlier
UBIFS: intialize LPT earlier
UBIFS: assert no fixup when writing a node
UBIFS: fix clean znode counter corruption in error cases
UBIFS: fix memory leak on error path
UBIFS: fix shrinker object count reports
UBIFS: fix recovery broken by the previous recovery fix
UBIFS: amend ubifs_recover_leb interface
UBIFS: introduce a "grouped" journal head flag
UBIFS: supress false error messages
| -rw-r--r-- | fs/ubifs/io.c | 2 | ||||
| -rw-r--r-- | fs/ubifs/journal.c | 1 | ||||
| -rw-r--r-- | fs/ubifs/orphan.c | 2 | ||||
| -rw-r--r-- | fs/ubifs/recovery.c | 164 | ||||
| -rw-r--r-- | fs/ubifs/replay.c | 3 | ||||
| -rw-r--r-- | fs/ubifs/shrinker.c | 6 | ||||
| -rw-r--r-- | fs/ubifs/super.c | 42 | ||||
| -rw-r--r-- | fs/ubifs/tnc.c | 9 | ||||
| -rw-r--r-- | fs/ubifs/ubifs.h | 4 |
9 files changed, 136 insertions, 97 deletions
diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c index 166951e0dcd3..3be645e012c9 100644 --- a/fs/ubifs/io.c +++ b/fs/ubifs/io.c | |||
| @@ -581,6 +581,7 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len) | |||
| 581 | ubifs_assert(wbuf->size % c->min_io_size == 0); | 581 | ubifs_assert(wbuf->size % c->min_io_size == 0); |
| 582 | ubifs_assert(mutex_is_locked(&wbuf->io_mutex)); | 582 | ubifs_assert(mutex_is_locked(&wbuf->io_mutex)); |
| 583 | ubifs_assert(!c->ro_media && !c->ro_mount); | 583 | ubifs_assert(!c->ro_media && !c->ro_mount); |
| 584 | ubifs_assert(!c->space_fixup); | ||
| 584 | if (c->leb_size - wbuf->offs >= c->max_write_size) | 585 | if (c->leb_size - wbuf->offs >= c->max_write_size) |
| 585 | ubifs_assert(!((wbuf->offs + wbuf->size) % c->max_write_size)); | 586 | ubifs_assert(!((wbuf->offs + wbuf->size) % c->max_write_size)); |
| 586 | 587 | ||
| @@ -759,6 +760,7 @@ int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum, | |||
| 759 | ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0); | 760 | ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0); |
| 760 | ubifs_assert(offs % c->min_io_size == 0 && offs < c->leb_size); | 761 | ubifs_assert(offs % c->min_io_size == 0 && offs < c->leb_size); |
| 761 | ubifs_assert(!c->ro_media && !c->ro_mount); | 762 | ubifs_assert(!c->ro_media && !c->ro_mount); |
| 763 | ubifs_assert(!c->space_fixup); | ||
| 762 | 764 | ||
| 763 | if (c->ro_error) | 765 | if (c->ro_error) |
| 764 | return -EROFS; | 766 | return -EROFS; |
diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index 34b1679e6e3a..cef0460f4c54 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c | |||
| @@ -669,6 +669,7 @@ out_free: | |||
| 669 | 669 | ||
| 670 | out_release: | 670 | out_release: |
| 671 | release_head(c, BASEHD); | 671 | release_head(c, BASEHD); |
| 672 | kfree(dent); | ||
| 672 | out_ro: | 673 | out_ro: |
| 673 | ubifs_ro_mode(c, err); | 674 | ubifs_ro_mode(c, err); |
| 674 | if (last_reference) | 675 | if (last_reference) |
diff --git a/fs/ubifs/orphan.c b/fs/ubifs/orphan.c index bd644bf587a8..a5422fffbd69 100644 --- a/fs/ubifs/orphan.c +++ b/fs/ubifs/orphan.c | |||
| @@ -674,7 +674,7 @@ static int kill_orphans(struct ubifs_info *c) | |||
| 674 | if (IS_ERR(sleb)) { | 674 | if (IS_ERR(sleb)) { |
| 675 | if (PTR_ERR(sleb) == -EUCLEAN) | 675 | if (PTR_ERR(sleb) == -EUCLEAN) |
| 676 | sleb = ubifs_recover_leb(c, lnum, 0, | 676 | sleb = ubifs_recover_leb(c, lnum, 0, |
| 677 | c->sbuf, 0); | 677 | c->sbuf, -1); |
| 678 | if (IS_ERR(sleb)) { | 678 | if (IS_ERR(sleb)) { |
| 679 | err = PTR_ERR(sleb); | 679 | err = PTR_ERR(sleb); |
| 680 | break; | 680 | break; |
diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c index 731d9e2e7b50..783d8e0beb76 100644 --- a/fs/ubifs/recovery.c +++ b/fs/ubifs/recovery.c | |||
| @@ -564,19 +564,15 @@ static int fix_unclean_leb(struct ubifs_info *c, struct ubifs_scan_leb *sleb, | |||
| 564 | } | 564 | } |
| 565 | 565 | ||
| 566 | /** | 566 | /** |
| 567 | * drop_last_node - drop the last node or group of nodes. | 567 | * drop_last_group - drop the last group of nodes. |
| 568 | * @sleb: scanned LEB information | 568 | * @sleb: scanned LEB information |
| 569 | * @offs: offset of dropped nodes is returned here | 569 | * @offs: offset of dropped nodes is returned here |
| 570 | * @grouped: non-zero if whole group of nodes have to be dropped | ||
| 571 | * | 570 | * |
| 572 | * This is a helper function for 'ubifs_recover_leb()' which drops the last | 571 | * This is a helper function for 'ubifs_recover_leb()' which drops the last |
| 573 | * node of the scanned LEB or the last group of nodes if @grouped is not zero. | 572 | * group of nodes of the scanned LEB. |
| 574 | * This function returns %1 if a node was dropped and %0 otherwise. | ||
| 575 | */ | 573 | */ |
| 576 | static int drop_last_node(struct ubifs_scan_leb *sleb, int *offs, int grouped) | 574 | static void drop_last_group(struct ubifs_scan_leb *sleb, int *offs) |
| 577 | { | 575 | { |
| 578 | int dropped = 0; | ||
| 579 | |||
| 580 | while (!list_empty(&sleb->nodes)) { | 576 | while (!list_empty(&sleb->nodes)) { |
| 581 | struct ubifs_scan_node *snod; | 577 | struct ubifs_scan_node *snod; |
| 582 | struct ubifs_ch *ch; | 578 | struct ubifs_ch *ch; |
| @@ -585,17 +581,40 @@ static int drop_last_node(struct ubifs_scan_leb *sleb, int *offs, int grouped) | |||
| 585 | list); | 581 | list); |
| 586 | ch = snod->node; | 582 | ch = snod->node; |
| 587 | if (ch->group_type != UBIFS_IN_NODE_GROUP) | 583 | if (ch->group_type != UBIFS_IN_NODE_GROUP) |
| 588 | return dropped; | 584 | break; |
| 589 | dbg_rcvry("dropping node at %d:%d", sleb->lnum, snod->offs); | 585 | |
| 586 | dbg_rcvry("dropping grouped node at %d:%d", | ||
| 587 | sleb->lnum, snod->offs); | ||
| 588 | *offs = snod->offs; | ||
| 589 | list_del(&snod->list); | ||
| 590 | kfree(snod); | ||
| 591 | sleb->nodes_cnt -= 1; | ||
| 592 | } | ||
| 593 | } | ||
| 594 | |||
| 595 | /** | ||
| 596 | * drop_last_node - drop the last node. | ||
| 597 | * @sleb: scanned LEB information | ||
| 598 | * @offs: offset of dropped nodes is returned here | ||
| 599 | * @grouped: non-zero if whole group of nodes have to be dropped | ||
| 600 | * | ||
| 601 | * This is a helper function for 'ubifs_recover_leb()' which drops the last | ||
| 602 | * node of the scanned LEB. | ||
| 603 | */ | ||
| 604 | static void drop_last_node(struct ubifs_scan_leb *sleb, int *offs) | ||
| 605 | { | ||
| 606 | struct ubifs_scan_node *snod; | ||
| 607 | |||
| 608 | if (!list_empty(&sleb->nodes)) { | ||
| 609 | snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node, | ||
| 610 | list); | ||
| 611 | |||
| 612 | dbg_rcvry("dropping last node at %d:%d", sleb->lnum, snod->offs); | ||
| 590 | *offs = snod->offs; | 613 | *offs = snod->offs; |
| 591 | list_del(&snod->list); | 614 | list_del(&snod->list); |
| 592 | kfree(snod); | 615 | kfree(snod); |
| 593 | sleb->nodes_cnt -= 1; | 616 | sleb->nodes_cnt -= 1; |
| 594 | dropped = 1; | ||
| 595 | if (!grouped) | ||
| 596 | break; | ||
| 597 | } | 617 | } |
| 598 | return dropped; | ||
| 599 | } | 618 | } |
| 600 | 619 | ||
| 601 | /** | 620 | /** |
| @@ -604,7 +623,8 @@ static int drop_last_node(struct ubifs_scan_leb *sleb, int *offs, int grouped) | |||
| 604 | * @lnum: LEB number | 623 | * @lnum: LEB number |
| 605 | * @offs: offset | 624 | * @offs: offset |
| 606 | * @sbuf: LEB-sized buffer to use | 625 | * @sbuf: LEB-sized buffer to use |
| 607 | * @grouped: nodes may be grouped for recovery | 626 | * @jhead: journal head number this LEB belongs to (%-1 if the LEB does not |
| 627 | * belong to any journal head) | ||
| 608 | * | 628 | * |
| 609 | * This function does a scan of a LEB, but caters for errors that might have | 629 | * This function does a scan of a LEB, but caters for errors that might have |
| 610 | * been caused by the unclean unmount from which we are attempting to recover. | 630 | * been caused by the unclean unmount from which we are attempting to recover. |
| @@ -612,13 +632,14 @@ static int drop_last_node(struct ubifs_scan_leb *sleb, int *offs, int grouped) | |||
| 612 | * found, and a negative error code in case of failure. | 632 | * found, and a negative error code in case of failure. |
| 613 | */ | 633 | */ |
| 614 | struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum, | 634 | struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum, |
| 615 | int offs, void *sbuf, int grouped) | 635 | int offs, void *sbuf, int jhead) |
| 616 | { | 636 | { |
| 617 | int ret = 0, err, len = c->leb_size - offs, start = offs, min_io_unit; | 637 | int ret = 0, err, len = c->leb_size - offs, start = offs, min_io_unit; |
| 638 | int grouped = jhead == -1 ? 0 : c->jheads[jhead].grouped; | ||
| 618 | struct ubifs_scan_leb *sleb; | 639 | struct ubifs_scan_leb *sleb; |
| 619 | void *buf = sbuf + offs; | 640 | void *buf = sbuf + offs; |
| 620 | 641 | ||
| 621 | dbg_rcvry("%d:%d", lnum, offs); | 642 | dbg_rcvry("%d:%d, jhead %d, grouped %d", lnum, offs, jhead, grouped); |
| 622 | 643 | ||
| 623 | sleb = ubifs_start_scan(c, lnum, offs, sbuf); | 644 | sleb = ubifs_start_scan(c, lnum, offs, sbuf); |
| 624 | if (IS_ERR(sleb)) | 645 | if (IS_ERR(sleb)) |
| @@ -635,7 +656,7 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum, | |||
| 635 | * Scan quietly until there is an error from which we cannot | 656 | * Scan quietly until there is an error from which we cannot |
| 636 | * recover | 657 | * recover |
| 637 | */ | 658 | */ |
| 638 | ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 0); | 659 | ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 1); |
| 639 | if (ret == SCANNED_A_NODE) { | 660 | if (ret == SCANNED_A_NODE) { |
| 640 | /* A valid node, and not a padding node */ | 661 | /* A valid node, and not a padding node */ |
| 641 | struct ubifs_ch *ch = buf; | 662 | struct ubifs_ch *ch = buf; |
| @@ -695,59 +716,62 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum, | |||
| 695 | * If nodes are grouped, always drop the incomplete group at | 716 | * If nodes are grouped, always drop the incomplete group at |
| 696 | * the end. | 717 | * the end. |
| 697 | */ | ||
