From: Jeff Mahoney The following patchset allows reiserfs to load its bitmap blocks on demand like other file systems. There are several reasons for this: * Bitmap blocks, relative to other metadata blocks, are among the least used blocks in the file system. We don't cache the root node block, so why do we pin the bitmaps? * Loading all the bitmaps at file system mount takes a lot of time. On multi- TB file systems, I've heard reports of file systems taking 15 minutes to mount. There go your 5 9's after one reboot. * Keeping bitmaps in memory isn't free. The old argument of "large storage implies large memory" is no longer true. It's possible to assemble a multi- TB RAID array for a desktop for under $1000 these days. Memory prices have not fallen at the same rate. This patch: 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 Signed-off-by: Andrew Morton --- fs/reiserfs/bitmap.c | 18 +++++++++++++++--- fs/reiserfs/super.c | 2 ++ include/linux/reiserfs_fs_sb.h | 1 + 3 files changed, 18 insertions(+), 3 deletions(-) diff -puN fs/reiserfs/bitmap.c~reiserfs-fix-is_reusable-bitmap-check-to-not-traverse-the-bitmap-info-array fs/reiserfs/bitmap.c --- 25/fs/reiserfs/bitmap.c~reiserfs-fix-is_reusable-bitmap-check-to-not-traverse-the-bitmap-info-array Tue Jan 17 16:35:12 2006 +++ 25-akpm/fs/reiserfs/bitmap.c Tue Jan 17 16:35:12 2006 @@ -61,6 +61,7 @@ static inline void get_bit_address(struc int is_reusable(struct super_block *s, b_blocknr_t block, int bit_value) { int i, j; + unsigned int bmap = block >> s->s_blocksize_bits; if (block == 0 || block >= SB_BLOCK_COUNT(s)) { reiserfs_warning(s, @@ -69,14 +70,25 @@ 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) { + /* 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 + bmap && 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 ((block & ((s->s_blocksize << 3) - 1)) == 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); diff -puN fs/reiserfs/super.c~reiserfs-fix-is_reusable-bitmap-check-to-not-traverse-the-bitmap-info-array fs/reiserfs/super.c --- 25/fs/reiserfs/super.c~reiserfs-fix-is_reusable-bitmap-check-to-not-traverse-the-bitmap-info-array Tue Jan 17 16:35:12 2006 +++ 25-akpm/fs/reiserfs/super.c Tue Jan 17 16:35:12 2006 @@ -1833,6 +1833,8 @@ static int reiserfs_fill_super(struct su 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 -puN include/linux/reiserfs_fs_sb.h~reiserfs-fix-is_reusable-bitmap-check-to-not-traverse-the-bitmap-info-array include/linux/reiserfs_fs_sb.h --- 25/include/linux/reiserfs_fs_sb.h~reiserfs-fix-is_reusable-bitmap-check-to-not-traverse-the-bitmap-info-array Tue Jan 17 16:35:12 2006 +++ 25-akpm/include/linux/reiserfs_fs_sb.h Tue Jan 17 16:35:12 2006 @@ -414,6 +414,7 @@ struct reiserfs_sb_info { /* 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 */ _