2024-05-29 08:53:19

by Zhiguo Niu

[permalink] [raw]
Subject: [PATCH] f2fs: fix to avoid use SSR allocate when do defragment

SSR allocate mode will be used when doing file defragment
if ATGC is working at the same time, that is because
set_page_private_gcing may make CURSEG_ALL_DATA_ATGC segment
type got in f2fs_allocate_data_block when defragment page
is writeback, which may cause file fragmentation is worse.

A file with 2 fragmentations is changed as following after defragment:

----------------file info-------------------
sensorsdata :
--------------------------------------------
dev [254:48]
ino [0x 3029 : 12329]
mode [0x 81b0 : 33200]
nlink [0x 1 : 1]
uid [0x 27e6 : 10214]
gid [0x 27e6 : 10214]
size [0x 242000 : 2367488]
blksize [0x 1000 : 4096]
blocks [0x 1210 : 4624]
--------------------------------------------

file_pos start_blk end_blk blks
0 11361121 11361207 87
356352 11361215 11361216 2
364544 11361218 11361218 1
368640 11361220 11361221 2
376832 11361224 11361225 2
385024 11361227 11361238 12
434176 11361240 11361252 13
487424 11361254 11361254 1
491520 11361271 11361279 9
528384 3681794 3681795 2
536576 3681797 3681797 1
540672 3681799 3681799 1
544768 3681803 3681803 1
548864 3681805 3681805 1
552960 3681807 3681807 1
557056 3681809 3681809 1

A new FI flag FI_DEFRAG_IN_PROGRESS is introduced to avoid
this scenarios.

Signed-off-by: Zhiguo Niu <[email protected]>
---
fs/f2fs/f2fs.h | 1 +
fs/f2fs/file.c | 2 ++
fs/f2fs/segment.c | 3 ++-
3 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 4044e67..9281c5e 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -803,6 +803,7 @@ enum {
FI_COW_FILE, /* indicate COW file */
FI_ATOMIC_COMMITTED, /* indicate atomic commit completed except disk sync */
FI_ATOMIC_REPLACE, /* indicate atomic replace */
+ FI_DEFRAG_IN_PROGRESS, /* indicate file was defragmenting */
FI_MAX, /* max flag, never be used */
};

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 5c0b281..93d2767 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -2717,6 +2717,7 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi,
goto out;
}

+ set_inode_flag(inode, FI_DEFRAG_IN_PROGRESS);
map.m_lblk = pg_start;
map.m_len = pg_end - pg_start;
total = 0;
@@ -2772,6 +2773,7 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi,
clear_out:
clear_inode_flag(inode, FI_SKIP_WRITES);
out:
+ clear_inode_flag(inode, FI_DEFRAG_IN_PROGRESS);
clear_inode_flag(inode, FI_OPU_WRITE);
unlock_out:
inode_unlock(inode);
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 7caf20a..dd6f8ac 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -3482,7 +3482,8 @@ static int __get_segment_type_6(struct f2fs_io_info *fio)
if (page_private_gcing(fio->page)) {
if (fio->sbi->am.atgc_enabled &&
(fio->io_type == FS_DATA_IO) &&
- (fio->sbi->gc_mode != GC_URGENT_HIGH))
+ (fio->sbi->gc_mode != GC_URGENT_HIGH) &&
+ !is_inode_flag_set(inode, FI_DEFRAG_IN_PROGRESS))
return CURSEG_ALL_DATA_ATGC;
else
return CURSEG_COLD_DATA;
--
1.9.1