From mboxrd@z Thu Jan 1 00:00:00 1970 From: Greg KH Subject: [patch 28/36] ext4: Use new buffer_head flag to check uninit group bitmaps initialization Date: Wed, 18 Feb 2009 14:29:48 -0800 Message-ID: <20090218222948.GC10668@kroah.com> References: <20090218222447.432108614@mini.kroah.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Cc: Justin Forbes , Zwane Mwaikambo , Theodore Ts'o , Randy Dunlap , Dave Jones , Chuck Wolber , Chris Wedgwood , Michael Krufky , Chuck Ebbert , Domenico Andreoli , Willy Tarreau , Rodrigo Rubira Branco , Jake Edge , Eugene Teo , torvalds@linux-foundation.org, akpm@linux-foundation.org, alan@lxorguk.ukuu.org.uk, linux-ext4@vger.kernel.org, "Aneesh Kumar K.V" To: linux-kernel@vger.kernel.org, stable@kernel.org Return-path: Received: from kroah.org ([198.145.64.141]:35046 "EHLO coco.kroah.org" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1754091AbZBRWcT (ORCPT ); Wed, 18 Feb 2009 17:32:19 -0500 Content-Disposition: inline; filename="ext4-use-new-buffer_head-flag-to-check-uninit-group-bitmaps-initialization.patch" In-Reply-To: <20090218222841.GA10668@kroah.com> Sender: linux-ext4-owner@vger.kernel.org List-ID: 2.6.27-stable review patch. If anyone has any objections, please let us know. ------------------ From: Aneesh Kumar K.V (cherry picked from commit 2ccb5fb9f113dae969d1ae9b6c10e80fa34f8cd3) For uninit block group, the ondisk 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 prevent the initializing the uninit group bitmap initialization every time we do a ext4_read_block_bitmap. Signed-off-by: Aneesh Kumar K.V Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman --- fs/ext4/balloc.c | 25 ++++++++++++++++++++++++- fs/ext4/ext4.h | 18 ++++++++++++++++++ fs/ext4/ialloc.c | 24 +++++++++++++++++++++++- fs/ext4/mballoc.c | 24 +++++++++++++++++++++++- 4 files changed, 88 insertions(+), 3 deletions(-) --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -319,18 +319,41 @@ ext4_read_block_bitmap(struct super_bloc block_group, bitmap_blk); return NULL; } - if (bh_uptodate_or_lock(bh)) + + if (bitmap_uptodate(bh)) return bh; + lock_buffer(bh); + if (bitmap_uptodate(bh)) { + unlock_buffer(bh); + return bh; + } spin_lock(sb_bgl_lock(EXT4_SB(sb), block_group)); if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { ext4_init_block_bitmap(sb, bh, block_group, desc); + set_bitmap_uptodate(bh); set_buffer_uptodate(bh); unlock_buffer(bh); spin_unlock(sb_bgl_lock(EXT4_SB(sb), block_group)); return bh; } 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) { put_bh(bh); ext4_error(sb, __func__, --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -19,6 +19,7 @@ #include #include #include +#include #include "ext4_i.h" /* @@ -1250,6 +1251,23 @@ extern int ext4_get_blocks_wrap(handle_t sector_t block, unsigned long max_blocks, struct buffer_head *bh, int create, int extend_disksize, int flag); +/* + * 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 /* _EXT4_H */ --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -115,18 +115,40 @@ ext4_read_inode_bitmap(struct super_bloc block_group, bitmap_blk); return NULL; } - if (bh_uptodate_or_lock(bh)) + if (bitmap_uptodate(bh)) return bh; + lock_buffer(bh); + if (bitmap_uptodate(bh)) { + unlock_buffer(bh); + return bh; + } spin_lock(sb_bgl_lock(EXT4_SB(sb), block_group)); if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) { ext4_init_inode_bitmap(sb, bh, block_group, desc); + set_bitmap_uptodate(bh); set_buffer_uptodate(bh); unlock_buffer(bh); spin_unlock(sb_bgl_lock(EXT4_SB(sb), block_group)); return bh; } 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) { put_bh(bh); ext4_error(sb, __func__, --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -796,20 +796,42 @@ static int ext4_mb_init_cache(struct pag if (bh[i] == NULL) goto out; - if (bh_uptodate_or_lock(bh[i])) + if (bitmap_uptodate(bh[i])) continue; + 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)); if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { ext4_init_block_bitmap(sb, bh[i], first_group + i, desc); + set_bitmap_uptodate(bh[i]); set_buffer_uptodate(bh[i]); unlock_buffer(bh[i]); spin_unlock(sb_bgl_lock(EXT4_SB(sb), first_group + i)); continue; } 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]); + /* + * 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; submit_bh(READ, bh[i]); mb_debug("read bitmap for group %lu\n", first_group + i);