ext4: Use new buffer_head flag to check uninit group bitmaps initialization

For uninit block group, the on-disk bitmap is not initialized. That
implies we cannot depend on the uptodate flag on the bitmap
buffer_head to find bitmap validity.  Use a new buffer_head flag which
would be set after we properly initialize the bitmap.  This also
prevents (re-)initializing the uninit group bitmap every time we call 
ext4_read_block_bitmap().

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Cc: stable@kernel.org
This commit is contained in:
Aneesh Kumar K.V 2009-01-05 21:49:55 -05:00 committed by Theodore Ts'o
parent 393418676a
commit 2ccb5fb9f1
4 changed files with 85 additions and 6 deletions

View File

@ -320,20 +320,41 @@ ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
block_group, bitmap_blk); block_group, bitmap_blk);
return NULL; return NULL;
} }
if (buffer_uptodate(bh) &&
!(desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) if (bitmap_uptodate(bh))
return bh; return bh;
lock_buffer(bh); lock_buffer(bh);
if (bitmap_uptodate(bh)) {
unlock_buffer(bh);
return bh;
}
spin_lock(sb_bgl_lock(EXT4_SB(sb), block_group)); spin_lock(sb_bgl_lock(EXT4_SB(sb), block_group));
if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
ext4_init_block_bitmap(sb, bh, block_group, desc); ext4_init_block_bitmap(sb, bh, block_group, desc);
set_bitmap_uptodate(bh);
set_buffer_uptodate(bh); set_buffer_uptodate(bh);
spin_unlock(sb_bgl_lock(EXT4_SB(sb), block_group)); spin_unlock(sb_bgl_lock(EXT4_SB(sb), block_group));
unlock_buffer(bh); unlock_buffer(bh);
return bh; return bh;
} }
spin_unlock(sb_bgl_lock(EXT4_SB(sb), block_group)); spin_unlock(sb_bgl_lock(EXT4_SB(sb), block_group));
if (buffer_uptodate(bh)) {
/*
* if not uninit if bh is uptodate,
* bitmap is also uptodate
*/
set_bitmap_uptodate(bh);
unlock_buffer(bh);
return bh;
}
/*
* submit the buffer_head for read. We can
* safely mark the bitmap as uptodate now.
* We do it here so the bitmap uptodate bit
* get set with buffer lock held.
*/
set_bitmap_uptodate(bh);
if (bh_submit_read(bh) < 0) { if (bh_submit_read(bh) < 0) {
put_bh(bh); put_bh(bh);
ext4_error(sb, __func__, ext4_error(sb, __func__,

View File

@ -19,6 +19,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/magic.h> #include <linux/magic.h>
#include <linux/jbd2.h>
#include "ext4_i.h" #include "ext4_i.h"
/* /*
@ -1352,6 +1353,23 @@ extern int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode,
extern int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, extern int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
__u64 start, __u64 len); __u64 start, __u64 len);
/*
* Add new method to test wether block and inode bitmaps are properly
* initialized. With uninit_bg reading the block from disk is not enough
* to mark the bitmap uptodate. We need to also zero-out the bitmap
*/
#define BH_BITMAP_UPTODATE BH_JBDPrivateStart
static inline int bitmap_uptodate(struct buffer_head *bh)
{
return (buffer_uptodate(bh) &&
test_bit(BH_BITMAP_UPTODATE, &(bh)->b_state));
}
static inline void set_bitmap_uptodate(struct buffer_head *bh)
{
set_bit(BH_BITMAP_UPTODATE, &(bh)->b_state);
}
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _EXT4_H */ #endif /* _EXT4_H */

View File

@ -115,20 +115,40 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
block_group, bitmap_blk); block_group, bitmap_blk);
return NULL; return NULL;
} }
if (buffer_uptodate(bh) && if (bitmap_uptodate(bh))
!(desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)))
return bh; return bh;
lock_buffer(bh); lock_buffer(bh);
if (bitmap_uptodate(bh)) {
unlock_buffer(bh);
return bh;
}
spin_lock(sb_bgl_lock(EXT4_SB(sb), block_group)); spin_lock(sb_bgl_lock(EXT4_SB(sb), block_group));
if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) { if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) {
ext4_init_inode_bitmap(sb, bh, block_group, desc); ext4_init_inode_bitmap(sb, bh, block_group, desc);
set_bitmap_uptodate(bh);
set_buffer_uptodate(bh); set_buffer_uptodate(bh);
spin_unlock(sb_bgl_lock(EXT4_SB(sb), block_group)); spin_unlock(sb_bgl_lock(EXT4_SB(sb), block_group));
unlock_buffer(bh); unlock_buffer(bh);
return bh; return bh;
} }
spin_unlock(sb_bgl_lock(EXT4_SB(sb), block_group)); spin_unlock(sb_bgl_lock(EXT4_SB(sb), block_group));
if (buffer_uptodate(bh)) {
/*
* if not uninit if bh is uptodate,
* bitmap is also uptodate
*/
set_bitmap_uptodate(bh);
unlock_buffer(bh);
return bh;
}
/*
* submit the buffer_head for read. We can
* safely mark the bitmap as uptodate now.
* We do it here so the bitmap uptodate bit
* get set with buffer lock held.
*/
set_bitmap_uptodate(bh);
if (bh_submit_read(bh) < 0) { if (bh_submit_read(bh) < 0) {
put_bh(bh); put_bh(bh);
ext4_error(sb, __func__, ext4_error(sb, __func__,

View File

@ -794,22 +794,42 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
if (bh[i] == NULL) if (bh[i] == NULL)
goto out; goto out;
if (buffer_uptodate(bh[i]) && if (bitmap_uptodate(bh[i]))
!(desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)))
continue; continue;
lock_buffer(bh[i]); lock_buffer(bh[i]);
if (bitmap_uptodate(bh[i])) {
unlock_buffer(bh[i]);
continue;
}
spin_lock(sb_bgl_lock(EXT4_SB(sb), first_group + i)); spin_lock(sb_bgl_lock(EXT4_SB(sb), first_group + i));
if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
ext4_init_block_bitmap(sb, bh[i], ext4_init_block_bitmap(sb, bh[i],
first_group + i, desc); first_group + i, desc);
set_bitmap_uptodate(bh[i]);
set_buffer_uptodate(bh[i]); set_buffer_uptodate(bh[i]);
spin_unlock(sb_bgl_lock(EXT4_SB(sb), first_group + i)); spin_unlock(sb_bgl_lock(EXT4_SB(sb), first_group + i));
unlock_buffer(bh[i]); unlock_buffer(bh[i]);
continue; continue;
} }
spin_unlock(sb_bgl_lock(EXT4_SB(sb), first_group + i)); spin_unlock(sb_bgl_lock(EXT4_SB(sb), first_group + i));
if (buffer_uptodate(bh[i])) {
/*
* if not uninit if bh is uptodate,
* bitmap is also uptodate
*/
set_bitmap_uptodate(bh[i]);
unlock_buffer(bh[i]);
continue;
}
get_bh(bh[i]); get_bh(bh[i]);
/*
* submit the buffer_head for read. We can
* safely mark the bitmap as uptodate now.
* We do it here so the bitmap uptodate bit
* get set with buffer lock held.
*/
set_bitmap_uptodate(bh[i]);
bh[i]->b_end_io = end_buffer_read_sync; bh[i]->b_end_io = end_buffer_read_sync;
submit_bh(READ, bh[i]); submit_bh(READ, bh[i]);
mb_debug("read bitmap for group %u\n", first_group + i); mb_debug("read bitmap for group %u\n", first_group + i);