ext4: add block bitmap validation

2008-01-29 Thread Linux Kernel Mailing List
Gitweb: 
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=abcb2947c91130426539f209f7a473a67a1f6663
Commit: abcb2947c91130426539f209f7a473a67a1f6663
Parent: 389d1b083c767a360ec84b27a95da06244becec8
Author: Aneesh Kumar K.V [EMAIL PROTECTED]
AuthorDate: Mon Jan 28 23:58:27 2008 -0500
Committer:  Theodore Ts'o [EMAIL PROTECTED]
CommitDate: Mon Jan 28 23:58:27 2008 -0500

ext4: add block bitmap validation

When a new block bitmap is read from disk in read_block_bitmap()
there are a few bits that should ALWAYS be set.  In particular,
the blocks given corresponding to block bitmap, inode bitmap and inode 
tables.
Validate the block bitmap against these blocks.

Signed-off-by: Aneesh Kumar K.V [EMAIL PROTECTED]
---
 fs/ext4/balloc.c |   99 --
 1 files changed, 81 insertions(+), 18 deletions(-)

diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index ff3428e..d460223 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -189,13 +189,65 @@ struct ext4_group_desc * ext4_get_group_desc(struct 
super_block * sb,
return desc;
 }
 
+static int ext4_valid_block_bitmap(struct super_block *sb,
+   struct ext4_group_desc *desc,
+   unsigned int block_group,
+   struct buffer_head *bh)
+{
+   ext4_grpblk_t offset;
+   ext4_grpblk_t next_zero_bit;
+   ext4_fsblk_t bitmap_blk;
+   ext4_fsblk_t group_first_block;
+
+   if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
+   /* with FLEX_BG, the inode/block bitmaps and itable
+* blocks may not be in the group at all
+* so the bitmap validation will be skipped for those groups
+* or it has to also read the block group where the bitmaps
+* are located to verify they are set.
+*/
+   return 1;
+   }
+   group_first_block = ext4_group_first_block_no(sb, block_group);
+
+   /* check whether block bitmap block number is set */
+   bitmap_blk = ext4_block_bitmap(sb, desc);
+   offset = bitmap_blk - group_first_block;
+   if (!ext4_test_bit(offset, bh-b_data))
+   /* bad block bitmap */
+   goto err_out;
+
+   /* check whether the inode bitmap block number is set */
+   bitmap_blk = ext4_inode_bitmap(sb, desc);
+   offset = bitmap_blk - group_first_block;
+   if (!ext4_test_bit(offset, bh-b_data))
+   /* bad block bitmap */
+   goto err_out;
+
+   /* check whether the inode table block number is set */
+   bitmap_blk = ext4_inode_table(sb, desc);
+   offset = bitmap_blk - group_first_block;
+   next_zero_bit = ext4_find_next_zero_bit(bh-b_data,
+   offset + EXT4_SB(sb)-s_itb_per_group,
+   offset);
+   if (next_zero_bit = offset + EXT4_SB(sb)-s_itb_per_group)
+   /* good bitmap for inode tables */
+   return 1;
+
+err_out:
+   ext4_error(sb, __FUNCTION__,
+   Invalid block bitmap - 
+   block_group = %d, block = %llu,
+   block_group, bitmap_blk);
+   return 0;
+}
 /**
  * read_block_bitmap()
  * @sb:super block
  * @block_group:   given block group
  *
- * Read the bitmap for a given block_group, reading into the specified
- * slot in the superblock's bitmap cache.
+ * Read the bitmap for a given block_group,and validate the
+ * bits for block/inode/inode tables are set in the bitmaps
  *
  * Return buffer_head on success or NULL in case of failure.
  */
@@ -210,25 +262,36 @@ read_block_bitmap(struct super_block *sb, ext4_group_t 
block_group)
if (!desc)
return NULL;
bitmap_blk = ext4_block_bitmap(sb, desc);
+   bh = sb_getblk(sb, bitmap_blk);
+   if (unlikely(!bh)) {
+   ext4_error(sb, __FUNCTION__,
+   Cannot read block bitmap - 
+   block_group = %d, block_bitmap = %llu,
+   (int)block_group, (unsigned long long)bitmap_blk);
+   return NULL;
+   }
+   if (bh_uptodate_or_lock(bh))
+   return bh;
+
if (desc-bg_flags  cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
-   bh = sb_getblk(sb, bitmap_blk);
-   if (!buffer_uptodate(bh)) {
-   lock_buffer(bh);
-   if (!buffer_uptodate(bh)) {
-   ext4_init_block_bitmap(sb, bh, block_group,
-  desc);
-   set_buffer_uptodate(bh);
-   }
-   unlock_buffer(bh);
-   }
-   } else {
-   bh = sb_bread(sb

Revert ext2/ext3/ext4: add block bitmap validation

2007-11-13 Thread Linux Kernel Mailing List
Gitweb: 
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=0b832a4b93932103d73c0c3f35ef1153e288327b
Commit: 0b832a4b93932103d73c0c3f35ef1153e288327b
Parent: 325d22df7b19e0116aff3391d3a03f73d0634ded
Author: Linus Torvalds [EMAIL PROTECTED]
AuthorDate: Tue Nov 13 08:07:31 2007 -0800
Committer:  Linus Torvalds [EMAIL PROTECTED]
CommitDate: Tue Nov 13 08:09:11 2007 -0800

Revert ext2/ext3/ext4: add block bitmap validation

This reverts commit 7c9e69faa28027913ee059c285a5ea8382e24b5d, fixing up
conflicts in fs/ext4/balloc.c manually.

The cost of doing the bitmap validation on each lookup - even when the
bitmap is cached - is absolutely prohibitive.  We could, and probably
should, do it only when adding the bitmap to the buffer cache.  However,
right now we are better off just reverting it.

Peter Zijlstra measured the cost of this extra validation as a 85%
decrease in cached iozone, and while I had a patch that took it down to
just 17% by not being _quite_ so stupid in the validation, it was still
a big slowdown that could have been avoided by just doing it right.

Cc: Peter Zijlstra [EMAIL PROTECTED]
Cc: Andrew Morton [EMAIL PROTECTED]
Cc: Aneesh Kumar [EMAIL PROTECTED]
Cc: Andreas Dilger [EMAIL PROTECTED]
Cc: Mingming Cao [EMAIL PROTECTED]
Signed-off-by: Linus Torvalds [EMAIL PROTECTED]
---
 fs/ext2/balloc.c |   50 +-
 fs/ext3/balloc.c |   48 
 fs/ext4/balloc.c |   41 -
 3 files changed, 9 insertions(+), 130 deletions(-)

diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
index 18a42de..377ad17 100644
--- a/fs/ext2/balloc.c
+++ b/fs/ext2/balloc.c
@@ -69,14 +69,6 @@ struct ext2_group_desc * ext2_get_group_desc(struct 
super_block * sb,
return desc + offset;
 }
 
-static inline int
-block_in_use(unsigned long block, struct super_block *sb, unsigned char *map)
-{
-   return ext2_test_bit ((block -
-   le32_to_cpu(EXT2_SB(sb)-s_es-s_first_data_block)) %
-EXT2_BLOCKS_PER_GROUP(sb), map);
-}
-
 /*
  * Read the bitmap for a given block_group, reading into the specified 
  * slot in the superblock's bitmap cache.
@@ -86,51 +78,20 @@ block_in_use(unsigned long block, struct super_block *sb, 
unsigned char *map)
 static struct buffer_head *
 read_block_bitmap(struct super_block *sb, unsigned int block_group)
 {
-   int i;
struct ext2_group_desc * desc;
struct buffer_head * bh = NULL;
-   unsigned int bitmap_blk;
-
+   
desc = ext2_get_group_desc (sb, block_group, NULL);
if (!desc)
-   return NULL;
-   bitmap_blk = le32_to_cpu(desc-bg_block_bitmap);
-   bh = sb_bread(sb, bitmap_blk);
+   goto error_out;
+   bh = sb_bread(sb, le32_to_cpu(desc-bg_block_bitmap));
if (!bh)
-   ext2_error (sb, __FUNCTION__,
+   ext2_error (sb, read_block_bitmap,
Cannot read block bitmap - 
block_group = %d, block_bitmap = %u,
block_group, le32_to_cpu(desc-bg_block_bitmap));
-
-   /* check whether block bitmap block number is set */
-   if (!block_in_use(bitmap_blk, sb, bh-b_data)) {
-   /* bad block bitmap */
-   goto error_out;
-   }
-   /* check whether the inode bitmap block number is set */
-   bitmap_blk = le32_to_cpu(desc-bg_inode_bitmap);
-   if (!block_in_use(bitmap_blk, sb, bh-b_data)) {
-   /* bad block bitmap */
-   goto error_out;
-   }
-   /* check whether the inode table block number is set */
-   bitmap_blk = le32_to_cpu(desc-bg_inode_table);
-   for (i = 0; i  EXT2_SB(sb)-s_itb_per_group; i++, bitmap_blk++) {
-   if (!block_in_use(bitmap_blk, sb, bh-b_data)) {
-   /* bad block bitmap */
-   goto error_out;
-   }
-   }
-
-   return bh;
-
 error_out:
-   brelse(bh);
-   ext2_error(sb, __FUNCTION__,
-   Invalid block bitmap - 
-   block_group = %d, block = %u,
-   block_group, bitmap_blk);
-   return NULL;
+   return bh;
 }
 
 static void release_blocks(struct super_block *sb, int count)
@@ -1461,7 +1422,6 @@ unsigned long ext2_count_free_blocks (struct super_block 
* sb)
 #endif
 }
 
-
 static inline int test_root(int a, int b)
 {
int num = b;
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index 7a87d15..a8ba7e8 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -80,14 +80,6 @@ struct ext3_group_desc * ext3_get_group_desc(struct 
super_block * sb,
return desc + offset;
 }
 
-static inline int
-block_in_use(ext3_fsblk_t block, struct super_block *sb, unsigned char *map

ext2/ext3/ext4: add block bitmap validation

2007-10-17 Thread Linux Kernel Mailing List
Gitweb: 
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=7c9e69faa28027913ee059c285a5ea8382e24b5d
Commit: 7c9e69faa28027913ee059c285a5ea8382e24b5d
Parent: 82df39738ba9e02c057fa99b7461a56117d36119
Author: Aneesh Kumar K.V [EMAIL PROTECTED]
AuthorDate: Tue Oct 16 23:27:02 2007 -0700
Committer:  Linus Torvalds [EMAIL PROTECTED]
CommitDate: Wed Oct 17 08:42:52 2007 -0700

ext2/ext3/ext4: add block bitmap validation

When a new block bitmap is read from disk in read_block_bitmap() there are
a few bits that should ALWAYS be set.  In particular, the blocks given by
ext4_blk_bitmap, ext4_inode_bitmap and ext4_inode_table.  Validate the
block bitmap against these blocks.

[EMAIL PROTECTED]: cleanups]
Signed-off-by: Aneesh Kumar K.V [EMAIL PROTECTED]
Signed-off-by: Andreas Dilger [EMAIL PROTECTED]
Acked-by: Mingming Cao [EMAIL PROTECTED]
Signed-off-by: Andrew Morton [EMAIL PROTECTED]
Signed-off-by: Linus Torvalds [EMAIL PROTECTED]
---
 fs/ext2/balloc.c |   56 ++--
 fs/ext3/balloc.c |   54 +-
 fs/ext4/balloc.c |   62 -
 3 files changed, 134 insertions(+), 38 deletions(-)

diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
index 834ad4c..ffaa6d8 100644
--- a/fs/ext2/balloc.c
+++ b/fs/ext2/balloc.c
@@ -69,6 +69,14 @@ struct ext2_group_desc * ext2_get_group_desc(struct 
super_block * sb,
return desc + offset;
 }
 
+static inline int
+block_in_use(unsigned long block, struct super_block *sb, unsigned char *map)
+{
+   return ext2_test_bit ((block -
+   le32_to_cpu(EXT2_SB(sb)-s_es-s_first_data_block)) %
+EXT2_BLOCKS_PER_GROUP(sb), map);
+}
+
 /*
  * Read the bitmap for a given block_group, reading into the specified 
  * slot in the superblock's bitmap cache.
@@ -78,20 +86,51 @@ struct ext2_group_desc * ext2_get_group_desc(struct 
super_block * sb,
 static struct buffer_head *
 read_block_bitmap(struct super_block *sb, unsigned int block_group)
 {
+   int i;
struct ext2_group_desc * desc;
struct buffer_head * bh = NULL;
-   
+   unsigned int bitmap_blk;
+
desc = ext2_get_group_desc (sb, block_group, NULL);
if (!desc)
-   goto error_out;
-   bh = sb_bread(sb, le32_to_cpu(desc-bg_block_bitmap));
+   return NULL;
+   bitmap_blk = le32_to_cpu(desc-bg_block_bitmap);
+   bh = sb_bread(sb, bitmap_blk);
if (!bh)
-   ext2_error (sb, read_block_bitmap,
+   ext2_error (sb, __FUNCTION__,
Cannot read block bitmap - 
block_group = %d, block_bitmap = %u,
block_group, le32_to_cpu(desc-bg_block_bitmap));
-error_out:
+
+   /* check whether block bitmap block number is set */
+   if (!block_in_use(bitmap_blk, sb, bh-b_data)) {
+   /* bad block bitmap */
+   goto error_out;
+   }
+   /* check whether the inode bitmap block number is set */
+   bitmap_blk = le32_to_cpu(desc-bg_inode_bitmap);
+   if (!block_in_use(bitmap_blk, sb, bh-b_data)) {
+   /* bad block bitmap */
+   goto error_out;
+   }
+   /* check whether the inode table block number is set */
+   bitmap_blk = le32_to_cpu(desc-bg_inode_table);
+   for (i = 0; i  EXT2_SB(sb)-s_itb_per_group; i++, bitmap_blk++) {
+   if (!block_in_use(bitmap_blk, sb, bh-b_data)) {
+   /* bad block bitmap */
+   goto error_out;
+   }
+   }
+
return bh;
+
+error_out:
+   brelse(bh);
+   ext2_error(sb, __FUNCTION__,
+   Invalid block bitmap - 
+   block_group = %d, block = %u,
+   block_group, bitmap_blk);
+   return NULL;
 }
 
 /*
@@ -583,13 +622,6 @@ unsigned long ext2_count_free_blocks (struct super_block * 
sb)
 #endif
 }
 
-static inline int
-block_in_use(unsigned long block, struct super_block *sb, unsigned char *map)
-{
-   return ext2_test_bit ((block -
-   le32_to_cpu(EXT2_SB(sb)-s_es-s_first_data_block)) %
-EXT2_BLOCKS_PER_GROUP(sb), map);
-}
 
 static inline int test_root(int a, int b)
 {
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index d3758ee..7a87d15 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -80,6 +80,14 @@ struct ext3_group_desc * ext3_get_group_desc(struct 
super_block * sb,
return desc + offset;
 }
 
+static inline int
+block_in_use(ext3_fsblk_t block, struct super_block *sb, unsigned char *map)
+{
+   return ext3_test_bit ((block -
+   le32_to_cpu(EXT3_SB(sb)-s_es-s_first_data_block)) %
+EXT3_BLOCKS_PER_GROUP(sb), map);
+}
+
 /**
  * read_block_bitmap()
  * @sb