Skip to content

Commit b40a2b0

Browse files
Sunmin JeongJaegeuk Kim
authored andcommitted
f2fs: use meta inode for GC of atomic file
The page cache of the atomic file keeps new data pages which will be stored in the COW file. It can also keep old data pages when GCing the atomic file. In this case, new data can be overwritten by old data if a GC thread sets the old data page as dirty after new data page was evicted. Also, since all writes to the atomic file are redirected to COW inodes, GC for the atomic file is not working well as below. f2fs_gc(gc_type=FG_GC) - select A as a victim segment do_garbage_collect - iget atomic file's inode for block B move_data_page f2fs_do_write_data_page - use dn of cow inode - set fio->old_blkaddr from cow inode - seg_freed is 0 since block B is still valid - goto gc_more and A is selected as victim again To solve the problem, let's separate GC writes and updates in the atomic file by using the meta inode for GC writes. Fixes: 3db1de0 ("f2fs: change the current atomic write way") Cc: [email protected] #v5.19+ Reviewed-by: Sungjong Seo <[email protected]> Reviewed-by: Yeongjin Gil <[email protected]> Signed-off-by: Sunmin Jeong <[email protected]> Reviewed-by: Chao Yu <[email protected]> Signed-off-by: Jaegeuk Kim <[email protected]>
1 parent e3a1997 commit b40a2b0

File tree

4 files changed

+14
-9
lines changed

4 files changed

+14
-9
lines changed

fs/f2fs/data.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2695,7 +2695,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
26952695
}
26962696

26972697
/* wait for GCed page writeback via META_MAPPING */
2698-
if (fio->post_read)
2698+
if (fio->meta_gc)
26992699
f2fs_wait_on_block_writeback(inode, fio->old_blkaddr);
27002700

27012701
/*
@@ -2790,7 +2790,7 @@ int f2fs_write_single_data_page(struct page *page, int *submitted,
27902790
.submitted = 0,
27912791
.compr_blocks = compr_blocks,
27922792
.need_lock = compr_blocks ? LOCK_DONE : LOCK_RETRY,
2793-
.post_read = f2fs_post_read_required(inode) ? 1 : 0,
2793+
.meta_gc = f2fs_meta_inode_gc_required(inode) ? 1 : 0,
27942794
.io_type = io_type,
27952795
.io_wbc = wbc,
27962796
.bio = bio,

fs/f2fs/f2fs.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1211,7 +1211,7 @@ struct f2fs_io_info {
12111211
unsigned int in_list:1; /* indicate fio is in io_list */
12121212
unsigned int is_por:1; /* indicate IO is from recovery or not */
12131213
unsigned int encrypted:1; /* indicate file is encrypted */
1214-
unsigned int post_read:1; /* require post read */
1214+
unsigned int meta_gc:1; /* require meta inode GC */
12151215
enum iostat_type io_type; /* io type */
12161216
struct writeback_control *io_wbc; /* writeback control */
12171217
struct bio **bio; /* bio for ipu */
@@ -4263,6 +4263,11 @@ static inline bool f2fs_post_read_required(struct inode *inode)
42634263
f2fs_compressed_file(inode);
42644264
}
42654265

4266+
static inline bool f2fs_meta_inode_gc_required(struct inode *inode)
4267+
{
4268+
return f2fs_post_read_required(inode) || f2fs_is_atomic_file(inode);
4269+
}
4270+
42664271
/*
42674272
* compress.c
42684273
*/

fs/f2fs/gc.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1589,7 +1589,7 @@ static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
15891589
start_bidx = f2fs_start_bidx_of_node(nofs, inode) +
15901590
ofs_in_node;
15911591

1592-
if (f2fs_post_read_required(inode)) {
1592+
if (f2fs_meta_inode_gc_required(inode)) {
15931593
int err = ra_data_block(inode, start_bidx);
15941594

15951595
f2fs_up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
@@ -1640,15 +1640,15 @@ static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
16401640

16411641
start_bidx = f2fs_start_bidx_of_node(nofs, inode)
16421642
+ ofs_in_node;
1643-
if (f2fs_post_read_required(inode))
1643+
if (f2fs_meta_inode_gc_required(inode))
16441644
err = move_data_block(inode, start_bidx,
16451645
gc_type, segno, off);
16461646
else
16471647
err = move_data_page(inode, start_bidx, gc_type,
16481648
segno, off);
16491649

16501650
if (!err && (gc_type == FG_GC ||
1651-
f2fs_post_read_required(inode)))
1651+
f2fs_meta_inode_gc_required(inode)))
16521652
submitted++;
16531653

16541654
if (locked) {

fs/f2fs/segment.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3859,7 +3859,7 @@ int f2fs_inplace_write_data(struct f2fs_io_info *fio)
38593859
goto drop_bio;
38603860
}
38613861

3862-
if (fio->post_read)
3862+
if (fio->meta_gc)
38633863
f2fs_truncate_meta_inode_pages(sbi, fio->new_blkaddr, 1);
38643864

38653865
stat_inc_inplace_blocks(fio->sbi);
@@ -4029,7 +4029,7 @@ void f2fs_wait_on_block_writeback(struct inode *inode, block_t blkaddr)
40294029
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
40304030
struct page *cpage;
40314031

4032-
if (!f2fs_post_read_required(inode))
4032+
if (!f2fs_meta_inode_gc_required(inode))
40334033
return;
40344034

40354035
if (!__is_valid_data_blkaddr(blkaddr))
@@ -4048,7 +4048,7 @@ void f2fs_wait_on_block_writeback_range(struct inode *inode, block_t blkaddr,
40484048
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
40494049
block_t i;
40504050

4051-
if (!f2fs_post_read_required(inode))
4051+
if (!f2fs_meta_inode_gc_required(inode))
40524052
return;
40534053

40544054
for (i = 0; i < len; i++)

0 commit comments

Comments
 (0)