在 2024/10/18 9:52, Zhiguo Niu 写道: > Chao Yu via Linux-f2fs-devel <linux-f2fs-devel@lists.sourceforge.net> > 于2024年10月17日周四 17:57写道: >> On 2024/10/9 18:27, Qi Han wrote: >>> When the free segment is used up during CP disable, many write or >>> ioctl operations will get ENOSPC error codes, even if there are >>> still many blocks available. We can reproduce it in the following >>> steps: >>> >>> dd if=/dev/zero of=f2fs.img bs=1M count=55 >>> mkfs.f2fs -f f2fs.img >>> mount f2fs.img f2fs_dir -o checkpoint=disable:10% >>> cd f2fs_dir >>> dd if=/dev/zero of=bigfile bs=1M count=50 >>> sync >>> rm bigfile >>> i=1; while [[ $i -lt 10000000 ]]; do (file_name=./file$i; dd \ >>> if=/dev/random of=$file_name bs=1M count=0); i=$((i+1)); done >>> stat -f ./ >>> >>> In f2fs_need_SSR() function, it is allowed to use SSR to allocate >>> blocks when CP is disabled, so in f2fs_is_checkpoint_ready function, > Hi Chao and Qi, > based on this comment and codes, I have some doubts: > unusable blocks are calculated from invalid blocks of Dirty segment > in f2fs_get_unsuable_blocks then minus ovp_hole, > but SSR is allowed when the checkpoint is disabled. > So actually SSR can not use most invalid blocks of Dirty segments? > Is this a contradiction? > Thanks!
I think that in the case of a disable CP, in order to restore the data to the state before the disable CP, SSR cannot reuse all the invalid blocks, for example, suppose there is a fileA which occupies 10 data blocks when the CP enable, and then we delete the fileA after the CP disable, the 10 blocks cannot be reused by SSR. >>> can we judge the number of invalid blocks when free segment is not >>> enough, and return ENOSPC only if the number of invalid blocks is >>> also not enough? >> Can you please try below patch? >> >> From 38b7c97dcc55ba83de4220c3dc54c2eb66148dd5 Mon Sep 17 00:00:00 2001 >> From: Chao Yu <c...@kernel.org> >> Date: Thu, 17 Oct 2024 17:07:05 +0800 >> Subject: [PATCH] f2fs: revalidate empty segment when checkpoint is disabled >> >> If checkpoint is off, let's set segment as free once all newly >> written datas were removed. >> >> Signed-off-by: Chao Yu <c...@kernel.org> >> --- >> fs/f2fs/segment.c | 13 ++++++++++++- >> 1 file changed, 12 insertions(+), 1 deletion(-) >> >> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c >> index f8d6e601e084..9bad13d70afb 100644 >> --- a/fs/f2fs/segment.c >> +++ b/fs/f2fs/segment.c >> @@ -853,6 +853,17 @@ static void locate_dirty_segment(struct f2fs_sb_info >> *sbi, unsigned int segno) >> valid_blocks = get_valid_blocks(sbi, segno, false); >> ckpt_valid_blocks = get_ckpt_valid_blocks(sbi, segno, false); >> >> + /* >> + * If checkpoint is off, let's set segment as free once all newly >> + * written datas were removed. >> + */ >> + if (is_sbi_flag_set(sbi, SBI_CP_DISABLED) && >> + valid_blocks == 0 && ckpt_valid_blocks == 0) { >> + __remove_dirty_segment(sbi, segno, DIRTY); >> + __set_test_and_free(sbi, segno, false); >> + goto out_lock; >> + } >> + >> if (valid_blocks == 0 && (!is_sbi_flag_set(sbi, SBI_CP_DISABLED) || >> ckpt_valid_blocks == usable_blocks)) { >> __locate_dirty_segment(sbi, segno, PRE); >> @@ -863,7 +874,7 @@ static void locate_dirty_segment(struct f2fs_sb_info >> *sbi, unsigned int segno) >> /* Recovery routine with SSR needs this */ >> __remove_dirty_segment(sbi, segno, DIRTY); >> } >> - >> +out_lock: >> mutex_unlock(&dirty_i->seglist_lock); >> } >> >> -- >> 2.40.1 >> >>> Signed-off-by: Qi Han <ha...@vivo.com> >>> --- >>> fs/f2fs/segment.h | 21 +++++++++++++++++++++ >>> 1 file changed, 21 insertions(+) >>> >>> diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h >>> index 71adb4a43bec..9bf0cf3a6a31 100644 >>> --- a/fs/f2fs/segment.h >>> +++ b/fs/f2fs/segment.h >>> @@ -637,12 +637,33 @@ static inline bool has_enough_free_secs(struct >>> f2fs_sb_info *sbi, >>> return !has_not_enough_free_secs(sbi, freed, needed); >>> } >>> >>> +static inline bool has_enough_available_blocks(struct f2fs_sb_info *sbi) >>> +{ >>> + unsigned int total_free_blocks = sbi->user_block_count - >>> + valid_user_blocks(sbi) - >>> + sbi->current_reserved_blocks; >>> + >>> + if (total_free_blocks <= sbi->unusable_block_count) >>> + total_free_blocks = 0; >>> + else >>> + total_free_blocks -= sbi->unusable_block_count; >>> + >>> + if (total_free_blocks > F2FS_OPTION(sbi).root_reserved_blocks) >>> + total_free_blocks -= F2FS_OPTION(sbi).root_reserved_blocks; >>> + else >>> + total_free_blocks = 0; >>> + >>> + return (total_free_blocks > 0) ? true : false; >>> +} >>> + >>> static inline bool f2fs_is_checkpoint_ready(struct f2fs_sb_info *sbi) >>> { >>> if (likely(!is_sbi_flag_set(sbi, SBI_CP_DISABLED))) >>> return true; >>> if (likely(has_enough_free_secs(sbi, 0, 0))) >>> return true; >>> + if (likely(has_enough_available_blocks(sbi))) >>> + return true; >>> return false; >>> } >>> >> >> >> _______________________________________________ >> Linux-f2fs-devel mailing list >> Linux-f2fs-devel@lists.sourceforge.net >> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel