On 06/06, Chao Yu wrote: > Commit 59c9081bc86e ("f2fs: allow write page cache when writting cp") > allows write() to write data to page cache during checkpoint, so block > count fields like .total_valid_block_count, .alloc_valid_block_count > and .rf_node_block_count may encounter race condition as below: > > CP Thread A > - write_checkpoint > - block_operations > - f2fs_down_write(&sbi->node_change) > - __prepare_cp_block > : ckpt->valid_block_count = .total_valid_block_count > - f2fs_up_write(&sbi->node_change) > - write > - f2fs_preallocate_blocks > - f2fs_map_blocks(,F2FS_GET_BLOCK_PRE_AIO) > - f2fs_map_lock > - f2fs_down_read(&sbi->node_change) > - f2fs_reserve_new_blocks > - inc_valid_block_count > : > percpu_counter_add(&sbi->alloc_valid_block_count, count) > : sbi->total_valid_block_count += count > - f2fs_up_read(&sbi->node_change) > - do_checkpoint > : sbi->last_valid_block_count = sbi->total_valid_block_count > : percpu_counter_set(&sbi->alloc_valid_block_count, 0) > : percpu_counter_set(&sbi->rf_node_block_count, 0) > - fsync > - need_do_checkpoint > - f2fs_space_for_roll_forward > : alloc_valid_block_count was reset to zero, > so, it may missed last data during > checkpoint > > Let's change to update .total_valid_block_count, .alloc_valid_block_count > and .rf_node_block_count in block_operations(), then their access can be > protected by .node_change and .cp_rwsem lock, so that it can avoid above > race condition. > > Fixes: 59c9081bc86e ("f2fs: allow write page cache when writting cp") > Cc: Yunlei He <heyun...@oppo.com> > Signed-off-by: Chao Yu <c...@kernel.org> > --- > fs/f2fs/checkpoint.c | 11 ++++++----- > 1 file changed, 6 insertions(+), 5 deletions(-) > > diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c > index 66eaad591b60..010bbd5af211 100644 > --- a/fs/f2fs/checkpoint.c > +++ b/fs/f2fs/checkpoint.c > @@ -1298,6 +1298,12 @@ static int block_operations(struct f2fs_sb_info *sbi) > * dirty node blocks and some checkpoint values by block allocation. > */ > __prepare_cp_block(sbi); > + > + /* update user_block_counts */ > + sbi->last_valid_block_count = sbi->total_valid_block_count; > + percpu_counter_set(&sbi->alloc_valid_block_count, 0); > + percpu_counter_set(&sbi->rf_node_block_count, 0);
Need to add this in __prepare_cp_block()? > + > f2fs_up_write(&sbi->node_change); > return err; > } > @@ -1575,11 +1581,6 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, > struct cp_control *cpc) > start_blk += NR_CURSEG_NODE_TYPE; > } > > - /* update user_block_counts */ > - sbi->last_valid_block_count = sbi->total_valid_block_count; > - percpu_counter_set(&sbi->alloc_valid_block_count, 0); > - percpu_counter_set(&sbi->rf_node_block_count, 0); > - > /* Here, we have one bio having CP pack except cp pack 2 page */ > f2fs_sync_meta_pages(sbi, META, LONG_MAX, FS_CP_META_IO); > /* Wait for all dirty meta pages to be submitted for IO */ > -- > 2.40.1 > _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel