Pull the code used to initialize a partial cluster into a single location to improve readability and to minimize the disturbance on other code. Take advantage of the change to track partial clusters in the logical space to use a more efficient means to search for a block adjacent to the block range to be removed. Signed-off-by: Eric Whitney <enwlinux@xxxxxxxxx> --- fs/ext4/extents.c | 70 +++++++++++++++++------------------------------ 1 file changed, 25 insertions(+), 45 deletions(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 793a9437be9f..a0c9e37ef804 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -2641,17 +2641,6 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, /* If this extent is beyond the end of the hole, skip it */ if (end < ex_ee_block) { - /* - * We're going to skip this extent and move to another, - * so note that its first cluster is in use to avoid - * freeing it when removing blocks. Eventually, the - * right edge of the truncated/punched region will - * be just to the left. - */ - if (sbi->s_cluster_ratio > 1) { - partial->lblk = ex_ee_block; - partial->state = keep; - } ex--; ex_ee_block = le32_to_cpu(ex->ee_block); ex_ee_len = ext4_ext_get_actual_len(ex); @@ -2812,10 +2801,6 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, handle_t *handle; int i = 0, err = 0; - partial.pclu = 0; - partial.lblk = 0; - partial.state = none; - ext_debug(inode, "truncate since %u to %u\n", start, end); /* probably first extent we're gonna free will be last in block */ @@ -2825,6 +2810,13 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, if (IS_ERR(handle)) return PTR_ERR(handle); + /* state never changes for non-bigalloc file systems */ + partial.state = none; + if (sbi->s_cluster_ratio > 1) { + partial.start_lclu = EXT4_B2C(sbi, start); + partial.end_lclu = EXT4_B2C(sbi, end); + } + again: trace_ext4_ext_remove_space(inode, start, end, depth); @@ -2838,7 +2830,6 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, if (end < EXT_MAX_BLOCKS - 1) { struct ext4_extent *ex; ext4_lblk_t ee_block, ex_end, lblk; - ext4_fsblk_t pblk; /* find extent for or closest extent to this block */ path = ext4_find_extent(inode, end, NULL, @@ -2871,16 +2862,6 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, */ if (end >= ee_block && end < ex_end) { - /* - * If we're going to split the extent, note that - * the cluster containing the block after 'end' is - * in use to avoid freeing it when removing blocks. - */ - if (sbi->s_cluster_ratio > 1) { - partial.lblk = end + 1; - partial.state = keep; - } - /* * Split the extent in two so that 'end' is the last * block in the first new extent. Also we should not @@ -2891,27 +2872,26 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, end + 1, 1); if (err < 0) goto out; + } - } else if (sbi->s_cluster_ratio > 1 && end >= ex_end && - partial.state == none) { - /* - * If we're punching, there's an extent to the right. - * If the partial cluster hasn't been set, set it to - * that extent's first cluster and its state to keep - * so it won't be freed should it contain blocks to be - * removed. If it's already set (free/keep), we're - * retrying and keep the original partial cluster info - * so a cluster marked free as a result of earlier - * extent removal is not lost. - */ - lblk = ex_end + 1; - err = ext4_ext_search_right(inode, path, &lblk, &pblk, - NULL); - if (err < 0) - goto out; - if (pblk) { - partial.lblk = lblk; + /* + * if there's a block following the space to be removed + * in a bigalloc file system note that the cluster + * containing it must not be freed + */ + if (sbi->s_cluster_ratio > 1 && partial.state == none) { + if (end < ee_block) { + partial.lblk = ee_block; partial.state = keep; + } else if (end >= ee_block && end < ex_end) { + partial.lblk = end + 1; + partial.state = keep; + } else if (end >= ex_end) { + lblk = ext4_ext_next_allocated_block(path); + if (lblk != EXT_MAX_BLOCKS) { + partial.lblk = lblk; + partial.state = keep; + } } } } -- 2.30.2