Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2ccb5fb9 authored by Aneesh Kumar K.V's avatar Aneesh Kumar K.V Committed by Theodore Ts'o
Browse files

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: default avatarAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
Cc: stable@kernel.org
parent 39341867
Loading
Loading
Loading
Loading
+23 −2
Original line number Diff line number Diff line
@@ -320,20 +320,41 @@ ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
			    block_group, bitmap_blk);
		return NULL;
	}
	if (buffer_uptodate(bh) &&
	    !(desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)))

	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);
		spin_unlock(sb_bgl_lock(EXT4_SB(sb), block_group));
		unlock_buffer(bh);
		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__,
+18 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <linux/types.h>
#include <linux/blkdev.h>
#include <linux/magic.h>
#include <linux/jbd2.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,
			__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	/* _EXT4_H */
+22 −2
Original line number Diff line number Diff line
@@ -115,20 +115,40 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
			    block_group, bitmap_blk);
		return NULL;
	}
	if (buffer_uptodate(bh) &&
	    !(desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)))
	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);
		spin_unlock(sb_bgl_lock(EXT4_SB(sb), block_group));
		unlock_buffer(bh);
		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__,
+22 −2
Original line number Diff line number Diff line
@@ -794,22 +794,42 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
		if (bh[i] == NULL)
			goto out;

		if (buffer_uptodate(bh[i]) &&
		    !(desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)))
		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]);
			spin_unlock(sb_bgl_lock(EXT4_SB(sb), first_group + i));
			unlock_buffer(bh[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 %u\n", first_group + i);