ext4: fix error processing in mb_free_blocks
PATCH 1/1 ext4: fix error processing in mb_free_blocks
The error processing of the return value of mb_free_blocks is meanless because it only return 0. This fix includes *make mb_free_blocks return void
*remove the error processing part in callers *unlock group before calling ext4_error in mb_free_blocks
--- fs/ext4/mballoc.c | 13 +++++-------- 1 files changed, 5 insertions(+), 8 deletions(-)
fs/ext4/mballoc.c +5 -8
@@ -1044,7 +1044,7 @@ static void mb_set_bits(spinlock_t *lock, void *bm, int cur, int len) } } -static int mb_free_blocks (struct inode *inode,struct ext4_buddy *e4b, +static void mb_free_blocks (struct inode *inode,struct ext4_buddy *e4b,int first,int count) {int block =0 ;
@@ -1084,11 +1084,12 @@ static int mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b, blocknr += block; blocknr +=le32_to_cpu (EXT4_SB (sb)->s_es->s_first_data_block); - +ext4_unlock_group (sb, e4b->bd_group);ext4_error (sb, __func__,"double-free of inode" " %lu's block %llu(bit %u in group %lu)\n" , inode ? inode->i_ino :0 , blocknr, block, e4b->bd_group); +ext4_lock_group (sb, e4b->bd_group); }mb_clear_bit (block,EXT4_MB_BITMAP (e4b)); e4b->bd_info->bb_counters[order]++;
@@ -1126,8 +1127,6 @@ static int mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b, }while (1 ); }mb_check_buddy (e4b); - -return 0 ; } static int mb_find_extent(struct ext4_buddy *e4b, int order, int block,
@@ -2561,8 +2560,7 @@ ext4_mb_free_committed_blocks(struct super_block *sb)ext4_lock_group (sb, md->group);for (i =0 ; i < md->num; i++) {mb_debug (" %u" , md->blocks[i]); - err =mb_free_blocks (NULL , &e4b, md->blocks[i],1 ); -BUG_ON (err !=0 ); +mb_free_blocks (NULL , &e4b, md->blocks[i],1 ); }mb_debug ("\n" );ext4_unlock_group (sb, md->group);
@@ -4326,10 +4324,9 @@ do_more:ext4_mb_free_metadata (handle, &e4b, block_group, bit, count); }else {ext4_lock_group (sb, block_group); - err =mb_free_blocks (inode, &e4b, bit, count); +mb_free_blocks (inode, &e4b, bit, count);ext4_mb_return_to_preallocation (inode, &e4b, block, count);ext4_unlock_group (sb, block_group); -BUG_ON (err !=0 ); }spin_lock (sb_bgl_lock (sbi, block_group));
Signature · 1 line
1.5.4.5
Quoted 4 lines · On Thu, 29 May 2008 11:21:18 +0800 Shen Feng <[email protected]> wrote:
The error processing of the return value of
mb_free_blocksis meanless because it only return 0. This fix includes *makemb_free_blocksreturn void
*remove the error processing part in callers
This:
Quoted 1 line
*unlock group before calling
ext4_errorinmb_free_blocks
fixes a potential deadlock.
Quoted 4 lines
fs/ext4/mballoc.c +0
-0@@ -1084,11 +1084,12 @@ static int mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b, blocknr += block; blocknr +=le32_to_cpu (EXT4_SB (sb)->s_es->s_first_data_block);
fs/ext4/mballoc.c static int mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b, · line 1095
Quoted 10 lines
fs/ext4/mballoc.c +2
-1- +ext4_unlock_group (sb, e4b->bd_group);ext4_error (sb, __func__,"double-free of inode" " %lu's block %llu(bit %u in group %lu)\n" , inode ? inode->i_ino :0 , blocknr, block, e4b->bd_group); +ext4_lock_group (sb, e4b->bd_group); }mb_clear_bit (block,EXT4_MB_BITMAP (e4b)); e4b->bd_info->bb_counters[order]++;
but are we sure we can just drop the lock and then cheerfully proceed? Whatever data that lock is protecting might have changed..
A safer-looking fix would be to return an error from mb_free_blocks() and handle the in the caller, once the ext4_unlock_group() has been performed.
Andrew Morton Wrote:
Quoted 22 lines · On Thu, 29 May 2008 11:21:18 +0800 Shen Feng <[email protected]> wrote:
Quoted 5 lines
The error processing of the return value of
mb_free_blocksis meanless because it only return 0. This fix includes *makemb_free_blocksreturn void
*remove the error processing part in callersThis:
Quoted 1 line
*unlock group before calling
ext4_errorinmb_free_blocksfixes a potential deadlock.
Quoted 9 lines
fs/ext4/mballoc.c +1
-1@@ -1084,11 +1084,12 @@ static int mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b, blocknr += block; blocknr +=le32_to_cpu (EXT4_SB (sb)->s_es->s_first_data_block); - +ext4_unlock_group (sb, e4b->bd_group); ext4_error(sb, __func__, "double-free of inode" " %lu's block %llu(bit %u in group %lu)\n", inode ? inode->i_ino : 0, blocknr, block,
Quoted 8 lines
fs/ext4/mballoc.c static int mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b, · line 1095
Quoted 5 lines
fs/ext4/mballoc.c +1
-0e4b->bd_group); +ext4_lock_group (sb, e4b->bd_group); }mb_clear_bit (block,EXT4_MB_BITMAP (e4b)); e4b->bd_info->bb_counters[order]++;but are we sure we can just drop the lock and then cheerfully proceed? Whatever data that lock is protecting might have changed..
That's a real question to me when I fixed this.
I got the similar code in balloc.c from line 740 in ext4_free_blocks_sb.
if (!ext4_clear_bit_atomic(sb_bgl_lock(sbi, block_group),
bit + i, bitmap_bh->b_data)) {
jbd_unlock_bh_state(bitmap_bh);
ext4_error(sb, __func__,
"bit already cleared for block %llu",
(ext4_fsblk_t)(block + i));
jbd_lock_bh_state(bitmap_bh);
BUFFER_TRACE(bitmap_bh, "bit already cleared");
} else {
group_freed++;
}So I did the same fix.
Maybe this also needs to be fixed.
Quoted 7 lines
A safer-looking fix would be to return an error from
mb_free_blocks()and handle the in the caller, once theext4_unlock_group()has been performed.