Jiri Slaby ef7db2
From: Heming Zhao via Ocfs2-devel <ocfs2-devel@oss.oracle.com>
Jiri Slaby ef7db2
Date: Mon, 20 Feb 2023 13:05:26 +0800
Jiri Slaby ef7db2
Subject: [PATCH] ocfs2: fix non-auto defrag path not working issue
Jiri Slaby ef7db2
References: bsc#1012628
Jiri Slaby ef7db2
Patch-mainline: 6.2.3
Jiri Slaby ef7db2
Git-commit: 236b9254f8d1edc273ad88b420aa85fbd84f492d
Jiri Slaby ef7db2
Jiri Slaby ef7db2
commit 236b9254f8d1edc273ad88b420aa85fbd84f492d upstream.
Jiri Slaby ef7db2
Jiri Slaby ef7db2
This fixes three issues on move extents ioctl without auto defrag:
Jiri Slaby ef7db2
Jiri Slaby ef7db2
a) In ocfs2_find_victim_alloc_group(), we have to convert bits to block
Jiri Slaby ef7db2
   first in case of global bitmap.
Jiri Slaby ef7db2
Jiri Slaby ef7db2
b) In ocfs2_probe_alloc_group(), when finding enough bits in block
Jiri Slaby ef7db2
   group bitmap, we have to back off move_len to start pos as well,
Jiri Slaby ef7db2
   otherwise it may corrupt filesystem.
Jiri Slaby ef7db2
Jiri Slaby ef7db2
c) In ocfs2_ioctl_move_extents(), set me_threshold both for non-auto
Jiri Slaby ef7db2
   and auto defrag paths.  Otherwise it will set move_max_hop to 0 and
Jiri Slaby ef7db2
   finally cause unexpectedly ENOSPC error.
Jiri Slaby ef7db2
Jiri Slaby ef7db2
Currently there are no tools triggering the above issues since
Jiri Slaby ef7db2
defragfs.ocfs2 enables auto defrag by default.  Tested with manually
Jiri Slaby ef7db2
changing defragfs.ocfs2 to run non auto defrag path.
Jiri Slaby ef7db2
Jiri Slaby ef7db2
Link: https://lkml.kernel.org/r/20230220050526.22020-1-heming.zhao@suse.com
Jiri Slaby ef7db2
Signed-off-by: Heming Zhao <heming.zhao@suse.com>
Jiri Slaby ef7db2
Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
Jiri Slaby ef7db2
Cc: Mark Fasheh <mark@fasheh.com>
Jiri Slaby ef7db2
Cc: Joel Becker <jlbec@evilplan.org>
Jiri Slaby ef7db2
Cc: Junxiao Bi <junxiao.bi@oracle.com>
Jiri Slaby ef7db2
Cc: Changwei Ge <gechangwei@live.cn>
Jiri Slaby ef7db2
Cc: Gang He <ghe@suse.com>
Jiri Slaby ef7db2
Cc: Jun Piao <piaojun@huawei.com>
Jiri Slaby ef7db2
Cc: <stable@vger.kernel.org>
Jiri Slaby ef7db2
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Jiri Slaby ef7db2
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Jiri Slaby ef7db2
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Jiri Slaby ef7db2
---
Jiri Slaby ef7db2
 fs/ocfs2/move_extents.c | 24 +++++++++++++-----------
Jiri Slaby ef7db2
 1 file changed, 13 insertions(+), 11 deletions(-)
Jiri Slaby ef7db2
Jiri Slaby ef7db2
diff --git a/fs/ocfs2/move_extents.c b/fs/ocfs2/move_extents.c
Jiri Slaby ef7db2
index 6251748c..b1e32ec4 100644
Jiri Slaby ef7db2
--- a/fs/ocfs2/move_extents.c
Jiri Slaby ef7db2
+++ b/fs/ocfs2/move_extents.c
Jiri Slaby ef7db2
@@ -434,7 +434,7 @@ static int ocfs2_find_victim_alloc_group(struct inode *inode,
Jiri Slaby ef7db2
 			bg = (struct ocfs2_group_desc *)gd_bh->b_data;
Jiri Slaby ef7db2
 
Jiri Slaby ef7db2
 			if (vict_blkno < (le64_to_cpu(bg->bg_blkno) +
Jiri Slaby ef7db2
-						le16_to_cpu(bg->bg_bits))) {
Jiri Slaby ef7db2
+						(le16_to_cpu(bg->bg_bits) << bits_per_unit))) {
Jiri Slaby ef7db2
 
Jiri Slaby ef7db2
 				*ret_bh = gd_bh;
Jiri Slaby ef7db2
 				*vict_bit = (vict_blkno - blkno) >>
Jiri Slaby ef7db2
@@ -549,6 +549,7 @@ static void ocfs2_probe_alloc_group(struct inode *inode, struct buffer_head *bh,
Jiri Slaby ef7db2
 			last_free_bits++;
Jiri Slaby ef7db2
 
Jiri Slaby ef7db2
 		if (last_free_bits == move_len) {
Jiri Slaby ef7db2
+			i -= move_len;
Jiri Slaby ef7db2
 			*goal_bit = i;
Jiri Slaby ef7db2
 			*phys_cpos = base_cpos + i;
Jiri Slaby ef7db2
 			break;
Jiri Slaby ef7db2
@@ -1020,18 +1021,19 @@ int ocfs2_ioctl_move_extents(struct file *filp, void __user *argp)
Jiri Slaby ef7db2
 
Jiri Slaby ef7db2
 	context->range = ⦥
Jiri Slaby ef7db2
 
Jiri Slaby ef7db2
+	/*
Jiri Slaby ef7db2
+	 * ok, the default theshold for the defragmentation
Jiri Slaby ef7db2
+	 * is 1M, since our maximum clustersize was 1M also.
Jiri Slaby ef7db2
+	 * any thought?
Jiri Slaby ef7db2
+	 */
Jiri Slaby ef7db2
+	if (!range.me_threshold)
Jiri Slaby ef7db2
+		range.me_threshold = 1024 * 1024;
Jiri Slaby ef7db2
+
Jiri Slaby ef7db2
+	if (range.me_threshold > i_size_read(inode))
Jiri Slaby ef7db2
+		range.me_threshold = i_size_read(inode);
Jiri Slaby ef7db2
+
Jiri Slaby ef7db2
 	if (range.me_flags & OCFS2_MOVE_EXT_FL_AUTO_DEFRAG) {
Jiri Slaby ef7db2
 		context->auto_defrag = 1;
Jiri Slaby ef7db2
-		/*
Jiri Slaby ef7db2
-		 * ok, the default theshold for the defragmentation
Jiri Slaby ef7db2
-		 * is 1M, since our maximum clustersize was 1M also.
Jiri Slaby ef7db2
-		 * any thought?
Jiri Slaby ef7db2
-		 */
Jiri Slaby ef7db2
-		if (!range.me_threshold)
Jiri Slaby ef7db2
-			range.me_threshold = 1024 * 1024;
Jiri Slaby ef7db2
-
Jiri Slaby ef7db2
-		if (range.me_threshold > i_size_read(inode))
Jiri Slaby ef7db2
-			range.me_threshold = i_size_read(inode);
Jiri Slaby ef7db2
 
Jiri Slaby ef7db2
 		if (range.me_flags & OCFS2_MOVE_EXT_FL_PART_DEFRAG)
Jiri Slaby ef7db2
 			context->partial = 1;
Jiri Slaby ef7db2
-- 
Jiri Slaby ef7db2
2.35.3
Jiri Slaby ef7db2