Commit a2c613b8 authored by Baokun Li's avatar Baokun Li Committed by Theodore Ts'o
Browse files

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: default avatarBaokun Li <libaokun1@huawei.com>
Reviewed-by: default avatarJan Kara <jack@suse.cz>
Reviewed-by: default avatarOjaswin Mujoo <ojaswin@linux.ibm.com>
Tested-by: default avatarOjaswin Mujoo <ojaswin@linux.ibm.com>
Link: https://patch.msgid.link/20240822023545.1994557-24-libaokun@huaweicloud.com


Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent 4191eefe
Loading
Loading
Loading
Loading
+22 −26
Original line number Diff line number Diff line
@@ -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:
errout:
	ext4_free_ext_path(path1);
	ext4_free_ext_path(path2);
		path1 = path2 = NULL;
	}
	return replaced_count;
}