[Ocfs2-devel] [PATCH] ocfs2: fix non-auto defrag path not working issue

Heming Zhao heming.zhao at suse.com
Fri Feb 17 01:20:00 UTC 2023


This commit fixes three issues on non-auto defrag path (defragfs.ocfs2
doesn't set OCFS2_MOVE_EXT_FL_AUTO_DEFRAG on range.me_flags):
- For ocfs2_find_victim_alloc_group(), old code forgot enlarge bitmap
  range for global_bitmap case. Old code could generate negative
  vict_bit.
- For ocfs2_probe_alloc_group(), old code forgot back off move_len when
  finding enough bitmap space. Old code has possibility to make data
  corruption.
- For ocfs2_ioctl_move_extents(), this func should set me_threshold for
  both auto & non-auto path. Without setting me_threshold,
  ocfs2_move_extent() will make 'move_max_hop = 0', then
  ocfs2_probe_alloc_group() returns 'phys_cpos == 0' under max_hop is 0.

Another info is current defragfs.ocfs2 doesn't have ability to trigger
non-auto defrag path. I modified defragfs.ocfs2 source code ".me_flags"
and hardcode ".me_goal" for running test.

Signed-off-by: Heming Zhao <heming.zhao at suse.com>
---
 fs/ocfs2/move_extents.c | 24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/fs/ocfs2/move_extents.c b/fs/ocfs2/move_extents.c
index 6251748c695b..b1e32ec4a9d4 100644
--- a/fs/ocfs2/move_extents.c
+++ b/fs/ocfs2/move_extents.c
@@ -434,7 +434,7 @@ static int ocfs2_find_victim_alloc_group(struct inode *inode,
 			bg = (struct ocfs2_group_desc *)gd_bh->b_data;
 
 			if (vict_blkno < (le64_to_cpu(bg->bg_blkno) +
-						le16_to_cpu(bg->bg_bits))) {
+						(le16_to_cpu(bg->bg_bits) << bits_per_unit))) {
 
 				*ret_bh = gd_bh;
 				*vict_bit = (vict_blkno - blkno) >>
@@ -549,6 +549,7 @@ static void ocfs2_probe_alloc_group(struct inode *inode, struct buffer_head *bh,
 			last_free_bits++;
 
 		if (last_free_bits == move_len) {
+			i -= move_len;
 			*goal_bit = i;
 			*phys_cpos = base_cpos + i;
 			break;
@@ -1020,18 +1021,19 @@ int ocfs2_ioctl_move_extents(struct file *filp, void __user *argp)
 
 	context->range = ⦥
 
+	/*
+	 * ok, the default theshold for the defragmentation
+	 * is 1M, since our maximum clustersize was 1M also.
+	 * any thought?
+	 */
+	if (!range.me_threshold)
+		range.me_threshold = 1024 * 1024;
+
+	if (range.me_threshold > i_size_read(inode))
+		range.me_threshold = i_size_read(inode);
+
 	if (range.me_flags & OCFS2_MOVE_EXT_FL_AUTO_DEFRAG) {
 		context->auto_defrag = 1;
-		/*
-		 * ok, the default theshold for the defragmentation
-		 * is 1M, since our maximum clustersize was 1M also.
-		 * any thought?
-		 */
-		if (!range.me_threshold)
-			range.me_threshold = 1024 * 1024;
-
-		if (range.me_threshold > i_size_read(inode))
-			range.me_threshold = i_size_read(inode);
 
 		if (range.me_flags & OCFS2_MOVE_EXT_FL_PART_DEFRAG)
 			context->partial = 1;
-- 
2.39.0




More information about the Ocfs2-devel mailing list