UPSTREAM: ext4: refactor ext4_free_blocks() to pull out ext4_mb_clear_bb()
commit 8ac3939db99f99667b8eb670cf4baf292896e72d upstream. ext4_free_blocks() function became too long and confusing, this patch just pulls out the ext4_mb_clear_bb() function logic from it which clears the block bitmap and frees it. No functionality change in this patch Signed-off-by: Ritesh Harjani <riteshh@linux.ibm.com> Reviewed-by: Jan Kara <jack@suse.cz> Link: https://lore.kernel.org/r/22c30fbb26ba409cf8aa5f0c7912970272c459e8.1644992610.git.riteshh@linux.ibm.com Signed-off-by: Theodore Ts'o <tytso@mit.edu> Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Bug: 237951970 Change-Id: Ib8c113a85e620eff6d4561a38c97f875a476ab7b Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
This commit is contained in:

committed by
Matthias Männich

parent
370cb1c270
commit
8ddbd3df93
@@ -5303,7 +5303,8 @@ static void ext4_free_blocks_simple(struct inode *inode, ext4_fsblk_t block,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ext4_free_blocks() -- Free given blocks and update quota
|
* ext4_mb_clear_bb() -- helper function for freeing blocks.
|
||||||
|
* Used by ext4_free_blocks()
|
||||||
* @handle: handle for this transaction
|
* @handle: handle for this transaction
|
||||||
* @inode: inode
|
* @inode: inode
|
||||||
* @bh: optional buffer of the block to be freed
|
* @bh: optional buffer of the block to be freed
|
||||||
@@ -5311,9 +5312,9 @@ static void ext4_free_blocks_simple(struct inode *inode, ext4_fsblk_t block,
|
|||||||
* @count: number of blocks to be freed
|
* @count: number of blocks to be freed
|
||||||
* @flags: flags used by ext4_free_blocks
|
* @flags: flags used by ext4_free_blocks
|
||||||
*/
|
*/
|
||||||
void ext4_free_blocks(handle_t *handle, struct inode *inode,
|
static void ext4_mb_clear_bb(handle_t *handle, struct inode *inode,
|
||||||
struct buffer_head *bh, ext4_fsblk_t block,
|
ext4_fsblk_t block, unsigned long count,
|
||||||
unsigned long count, int flags)
|
int flags)
|
||||||
{
|
{
|
||||||
struct buffer_head *bitmap_bh = NULL;
|
struct buffer_head *bitmap_bh = NULL;
|
||||||
struct super_block *sb = inode->i_sb;
|
struct super_block *sb = inode->i_sb;
|
||||||
@@ -5330,80 +5331,6 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
|
|||||||
|
|
||||||
sbi = EXT4_SB(sb);
|
sbi = EXT4_SB(sb);
|
||||||
|
|
||||||
if (sbi->s_mount_state & EXT4_FC_REPLAY) {
|
|
||||||
ext4_free_blocks_simple(inode, block, count);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
might_sleep();
|
|
||||||
if (bh) {
|
|
||||||
if (block)
|
|
||||||
BUG_ON(block != bh->b_blocknr);
|
|
||||||
else
|
|
||||||
block = bh->b_blocknr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(flags & EXT4_FREE_BLOCKS_VALIDATED) &&
|
|
||||||
!ext4_inode_block_valid(inode, block, count)) {
|
|
||||||
ext4_error(sb, "Freeing blocks not in datazone - "
|
|
||||||
"block = %llu, count = %lu", block, count);
|
|
||||||
goto error_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ext4_debug("freeing block %llu\n", block);
|
|
||||||
trace_ext4_free_blocks(inode, block, count, flags);
|
|
||||||
|
|
||||||
if (bh && (flags & EXT4_FREE_BLOCKS_FORGET)) {
|
|
||||||
BUG_ON(count > 1);
|
|
||||||
|
|
||||||
ext4_forget(handle, flags & EXT4_FREE_BLOCKS_METADATA,
|
|
||||||
inode, bh, block);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the extent to be freed does not begin on a cluster
|
|
||||||
* boundary, we need to deal with partial clusters at the
|
|
||||||
* beginning and end of the extent. Normally we will free
|
|
||||||
* blocks at the beginning or the end unless we are explicitly
|
|
||||||
* requested to avoid doing so.
|
|
||||||
*/
|
|
||||||
overflow = EXT4_PBLK_COFF(sbi, block);
|
|
||||||
if (overflow) {
|
|
||||||
if (flags & EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER) {
|
|
||||||
overflow = sbi->s_cluster_ratio - overflow;
|
|
||||||
block += overflow;
|
|
||||||
if (count > overflow)
|
|
||||||
count -= overflow;
|
|
||||||
else
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
block -= overflow;
|
|
||||||
count += overflow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
overflow = EXT4_LBLK_COFF(sbi, count);
|
|
||||||
if (overflow) {
|
|
||||||
if (flags & EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER) {
|
|
||||||
if (count > overflow)
|
|
||||||
count -= overflow;
|
|
||||||
else
|
|
||||||
return;
|
|
||||||
} else
|
|
||||||
count += sbi->s_cluster_ratio - overflow;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bh && (flags & EXT4_FREE_BLOCKS_FORGET)) {
|
|
||||||
int i;
|
|
||||||
int is_metadata = flags & EXT4_FREE_BLOCKS_METADATA;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
|
||||||
cond_resched();
|
|
||||||
if (is_metadata)
|
|
||||||
bh = sb_find_get_block(inode->i_sb, block + i);
|
|
||||||
ext4_forget(handle, is_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);
|
||||||
@@ -5570,6 +5497,103 @@ error_return:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ext4_free_blocks() -- Free given blocks and update quota
|
||||||
|
* @handle: handle for this transaction
|
||||||
|
* @inode: inode
|
||||||
|
* @bh: optional buffer of the block to be freed
|
||||||
|
* @block: starting physical block to be freed
|
||||||
|
* @count: number of blocks to be freed
|
||||||
|
* @flags: flags used by ext4_free_blocks
|
||||||
|
*/
|
||||||
|
void ext4_free_blocks(handle_t *handle, struct inode *inode,
|
||||||
|
struct buffer_head *bh, ext4_fsblk_t block,
|
||||||
|
unsigned long count, int flags)
|
||||||
|
{
|
||||||
|
struct super_block *sb = inode->i_sb;
|
||||||
|
unsigned int overflow;
|
||||||
|
struct ext4_sb_info *sbi;
|
||||||
|
|
||||||
|
sbi = EXT4_SB(sb);
|
||||||
|
|
||||||
|
if (sbi->s_mount_state & EXT4_FC_REPLAY) {
|
||||||
|
ext4_free_blocks_simple(inode, block, count);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
might_sleep();
|
||||||
|
if (bh) {
|
||||||
|
if (block)
|
||||||
|
BUG_ON(block != bh->b_blocknr);
|
||||||
|
else
|
||||||
|
block = bh->b_blocknr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(flags & EXT4_FREE_BLOCKS_VALIDATED) &&
|
||||||
|
!ext4_inode_block_valid(inode, block, count)) {
|
||||||
|
ext4_error(sb, "Freeing blocks not in datazone - "
|
||||||
|
"block = %llu, count = %lu", block, count);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ext4_debug("freeing block %llu\n", block);
|
||||||
|
trace_ext4_free_blocks(inode, block, count, flags);
|
||||||
|
|
||||||
|
if (bh && (flags & EXT4_FREE_BLOCKS_FORGET)) {
|
||||||
|
BUG_ON(count > 1);
|
||||||
|
|
||||||
|
ext4_forget(handle, flags & EXT4_FREE_BLOCKS_METADATA,
|
||||||
|
inode, bh, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the extent to be freed does not begin on a cluster
|
||||||
|
* boundary, we need to deal with partial clusters at the
|
||||||
|
* beginning and end of the extent. Normally we will free
|
||||||
|
* blocks at the beginning or the end unless we are explicitly
|
||||||
|
* requested to avoid doing so.
|
||||||
|
*/
|
||||||
|
overflow = EXT4_PBLK_COFF(sbi, block);
|
||||||
|
if (overflow) {
|
||||||
|
if (flags & EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER) {
|
||||||
|
overflow = sbi->s_cluster_ratio - overflow;
|
||||||
|
block += overflow;
|
||||||
|
if (count > overflow)
|
||||||
|
count -= overflow;
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
block -= overflow;
|
||||||
|
count += overflow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
overflow = EXT4_LBLK_COFF(sbi, count);
|
||||||
|
if (overflow) {
|
||||||
|
if (flags & EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER) {
|
||||||
|
if (count > overflow)
|
||||||
|
count -= overflow;
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
} else
|
||||||
|
count += sbi->s_cluster_ratio - overflow;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bh && (flags & EXT4_FREE_BLOCKS_FORGET)) {
|
||||||
|
int i;
|
||||||
|
int is_metadata = flags & EXT4_FREE_BLOCKS_METADATA;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
cond_resched();
|
||||||
|
if (is_metadata)
|
||||||
|
bh = sb_find_get_block(inode->i_sb, block + i);
|
||||||
|
ext4_forget(handle, is_metadata, inode, bh, block + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ext4_mb_clear_bb(handle, inode, block, count, flags);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ext4_group_add_blocks() -- Add given blocks to an existing group
|
* ext4_group_add_blocks() -- Add given blocks to an existing group
|
||||||
* @handle: handle to this transaction
|
* @handle: handle to this transaction
|
||||||
|
Reference in New Issue
Block a user