diff options
Diffstat (limited to 'fs/reiserfs/journal.c')
-rw-r--r-- | fs/reiserfs/journal.c | 145 |
1 files changed, 91 insertions, 54 deletions
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index f25086aeef5..4cad9e75ef5 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c | |||
@@ -615,6 +615,31 @@ static int journal_list_still_alive(struct super_block *s, | |||
615 | return 0; | 615 | return 0; |
616 | } | 616 | } |
617 | 617 | ||
618 | /* | ||
619 | * If page->mapping was null, we failed to truncate this page for | ||
620 | * some reason. Most likely because it was truncated after being | ||
621 | * logged via data=journal. | ||
622 | * | ||
623 | * This does a check to see if the buffer belongs to one of these | ||
624 | * lost pages before doing the final put_bh. If page->mapping was | ||
625 | * null, it tries to free buffers on the page, which should make the | ||
626 | * final page_cache_release drop the page from the lru. | ||
627 | */ | ||
628 | static void release_buffer_page(struct buffer_head *bh) | ||
629 | { | ||
630 | struct page *page = bh->b_page; | ||
631 | if (!page->mapping && !TestSetPageLocked(page)) { | ||
632 | page_cache_get(page); | ||
633 | put_bh(bh); | ||
634 | if (!page->mapping) | ||
635 | try_to_free_buffers(page); | ||
636 | unlock_page(page); | ||
637 | page_cache_release(page); | ||
638 | } else { | ||
639 | put_bh(bh); | ||
640 | } | ||
641 | } | ||
642 | |||
618 | static void reiserfs_end_buffer_io_sync(struct buffer_head *bh, int uptodate) | 643 | static void reiserfs_end_buffer_io_sync(struct buffer_head *bh, int uptodate) |
619 | { | 644 | { |
620 | char b[BDEVNAME_SIZE]; | 645 | char b[BDEVNAME_SIZE]; |
@@ -628,8 +653,9 @@ static void reiserfs_end_buffer_io_sync(struct buffer_head *bh, int uptodate) | |||
628 | set_buffer_uptodate(bh); | 653 | set_buffer_uptodate(bh); |
629 | else | 654 | else |
630 | clear_buffer_uptodate(bh); | 655 | clear_buffer_uptodate(bh); |
656 | |||
631 | unlock_buffer(bh); | 657 | unlock_buffer(bh); |
632 | put_bh(bh); | 658 | release_buffer_page(bh); |
633 | } | 659 | } |
634 | 660 | ||
635 | static void reiserfs_end_ordered_io(struct buffer_head *bh, int uptodate) | 661 | static void reiserfs_end_ordered_io(struct buffer_head *bh, int uptodate) |
@@ -966,7 +992,8 @@ static int flush_older_commits(struct super_block *s, | |||
966 | } | 992 | } |
967 | return 0; | 993 | return 0; |
968 | } | 994 | } |
969 | int reiserfs_async_progress_wait(struct super_block *s) | 995 | |
996 | static int reiserfs_async_progress_wait(struct super_block *s) | ||
970 | { | 997 | { |
971 | DEFINE_WAIT(wait); | 998 | DEFINE_WAIT(wait); |
972 | struct reiserfs_journal *j = SB_JOURNAL(s); | 999 | struct reiserfs_journal *j = SB_JOURNAL(s); |
@@ -1546,9 +1573,10 @@ static int flush_journal_list(struct super_block *s, | |||
1546 | BUG_ON(!test_clear_buffer_journal_dirty | 1573 | BUG_ON(!test_clear_buffer_journal_dirty |
1547 | (cn->bh)); | 1574 | (cn->bh)); |
1548 | 1575 | ||
1549 | /* undo the inc from journal_mark_dirty */ | 1576 | /* drop one ref for us */ |
1550 | put_bh(cn->bh); | 1577 | put_bh(cn->bh); |
1551 | brelse(cn->bh); | 1578 | /* drop one ref for journal_mark_dirty */ |
1579 | release_buffer_page(cn->bh); | ||
1552 | } | 1580 | } |
1553 | cn = cn->next; | 1581 | cn = cn->next; |
1554 | } | 1582 | } |
@@ -2621,6 +2649,61 @@ static int journal_init_dev(struct super_block *super, | |||
2621 | return result; | 2649 | return result; |
2622 | } | 2650 | } |
2623 | 2651 | ||
2652 | /** | ||
2653 | * When creating/tuning a file system user can assign some | ||
2654 | * journal params within boundaries which depend on the ratio | ||
2655 | * blocksize/standard_blocksize. | ||
2656 | * | ||
2657 | * For blocks >= standard_blocksize transaction size should | ||
2658 | * be not less then JOURNAL_TRANS_MIN_DEFAULT, and not more | ||
2659 | * then JOURNAL_TRANS_MAX_DEFAULT. | ||
2660 | * | ||
2661 | * For blocks < standard_blocksize these boundaries should be | ||
2662 | * decreased proportionally. | ||
2663 | */ | ||
2664 | #define REISERFS_STANDARD_BLKSIZE (4096) | ||
2665 | |||
2666 | static int check_advise_trans_params(struct super_block *p_s_sb, | ||
2667 | struct reiserfs_journal *journal) | ||
2668 | { | ||
2669 | if (journal->j_trans_max) { | ||
2670 | /* Non-default journal params. | ||
2671 | Do sanity check for them. */ | ||
2672 | int ratio = 1; | ||
2673 | if (p_s_sb->s_blocksize < REISERFS_STANDARD_BLKSIZE) | ||
2674 | ratio = REISERFS_STANDARD_BLKSIZE / p_s_sb->s_blocksize; | ||
2675 | |||
2676 | if (journal->j_trans_max > JOURNAL_TRANS_MAX_DEFAULT / ratio || | ||
2677 | journal->j_trans_max < JOURNAL_TRANS_MIN_DEFAULT / ratio || | ||
2678 | SB_ONDISK_JOURNAL_SIZE(p_s_sb) / journal->j_trans_max < | ||
2679 | JOURNAL_MIN_RATIO) { | ||
2680 | reiserfs_warning(p_s_sb, | ||
2681 | "sh-462: bad transaction max size (%u). FSCK?", | ||
2682 | journal->j_trans_max); | ||
2683 | return 1; | ||
2684 | } | ||
2685 | if (journal->j_max_batch != (journal->j_trans_max) * | ||
2686 | JOURNAL_MAX_BATCH_DEFAULT/JOURNAL_TRANS_MAX_DEFAULT) { | ||
2687 | reiserfs_warning(p_s_sb, | ||
2688 | "sh-463: bad transaction max batch (%u). FSCK?", | ||
2689 | journal->j_max_batch); | ||
2690 | return 1; | ||
2691 | } | ||
2692 | } else { | ||
2693 | /* Default journal params. | ||
2694 | The file system was created by old version | ||
2695 | of mkreiserfs, so some fields contain zeros, | ||
2696 | and we need to advise proper values for them */ | ||
2697 | if (p_s_sb->s_blocksize != REISERFS_STANDARD_BLKSIZE) | ||
2698 | reiserfs_panic(p_s_sb, "sh-464: bad blocksize (%u)", | ||
2699 | p_s_sb->s_blocksize); | ||
2700 | journal->j_trans_max = JOURNAL_TRANS_MAX_DEFAULT; | ||
2701 | journal->j_max_batch = JOURNAL_MAX_BATCH_DEFAULT; | ||
2702 | journal->j_max_commit_age = JOURNAL_MAX_COMMIT_AGE; | ||
2703 | } | ||
2704 | return 0; | ||
2705 | } | ||
2706 | |||
2624 | /* | 2707 | /* |
2625 | ** must be called once on fs mount. calls journal_read for you | 2708 | ** must be called once on fs mount. calls journal_read for you |
2626 | */ | 2709 | */ |
@@ -2716,49 +2799,8 @@ int journal_init(struct super_block *p_s_sb, const char *j_dev_name, | |||
2716 | le32_to_cpu(jh->jh_journal.jp_journal_max_commit_age); | 2799 | le32_to_cpu(jh->jh_journal.jp_journal_max_commit_age); |
2717 | journal->j_max_trans_age = JOURNAL_MAX_TRANS_AGE; | 2800 | journal->j_max_trans_age = JOURNAL_MAX_TRANS_AGE; |
2718 | 2801 | ||
2719 | if (journal->j_trans_max) { | 2802 | if (check_advise_trans_params(p_s_sb, journal) != 0) |
2720 | /* make sure these parameters are available, assign it if they are not */ | 2803 | goto free_and_return; |
2721 | __u32 initial = journal->j_trans_max; | ||
2722 | __u32 ratio = 1; | ||
2723 | |||
2724 | if (p_s_sb->s_blocksize < 4096) | ||
2725 | ratio = 4096 / p_s_sb->s_blocksize; | ||
2726 | |||
2727 | if (SB_ONDISK_JOURNAL_SIZE(p_s_sb) / journal->j_trans_max < | ||
2728 | JOURNAL_MIN_RATIO) | ||
2729 | journal->j_trans_max = | ||
2730 | SB_ONDISK_JOURNAL_SIZE(p_s_sb) / JOURNAL_MIN_RATIO; | ||
2731 | if (journal->j_trans_max > JOURNAL_TRANS_MAX_DEFAULT / ratio) | ||
2732 | journal->j_trans_max = | ||
2733 | JOURNAL_TRANS_MAX_DEFAULT / ratio; | ||
2734 | if (journal->j_trans_max < JOURNAL_TRANS_MIN_DEFAULT / ratio) | ||
2735 | journal->j_trans_max = | ||
2736 | JOURNAL_TRANS_MIN_DEFAULT / ratio; | ||
2737 | |||
2738 | if (journal->j_trans_max != initial) | ||
2739 | reiserfs_warning(p_s_sb, | ||
2740 | "sh-461: journal_init: wrong transaction max size (%u). Changed to %u", | ||
2741 | initial, journal->j_trans_max); | ||
2742 | |||
2743 | journal->j_max_batch = journal->j_trans_max * | ||
2744 | JOURNAL_MAX_BATCH_DEFAULT / JOURNAL_TRANS_MAX_DEFAULT; | ||
2745 | } | ||
2746 | |||
2747 | if (!journal->j_trans_max) { | ||
2748 | /*we have the file system was created by old version of mkreiserfs | ||
2749 | so this field contains zero value */ | ||
2750 | journal->j_trans_max = JOURNAL_TRANS_MAX_DEFAULT; | ||
2751 | journal->j_max_batch = JOURNAL_MAX_BATCH_DEFAULT; | ||
2752 | journal->j_max_commit_age = JOURNAL_MAX_COMMIT_AGE; | ||
2753 | |||
2754 | /* for blocksize >= 4096 - max transaction size is 1024. For block size < 4096 | ||
2755 | trans max size is decreased proportionally */ | ||
2756 | if (p_s_sb->s_blocksize < 4096) { | ||
2757 | journal->j_trans_max /= (4096 / p_s_sb->s_blocksize); | ||
2758 | journal->j_max_batch = (journal->j_trans_max) * 9 / 10; | ||
2759 | } | ||
2760 | } | ||
2761 | |||
2762 | journal->j_default_max_commit_age = journal->j_max_commit_age; | 2804 | journal->j_default_max_commit_age = journal->j_max_commit_age; |
2763 | 2805 | ||
2764 | if (commit_max_age != 0) { | 2806 | if (commit_max_age != 0) { |
@@ -3708,13 +3750,8 @@ int journal_mark_freed(struct reiserfs_transaction_handle *th, | |||
3708 | } | 3750 | } |
3709 | } | 3751 | } |
3710 | 3752 | ||
3711 | if (bh) { | 3753 | if (bh) |
3712 | put_bh(bh); /* get_hash grabs the buffer */ | 3754 | release_buffer_page(bh); /* get_hash grabs the buffer */ |
3713 | if (atomic_read(&(bh->b_count)) < 0) { | ||
3714 | reiserfs_warning(p_s_sb, | ||
3715 | "journal-2165: bh->b_count < 0"); | ||
3716 | } | ||
3717 | } | ||
3718 | return 0; | 3755 | return 0; |
3719 | } | 3756 | } |
3720 | 3757 | ||