mirror of https://gitee.com/openkylin/linux.git
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:
parent
393418676a
commit
2ccb5fb9f1
|
@ -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__,
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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__,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue