| From 236b9254f8d1edc273ad88b420aa85fbd84f492d Mon Sep 17 00:00:00 2001 |
| From: Heming Zhao via Ocfs2-devel <ocfs2-devel@oss.oracle.com> |
| Date: Mon, 20 Feb 2023 13:05:26 +0800 |
| Subject: ocfs2: fix non-auto defrag path not working issue |
| |
| From: Heming Zhao via Ocfs2-devel <ocfs2-devel@oss.oracle.com> |
| |
| commit 236b9254f8d1edc273ad88b420aa85fbd84f492d upstream. |
| |
| This fixes three issues on move extents ioctl without auto defrag: |
| |
| a) In ocfs2_find_victim_alloc_group(), we have to convert bits to block |
| first in case of global bitmap. |
| |
| b) In ocfs2_probe_alloc_group(), when finding enough bits in block |
| group bitmap, we have to back off move_len to start pos as well, |
| otherwise it may corrupt filesystem. |
| |
| c) In ocfs2_ioctl_move_extents(), set me_threshold both for non-auto |
| and auto defrag paths. Otherwise it will set move_max_hop to 0 and |
| finally cause unexpectedly ENOSPC error. |
| |
| Currently there are no tools triggering the above issues since |
| defragfs.ocfs2 enables auto defrag by default. Tested with manually |
| changing defragfs.ocfs2 to run non auto defrag path. |
| |
| Link: https://lkml.kernel.org/r/20230220050526.22020-1-heming.zhao@suse.com |
| Signed-off-by: Heming Zhao <heming.zhao@suse.com> |
| Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com> |
| Cc: Mark Fasheh <mark@fasheh.com> |
| Cc: Joel Becker <jlbec@evilplan.org> |
| Cc: Junxiao Bi <junxiao.bi@oracle.com> |
| Cc: Changwei Ge <gechangwei@live.cn> |
| Cc: Gang He <ghe@suse.com> |
| Cc: Jun Piao <piaojun@huawei.com> |
| Cc: <stable@vger.kernel.org> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| fs/ocfs2/move_extents.c | 24 +++++++++++++----------- |
| 1 file changed, 13 insertions(+), 11 deletions(-) |
| |
| --- a/fs/ocfs2/move_extents.c |
| +++ b/fs/ocfs2/move_extents.c |
| @@ -444,7 +444,7 @@ static int ocfs2_find_victim_alloc_group |
| 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) >> |
| @@ -559,6 +559,7 @@ static void ocfs2_probe_alloc_group(stru |
| last_free_bits++; |
| |
| if (last_free_bits == move_len) { |
| + i -= move_len; |
| *goal_bit = i; |
| *phys_cpos = base_cpos + i; |
| break; |
| @@ -1030,18 +1031,19 @@ int ocfs2_ioctl_move_extents(struct file |
| |
| 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; |