diff --git a/debian/changelog b/debian/changelog index e07a8d7af..404b94102 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,16 @@ +linux-2.6 (2.6.18-6) UNRELEASED; urgency=low + + * reiserfs backport 2.6.19 SUSE fixes: + - use gcc -O1 in fs/reiserfs only for ancient gcc versions + - reiserfs_fsync should only use barriers when they are enabled + - Fix reiserfs latencies caused by data=ordered + - fix is_reusable bitmap check to not traverse the bitmap info array + - clean up bitmap block buffer head references + - reorganize bitmap loading functions + - on-demand bitmap loading + + -- maximilian attems Thu, 9 Nov 2006 00:09:36 +0100 + linux-2.6 (2.6.18-5) unstable; urgency=low [ maximilian attems ] diff --git a/debian/patches/features/fs-reiserfs-bitmap-block-cleanup.patch b/debian/patches/features/fs-reiserfs-bitmap-block-cleanup.patch new file mode 100644 index 000000000..43ce7d5cc --- /dev/null +++ b/debian/patches/features/fs-reiserfs-bitmap-block-cleanup.patch @@ -0,0 +1,291 @@ +From git-commits-head-owner@vger.kernel.org Wed Oct 4 17:36:49 2006 +Date: Sun, 1 Oct 2006 08:01:29 GMT +Message-Id: <200610010801.k9181TNv010078@hera.kernel.org> +From: Linux Kernel Mailing List +To: git-commits-head@vger.kernel.org +Subject: [PATCH] reiserfs: clean up bitmap block buffer head references + +commit 0b3dc17bc0c0997bde9f5d7691ec0cae24258cf7 +tree ecdbb6f830737358706b0ba7c628f47f9fdc0ff4 +parent e1fabd3ccf02901374bffa434e0af472749a5bd9 +author Jeff Mahoney 1159684122 -0700 +committer Linus Torvalds 1159688367 -0700 + +[PATCH] reiserfs: clean up bitmap block buffer head references + +Similar to the SB_JOURNAL cleanup that was accepted a while ago, this patch +uses a temporary variable for buffer head references from the bitmap info +array. + +This makes the code much more readable in some areas. + +It also uses proper reference counting, doing a get_bh() after using the +pointer from the array and brelse()'ing it later. This may seem silly, but a +later patch will replace the simple temporary variables with an actual read, +so the reference freeing will be used then. + +Signed-off-by: Jeff Mahoney +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds + + fs/reiserfs/bitmap.c | 60 ++++++++++++++++++++++++++++++--------------------- + fs/reiserfs/resize.c | 60 +++++++++++++++++++++++++++++---------------------- + 2 files changed, 71 insertions(+), 49 deletions(-) + +diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c +index 1022347..44d9410 100644 +--- a/fs/reiserfs/bitmap.c ++++ b/fs/reiserfs/bitmap.c +@@ -59,6 +59,7 @@ #ifdef CONFIG_REISERFS_CHECK + int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value) + { + int bmap, offset; ++ struct buffer_head *bh; + + if (block == 0 || block >= SB_BLOCK_COUNT(s)) { + reiserfs_warning(s, +@@ -96,20 +97,21 @@ int is_reusable(struct super_block *s, b + return 0; + } + +- if ((bit_value == 0 && +- reiserfs_test_le_bit(offset, SB_AP_BITMAP(s)[bmap].bh->b_data)) || +- (bit_value == 1 && +- reiserfs_test_le_bit(offset, SB_AP_BITMAP(s)[bmap].bh->b_data) == 0)) { ++ bh = SB_AP_BITMAP(s)[bmap].bh; ++ get_bh(bh); ++ ++ if ((bit_value == 0 && reiserfs_test_le_bit(offset, bh->b_data)) || ++ (bit_value == 1 && reiserfs_test_le_bit(offset, bh->b_data) == 0)) { + reiserfs_warning(s, + "vs-4040: is_reusable: corresponding bit of block %lu does not " + "match required value (bmap==%d, offset==%d) test_bit==%d", +- block, bmap, offset, reiserfs_test_le_bit(offset, +- SB_AP_BITMAP +- (s)[bmap].bh-> +- b_data)); ++ block, bmap, offset, ++ reiserfs_test_le_bit(offset, bh->b_data)); + ++ brelse(bh); + return 0; + } ++ brelse(bh); + + if (bit_value == 0 && block == SB_ROOT_BLOCK(s)) { + reiserfs_warning(s, +@@ -151,6 +153,7 @@ static int scan_bitmap_block(struct reis + { + struct super_block *s = th->t_super; + struct reiserfs_bitmap_info *bi = &SB_AP_BITMAP(s)[bmap_n]; ++ struct buffer_head *bh; + int end, next; + int org = *beg; + +@@ -169,22 +172,28 @@ static int scan_bitmap_block(struct reis + bmap_n); + return 0; + } +- if (buffer_locked(bi->bh)) { ++ bh = bi->bh; ++ get_bh(bh); ++ ++ if (buffer_locked(bh)) { + PROC_INFO_INC(s, scan_bitmap.wait); +- __wait_on_buffer(bi->bh); ++ __wait_on_buffer(bh); + } + + while (1) { + cont: +- if (bi->free_count < min) ++ if (bi->free_count < min) { ++ brelse(bh); + return 0; // No free blocks in this bitmap ++ } + + /* search for a first zero bit -- beggining of a window */ + *beg = reiserfs_find_next_zero_le_bit +- ((unsigned long *)(bi->bh->b_data), boundary, *beg); ++ ((unsigned long *)(bh->b_data), boundary, *beg); + + if (*beg + min > boundary) { /* search for a zero bit fails or the rest of bitmap block + * cannot contain a zero window of minimum size */ ++ brelse(bh); + return 0; + } + +@@ -193,7 +202,7 @@ static int scan_bitmap_block(struct reis + /* first zero bit found; we check next bits */ + for (end = *beg + 1;; end++) { + if (end >= *beg + max || end >= boundary +- || reiserfs_test_le_bit(end, bi->bh->b_data)) { ++ || reiserfs_test_le_bit(end, bh->b_data)) { + next = end; + break; + } +@@ -207,12 +216,12 @@ static int scan_bitmap_block(struct reis + * (end) points to one bit after the window end */ + if (end - *beg >= min) { /* it seems we have found window of proper size */ + int i; +- reiserfs_prepare_for_journal(s, bi->bh, 1); ++ reiserfs_prepare_for_journal(s, bh, 1); + /* try to set all blocks used checking are they still free */ + for (i = *beg; i < end; i++) { + /* It seems that we should not check in journal again. */ + if (reiserfs_test_and_set_le_bit +- (i, bi->bh->b_data)) { ++ (i, bh->b_data)) { + /* bit was set by another process + * while we slept in prepare_for_journal() */ + PROC_INFO_INC(s, scan_bitmap.stolen); +@@ -224,17 +233,16 @@ static int scan_bitmap_block(struct reis + /* otherwise we clear all bit were set ... */ + while (--i >= *beg) + reiserfs_test_and_clear_le_bit +- (i, bi->bh->b_data); +- reiserfs_restore_prepared_buffer(s, +- bi-> +- bh); ++ (i, bh->b_data); ++ reiserfs_restore_prepared_buffer(s, bh); + *beg = org; + /* ... and search again in current block from beginning */ + goto cont; + } + } + bi->free_count -= (end - *beg); +- journal_mark_dirty(th, s, bi->bh); ++ journal_mark_dirty(th, s, bh); ++ brelse(bh); + + /* free block count calculation */ + reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), +@@ -383,7 +391,7 @@ static void _reiserfs_free_block(struct + { + struct super_block *s = th->t_super; + struct reiserfs_super_block *rs; +- struct buffer_head *sbh; ++ struct buffer_head *sbh, *bmbh; + struct reiserfs_bitmap_info *apbi; + int nr, offset; + +@@ -404,16 +412,20 @@ static void _reiserfs_free_block(struct + return; + } + +- reiserfs_prepare_for_journal(s, apbi[nr].bh, 1); ++ bmbh = apbi[nr].bh; ++ get_bh(bmbh); ++ ++ reiserfs_prepare_for_journal(s, bmbh, 1); + + /* clear bit for the given block in bit map */ +- if (!reiserfs_test_and_clear_le_bit(offset, apbi[nr].bh->b_data)) { ++ if (!reiserfs_test_and_clear_le_bit(offset, bmbh->b_data)) { + reiserfs_warning(s, "vs-4080: reiserfs_free_block: " + "free_block (%s:%lu)[dev:blocknr]: bit already cleared", + reiserfs_bdevname(s), block); + } + apbi[nr].free_count++; +- journal_mark_dirty(th, s, apbi[nr].bh); ++ journal_mark_dirty(th, s, bmbh); ++ brelse(bmbh); + + reiserfs_prepare_for_journal(s, sbh, 1); + /* update super block */ +diff --git a/fs/reiserfs/resize.c b/fs/reiserfs/resize.c +index 39cc7f4..958b759 100644 +--- a/fs/reiserfs/resize.c ++++ b/fs/reiserfs/resize.c +@@ -22,6 +22,7 @@ int reiserfs_resize(struct super_block * + int err = 0; + struct reiserfs_super_block *sb; + struct reiserfs_bitmap_info *bitmap; ++ struct reiserfs_bitmap_info *info; + struct reiserfs_bitmap_info *old_bitmap = SB_AP_BITMAP(s); + struct buffer_head *bh; + struct reiserfs_transaction_handle th; +@@ -127,16 +128,19 @@ int reiserfs_resize(struct super_block * + * transaction begins, and the new bitmaps don't matter if the + * transaction fails. */ + for (i = bmap_nr; i < bmap_nr_new; i++) { +- bitmap[i].bh = sb_getblk(s, i * s->s_blocksize * 8); +- memset(bitmap[i].bh->b_data, 0, sb_blocksize(sb)); +- reiserfs_test_and_set_le_bit(0, bitmap[i].bh->b_data); +- +- set_buffer_uptodate(bitmap[i].bh); +- mark_buffer_dirty(bitmap[i].bh); +- sync_dirty_buffer(bitmap[i].bh); ++ bh = sb_getblk(s, i * s->s_blocksize * 8); ++ get_bh(bh); ++ memset(bh->b_data, 0, sb_blocksize(sb)); ++ reiserfs_test_and_set_le_bit(0, bh->b_data); ++ ++ set_buffer_uptodate(bh); ++ mark_buffer_dirty(bh); ++ sync_dirty_buffer(bh); + // update bitmap_info stuff + bitmap[i].first_zero_hint = 1; + bitmap[i].free_count = sb_blocksize(sb) * 8 - 1; ++ bitmap[i].bh = bh; ++ brelse(bh); + } + /* free old bitmap blocks array */ + SB_AP_BITMAP(s) = bitmap; +@@ -150,30 +154,36 @@ int reiserfs_resize(struct super_block * + if (err) + return err; + +- /* correct last bitmap blocks in old and new disk layout */ +- reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[bmap_nr - 1].bh, 1); ++ /* Extend old last bitmap block - new blocks have been made available */ ++ info = SB_AP_BITMAP(s) + bmap_nr - 1; ++ bh = info->bh; ++ get_bh(bh); ++ ++ reiserfs_prepare_for_journal(s, bh, 1); + for (i = block_r; i < s->s_blocksize * 8; i++) +- reiserfs_test_and_clear_le_bit(i, +- SB_AP_BITMAP(s)[bmap_nr - +- 1].bh->b_data); +- SB_AP_BITMAP(s)[bmap_nr - 1].free_count += s->s_blocksize * 8 - block_r; +- if (!SB_AP_BITMAP(s)[bmap_nr - 1].first_zero_hint) +- SB_AP_BITMAP(s)[bmap_nr - 1].first_zero_hint = block_r; ++ reiserfs_test_and_clear_le_bit(i, bh->b_data); ++ info->free_count += s->s_blocksize * 8 - block_r; ++ if (!info->first_zero_hint) ++ info->first_zero_hint = block_r; ++ ++ journal_mark_dirty(&th, s, bh); ++ brelse(bh); + +- journal_mark_dirty(&th, s, SB_AP_BITMAP(s)[bmap_nr - 1].bh); ++ /* Correct new last bitmap block - It may not be full */ ++ info = SB_AP_BITMAP(s) + bmap_nr_new - 1; ++ bh = info->bh; ++ get_bh(bh); + +- reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[bmap_nr_new - 1].bh, 1); ++ reiserfs_prepare_for_journal(s, bh, 1); + for (i = block_r_new; i < s->s_blocksize * 8; i++) +- reiserfs_test_and_set_le_bit(i, +- SB_AP_BITMAP(s)[bmap_nr_new - +- 1].bh->b_data); +- journal_mark_dirty(&th, s, SB_AP_BITMAP(s)[bmap_nr_new - 1].bh); ++ reiserfs_test_and_set_le_bit(i, bh->b_data); ++ journal_mark_dirty(&th, s, bh); ++ brelse(bh); + +- SB_AP_BITMAP(s)[bmap_nr_new - 1].free_count -= +- s->s_blocksize * 8 - block_r_new; ++ info->free_count -= s->s_blocksize * 8 - block_r_new; + /* Extreme case where last bitmap is the only valid block in itself. */ +- if (!SB_AP_BITMAP(s)[bmap_nr_new - 1].free_count) +- SB_AP_BITMAP(s)[bmap_nr_new - 1].first_zero_hint = 0; ++ if (!info->free_count) ++ info->first_zero_hint = 0; + /* update super */ + reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); + free_blocks = SB_FREE_BLOCKS(s); diff --git a/debian/patches/features/fs-reiserfs-bitmap-block-optimization.patch b/debian/patches/features/fs-reiserfs-bitmap-block-optimization.patch new file mode 100644 index 000000000..4c033a776 --- /dev/null +++ b/debian/patches/features/fs-reiserfs-bitmap-block-optimization.patch @@ -0,0 +1,184 @@ +From git-commits-head-owner@vger.kernel.org Wed Oct 4 17:36:47 2006 +Return-Path: +Delivered-To: unknown +Received: from baikonur.stro.at (213.239.196.228) by nancy with IMAP4-SSL; 04 + Oct 2006 15:36:47 -0000 +X-Original-To: janitor@sternwelten.at +Delivered-To: janitor@sternwelten.at +Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) + by baikonur.stro.at (Postfix) with ESMTP id 3DFD35C066 + for ; Sun, 1 Oct 2006 10:01:38 +0200 (CEST) +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S932105AbWJAIBp (ORCPT ); + Sun, 1 Oct 2006 04:01:45 -0400 +Received: (majordomo@vger.kernel.org) by vger.kernel.org id S932106AbWJAIBp + (ORCPT ); + Sun, 1 Oct 2006 04:01:45 -0400 +Received: from hera.kernel.org ([140.211.167.34]:36786 "EHLO hera.kernel.org") + by vger.kernel.org with ESMTP id S932105AbWJAIB3 (ORCPT + ); + Sun, 1 Oct 2006 04:01:29 -0400 +Received: from hera.kernel.org (IDENT:U2FsdGVkX1/qIwMDDPAqUjfbNz4+pldcJIqmPXsPjR0@localhost [127.0.0.1]) + by hera.kernel.org (8.13.7/8.13.7) with ESMTP id k9181St4010065 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) + for ; Sun, 1 Oct 2006 08:01:28 GMT +Received: (from dwmw2@localhost) + by hera.kernel.org (8.13.7/8.13.1/Submit) id k9181Rot010064 + for git-commits-head@vger.kernel.org; Sun, 1 Oct 2006 08:01:27 GMT +Date: Sun, 1 Oct 2006 08:01:27 GMT +Message-Id: <200610010801.k9181Rot010064@hera.kernel.org> +From: Linux Kernel Mailing List +To: git-commits-head@vger.kernel.org +Subject: [PATCH] reiserfs: fix is_reusable bitmap check to not traverse the bitmap info array +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +X-Git-Commit: e1fabd3ccf02901374bffa434e0af472749a5bd9 +X-Git-Parent: 8ef386092d7c2891bd7acefb2a87f878f7e9a0d6 +Sender: git-commits-head-owner@vger.kernel.org +Precedence: bulk +X-Mailing-List: git-commits-head@vger.kernel.org +X-Virus-Scanned: by Amavis (ClamAV) at stro.at +Status: RO +Content-Length: 5049 + +commit e1fabd3ccf02901374bffa434e0af472749a5bd9 +tree 66d618e98020422874a521142ca2da797c9930f3 +parent 8ef386092d7c2891bd7acefb2a87f878f7e9a0d6 +author Jeff Mahoney 1159684120 -0700 +committer Linus Torvalds 1159688367 -0700 + +[PATCH] reiserfs: fix is_reusable bitmap check to not traverse the bitmap info array + +There is a check in is_reusable to determine if a particular block is a bitmap +block. It verifies this by going through the array of bitmap block buffer +heads and comparing the block number to each one. + +Bitmap blocks are at defined locations on the disk in both old and current +formats. Simply checking against the known good values is enough. + +This is a trivial optimization for a non-production codepath, but this is the +first in a series of patches that will ultimately remove the buffer heads from +that array. + +Signed-off-by: Jeff Mahoney +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds + + fs/reiserfs/bitmap.c | 40 +++++++++++++++++++++++++--------------- + fs/reiserfs/super.c | 2 ++ + include/linux/reiserfs_fs_sb.h | 1 + + 3 files changed, 28 insertions(+), 15 deletions(-) + +diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c +index 4a7dbde..1022347 100644 +--- a/fs/reiserfs/bitmap.c ++++ b/fs/reiserfs/bitmap.c +@@ -50,16 +50,15 @@ static inline void get_bit_address(struc + { + /* It is in the bitmap block number equal to the block + * number divided by the number of bits in a block. */ +- *bmap_nr = block / (s->s_blocksize << 3); ++ *bmap_nr = block >> (s->s_blocksize_bits + 3); + /* Within that bitmap block it is located at bit offset *offset. */ + *offset = block & ((s->s_blocksize << 3) - 1); +- return; + } + + #ifdef CONFIG_REISERFS_CHECK + int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value) + { +- int i, j; ++ int bmap, offset; + + if (block == 0 || block >= SB_BLOCK_COUNT(s)) { + reiserfs_warning(s, +@@ -68,34 +67,45 @@ int is_reusable(struct super_block *s, b + return 0; + } + +- /* it can't be one of the bitmap blocks */ +- for (i = 0; i < SB_BMAP_NR(s); i++) +- if (block == SB_AP_BITMAP(s)[i].bh->b_blocknr) { ++ get_bit_address(s, block, &bmap, &offset); ++ ++ /* Old format filesystem? Unlikely, but the bitmaps are all up front so ++ * we need to account for it. */ ++ if (unlikely(test_bit(REISERFS_OLD_FORMAT, ++ &(REISERFS_SB(s)->s_properties)))) { ++ b_blocknr_t bmap1 = REISERFS_SB(s)->s_sbh->b_blocknr + 1; ++ if (block >= bmap1 && block <= bmap1 + SB_BMAP_NR(s)) { ++ reiserfs_warning(s, "vs: 4019: is_reusable: " ++ "bitmap block %lu(%u) can't be freed or reused", ++ block, SB_BMAP_NR(s)); ++ return 0; ++ } ++ } else { ++ if (offset == 0) { + reiserfs_warning(s, "vs: 4020: is_reusable: " + "bitmap block %lu(%u) can't be freed or reused", + block, SB_BMAP_NR(s)); + return 0; + } ++ } + +- get_bit_address(s, block, &i, &j); +- +- if (i >= SB_BMAP_NR(s)) { ++ if (bmap >= SB_BMAP_NR(s)) { + reiserfs_warning(s, + "vs-4030: is_reusable: there is no so many bitmap blocks: " +- "block=%lu, bitmap_nr=%d", block, i); ++ "block=%lu, bitmap_nr=%d", block, bmap); + return 0; + } + + if ((bit_value == 0 && +- reiserfs_test_le_bit(j, SB_AP_BITMAP(s)[i].bh->b_data)) || ++ reiserfs_test_le_bit(offset, SB_AP_BITMAP(s)[bmap].bh->b_data)) || + (bit_value == 1 && +- reiserfs_test_le_bit(j, SB_AP_BITMAP(s)[i].bh->b_data) == 0)) { ++ reiserfs_test_le_bit(offset, SB_AP_BITMAP(s)[bmap].bh->b_data) == 0)) { + reiserfs_warning(s, + "vs-4040: is_reusable: corresponding bit of block %lu does not " +- "match required value (i==%d, j==%d) test_bit==%d", +- block, i, j, reiserfs_test_le_bit(j, ++ "match required value (bmap==%d, offset==%d) test_bit==%d", ++ block, bmap, offset, reiserfs_test_le_bit(offset, + SB_AP_BITMAP +- (s)[i].bh-> ++ (s)[bmap].bh-> + b_data)); + + return 0; +diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c +index 80fc3b3..db2c581 100644 +--- a/fs/reiserfs/super.c ++++ b/fs/reiserfs/super.c +@@ -1818,6 +1818,8 @@ #endif + if (is_reiserfs_3_5(rs) + || (is_reiserfs_jr(rs) && SB_VERSION(s) == REISERFS_VERSION_1)) + set_bit(REISERFS_3_5, &(sbi->s_properties)); ++ else if (old_format) ++ set_bit(REISERFS_OLD_FORMAT, &(sbi->s_properties)); + else + set_bit(REISERFS_3_6, &(sbi->s_properties)); + +diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h +index 31b4c0b..4f21ad3 100644 +--- a/include/linux/reiserfs_fs_sb.h ++++ b/include/linux/reiserfs_fs_sb.h +@@ -414,6 +414,7 @@ #endif + /* Definitions of reiserfs on-disk properties: */ + #define REISERFS_3_5 0 + #define REISERFS_3_6 1 ++#define REISERFS_OLD_FORMAT 2 + + enum reiserfs_mount_options { + /* Mount options */ +- +To unsubscribe from this list: send the line "unsubscribe git-commits-head" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html + diff --git a/debian/patches/features/fs-reiserfs-bitmap-on-demand-loading.patch b/debian/patches/features/fs-reiserfs-bitmap-on-demand-loading.patch new file mode 100644 index 000000000..d7ceb5a61 --- /dev/null +++ b/debian/patches/features/fs-reiserfs-bitmap-on-demand-loading.patch @@ -0,0 +1,368 @@ +From git-commits-head-owner@vger.kernel.org Wed Oct 4 17:36:49 2006 +Date: Sun, 1 Oct 2006 08:01:31 GMT +Message-Id: <200610010801.k9181V7G010116@hera.kernel.org> +From: Linux Kernel Mailing List +To: git-commits-head@vger.kernel.org +Subject: [PATCH] reiserfs: on-demand bitmap loading + +commit 5065227b46235ec0131b383cc2f537069b55c6b6 +tree 12187734ef619626c901b9d2b43ad72286d4d258 +parent 6f01046b35d940079822827498a7dd6d3eec8c6b +author Jeff Mahoney 1159684124 -0700 +committer Linus Torvalds 1159688368 -0700 + +[PATCH] reiserfs: on-demand bitmap loading + +This is the patch the three previous ones have been leading up to. + +It changes the behavior of ReiserFS from loading and caching all the bitmaps +as special, to treating the bitmaps like any other bit of metadata and just +letting the system-wide caches figure out what to hang on to. + +Buffer heads are allocated on the fly, so there is no need to retain pointers +to all of them. The caching of the metadata occurs when the data is read and +updated, and is considered invalid and uncached until then. + +I needed to remove the vs-4040 check for performing a duplicate operation on a +particular bit. The reason is that while the other sites for working with +bitmaps are allowed to schedule, is_reusable() is called from do_balance(), +which will panic if a schedule occurs in certain places. + +The benefit of on-demand bitmaps clearly outweighs a sanity check that depends +on a compile-time option that is discouraged. + +[akpm@osdl.org: warning fix] +Signed-off-by: Jeff Mahoney +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds + + fs/reiserfs/bitmap.c | 97 ++++++++++++++++++----------------------- + fs/reiserfs/resize.c | 24 +++++++--- + fs/reiserfs/super.c | 39 +++------------- + include/linux/reiserfs_fs_sb.h | 1 + 4 files changed, 70 insertions(+), 91 deletions(-) + +diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c +index abdd6d9..cca1dbf 100644 +--- a/fs/reiserfs/bitmap.c ++++ b/fs/reiserfs/bitmap.c +@@ -60,7 +60,6 @@ #ifdef CONFIG_REISERFS_CHECK + int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value) + { + int bmap, offset; +- struct buffer_head *bh; + + if (block == 0 || block >= SB_BLOCK_COUNT(s)) { + reiserfs_warning(s, +@@ -98,22 +97,6 @@ int is_reusable(struct super_block *s, b + return 0; + } + +- bh = SB_AP_BITMAP(s)[bmap].bh; +- get_bh(bh); +- +- if ((bit_value == 0 && reiserfs_test_le_bit(offset, bh->b_data)) || +- (bit_value == 1 && reiserfs_test_le_bit(offset, bh->b_data) == 0)) { +- reiserfs_warning(s, +- "vs-4040: is_reusable: corresponding bit of block %lu does not " +- "match required value (bmap==%d, offset==%d) test_bit==%d", +- block, bmap, offset, +- reiserfs_test_le_bit(offset, bh->b_data)); +- +- brelse(bh); +- return 0; +- } +- brelse(bh); +- + if (bit_value == 0 && block == SB_ROOT_BLOCK(s)) { + reiserfs_warning(s, + "vs-4050: is_reusable: this is root block (%u), " +@@ -173,13 +156,10 @@ static int scan_bitmap_block(struct reis + bmap_n); + return 0; + } +- bh = bi->bh; +- get_bh(bh); + +- if (buffer_locked(bh)) { +- PROC_INFO_INC(s, scan_bitmap.wait); +- __wait_on_buffer(bh); +- } ++ bh = reiserfs_read_bitmap_block(s, bmap_n); ++ if (bh == NULL) ++ return 0; + + while (1) { + cont: +@@ -285,9 +265,20 @@ static int bmap_hash_id(struct super_blo + */ + static inline int block_group_used(struct super_block *s, u32 id) + { +- int bm; +- bm = bmap_hash_id(s, id); +- if (SB_AP_BITMAP(s)[bm].free_count > ((s->s_blocksize << 3) * 60 / 100)) { ++ int bm = bmap_hash_id(s, id); ++ struct reiserfs_bitmap_info *info = &SB_AP_BITMAP(s)[bm]; ++ ++ /* If we don't have cached information on this bitmap block, we're ++ * going to have to load it later anyway. Loading it here allows us ++ * to make a better decision. This favors long-term performace gain ++ * with a better on-disk layout vs. a short term gain of skipping the ++ * read and potentially having a bad placement. */ ++ if (info->first_zero_hint == 0) { ++ struct buffer_head *bh = reiserfs_read_bitmap_block(s, bm); ++ brelse(bh); ++ } ++ ++ if (info->free_count > ((s->s_blocksize << 3) * 60 / 100)) { + return 0; + } + return 1; +@@ -413,8 +404,9 @@ static void _reiserfs_free_block(struct + return; + } + +- bmbh = apbi[nr].bh; +- get_bh(bmbh); ++ bmbh = reiserfs_read_bitmap_block(s, nr); ++ if (!bmbh) ++ return; + + reiserfs_prepare_for_journal(s, bmbh, 1); + +@@ -1320,6 +1312,7 @@ struct buffer_head *reiserfs_read_bitmap + unsigned int bitmap) + { + b_blocknr_t block = (sb->s_blocksize << 3) * bitmap; ++ struct reiserfs_bitmap_info *info = SB_AP_BITMAP(sb) + bitmap; + struct buffer_head *bh; + + /* Way old format filesystems had the bitmaps packed up front. +@@ -1330,9 +1323,21 @@ struct buffer_head *reiserfs_read_bitmap + else if (bitmap == 0) + block = (REISERFS_DISK_OFFSET_IN_BYTES >> sb->s_blocksize_bits) + 1; + +- bh = sb_getblk(sb, block); +- if (!buffer_uptodate(bh)) +- ll_rw_block(READ, 1, &bh); ++ bh = sb_bread(sb, block); ++ if (bh == NULL) ++ reiserfs_warning(sb, "sh-2029: %s: bitmap block (#%lu) " ++ "reading failed", __FUNCTION__, bh->b_blocknr); ++ else { ++ if (buffer_locked(bh)) { ++ PROC_INFO_INC(sb, scan_bitmap.wait); ++ __wait_on_buffer(bh); ++ } ++ BUG_ON(!buffer_uptodate(bh)); ++ BUG_ON(atomic_read(&bh->b_count) == 0); ++ ++ if (info->first_zero_hint == 0) ++ reiserfs_cache_bitmap_metadata(sb, bh, info); ++ } + + return bh; + } +@@ -1340,7 +1345,6 @@ struct buffer_head *reiserfs_read_bitmap + int reiserfs_init_bitmap_cache(struct super_block *sb) + { + struct reiserfs_bitmap_info *bitmap; +- int i; + + bitmap = vmalloc(sizeof (*bitmap) * SB_BMAP_NR(sb)); + if (bitmap == NULL) +@@ -1348,28 +1352,15 @@ int reiserfs_init_bitmap_cache(struct su + + memset(bitmap, 0, sizeof (*bitmap) * SB_BMAP_NR(sb)); + +- for (i = 0; i < SB_BMAP_NR(sb); i++) +- bitmap[i].bh = reiserfs_read_bitmap_block(sb, i); +- +- /* make sure we have them all */ +- for (i = 0; i < SB_BMAP_NR(sb); i++) { +- wait_on_buffer(bitmap[i].bh); +- if (!buffer_uptodate(bitmap[i].bh)) { +- reiserfs_warning(sb, "sh-2029: %s: " +- "bitmap block (#%lu) reading failed", +- __FUNCTION__, bitmap[i].bh->b_blocknr); +- for (i = 0; i < SB_BMAP_NR(sb); i++) +- brelse(bitmap[i].bh); +- vfree(bitmap); +- return -EIO; +- } +- } +- +- /* Cache the info on the bitmaps before we get rolling */ +- for (i = 0; i < SB_BMAP_NR(sb); i++) +- reiserfs_cache_bitmap_metadata(sb, bitmap[i].bh, &bitmap[i]); +- + SB_AP_BITMAP(sb) = bitmap; + + return 0; + } ++ ++void reiserfs_free_bitmap_cache(struct super_block *sb) ++{ ++ if (SB_AP_BITMAP(sb)) { ++ vfree(SB_AP_BITMAP(sb)); ++ SB_AP_BITMAP(sb) = NULL; ++ } ++} +diff --git a/fs/reiserfs/resize.c b/fs/reiserfs/resize.c +index 90d39fd..3156847 100644 +--- a/fs/reiserfs/resize.c ++++ b/fs/reiserfs/resize.c +@@ -128,8 +128,9 @@ int reiserfs_resize(struct super_block * + * transaction begins, and the new bitmaps don't matter if the + * transaction fails. */ + for (i = bmap_nr; i < bmap_nr_new; i++) { +- bh = sb_getblk(s, i * s->s_blocksize * 8); +- get_bh(bh); ++ /* don't use read_bitmap_block since it will cache ++ * the uninitialized bitmap */ ++ bh = sb_bread(s, i * s->s_blocksize * 8); + memset(bh->b_data, 0, sb_blocksize(sb)); + reiserfs_test_and_set_le_bit(0, bh->b_data); + reiserfs_cache_bitmap_metadata(s, bh, bitmap + i); +@@ -140,7 +141,6 @@ int reiserfs_resize(struct super_block * + // update bitmap_info stuff + bitmap[i].first_zero_hint = 1; + bitmap[i].free_count = sb_blocksize(sb) * 8 - 1; +- bitmap[i].bh = bh; + brelse(bh); + } + /* free old bitmap blocks array */ +@@ -157,8 +157,13 @@ int reiserfs_resize(struct super_block * + + /* Extend old last bitmap block - new blocks have been made available */ + info = SB_AP_BITMAP(s) + bmap_nr - 1; +- bh = info->bh; +- get_bh(bh); ++ bh = reiserfs_read_bitmap_block(s, bmap_nr - 1); ++ if (!bh) { ++ int jerr = journal_end(&th, s, 10); ++ if (jerr) ++ return jerr; ++ return -EIO; ++ } + + reiserfs_prepare_for_journal(s, bh, 1); + for (i = block_r; i < s->s_blocksize * 8; i++) +@@ -172,8 +177,13 @@ int reiserfs_resize(struct super_block * + + /* Correct new last bitmap block - It may not be full */ + info = SB_AP_BITMAP(s) + bmap_nr_new - 1; +- bh = info->bh; +- get_bh(bh); ++ bh = reiserfs_read_bitmap_block(s, bmap_nr_new - 1); ++ if (!bh) { ++ int jerr = journal_end(&th, s, 10); ++ if (jerr) ++ return jerr; ++ return -EIO; ++ } + + reiserfs_prepare_for_journal(s, bh, 1); + for (i = block_r_new; i < s->s_blocksize * 8; i++) +diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c +index c78e99e..c89aa23 100644 +--- a/fs/reiserfs/super.c ++++ b/fs/reiserfs/super.c +@@ -432,7 +432,6 @@ int remove_save_link(struct inode *inode + + static void reiserfs_put_super(struct super_block *s) + { +- int i; + struct reiserfs_transaction_handle th; + th.t_trans_id = 0; + +@@ -462,10 +461,7 @@ static void reiserfs_put_super(struct su + */ + journal_release(&th, s); + +- for (i = 0; i < SB_BMAP_NR(s); i++) +- brelse(SB_AP_BITMAP(s)[i].bh); +- +- vfree(SB_AP_BITMAP(s)); ++ reiserfs_free_bitmap_cache(s); + + brelse(SB_BUFFER_WITH_SB(s)); + +@@ -1344,7 +1340,6 @@ #endif + /* after journal replay, reread all bitmap and super blocks */ + static int reread_meta_blocks(struct super_block *s) + { +- int i; + ll_rw_block(READ, 1, &(SB_BUFFER_WITH_SB(s))); + wait_on_buffer(SB_BUFFER_WITH_SB(s)); + if (!buffer_uptodate(SB_BUFFER_WITH_SB(s))) { +@@ -1353,20 +1348,7 @@ static int reread_meta_blocks(struct sup + return 1; + } + +- for (i = 0; i < SB_BMAP_NR(s); i++) { +- ll_rw_block(READ, 1, &(SB_AP_BITMAP(s)[i].bh)); +- wait_on_buffer(SB_AP_BITMAP(s)[i].bh); +- if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh)) { +- reiserfs_warning(s, +- "reread_meta_blocks, error reading bitmap block number %d at %llu", +- i, +- (unsigned long long)SB_AP_BITMAP(s)[i]. +- bh->b_blocknr); +- return 1; +- } +- } + return 0; +- + } + + ///////////////////////////////////////////////////// +@@ -1547,7 +1529,6 @@ #define SWARN(silent, s, ...) \ + static int reiserfs_fill_super(struct super_block *s, void *data, int silent) + { + struct inode *root_inode; +- int j; + struct reiserfs_transaction_handle th; + int old_format = 0; + unsigned long blocks; +@@ -1793,19 +1774,17 @@ #endif + if (jinit_done) { /* kill the commit thread, free journal ram */ + journal_release_error(NULL, s); + } +- if (SB_DISK_SUPER_BLOCK(s)) { +- for (j = 0; j < SB_BMAP_NR(s); j++) { +- if (SB_AP_BITMAP(s)) +- brelse(SB_AP_BITMAP(s)[j].bh); +- } +- vfree(SB_AP_BITMAP(s)); +- } ++ ++ reiserfs_free_bitmap_cache(s); + if (SB_BUFFER_WITH_SB(s)) + brelse(SB_BUFFER_WITH_SB(s)); + #ifdef CONFIG_QUOTA +- for (j = 0; j < MAXQUOTAS; j++) { +- kfree(sbi->s_qf_names[j]); +- sbi->s_qf_names[j] = NULL; ++ { ++ int j; ++ for (j = 0; j < MAXQUOTAS; j++) { ++ kfree(sbi->s_qf_names[j]); ++ sbi->s_qf_names[j] = NULL; ++ } + } + #endif + kfree(sbi); +diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h +index 4f21ad3..73e0bec 100644 +--- a/include/linux/reiserfs_fs_sb.h ++++ b/include/linux/reiserfs_fs_sb.h +@@ -267,7 +267,6 @@ struct reiserfs_bitmap_info { + // FIXME: Won't work with block sizes > 8K + __u16 first_zero_hint; + __u16 free_count; +- struct buffer_head *bh; /* the actual bitmap */ + }; + + struct proc_dir_entry; diff --git a/debian/patches/features/fs-reiserfs-bitmap-reorganize.patch b/debian/patches/features/fs-reiserfs-bitmap-reorganize.patch new file mode 100644 index 000000000..01258ffb2 --- /dev/null +++ b/debian/patches/features/fs-reiserfs-bitmap-reorganize.patch @@ -0,0 +1,314 @@ +From git-commits-head-owner@vger.kernel.org Wed Oct 4 17:36:48 2006 +Date: Sun, 1 Oct 2006 08:01:30 GMT +Message-Id: <200610010801.k9181U4g010098@hera.kernel.org> +From: Linux Kernel Mailing List +To: git-commits-head@vger.kernel.org +Subject: [PATCH] reiserfs: reorganize bitmap loading functions + +commit 6f01046b35d940079822827498a7dd6d3eec8c6b +tree e65426389691c9d3e7d4f29da73725d15ee8e2f6 +parent 0b3dc17bc0c0997bde9f5d7691ec0cae24258cf7 +author Jeff Mahoney 1159684123 -0700 +committer Linus Torvalds 1159688367 -0700 + +[PATCH] reiserfs: reorganize bitmap loading functions + +This patch moves the bitmap loading code from super.c to bitmap.c + +The code is also restructured somewhat. The only difference between new +format bitmaps and old format bitmaps is where they are. That's a two liner +before loading the block to use the correct one. There's no need for an +entirely separate code path. + +The load path is generally the same, with the pattern being to throw out a +bunch of requests and then wait for them, then cache the metadata from the +contents. + +Again, like the previous patches, the purpose is to set up for later ones. + +Update: There was a bug in the previously posted version of this that resulted +in corruption. The problem was that bitmap 0 on new format file systems must +be treated specially, and wasn't. A stupid bug with an easy fix. + +This is hopefully the last fix for the disaster that is the reiserfs bitmap +patch set. + +If a bitmap block was full, first_zero_hint would end up at zero since it +would never be changed from it's zeroed out value. This just sets it +beyond the end of the bitmap block. If any bits are freed, it will be +reset to a valid bit. When info->free_count = 0, then we already know it's +full. + +Signed-off-by: Jeff Mahoney +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds + + fs/reiserfs/bitmap.c | 88 +++++++++++++++++++++++++++++++++ + fs/reiserfs/resize.c | 1 + fs/reiserfs/super.c | 114 -------------------------------------------- + include/linux/reiserfs_fs.h | 4 + + 4 files changed, 94 insertions(+), 113 deletions(-) + +diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c +index 44d9410..abdd6d9 100644 +--- a/fs/reiserfs/bitmap.c ++++ b/fs/reiserfs/bitmap.c +@@ -9,6 +9,7 @@ #include + #include + #include + #include ++#include + #include + #include + #include +@@ -1285,3 +1286,90 @@ int reiserfs_can_fit_pages(struct super_ + + return space > 0 ? space : 0; + } ++ ++void reiserfs_cache_bitmap_metadata(struct super_block *sb, ++ struct buffer_head *bh, ++ struct reiserfs_bitmap_info *info) ++{ ++ unsigned long *cur = (unsigned long *)(bh->b_data + bh->b_size); ++ ++ info->first_zero_hint = 1 << (sb->s_blocksize_bits + 3); ++ ++ while (--cur >= (unsigned long *)bh->b_data) { ++ int base = ((char *)cur - bh->b_data) << 3; ++ ++ /* 0 and ~0 are special, we can optimize for them */ ++ if (*cur == 0) { ++ info->first_zero_hint = base; ++ info->free_count += BITS_PER_LONG; ++ } else if (*cur != ~0L) { /* A mix, investigate */ ++ int b; ++ for (b = BITS_PER_LONG - 1; b >= 0; b--) { ++ if (!reiserfs_test_le_bit(b, cur)) { ++ info->first_zero_hint = base + b; ++ info->free_count++; ++ } ++ } ++ } ++ } ++ /* The first bit must ALWAYS be 1 */ ++ BUG_ON(info->first_zero_hint == 0); ++} ++ ++struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb, ++ unsigned int bitmap) ++{ ++ b_blocknr_t block = (sb->s_blocksize << 3) * bitmap; ++ struct buffer_head *bh; ++ ++ /* Way old format filesystems had the bitmaps packed up front. ++ * I doubt there are any of these left, but just in case... */ ++ if (unlikely(test_bit(REISERFS_OLD_FORMAT, ++ &(REISERFS_SB(sb)->s_properties)))) ++ block = REISERFS_SB(sb)->s_sbh->b_blocknr + 1 + bitmap; ++ else if (bitmap == 0) ++ block = (REISERFS_DISK_OFFSET_IN_BYTES >> sb->s_blocksize_bits) + 1; ++ ++ bh = sb_getblk(sb, block); ++ if (!buffer_uptodate(bh)) ++ ll_rw_block(READ, 1, &bh); ++ ++ return bh; ++} ++ ++int reiserfs_init_bitmap_cache(struct super_block *sb) ++{ ++ struct reiserfs_bitmap_info *bitmap; ++ int i; ++ ++ bitmap = vmalloc(sizeof (*bitmap) * SB_BMAP_NR(sb)); ++ if (bitmap == NULL) ++ return -ENOMEM; ++ ++ memset(bitmap, 0, sizeof (*bitmap) * SB_BMAP_NR(sb)); ++ ++ for (i = 0; i < SB_BMAP_NR(sb); i++) ++ bitmap[i].bh = reiserfs_read_bitmap_block(sb, i); ++ ++ /* make sure we have them all */ ++ for (i = 0; i < SB_BMAP_NR(sb); i++) { ++ wait_on_buffer(bitmap[i].bh); ++ if (!buffer_uptodate(bitmap[i].bh)) { ++ reiserfs_warning(sb, "sh-2029: %s: " ++ "bitmap block (#%lu) reading failed", ++ __FUNCTION__, bitmap[i].bh->b_blocknr); ++ for (i = 0; i < SB_BMAP_NR(sb); i++) ++ brelse(bitmap[i].bh); ++ vfree(bitmap); ++ return -EIO; ++ } ++ } ++ ++ /* Cache the info on the bitmaps before we get rolling */ ++ for (i = 0; i < SB_BMAP_NR(sb); i++) ++ reiserfs_cache_bitmap_metadata(sb, bitmap[i].bh, &bitmap[i]); ++ ++ SB_AP_BITMAP(sb) = bitmap; ++ ++ return 0; ++} +diff --git a/fs/reiserfs/resize.c b/fs/reiserfs/resize.c +index 958b759..90d39fd 100644 +--- a/fs/reiserfs/resize.c ++++ b/fs/reiserfs/resize.c +@@ -132,6 +132,7 @@ int reiserfs_resize(struct super_block * + get_bh(bh); + memset(bh->b_data, 0, sb_blocksize(sb)); + reiserfs_test_and_set_le_bit(0, bh->b_data); ++ reiserfs_cache_bitmap_metadata(s, bh, bitmap + i); + + set_buffer_uptodate(bh); + mark_buffer_dirty(bh); +diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c +index db2c581..c78e99e 100644 +--- a/fs/reiserfs/super.c ++++ b/fs/reiserfs/super.c +@@ -1243,118 +1243,6 @@ #endif + return 0; + } + +-/* load_bitmap_info_data - Sets up the reiserfs_bitmap_info structure from disk. +- * @sb - superblock for this filesystem +- * @bi - the bitmap info to be loaded. Requires that bi->bh is valid. +- * +- * This routine counts how many free bits there are, finding the first zero +- * as a side effect. Could also be implemented as a loop of test_bit() calls, or +- * a loop of find_first_zero_bit() calls. This implementation is similar to +- * find_first_zero_bit(), but doesn't return after it finds the first bit. +- * Should only be called on fs mount, but should be fairly efficient anyways. +- * +- * bi->first_zero_hint is considered unset if it == 0, since the bitmap itself +- * will * invariably occupt block 0 represented in the bitmap. The only +- * exception to this is when free_count also == 0, since there will be no +- * free blocks at all. +- */ +- +-static void load_bitmap_info_data(struct super_block *sb, +- struct reiserfs_bitmap_info *bi) +-{ +- unsigned long *cur = (unsigned long *)bi->bh->b_data; +- +- while ((char *)cur < (bi->bh->b_data + sb->s_blocksize)) { +- +- /* No need to scan if all 0's or all 1's. +- * Since we're only counting 0's, we can simply ignore all 1's */ +- if (*cur == 0) { +- if (bi->first_zero_hint == 0) { +- bi->first_zero_hint = +- ((char *)cur - bi->bh->b_data) << 3; +- } +- bi->free_count += sizeof(unsigned long) * 8; +- } else if (*cur != ~0L) { +- int b; +- for (b = 0; b < sizeof(unsigned long) * 8; b++) { +- if (!reiserfs_test_le_bit(b, cur)) { +- bi->free_count++; +- if (bi->first_zero_hint == 0) +- bi->first_zero_hint = +- (((char *)cur - +- bi->bh->b_data) << 3) + b; +- } +- } +- } +- cur++; +- } +- +-#ifdef CONFIG_REISERFS_CHECK +-// This outputs a lot of unneded info on big FSes +-// reiserfs_warning ("bitmap loaded from block %d: %d free blocks", +-// bi->bh->b_blocknr, bi->free_count); +-#endif +-} +- +-static int read_bitmaps(struct super_block *s) +-{ +- int i, bmap_nr; +- +- SB_AP_BITMAP(s) = +- vmalloc(sizeof(struct reiserfs_bitmap_info) * SB_BMAP_NR(s)); +- if (SB_AP_BITMAP(s) == 0) +- return 1; +- memset(SB_AP_BITMAP(s), 0, +- sizeof(struct reiserfs_bitmap_info) * SB_BMAP_NR(s)); +- for (i = 0, bmap_nr = +- REISERFS_DISK_OFFSET_IN_BYTES / s->s_blocksize + 1; +- i < SB_BMAP_NR(s); i++, bmap_nr = s->s_blocksize * 8 * i) { +- SB_AP_BITMAP(s)[i].bh = sb_getblk(s, bmap_nr); +- if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh)) +- ll_rw_block(READ, 1, &SB_AP_BITMAP(s)[i].bh); +- } +- for (i = 0; i < SB_BMAP_NR(s); i++) { +- wait_on_buffer(SB_AP_BITMAP(s)[i].bh); +- if (!buffer_uptodate(SB_AP_BITMAP(s)[i].bh)) { +- reiserfs_warning(s, "sh-2029: reiserfs read_bitmaps: " +- "bitmap block (#%lu) reading failed", +- SB_AP_BITMAP(s)[i].bh->b_blocknr); +- for (i = 0; i < SB_BMAP_NR(s); i++) +- brelse(SB_AP_BITMAP(s)[i].bh); +- vfree(SB_AP_BITMAP(s)); +- SB_AP_BITMAP(s) = NULL; +- return 1; +- } +- load_bitmap_info_data(s, SB_AP_BITMAP(s) + i); +- } +- return 0; +-} +- +-static int read_old_bitmaps(struct super_block *s) +-{ +- int i; +- struct reiserfs_super_block *rs = SB_DISK_SUPER_BLOCK(s); +- int bmp1 = (REISERFS_OLD_DISK_OFFSET_IN_BYTES / s->s_blocksize) + 1; /* first of bitmap blocks */ +- +- /* read true bitmap */ +- SB_AP_BITMAP(s) = +- vmalloc(sizeof(struct reiserfs_buffer_info *) * sb_bmap_nr(rs)); +- if (SB_AP_BITMAP(s) == 0) +- return 1; +- +- memset(SB_AP_BITMAP(s), 0, +- sizeof(struct reiserfs_buffer_info *) * sb_bmap_nr(rs)); +- +- for (i = 0; i < sb_bmap_nr(rs); i++) { +- SB_AP_BITMAP(s)[i].bh = sb_bread(s, bmp1 + i); +- if (!SB_AP_BITMAP(s)[i].bh) +- return 1; +- load_bitmap_info_data(s, SB_AP_BITMAP(s) + i); +- } +- +- return 0; +-} +- + static int read_super_block(struct super_block *s, int offset) + { + struct buffer_head *bh; +@@ -1736,7 +1624,7 @@ static int reiserfs_fill_super(struct su + sbi->s_mount_state = SB_REISERFS_STATE(s); + sbi->s_mount_state = REISERFS_VALID_FS; + +- if (old_format ? read_old_bitmaps(s) : read_bitmaps(s)) { ++ if ((errval = reiserfs_init_bitmap_cache(s))) { + SWARN(silent, s, + "jmacd-8: reiserfs_fill_super: unable to read bitmap"); + goto error; +diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h +index 9c63abf..7bc6bfb 100644 +--- a/include/linux/reiserfs_fs.h ++++ b/include/linux/reiserfs_fs.h +@@ -2073,6 +2073,10 @@ void reiserfs_init_alloc_options(struct + */ + __le32 reiserfs_choose_packing(struct inode *dir); + ++int reiserfs_init_bitmap_cache(struct super_block *sb); ++void reiserfs_free_bitmap_cache(struct super_block *sb); ++void reiserfs_cache_bitmap_metadata(struct super_block *sb, struct buffer_head *bh, struct reiserfs_bitmap_info *info); ++struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb, unsigned int bitmap); + int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value); + void reiserfs_free_block(struct reiserfs_transaction_handle *th, struct inode *, + b_blocknr_t, int for_unformatted); diff --git a/debian/patches/features/fs-reiserfs-fsync-barriers.patch b/debian/patches/features/fs-reiserfs-fsync-barriers.patch new file mode 100644 index 000000000..a902074cf --- /dev/null +++ b/debian/patches/features/fs-reiserfs-fsync-barriers.patch @@ -0,0 +1,38 @@ +From git-commits-head-owner@vger.kernel.org Sat Sep 30 01:10:37 2006 +Date: Fri, 29 Sep 2006 17:02:12 GMT +Message-Id: <200609291702.k8TH2C5A031438@hera.kernel.org> +From: Linux Kernel Mailing List +To: git-commits-head@vger.kernel.org +Subject: [PATCH] reiserfs_fsync should only use barriers when they are enabled + +commit 25736b1c692d436508585d1d710912e6f76be2d8 +tree 8cf9a65b5a6d464ceabfe992b49a028a9a939198 +parent d4328b40af16bae62ff8f854060d33daad237093 +author Chris Mason 1159520394 -0700 +committer Linus Torvalds 1159546691 -0700 + +[PATCH] reiserfs_fsync should only use barriers when they are enabled + +make sure that reiserfs_fsync only triggers barriers when mounted with -o +barrier=flush + +Signed-off-by: Chris Mason +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds + + fs/reiserfs/file.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c +index 1627edd..1cfbe85 100644 +--- a/fs/reiserfs/file.c ++++ b/fs/reiserfs/file.c +@@ -130,7 +130,7 @@ static int reiserfs_sync_file(struct fil + reiserfs_write_lock(p_s_inode->i_sb); + barrier_done = reiserfs_commit_for_inode(p_s_inode); + reiserfs_write_unlock(p_s_inode->i_sb); +- if (barrier_done != 1) ++ if (barrier_done != 1 && reiserfs_barrier_flush(p_s_inode->i_sb)) + blkdev_issue_flush(p_s_inode->i_sb->s_bdev, NULL); + if (barrier_done < 0) + return barrier_done; diff --git a/debian/patches/features/fs-reiserfs-gcc-flags.patch b/debian/patches/features/fs-reiserfs-gcc-flags.patch new file mode 100644 index 000000000..f467ff362 --- /dev/null +++ b/debian/patches/features/fs-reiserfs-gcc-flags.patch @@ -0,0 +1,40 @@ +From git-commits-head-owner@vger.kernel.org Sat Sep 30 01:10:28 2006 +Date: Fri, 29 Sep 2006 17:01:39 GMT +Message-Id: <200609291701.k8TH1dVv030631@hera.kernel.org> +From: Linux Kernel Mailing List +To: git-commits-head@vger.kernel.org +Subject: [PATCH] use gcc -O1 in fs/reiserfs only for ancient gcc versions + +commit 42012cc4a2183c555a907eee32d7ce4fc7dc3a6a +tree 90fbd712085050fac8f06544e3186736539cf2bc +parent 4d24607bfaab3d02fd0d6e0ffc22f29c2bc8eb30 +author Olaf Hering 1159520361 -0700 +committer Linus Torvalds 1159546687 -0700 + +[PATCH] use gcc -O1 in fs/reiserfs only for ancient gcc versions + +Only compile with -O1 if the (very old) compiler is broken. We use +reiserfs alot since SLES9 on ppc64, and it was never seen with gcc33. +Assume the broken gcc is gcc-3.4 or older. + +Signed-off-by: Olaf Hering +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds + + fs/reiserfs/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/reiserfs/Makefile b/fs/reiserfs/Makefile +index 3a59309..0eb7ac0 100644 +--- a/fs/reiserfs/Makefile ++++ b/fs/reiserfs/Makefile +@@ -28,7 +28,7 @@ # and causing a panic. Since this behavi + # will work around it. If any other architecture displays this behavior, + # add it here. + ifeq ($(CONFIG_PPC32),y) +-EXTRA_CFLAGS := -O1 ++EXTRA_CFLAGS := $(call cc-ifversion, -lt, 0400, -O1) + endif + + TAGS: + diff --git a/debian/patches/features/fs-reiserfs-latency-journal_begin.patch b/debian/patches/features/fs-reiserfs-latency-journal_begin.patch new file mode 100644 index 000000000..a8d6efcb8 --- /dev/null +++ b/debian/patches/features/fs-reiserfs-latency-journal_begin.patch @@ -0,0 +1,119 @@ +From git-commits-head-owner@vger.kernel.org Sat Sep 30 01:10:36 2006 +Date: Fri, 29 Sep 2006 17:02:13 GMT +Message-Id: <200609291702.k8TH2D50031449@hera.kernel.org> +From: Linux Kernel Mailing List +To: git-commits-head@vger.kernel.org +Subject: [PATCH] Fix reiserfs latencies caused by data=ordered + +commit a3172027148120b8f8797cbecc7d0a0b215736a1 +tree 9da7b5eafe136c8c5b9e76e9a9cccd70899df252 +parent 25736b1c692d436508585d1d710912e6f76be2d8 +author Chris Mason 1159520396 -0700 +committer Linus Torvalds 1159546691 -0700 + +[PATCH] Fix reiserfs latencies caused by data=ordered + +ReiserFS does periodic cleanup of old transactions in order to limit the +length of time a journal replay may take after a crash. Sometimes, writing +metadata from an old (already committed) transaction may require committing +a newer transaction, which also requires writing all data=ordered buffers. +This can cause very long stalls on journal_begin. + +This patch makes sure new transactions will not need to be committed before +trying a periodic reclaim of an old transaction. It is low risk because if +a bad decision is made, it just means a slightly longer journal replay +after a crash. + +Signed-off-by: Chris Mason +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds + + fs/reiserfs/journal.c | 54 +++++++++++++++++++++++++++++++++++++++----------- + 1 file changed, 43 insertions(+), 11 deletions(-) + +diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c +index 9b3672d..e6b5ccf 100644 +--- a/fs/reiserfs/journal.c ++++ b/fs/reiserfs/journal.c +@@ -1186,6 +1186,21 @@ static struct reiserfs_journal_list *fin + return NULL; + } + ++static int newer_jl_done(struct reiserfs_journal_cnode *cn) ++{ ++ struct super_block *sb = cn->sb; ++ b_blocknr_t blocknr = cn->blocknr; ++ ++ cn = cn->hprev; ++ while (cn) { ++ if (cn->sb == sb && cn->blocknr == blocknr && cn->jlist && ++ atomic_read(&cn->jlist->j_commit_left) != 0) ++ return 0; ++ cn = cn->hprev; ++ } ++ return 1; ++} ++ + static void remove_journal_hash(struct super_block *, + struct reiserfs_journal_cnode **, + struct reiserfs_journal_list *, unsigned long, +@@ -1604,6 +1619,31 @@ #endif + return err; + } + ++static int test_transaction(struct super_block *s, ++ struct reiserfs_journal_list *jl) ++{ ++ struct reiserfs_journal_cnode *cn; ++ ++ if (jl->j_len == 0 || atomic_read(&jl->j_nonzerolen) == 0) ++ return 1; ++ ++ cn = jl->j_realblock; ++ while (cn) { ++ /* if the blocknr == 0, this has been cleared from the hash, ++ ** skip it ++ */ ++ if (cn->blocknr == 0) { ++ goto next; ++ } ++ if (cn->bh && !newer_jl_done(cn)) ++ return 0; ++ next: ++ cn = cn->next; ++ cond_resched(); ++ } ++ return 0; ++} ++ + static int write_one_transaction(struct super_block *s, + struct reiserfs_journal_list *jl, + struct buffer_chunk *chunk) +@@ -3433,16 +3473,6 @@ static void flush_async_commits(void *p) + flush_commit_list(p_s_sb, jl, 1); + } + unlock_kernel(); +- /* +- * this is a little racey, but there's no harm in missing +- * the filemap_fdata_write +- */ +- if (!atomic_read(&journal->j_async_throttle) +- && !reiserfs_is_journal_aborted(journal)) { +- atomic_inc(&journal->j_async_throttle); +- filemap_fdatawrite(p_s_sb->s_bdev->bd_inode->i_mapping); +- atomic_dec(&journal->j_async_throttle); +- } + } + + /* +@@ -3844,7 +3874,9 @@ static void flush_old_journal_lists(stru + entry = journal->j_journal_list.next; + jl = JOURNAL_LIST_ENTRY(entry); + /* this check should always be run, to send old lists to disk */ +- if (jl->j_timestamp < (now - (JOURNAL_MAX_TRANS_AGE * 4))) { ++ if (jl->j_timestamp < (now - (JOURNAL_MAX_TRANS_AGE * 4)) && ++ atomic_read(&jl->j_commit_left) == 0 && ++ test_transaction(s, jl)) { + flush_used_journal_lists(s, jl); + } else { + break; diff --git a/debian/patches/series/6 b/debian/patches/series/6 new file mode 100644 index 000000000..198ed53d3 --- /dev/null +++ b/debian/patches/series/6 @@ -0,0 +1,7 @@ ++ features/fs-reiserfs-gcc-flags.patch ++ features/fs-reiserfs-fsync-barriers.patch ++ features/fs-reiserfs-latency-journal_begin.patch ++ features/fs-reiserfs-bitmap-block-optimization.patch ++ features/fs-reiserfs-bitmap-block-cleanup.patch ++ features/fs-reiserfs-bitmap-reorganize.patch ++ features/fs-reiserfs-bitmap-on-demand-loading.patch