diff options
| author | Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | 2009-01-05 21:49:55 -0500 |
|---|---|---|
| committer | Theodore Ts'o <tytso@mit.edu> | 2009-01-05 21:49:55 -0500 |
| commit | 2ccb5fb9f113dae969d1ae9b6c10e80fa34f8cd3 (patch) | |
| tree | d9dc5bca94748d4173a7783e963d20b5a75f8db8 | |
| parent | 393418676a7602e1d7d3f6e560159c65c8cbd50e (diff) | |
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
| -rw-r--r-- | fs/ext4/balloc.c | 25 | ||||
| -rw-r--r-- | fs/ext4/ext4.h | 18 | ||||
| -rw-r--r-- | fs/ext4/ialloc.c | 24 | ||||
| -rw-r--r-- | fs/ext4/mballoc.c | 24 |
4 files changed, 85 insertions, 6 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 1b26b68aa428..6bba06b09dd1 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c | |||
| @@ -320,20 +320,41 @@ ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group) | |||
| 320 | block_group, bitmap_blk); | 320 | block_group, bitmap_blk); |
| 321 | return NULL; | 321 | return NULL; |
| 322 | } | 322 | } |
| 323 | if (buffer_uptodate(bh) && | 323 | |
| 324 | !(desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) | 324 | if (bitmap_uptodate(bh)) |
| 325 | return bh; | 325 | return bh; |
| 326 | 326 | ||
| 327 | lock_buffer(bh); | 327 | lock_buffer(bh); |
| 328 | if (bitmap_uptodate(bh)) { | ||
| 329 | unlock_buffer(bh); | ||
| 330 | return bh; | ||
| 331 | } | ||
| 328 | spin_lock(sb_bgl_lock(EXT4_SB(sb), block_group)); | 332 | spin_lock(sb_bgl_lock(EXT4_SB(sb), block_group)); |
| 329 | if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { | 333 | if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { |
| 330 | ext4_init_block_bitmap(sb, bh, block_group, desc); | 334 | ext4_init_block_bitmap(sb, bh, block_group, desc); |
| 335 | set_bitmap_uptodate(bh); | ||
| 331 | set_buffer_uptodate(bh); | 336 | set_buffer_uptodate(bh); |
| 332 | spin_unlock(sb_bgl_lock(EXT4_SB(sb), block_group)); | 337 | spin_unlock(sb_bgl_lock(EXT4_SB(sb), block_group)); |
| 333 | unlock_buffer(bh); | 338 | unlock_buffer(bh); |
| 334 | return bh; | 339 | return bh; |
| 335 | } | 340 | } |
| 336 | spin_unlock(sb_bgl_lock(EXT4_SB(sb), block_group)); | 341 | spin_unlock(sb_bgl_lock(EXT4_SB(sb), block_group)); |
| 342 | if (buffer_uptodate(bh)) { | ||
| 343 | /* | ||
| 344 | * if not uninit if bh is uptodate, | ||
| 345 | * bitmap is also uptodate | ||
| 346 | */ | ||
| 347 | set_bitmap_uptodate(bh); | ||
| 348 | unlock_buffer(bh); | ||
| 349 | return bh; | ||
| 350 | } | ||
| 351 | /* | ||
| 352 | * submit the buffer_head for read. We can | ||
| 353 | * safely mark the bitmap as uptodate now. | ||
| 354 | * We do it here so the bitmap uptodate bit | ||
| 355 | * get set with buffer lock held. | ||
| 356 | */ | ||
| 357 | set_bitmap_uptodate(bh); | ||
| 337 | if (bh_submit_read(bh) < 0) { | 358 | if (bh_submit_read(bh) < 0) { |
| 338 | put_bh(bh); | 359 | put_bh(bh); |
| 339 | ext4_error(sb, __func__, | 360 | ext4_error(sb, __func__, |
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index ec862f4ca89f..695b45cc34e7 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/types.h> | 19 | #include <linux/types.h> |
| 20 | #include <linux/blkdev.h> | 20 | #include <linux/blkdev.h> |
| 21 | #include <linux/magic.h> | 21 | #include <linux/magic.h> |
| 22 | #include <linux/jbd2.h> | ||
| 22 | #include "ext4_i.h" | 23 | #include "ext4_i.h" |
| 23 | 24 | ||
| 24 | /* | 25 | /* |
| @@ -1352,6 +1353,23 @@ extern int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, | |||
| 1352 | extern int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | 1353 | extern int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, |
| 1353 | __u64 start, __u64 len); | 1354 | __u64 start, __u64 len); |
| 1354 | 1355 | ||
| 1356 | /* | ||
| 1357 | * Add new method to test wether block and inode bitmaps are properly | ||
| 1358 | * initialized. With uninit_bg reading the block from disk is not enough | ||
| 1359 | * to mark the bitmap uptodate. We need to also zero-out the bitmap | ||
| 1360 | */ | ||
| 1361 | #define BH_BITMAP_UPTODATE BH_JBDPrivateStart | ||
| 1362 | |||
| 1363 | static inline int bitmap_uptodate(struct buffer_head *bh) | ||
| 1364 | { | ||
| 1365 | return (buffer_uptodate(bh) && | ||
| 1366 | test_bit(BH_BITMAP_UPTODATE, &(bh)->b_state)); | ||
| 1367 | } | ||
| 1368 | static inline void set_bitmap_uptodate(struct buffer_head *bh) | ||
| 1369 | { | ||
| 1370 | set_bit(BH_BITMAP_UPTODATE, &(bh)->b_state); | ||
| 1371 | } | ||
| 1372 | |||
| 1355 | #endif /* __KERNEL__ */ | 1373 | #endif /* __KERNEL__ */ |
| 1356 | 1374 | ||
| 1357 | #endif /* _EXT4_H */ | 1375 | #endif /* _EXT4_H */ |
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index d4e544f30be2..7b12aedc5319 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
| @@ -115,20 +115,40 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group) | |||
| 115 | block_group, bitmap_blk); | 115 | block_group, bitmap_blk); |
| 116 | return NULL; | 116 | return NULL; |
| 117 | } | 117 | } |
| 118 | if (buffer_uptodate(bh) && | 118 | if (bitmap_uptodate(bh)) |
| 119 | !(desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT))) | ||
| 120 | return bh; | 119 | return bh; |
| 121 | 120 | ||
| 122 | lock_buffer(bh); | 121 | lock_buffer(bh); |
| 122 | if (bitmap_uptodate(bh)) { | ||
| 123 | unlock_buffer(bh); | ||
| 124 | return bh; | ||
| 125 | } | ||
| 123 | spin_lock(sb_bgl_lock(EXT4_SB(sb), block_group)); | 126 | spin_lock(sb_bgl_lock(EXT4_SB(sb), block_group)); |
| 124 | if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) { | 127 | if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) { |
| 125 | ext4_init_inode_bitmap(sb, bh, block_group, desc); | 128 | ext4_init_inode_bitmap(sb, bh, block_group, desc); |
| 129 | set_bitmap_uptodate(bh); | ||
| 126 | set_buffer_uptodate(bh); | 130 | set_buffer_uptodate(bh); |
| 127 | spin_unlock(sb_bgl_lock(EXT4_SB(sb), block_group)); | 131 | spin_unlock(sb_bgl_lock(EXT4_SB(sb), block_group)); |
| 128 | unlock_buffer(bh); | 132 | unlock_buffer(bh); |
| 129 | return bh; | 133 | return bh; |
| 130 | } | 134 | } |
| 131 | spin_unlock(sb_bgl_lock(EXT4_SB(sb), block_group)); | 135 | spin_unlock(sb_bgl_lock(EXT4_SB(sb), block_group)); |
| 136 | if (buffer_uptodate(bh)) { | ||
| 137 | /* | ||
| 138 | * if not uninit if bh is uptodate, | ||
| 139 | * bitmap is also uptodate | ||
| 140 | */ | ||
| 141 | set_bitmap_uptodate(bh); | ||
| 142 | unlock_buffer(bh); | ||
| 143 | return bh; | ||
| 144 | } | ||
| 145 | /* | ||
| 146 | * submit the buffer_head for read. We can | ||
| 147 | * safely mark the bitmap as uptodate now. | ||
| 148 | * We do it here so the bitmap uptodate bit | ||
| 149 | * get set with buffer lock held. | ||
| 150 | */ | ||
| 151 | set_bitmap_uptodate(bh); | ||
| 132 | if (bh_submit_read(bh) < 0) { | 152 | if (bh_submit_read(bh) < 0) { |
| 133 | put_bh(bh); | 153 | put_bh(bh); |
| 134 | ext4_error(sb, __func__, | 154 | ext4_error(sb, __func__, |
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index aac33590ac64..18a52d39d094 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
| @@ -794,22 +794,42 @@ static int ext4_mb_init_cache(struct page *page, char *incore) | |||
| 794 | if (bh[i] == NULL) | 794 | if (bh[i] == NULL) |
| 795 | goto out; | 795 | goto out; |
| 796 | 796 | ||
| 797 | if (buffer_uptodate(bh[i]) && | 797 | if (bitmap_uptodate(bh[i])) |
| 798 | !(desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) | ||
| 799 | continue; | 798 | continue; |
| 800 | 799 | ||
| 801 | lock_buffer(bh[i]); | 800 | lock_buffer(bh[i]); |
| 801 | if (bitmap_uptodate(bh[i])) { | ||
| 802 | unlock_buffer(bh[i]); | ||
| 803 | continue; | ||
| 804 | } | ||
| 802 | spin_lock(sb_bgl_lock(EXT4_SB(sb), first_group + i)); | 805 | spin_lock(sb_bgl_lock(EXT4_SB(sb), first_group + i)); |
| 803 | if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { | 806 | if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { |
| 804 | ext4_init_block_bitmap(sb, bh[i], | 807 | ext4_init_block_bitmap(sb, bh[i], |
| 805 | first_group + i, desc); | 808 | first_group + i, desc); |
| 809 | set_bitmap_uptodate(bh[i]); | ||
| 806 | set_buffer_uptodate(bh[i]); | 810 | set_buffer_uptodate(bh[i]); |
| 807 | spin_unlock(sb_bgl_lock(EXT4_SB(sb), first_group + i)); | 811 | spin_unlock(sb_bgl_lock(EXT4_SB(sb), first_group + i)); |
| 808 | unlock_buffer(bh[i]); | 812 | unlock_buffer(bh[i]); |
| 809 | continue; | 813 | continue; |
| 810 | } | 814 | } |
| 811 | spin_unlock(sb_bgl_lock(EXT4_SB(sb), first_group + i)); | 815 | spin_unlock(sb_bgl_lock(EXT4_SB(sb), first_group + i)); |
| 816 | if (buffer_uptodate(bh[i])) { | ||
| 817 | /* | ||
| 818 | * if not uninit if bh is uptodate, | ||
| 819 | * bitmap is also uptodate | ||
| 820 | */ | ||
| 821 | set_bitmap_uptodate(bh[i]); | ||
| 822 | unlock_buffer(bh[i]); | ||
| 823 | continue; | ||
| 824 | } | ||
| 812 | get_bh(bh[i]); | 825 | get_bh(bh[i]); |
| 826 | /* | ||
| 827 | * submit the buffer_head for read. We can | ||
| 828 | * safely mark the bitmap as uptodate now. | ||
| 829 | * We do it here so the bitmap uptodate bit | ||
| 830 | * get set with buffer lock held. | ||
| 831 | */ | ||
| 832 | set_bitmap_uptodate(bh[i]); | ||
| 813 | bh[i]->b_end_io = end_buffer_read_sync; | 833 | bh[i]->b_end_io = end_buffer_read_sync; |
| 814 | submit_bh(READ, bh[i]); | 834 | submit_bh(READ, bh[i]); |
| 815 | mb_debug("read bitmap for group %u\n", first_group + i); | 835 | mb_debug("read bitmap for group %u\n", first_group + i); |
