ext4: fix xfstest generic/269 double revoked buffer bug with bigalloc
When you repeatly execute xfstest generic/269 with bigalloc_1k option enabled using the below command: "./kvm-xfstests -c bigalloc_1k -m nodelalloc -C 1000 generic/269" you can easily see the below bug message. "JBD2 unexpected failure: jbd2_journal_revoke: !buffer_revoked(bh);" This means that an already revoked buffer is erroneously revoked again and it is caused by doing revoke for the buffer at the wrong position in ext4_free_blocks(). We need to re-position the buffer revoke procedure for an unspecified buffer after checking the cluster boundary for bigalloc option. If not, some part of the cluster can be doubly revoked. Signed-off-by: Daeho Jeong <daeho.jeong@samsung.com>
This commit is contained in:
parent
9008a58e5d
commit
9c02ac9798
|
@ -4687,22 +4687,11 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
|
||||||
ext4_debug("freeing block %llu\n", block);
|
ext4_debug("freeing block %llu\n", block);
|
||||||
trace_ext4_free_blocks(inode, block, count, flags);
|
trace_ext4_free_blocks(inode, block, count, flags);
|
||||||
|
|
||||||
if (flags & EXT4_FREE_BLOCKS_FORGET) {
|
if (bh && (flags & EXT4_FREE_BLOCKS_FORGET)) {
|
||||||
struct buffer_head *tbh = bh;
|
BUG_ON(count > 1);
|
||||||
int i;
|
|
||||||
|
|
||||||
BUG_ON(bh && (count > 1));
|
ext4_forget(handle, flags & EXT4_FREE_BLOCKS_METADATA,
|
||||||
|
inode, bh, block);
|
||||||
for (i = 0; i < count; i++) {
|
|
||||||
cond_resched();
|
|
||||||
if (!bh)
|
|
||||||
tbh = sb_find_get_block(inode->i_sb,
|
|
||||||
block + i);
|
|
||||||
if (!tbh)
|
|
||||||
continue;
|
|
||||||
ext4_forget(handle, flags & EXT4_FREE_BLOCKS_METADATA,
|
|
||||||
inode, tbh, block + i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -4747,6 +4736,19 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
|
||||||
count += sbi->s_cluster_ratio - overflow;
|
count += sbi->s_cluster_ratio - overflow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!bh && (flags & EXT4_FREE_BLOCKS_FORGET)) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
cond_resched();
|
||||||
|
bh = sb_find_get_block(inode->i_sb, block + i);
|
||||||
|
if (!bh)
|
||||||
|
continue;
|
||||||
|
ext4_forget(handle, flags & EXT4_FREE_BLOCKS_METADATA,
|
||||||
|
inode, bh, block + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
do_more:
|
do_more:
|
||||||
overflow = 0;
|
overflow = 0;
|
||||||
ext4_get_group_no_and_offset(sb, block, &block_group, &bit);
|
ext4_get_group_no_and_offset(sb, block, &block_group, &bit);
|
||||||
|
|
Loading…
Reference in New Issue