ext4: refactor ext4_swap_extents() to reuse extents path

The ext4_find_extent() can update the extent path so it doesn't have to
allocate and free path repeatedly, thus reducing the consumption of memory
allocation and freeing in ext4_swap_extents().

Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Link: https://patch.msgid.link/20240822023545.1994557-24-libaokun@huaweicloud.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
This commit is contained in:
Baokun Li 2024-08-22 10:35:43 +08:00 committed by Theodore Ts'o
parent 4191eefef9
commit a2c613b8c4

View File

@ -5663,25 +5663,21 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
int e1_len, e2_len, len;
int split = 0;
path1 = ext4_find_extent(inode1, lblk1, NULL, EXT4_EX_NOCACHE);
path1 = ext4_find_extent(inode1, lblk1, path1, EXT4_EX_NOCACHE);
if (IS_ERR(path1)) {
*erp = PTR_ERR(path1);
path1 = NULL;
finish:
count = 0;
goto repeat;
goto errout;
}
path2 = ext4_find_extent(inode2, lblk2, NULL, EXT4_EX_NOCACHE);
path2 = ext4_find_extent(inode2, lblk2, path2, EXT4_EX_NOCACHE);
if (IS_ERR(path2)) {
*erp = PTR_ERR(path2);
path2 = NULL;
goto finish;
goto errout;
}
ex1 = path1[path1->p_depth].p_ext;
ex2 = path2[path2->p_depth].p_ext;
/* Do we have something to swap ? */
if (unlikely(!ex2 || !ex1))
goto finish;
goto errout;
e1_blk = le32_to_cpu(ex1->ee_block);
e2_blk = le32_to_cpu(ex2->ee_block);
@ -5703,7 +5699,7 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
next2 = e2_blk;
/* Do we have something to swap */
if (next1 == EXT_MAX_BLOCKS || next2 == EXT_MAX_BLOCKS)
goto finish;
goto errout;
/* Move to the rightest boundary */
len = next1 - lblk1;
if (len < next2 - lblk2)
@ -5713,7 +5709,7 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
lblk1 += len;
lblk2 += len;
count -= len;
goto repeat;
continue;
}
/* Prepare left boundary */
@ -5723,7 +5719,7 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
path1, lblk1, 0);
if (IS_ERR(path1)) {
*erp = PTR_ERR(path1);
goto finish;
goto errout;
}
}
if (e2_blk < lblk2) {
@ -5732,13 +5728,13 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
path2, lblk2, 0);
if (IS_ERR(path2)) {
*erp = PTR_ERR(path2);
goto finish;
goto errout;
}
}
/* ext4_split_extent_at() may result in leaf extent split,
* path must to be revalidated. */
if (split)
goto repeat;
continue;
/* Prepare right boundary */
len = count;
@ -5753,7 +5749,7 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
path1, lblk1 + len, 0);
if (IS_ERR(path1)) {
*erp = PTR_ERR(path1);
goto finish;
goto errout;
}
}
if (len != e2_len) {
@ -5762,21 +5758,21 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
path2, lblk2 + len, 0);
if (IS_ERR(path2)) {
*erp = PTR_ERR(path2);
goto finish;
goto errout;
}
}
/* ext4_split_extent_at() may result in leaf extent split,
* path must to be revalidated. */
if (split)
goto repeat;
continue;
BUG_ON(e2_len != e1_len);
*erp = ext4_ext_get_access(handle, inode1, path1 + path1->p_depth);
if (unlikely(*erp))
goto finish;
goto errout;
*erp = ext4_ext_get_access(handle, inode2, path2 + path2->p_depth);
if (unlikely(*erp))
goto finish;
goto errout;
/* Both extents are fully inside boundaries. Swap it now */
tmp_ex = *ex1;
@ -5794,7 +5790,7 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
*erp = ext4_ext_dirty(handle, inode2, path2 +
path2->p_depth);
if (unlikely(*erp))
goto finish;
goto errout;
*erp = ext4_ext_dirty(handle, inode1, path1 +
path1->p_depth);
/*
@ -5804,17 +5800,17 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1,
* aborted anyway.
*/
if (unlikely(*erp))
goto finish;
goto errout;
lblk1 += len;
lblk2 += len;
replaced_count += len;
count -= len;
repeat:
ext4_free_ext_path(path1);
ext4_free_ext_path(path2);
path1 = path2 = NULL;
}
errout:
ext4_free_ext_path(path1);
ext4_free_ext_path(path2);
return replaced_count;
}