[PATCH] reiserfs: fix is_reusable bitmap check to not traverse the bitmap info array
authorJeff Mahoney <jeffm@suse.com>
Sun, 1 Oct 2006 06:28:40 +0000 (23:28 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Sun, 1 Oct 2006 07:39:27 +0000 (00:39 -0700)
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 <jeffm@suse.com>
Cc: <reiserfs-dev@namesys.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
fs/reiserfs/bitmap.c
fs/reiserfs/super.c
include/linux/reiserfs_fs_sb.h

index 4a7dbdee1b6d73f1d1ae8fb44becb0410c6e58d1..1022347a211f80099dd06f1879e26c7945c853c7 100644 (file)
@@ -50,16 +50,15 @@ static inline void get_bit_address(struct super_block *s,
 {
        /* 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_blocknr_t block, int bit_value)
                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;
index 80fc3b32802f827d6fe1bf8e9e919321d3f9e6d0..db2c581df766eeadbb3c698754c3b139d5bc136d 100644 (file)
@@ -1818,6 +1818,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        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));
 
index 31b4c0bd4fa000e94a32f5b8b5f99c9211f68f4e..4f21ad388c79079f28dd17a3b9619fea3d1ad214 100644 (file)
@@ -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 */