From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EA82A322C78 for ; Sat, 14 Mar 2026 05:14:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773465253; cv=none; b=mkPEckWXAQEqoQwgfKdBmITL+xoWybiPrZVXaO5/V4TPQqUSE3sIHc/XozMasIHaGbyKOyrwEuy1oadQ+Swqjf47QF2cLT2mmQa9RlZSeCb7r+nx+vgze0VAsRcSYo/1G78q5pj5BGohYdBfXuOfiq0eCdeh7+XeXEwcKBFB+Ko= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773465253; c=relaxed/simple; bh=5cuoiJFh054oZmahtH93aR6KjeqO2fB4Vi01T90nfcQ=; h=Message-ID:Date:MIME-Version:Cc:Subject:To:References:From: In-Reply-To:Content-Type; b=JXCvh1iQGDpuJ4ia5wnAxmZDH6e5KnszK7m3Oac1wA0I3mlaaW2arjv235guOG/hkTq70JUsZx7vQ+CSux/la7k6xPDZQJLxB0/F8hp6BzIwU8ZcaOlJvDakw4cOV0i+pt1EZ9LUkddq2bnlbtfWa3nOcQ2OmiurrY8kTuO+82w= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=fTM4RtaP; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="fTM4RtaP" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 40553C116C6; Sat, 14 Mar 2026 05:14:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773465252; bh=5cuoiJFh054oZmahtH93aR6KjeqO2fB4Vi01T90nfcQ=; h=Date:Cc:Subject:To:References:From:In-Reply-To:From; b=fTM4RtaPvTEglugId0BYoSi7STUOhW1X4DmL9FO5Zlo7KWuix42Ectkcc++rMY65p q3e9t3YPURYEBqz7moyTDc+4R6ts24LAUvX5k0zspZJq+tGTFFbyKpintw26clCcRK cuD0DB0hpUoBKDlaOaTzUGe9U9gJzSu4e4K2bw7Miv7QwR9mvgsoHf9+sDlDsA5njX B1muFDrSGAMqP9y2KRSyMtTlTe0S1AiHV3olKPPr2pQjCEUrai0uU8I1LcNBZr4R15 raKYVYIQOfN9YmAsjgRzJ2xTec3PZGRsD+V4cNW8ImoNSc1II0Xpy0WgLb2zIt1EMQ kgDrgbFA4blKA== Message-ID: <76d4e46c-5c34-4dc4-8aa4-1efbcbe1415f@kernel.org> Date: Sat, 14 Mar 2026 13:14:07 +0800 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Cc: chao@kernel.org, jaegeuk@kernel.org, linux-kernel@vger.kernel.org Subject: Re: [RFC PATCH 3/3] f2fs: add mount option to disable shared SIT mirror checks To: 'wallentx , linux-f2fs-devel@lists.sourceforge.net References: <20260309103700.489932-1-william.allentx@gmail.com> <20260309103700.489932-4-william.allentx@gmail.com> Content-Language: en-US From: Chao Yu In-Reply-To: <20260309103700.489932-4-william.allentx@gmail.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit On 2026/3/9 18:37, 'wallentx wrote: > From: wallentx > > When CONFIG_F2FS_CHECK_FS=y, zoned shared-SIT mode still keeps > per-segment cur_valid_map_mir together with auxiliary SIT mirror state > for runtime consistency checks. After shared SIT maps are introduced, > that mirror path becomes the next major static memory cost on large > zoned systems. > > Add shared_sit_check/noshared_sit_check to control that extra mirror > tracking explicitly. Keep shared_sit_check as the default, limit the > option to zoned shared-SIT mounts, and reject changing it by remount > because the mirror state is built at mount time. > > With noshared_sit_check, shared-SIT mode skips cur_valid_map_mir, > sit_bitmap_mir, and invalid_segmap allocation and their associated > check paths. This does not disable all CONFIG_F2FS_CHECK_FS behavior; it > only disables the extra shared-SIT mirror tracking. > > On the same 43-volume HM-SMR test system (~550 TB total) with > CONFIG_F2FS_CHECK_FS=y, shared SIT with the default mirror path enabled > reported 27.70 GiB of static F2FS memory. Mounting with > noshared_sit_check reduced that to 12.10 GiB. Jaegeuk and me think that we can drop sit bitmap and version bitmap sanity check, since we haven't got any report for almost a decade. So how about dropping the bitmaps w/ two separated patch? Thanks, > > Signed-off-by: wallentx > --- > Documentation/filesystems/f2fs.rst | 11 ++ > fs/f2fs/debug.c | 7 +- > fs/f2fs/f2fs.h | 16 +++ > fs/f2fs/gc.c | 29 ++-- > fs/f2fs/segment.c | 213 ++++++++++++++++------------- > fs/f2fs/segment.h | 28 ++-- > fs/f2fs/super.c | 21 +++ > 7 files changed, 204 insertions(+), 121 deletions(-) > > diff --git a/Documentation/filesystems/f2fs.rst b/Documentation/filesystems/f2fs.rst > index 7e4031631286..3ca191f92309 100644 > --- a/Documentation/filesystems/f2fs.rst > +++ b/Documentation/filesystems/f2fs.rst > @@ -363,6 +363,17 @@ memory=%s Control memory mode. This supports "normal" and "low" modes. > Because of the nature of low memory devices, in this mode, f2fs > will try to save memory sometimes by sacrificing performance. > "normal" mode is the default mode and same as before. > +shared_sit_check/ > +noshared_sit_check Enable or disable extra SIT mirror consistency checks in > + zoned shared-SIT mode. This only affects zoned devices > + mounted with ``mode=lfs``, where shared SIT valid maps are > + used. ``shared_sit_check`` is enabled by default. Setting > + ``noshared_sit_check`` reduces memory usage when the kernel > + is built with ``CONFIG_F2FS_CHECK_FS=y`` by skipping the > + per-segment SIT mirror tracking. This option has no effect > + when shared SIT maps are not in use and cannot be changed > + by remount. To use a different setting, unmount and > + mount again with the new option. > age_extent_cache Enable an age extent cache based on rb-tree. It records > data block update frequency of the extent per inode, in > order to provide better temperature hints for data block > diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c > index d8bfdac5c1e4..ed6e03b42836 100644 > --- a/fs/f2fs/debug.c > +++ b/fs/f2fs/debug.c > @@ -325,9 +325,10 @@ static void update_mem_info(struct f2fs_sb_info *sbi) > si->base_mem += SIT_VBLOCK_MAP_SIZE * 2; > /* Approximate private bitmaps for active logs */ > si->base_mem += SIT_VBLOCK_MAP_SIZE * NR_CURSEG_TYPE; > -#ifdef CONFIG_F2FS_CHECK_FS > - si->base_mem += SIT_VBLOCK_MAP_SIZE * MAIN_SEGS(sbi); > -#endif > + #ifdef CONFIG_F2FS_CHECK_FS > + if (f2fs_sit_check_enabled(sbi)) > + si->base_mem += SIT_VBLOCK_MAP_SIZE * MAIN_SEGS(sbi); > + #endif > if (f2fs_block_unit_discard(sbi)) > si->base_mem += SIT_VBLOCK_MAP_SIZE * MAIN_SEGS(sbi); > } else { > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h > index 11f3601ffd34..d8526103d86a 100644 > --- a/fs/f2fs/f2fs.h > +++ b/fs/f2fs/f2fs.h > @@ -130,6 +130,7 @@ enum f2fs_mount_opt { > F2FS_MOUNT_COMPRESS_CACHE, > F2FS_MOUNT_AGE_EXTENT_CACHE, > F2FS_MOUNT_NAT_BITS, > + F2FS_MOUNT_SHARED_SIT_CHECK, > F2FS_MOUNT_INLINECRYPT, > /* > * Some f2fs environments expect to be able to pass the "lazytime" option > @@ -4920,6 +4921,21 @@ static inline bool f2fs_use_shared_sit_map(struct f2fs_sb_info *sbi) > return f2fs_sb_has_blkzoned(sbi) && f2fs_lfs_mode(sbi); > } > > +/* > + * shared_sit_check is a mount-time escape hatch for the extra SIT mirror > + * tracking kept by CONFIG_F2FS_CHECK_FS in zoned shared-SIT mode. > + */ > +static inline bool f2fs_sit_check_enabled(struct f2fs_sb_info *sbi) > +{ > + if (!IS_ENABLED(CONFIG_F2FS_CHECK_FS)) > + return false; > + > + if (!f2fs_use_shared_sit_map(sbi)) > + return true; > + > + return test_opt(sbi, SHARED_SIT_CHECK); > +} > + > static inline bool f2fs_is_sequential_zone_area(struct f2fs_sb_info *sbi, > block_t blkaddr) > { > diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c > index 80b8500fa987..1decb0caea1b 100644 > --- a/fs/f2fs/gc.c > +++ b/fs/f2fs/gc.c > @@ -877,15 +877,16 @@ int f2fs_get_victim(struct f2fs_sb_info *sbi, unsigned int *result, > p.offset = segno + p.ofs_unit; > nsearched++; > > -#ifdef CONFIG_F2FS_CHECK_FS > - /* > - * skip selecting the invalid segno (that is failed due to block > - * validity check failure during GC) to avoid endless GC loop in > - * such cases. > - */ > - if (test_bit(segno, sm->invalid_segmap)) > - goto next; > -#endif > + #ifdef CONFIG_F2FS_CHECK_FS > + /* > + * skip selecting the invalid segno (that is failed due to block > + * validity check failure during GC) to avoid endless GC loop in > + * such cases. > + */ > + if (f2fs_sit_check_enabled(sbi) && > + test_bit(segno, sm->invalid_segmap)) > + goto next; > + #endif > > secno = GET_SEC_FROM_SEG(sbi, segno); > > @@ -1197,18 +1198,20 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, > f2fs_folio_put(node_folio, true); > > if (source_blkaddr != blkaddr) { > -#ifdef CONFIG_F2FS_CHECK_FS > + #ifdef CONFIG_F2FS_CHECK_FS > unsigned int segno = GET_SEGNO(sbi, blkaddr); > unsigned long offset = GET_BLKOFF_FROM_SEG0(sbi, blkaddr); > > - if (unlikely(check_valid_map(sbi, segno, offset))) { > + if (f2fs_sit_check_enabled(sbi) && > + unlikely(check_valid_map(sbi, segno, offset))) { > if (!test_and_set_bit(segno, SIT_I(sbi)->invalid_segmap)) { > - f2fs_err(sbi, "mismatched blkaddr %u (source_blkaddr %u) in seg %u", > + f2fs_err(sbi, > + "mismatched blkaddr %u (source_blkaddr %u) in seg %u", > blkaddr, source_blkaddr, segno); > set_sbi_flag(sbi, SBI_NEED_FSCK); > } > } > -#endif > + #endif > return false; > } > return true; > diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c > index 0dab6b16ba56..dce66eec2a5f 100644 > --- a/fs/f2fs/segment.c > +++ b/fs/f2fs/segment.c > @@ -38,6 +38,11 @@ struct f2fs_sit_bitmap { > unsigned char map[SIT_VBLOCK_MAP_SIZE]; > }; > > +static inline struct f2fs_sit_bitmap *f2fs_sit_bitmap_from_map(void *map) > +{ > + return container_of(map, struct f2fs_sit_bitmap, map); > +} > + > static void f2fs_free_sit_bitmap_rcu(struct rcu_head *rcu) > { > struct f2fs_sit_bitmap *b = container_of(rcu, struct f2fs_sit_bitmap, rcu); > @@ -45,11 +50,6 @@ static void f2fs_free_sit_bitmap_rcu(struct rcu_head *rcu) > kmem_cache_free(sit_bitmap_slab, b); > } > > -static struct f2fs_sit_bitmap *f2fs_sit_bitmap_from_map(void *map) > -{ > - return container_of(map, struct f2fs_sit_bitmap, map); > -} > - > static unsigned long __reverse_ulong(unsigned char *str) > { > unsigned long tmp = 0; > @@ -845,9 +845,10 @@ static void __remove_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno, > if (valid_blocks == 0) { > clear_bit(GET_SEC_FROM_SEG(sbi, segno), > dirty_i->victim_secmap); > -#ifdef CONFIG_F2FS_CHECK_FS > - clear_bit(segno, SIT_I(sbi)->invalid_segmap); > -#endif > + #ifdef CONFIG_F2FS_CHECK_FS > + if (f2fs_sit_check_enabled(sbi)) > + clear_bit(segno, SIT_I(sbi)->invalid_segmap); > + #endif > } > if (__is_large_section(sbi)) { > unsigned int secno = GET_SEC_FROM_SEG(sbi, segno); > @@ -2471,9 +2472,10 @@ static int update_sit_entry_for_release(struct f2fs_sb_info *sbi, struct seg_ent > memset(b->map, 0xff, SIT_VBLOCK_MAP_SIZE); > rcu_assign_pointer(se->cur_valid_map, b->map); > se->ckpt_valid_map = b->map; > -#ifdef CONFIG_F2FS_CHECK_FS > - memcpy(se->cur_valid_map_mir, b->map, SIT_VBLOCK_MAP_SIZE); > -#endif > + #ifdef CONFIG_F2FS_CHECK_FS > + if (f2fs_sit_check_enabled(sbi)) > + memcpy(se->cur_valid_map_mir, b->map, SIT_VBLOCK_MAP_SIZE); > + #endif > } else if (se->cur_valid_map == sit_i->bitmap_zero) { > /* Should not happen, freeing empty segment */ > struct f2fs_sit_bitmap *b = f2fs_kmem_cache_alloc(sit_bitmap_slab, > @@ -2481,23 +2483,27 @@ static int update_sit_entry_for_release(struct f2fs_sb_info *sbi, struct seg_ent > memset(b->map, 0, SIT_VBLOCK_MAP_SIZE); > rcu_assign_pointer(se->cur_valid_map, b->map); > se->ckpt_valid_map = b->map; > -#ifdef CONFIG_F2FS_CHECK_FS > - memcpy(se->cur_valid_map_mir, b->map, SIT_VBLOCK_MAP_SIZE); > -#endif > + #ifdef CONFIG_F2FS_CHECK_FS > + if (f2fs_sit_check_enabled(sbi)) > + memcpy(se->cur_valid_map_mir, b->map, SIT_VBLOCK_MAP_SIZE); > + #endif > } > } > > for (i = 0; i < del_count; i++) { > exist = f2fs_test_and_clear_bit(offset + i, se->cur_valid_map); > -#ifdef CONFIG_F2FS_CHECK_FS > - mir_exist = f2fs_test_and_clear_bit(offset + i, > - se->cur_valid_map_mir); > - if (unlikely(exist != mir_exist)) { > - f2fs_err(sbi, "Inconsistent error when clearing bitmap, blk:%u, old bit:%d", > - blkaddr + i, exist); > - f2fs_bug_on(sbi, 1); > - } > -#endif > + #ifdef CONFIG_F2FS_CHECK_FS > + if (f2fs_sit_check_enabled(sbi)) { > + mir_exist = f2fs_test_and_clear_bit(offset + i, > + se->cur_valid_map_mir); > + if (unlikely(exist != mir_exist)) { > + f2fs_err(sbi, > + "Inconsistent error when clearing bitmap, blk:%u, old bit:%d", > + blkaddr + i, exist); > + f2fs_bug_on(sbi, 1); > + } > + } > + #endif > if (unlikely(!exist)) { > f2fs_err(sbi, "Bitmap was wrongly cleared, blk:%u", blkaddr + i); > f2fs_bug_on(sbi, 1); > @@ -2559,9 +2565,10 @@ static int update_sit_entry_for_alloc(struct f2fs_sb_info *sbi, struct seg_entry > memset(b->map, 0, SIT_VBLOCK_MAP_SIZE); > rcu_assign_pointer(se->cur_valid_map, b->map); > se->ckpt_valid_map = b->map; > -#ifdef CONFIG_F2FS_CHECK_FS > - memcpy(se->cur_valid_map_mir, b->map, SIT_VBLOCK_MAP_SIZE); > -#endif > + #ifdef CONFIG_F2FS_CHECK_FS > + if (f2fs_sit_check_enabled(sbi)) > + memcpy(se->cur_valid_map_mir, b->map, SIT_VBLOCK_MAP_SIZE); > + #endif > } else if (se->cur_valid_map == sit_i->bitmap_full) { > /* Should not happen in LFS alloc, but for safety */ > struct f2fs_sit_bitmap *b = f2fs_kmem_cache_alloc(sit_bitmap_slab, > @@ -2569,22 +2576,26 @@ static int update_sit_entry_for_alloc(struct f2fs_sb_info *sbi, struct seg_entry > memset(b->map, 0xff, SIT_VBLOCK_MAP_SIZE); > rcu_assign_pointer(se->cur_valid_map, b->map); > se->ckpt_valid_map = b->map; > -#ifdef CONFIG_F2FS_CHECK_FS > - memcpy(se->cur_valid_map_mir, b->map, SIT_VBLOCK_MAP_SIZE); > -#endif > + #ifdef CONFIG_F2FS_CHECK_FS > + if (f2fs_sit_check_enabled(sbi)) > + memcpy(se->cur_valid_map_mir, b->map, SIT_VBLOCK_MAP_SIZE); > + #endif > } > } > > exist = f2fs_test_and_set_bit(offset, se->cur_valid_map); > -#ifdef CONFIG_F2FS_CHECK_FS > - mir_exist = f2fs_test_and_set_bit(offset, > - se->cur_valid_map_mir); > - if (unlikely(exist != mir_exist)) { > - f2fs_err(sbi, "Inconsistent error when setting bitmap, blk:%u, old bit:%d", > - blkaddr, exist); > - f2fs_bug_on(sbi, 1); > + #ifdef CONFIG_F2FS_CHECK_FS > + if (f2fs_sit_check_enabled(sbi)) { > + mir_exist = f2fs_test_and_set_bit(offset, > + se->cur_valid_map_mir); > + if (unlikely(exist != mir_exist)) { > + f2fs_err(sbi, > + "Inconsistent error when setting bitmap, blk:%u, old bit:%d", > + blkaddr, exist); > + f2fs_bug_on(sbi, 1); > + } > } > -#endif > + #endif > if (unlikely(exist)) { > f2fs_err(sbi, "Bitmap was wrongly set, blk:%u", blkaddr); > f2fs_bug_on(sbi, 1); > @@ -2677,13 +2688,15 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del) > > rcu_assign_pointer(se->cur_valid_map, sit_i->bitmap_zero); > se->ckpt_valid_map = sit_i->bitmap_zero; > -#ifdef CONFIG_F2FS_CHECK_FS > - memset(se->cur_valid_map_mir, 0, SIT_VBLOCK_MAP_SIZE); > -#endif > + #ifdef CONFIG_F2FS_CHECK_FS > + if (f2fs_sit_check_enabled(sbi)) > + memset(se->cur_valid_map_mir, 0, SIT_VBLOCK_MAP_SIZE); > + #endif > if (old_map != sit_i->bitmap_zero && > old_map != sit_i->bitmap_full) { > - call_rcu(&f2fs_sit_bitmap_from_map(old_map)->rcu, > - f2fs_free_sit_bitmap_rcu); > + struct f2fs_sit_bitmap *b = > + f2fs_sit_bitmap_from_map(old_map); > + call_rcu(&b->rcu, f2fs_free_sit_bitmap_rcu); > } > } else if (new_vblocks == BLKS_PER_SEG(sbi) && > se->cur_valid_map != sit_i->bitmap_full) { > @@ -2691,13 +2704,15 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del) > > rcu_assign_pointer(se->cur_valid_map, sit_i->bitmap_full); > se->ckpt_valid_map = sit_i->bitmap_full; > -#ifdef CONFIG_F2FS_CHECK_FS > - memset(se->cur_valid_map_mir, 0xff, SIT_VBLOCK_MAP_SIZE); > -#endif > + #ifdef CONFIG_F2FS_CHECK_FS > + if (f2fs_sit_check_enabled(sbi)) > + memset(se->cur_valid_map_mir, 0xff, SIT_VBLOCK_MAP_SIZE); > + #endif > if (old_map != sit_i->bitmap_zero && > old_map != sit_i->bitmap_full) { > - call_rcu(&f2fs_sit_bitmap_from_map(old_map)->rcu, > - f2fs_free_sit_bitmap_rcu); > + struct f2fs_sit_bitmap *b = > + f2fs_sit_bitmap_from_map(old_map); > + call_rcu(&b->rcu, f2fs_free_sit_bitmap_rcu); > } > } > } > @@ -4701,7 +4716,7 @@ static struct folio *get_next_sit_folio(struct f2fs_sb_info *sbi, > seg_info_to_sit_folio(sbi, folio, start); > > folio_mark_dirty(folio); > - set_to_next_sit(sit_i, start); > + set_to_next_sit(sbi, sit_i, start); > > return folio; > } > @@ -4857,11 +4872,12 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc) > int offset, sit_offset; > > se = get_seg_entry(sbi, segno); > -#ifdef CONFIG_F2FS_CHECK_FS > - if (memcmp(se->cur_valid_map, se->cur_valid_map_mir, > - SIT_VBLOCK_MAP_SIZE)) > + #ifdef CONFIG_F2FS_CHECK_FS > + if (f2fs_sit_check_enabled(sbi) && > + memcmp(se->cur_valid_map, se->cur_valid_map_mir, > + SIT_VBLOCK_MAP_SIZE)) > f2fs_bug_on(sbi, 1); > -#endif > + #endif > > /* add discard candidates */ > if (!(cpc->reason & CP_DISCARD)) { > @@ -4953,11 +4969,8 @@ static int build_sit_info(struct f2fs_sb_info *sbi) > if (!sit_i->dirty_sentries_bitmap) > return -ENOMEM; > > -#ifdef CONFIG_F2FS_CHECK_FS > - bitmap_size = MAIN_SEGS(sbi) * SIT_VBLOCK_MAP_SIZE * (3 + discard_map); > -#else > - bitmap_size = MAIN_SEGS(sbi) * SIT_VBLOCK_MAP_SIZE * (2 + discard_map); > -#endif > + bitmap_size = MAIN_SEGS(sbi) * SIT_VBLOCK_MAP_SIZE * > + (2 + discard_map + f2fs_sit_check_enabled(sbi)); > > if (share_map) { > sit_i->bitmap_zero = f2fs_kzalloc(sbi, SIT_VBLOCK_MAP_SIZE, GFP_KERNEL); > @@ -4971,10 +4984,9 @@ static int build_sit_info(struct f2fs_sb_info *sbi) > } > memset(sit_i->bitmap_full, 0xff, SIT_VBLOCK_MAP_SIZE); > > - bitmap_size = MAIN_SEGS(sbi) * SIT_VBLOCK_MAP_SIZE * discard_map; > -#ifdef CONFIG_F2FS_CHECK_FS > - bitmap_size += MAIN_SEGS(sbi) * SIT_VBLOCK_MAP_SIZE; > -#endif > + bitmap_size = MAIN_SEGS(sbi) * SIT_VBLOCK_MAP_SIZE * discard_map; > + if (f2fs_sit_check_enabled(sbi)) > + bitmap_size += MAIN_SEGS(sbi) * SIT_VBLOCK_MAP_SIZE; > if (bitmap_size) { > sit_i->bitmap = f2fs_kvzalloc(sbi, bitmap_size, GFP_KERNEL); > if (!sit_i->bitmap) { > @@ -4993,9 +5005,10 @@ static int build_sit_info(struct f2fs_sb_info *sbi) > sit_i->sentries[start].ckpt_valid_map = > sit_i->bitmap_zero; > #ifdef CONFIG_F2FS_CHECK_FS > - sit_i->sentries[start].cur_valid_map_mir = > - bitmap; > - bitmap += SIT_VBLOCK_MAP_SIZE; > + if (f2fs_sit_check_enabled(sbi)) { > + sit_i->sentries[start].cur_valid_map_mir = bitmap; > + bitmap += SIT_VBLOCK_MAP_SIZE; > + } > #endif > if (discard_map) { > sit_i->sentries[start].discard_map = bitmap; > @@ -5017,8 +5030,10 @@ static int build_sit_info(struct f2fs_sb_info *sbi) > bitmap += SIT_VBLOCK_MAP_SIZE; > > #ifdef CONFIG_F2FS_CHECK_FS > - sit_i->sentries[start].cur_valid_map_mir = bitmap; > - bitmap += SIT_VBLOCK_MAP_SIZE; > + if (f2fs_sit_check_enabled(sbi)) { > + sit_i->sentries[start].cur_valid_map_mir = bitmap; > + bitmap += SIT_VBLOCK_MAP_SIZE; > + } > #endif > > if (discard_map) { > @@ -5052,16 +5067,20 @@ static int build_sit_info(struct f2fs_sb_info *sbi) > if (!sit_i->sit_bitmap) > return -ENOMEM; > > -#ifdef CONFIG_F2FS_CHECK_FS > - sit_i->sit_bitmap_mir = kmemdup(src_bitmap, > - sit_bitmap_size, GFP_KERNEL); > - if (!sit_i->sit_bitmap_mir) > - return -ENOMEM; > + #ifdef CONFIG_F2FS_CHECK_FS > + if (f2fs_sit_check_enabled(sbi)) { > + sit_i->sit_bitmap_mir = kmemdup(src_bitmap, > + sit_bitmap_size, > + GFP_KERNEL); > + if (!sit_i->sit_bitmap_mir) > + return -ENOMEM; > > - sit_i->invalid_segmap = f2fs_kvzalloc(sbi, > - main_bitmap_size, GFP_KERNEL); > - if (!sit_i->invalid_segmap) > - return -ENOMEM; > + sit_i->invalid_segmap = f2fs_kvzalloc(sbi, > + main_bitmap_size, > + GFP_KERNEL); > + if (!sit_i->invalid_segmap) > + return -ENOMEM; > + } > #endif > > sit_i->sit_base_addr = le32_to_cpu(raw_super->sit_blkaddr); > @@ -5200,12 +5219,13 @@ static int build_sit_entries(struct f2fs_sb_info *sbi) > rcu_assign_pointer(se->cur_valid_map, map); > se->ckpt_valid_map = map; > #ifdef CONFIG_F2FS_CHECK_FS > - memcpy(se->cur_valid_map_mir, map, SIT_VBLOCK_MAP_SIZE); > + if (f2fs_sit_check_enabled(sbi)) > + memcpy(se->cur_valid_map_mir, map, SIT_VBLOCK_MAP_SIZE); > #endif > se->type = GET_SIT_TYPE(&sit); > se->mtime = le64_to_cpu(sit.mtime); > } else { > - seg_info_from_raw_sit(se, &sit); > + seg_info_from_raw_sit(sbi, se, &sit); > } > > if (se->type >= NR_PERSISTENT_LOG) { > @@ -5279,15 +5299,19 @@ static int build_sit_entries(struct f2fs_sb_info *sbi) > > if (vblocks == 0 && !is_active) { > if (map != sit_i->bitmap_zero && > - map != sit_i->bitmap_full) > - kmem_cache_free(sit_bitmap_slab, > - f2fs_sit_bitmap_from_map(map)); > + map != sit_i->bitmap_full) { > + struct f2fs_sit_bitmap *b = > + f2fs_sit_bitmap_from_map(map); > + kmem_cache_free(sit_bitmap_slab, b); > + } > map = sit_i->bitmap_zero; > } else if (vblocks == BLKS_PER_SEG(sbi) && !is_active) { > if (map != sit_i->bitmap_zero && > - map != sit_i->bitmap_full) > - kmem_cache_free(sit_bitmap_slab, > - f2fs_sit_bitmap_from_map(map)); > + map != sit_i->bitmap_full) { > + struct f2fs_sit_bitmap *b = > + f2fs_sit_bitmap_from_map(map); > + kmem_cache_free(sit_bitmap_slab, b); > + } > map = sit_i->bitmap_full; > } else { > if (map == sit_i->bitmap_zero || > @@ -5310,12 +5334,13 @@ static int build_sit_entries(struct f2fs_sb_info *sbi) > rcu_assign_pointer(se->cur_valid_map, map); > se->ckpt_valid_map = map; > #ifdef CONFIG_F2FS_CHECK_FS > - memcpy(se->cur_valid_map_mir, map, SIT_VBLOCK_MAP_SIZE); > + if (f2fs_sit_check_enabled(sbi)) > + memcpy(se->cur_valid_map_mir, map, SIT_VBLOCK_MAP_SIZE); > #endif > se->type = GET_SIT_TYPE(&sit); > se->mtime = le64_to_cpu(sit.mtime); > } else { > - seg_info_from_raw_sit(se, &sit); > + seg_info_from_raw_sit(sbi, se, &sit); > } > > if (se->type >= NR_PERSISTENT_LOG) { > @@ -6099,18 +6124,18 @@ static void destroy_sit_info(struct f2fs_sb_info *sbi) > if (f2fs_use_shared_sit_map(sbi)) { > unsigned int start; > > - for (start = 0; start < MAIN_SEGS(sbi); start++) { > - struct seg_entry *se = &sit_i->sentries[start]; > + for (start = 0; start < MAIN_SEGS(sbi); start++) { > + struct seg_entry *se = &sit_i->sentries[start]; > > - if (se->cur_valid_map && > - se->cur_valid_map != sit_i->bitmap_zero && > - se->cur_valid_map != sit_i->bitmap_full) { > - struct f2fs_sit_bitmap *b; > + if (se->cur_valid_map && > + se->cur_valid_map != sit_i->bitmap_zero && > + se->cur_valid_map != sit_i->bitmap_full) { > + struct f2fs_sit_bitmap *b; > > - b = f2fs_sit_bitmap_from_map(se->cur_valid_map); > - kmem_cache_free(sit_bitmap_slab, b); > + b = f2fs_sit_bitmap_from_map(se->cur_valid_map); > + kmem_cache_free(sit_bitmap_slab, b); > + } > } > - } > kfree(sit_i->bitmap_zero); > kfree(sit_i->bitmap_full); > if (sit_i->bitmap) > diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h > index cb45cfa7a658..0f4445375ed1 100644 > --- a/fs/f2fs/segment.h > +++ b/fs/f2fs/segment.h > @@ -404,15 +404,17 @@ static inline void sanity_check_valid_blocks(struct f2fs_sb_info *sbi, > { > } > #endif > -static inline void seg_info_from_raw_sit(struct seg_entry *se, > - struct f2fs_sit_entry *rs) > +static inline void seg_info_from_raw_sit(struct f2fs_sb_info *sbi, > + struct seg_entry *se, > + struct f2fs_sit_entry *rs) > { > se->valid_blocks = GET_SIT_VBLOCKS(rs); > se->ckpt_valid_blocks = GET_SIT_VBLOCKS(rs); > memcpy(se->cur_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE); > memcpy(se->ckpt_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE); > #ifdef CONFIG_F2FS_CHECK_FS > - memcpy(se->cur_valid_map_mir, rs->valid_map, SIT_VBLOCK_MAP_SIZE); > + if (f2fs_sit_check_enabled(sbi)) > + memcpy(se->cur_valid_map_mir, rs->valid_map, SIT_VBLOCK_MAP_SIZE); > #endif > se->type = GET_SIT_TYPE(rs); > se->mtime = le64_to_cpu(rs->mtime); > @@ -558,11 +560,12 @@ static inline void get_sit_bitmap(struct f2fs_sb_info *sbi, > { > struct sit_info *sit_i = SIT_I(sbi); > > -#ifdef CONFIG_F2FS_CHECK_FS > - if (memcmp(sit_i->sit_bitmap, sit_i->sit_bitmap_mir, > - sit_i->bitmap_size)) > + #ifdef CONFIG_F2FS_CHECK_FS > + if (f2fs_sit_check_enabled(sbi) && > + memcmp(sit_i->sit_bitmap, sit_i->sit_bitmap_mir, > + sit_i->bitmap_size)) > f2fs_bug_on(sbi, 1); > -#endif > + #endif > memcpy(dst_addr, sit_i->sit_bitmap, sit_i->bitmap_size); > } > > @@ -904,8 +907,9 @@ static inline pgoff_t current_sit_addr(struct f2fs_sb_info *sbi, > f2fs_bug_on(sbi, !valid_main_segno(sbi, start)); > > #ifdef CONFIG_F2FS_CHECK_FS > - if (f2fs_test_bit(offset, sit_i->sit_bitmap) != > - f2fs_test_bit(offset, sit_i->sit_bitmap_mir)) > + if (f2fs_sit_check_enabled(sbi) && > + f2fs_test_bit(offset, sit_i->sit_bitmap) != > + f2fs_test_bit(offset, sit_i->sit_bitmap_mir)) > f2fs_bug_on(sbi, 1); > #endif > > @@ -929,13 +933,15 @@ static inline pgoff_t next_sit_addr(struct f2fs_sb_info *sbi, > return block_addr + sit_i->sit_base_addr; > } > > -static inline void set_to_next_sit(struct sit_info *sit_i, unsigned int start) > +static inline void set_to_next_sit(struct f2fs_sb_info *sbi, > + struct sit_info *sit_i, unsigned int start) > { > unsigned int block_off = SIT_BLOCK_OFFSET(start); > > f2fs_change_bit(block_off, sit_i->sit_bitmap); > #ifdef CONFIG_F2FS_CHECK_FS > - f2fs_change_bit(block_off, sit_i->sit_bitmap_mir); > + if (f2fs_sit_check_enabled(sbi)) > + f2fs_change_bit(block_off, sit_i->sit_bitmap_mir); > #endif > } > > diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c > index 83ce88ce12cb..e2bb5d0ab3e1 100644 > --- a/fs/f2fs/super.c > +++ b/fs/f2fs/super.c > @@ -228,6 +228,7 @@ enum { > Opt_gc_merge, > Opt_discard_unit, > Opt_memory_mode, > + Opt_shared_sit_check, > Opt_age_extent_cache, > Opt_errors, > Opt_nat_bits, > @@ -359,6 +360,7 @@ static const struct fs_parameter_spec f2fs_param_specs[] = { > fsparam_flag_no("gc_merge", Opt_gc_merge), > fsparam_enum("discard_unit", Opt_discard_unit, f2fs_param_discard_unit), > fsparam_enum("memory", Opt_memory_mode, f2fs_param_memory_mode), > + fsparam_flag_no("shared_sit_check", Opt_shared_sit_check), > fsparam_flag("age_extent_cache", Opt_age_extent_cache), > fsparam_enum("errors", Opt_errors, f2fs_param_errors), > fsparam_enum("lookup_mode", Opt_lookup_mode, f2fs_param_lookup_mode), > @@ -1217,6 +1219,12 @@ static int f2fs_parse_param(struct fs_context *fc, struct fs_parameter *param) > F2FS_CTX_INFO(ctx).memory_mode = result.uint_32; > ctx->spec_mask |= F2FS_SPEC_memory_mode; > break; > + case Opt_shared_sit_check: > + if (result.negated) > + ctx_clear_opt(ctx, F2FS_MOUNT_SHARED_SIT_CHECK); > + else > + ctx_set_opt(ctx, F2FS_MOUNT_SHARED_SIT_CHECK); > + break; > case Opt_age_extent_cache: > ctx_set_opt(ctx, F2FS_MOUNT_AGE_EXTENT_CACHE); > break; > @@ -2514,6 +2522,11 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root) > else if (F2FS_OPTION(sbi).memory_mode == MEMORY_MODE_LOW) > seq_printf(seq, ",memory=%s", "low"); > > + if (test_opt(sbi, SHARED_SIT_CHECK)) > + seq_puts(seq, ",shared_sit_check"); > + else > + seq_puts(seq, ",noshared_sit_check"); > + > if (F2FS_OPTION(sbi).errors == MOUNT_ERRORS_READONLY) > seq_printf(seq, ",errors=%s", "remount-ro"); > else if (F2FS_OPTION(sbi).errors == MOUNT_ERRORS_CONTINUE) > @@ -2573,6 +2586,7 @@ static void default_options(struct f2fs_sb_info *sbi, bool remount) > F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_ON; > F2FS_OPTION(sbi).memory_mode = MEMORY_MODE_NORMAL; > F2FS_OPTION(sbi).errors = MOUNT_ERRORS_CONTINUE; > + set_opt(sbi, SHARED_SIT_CHECK); > > set_opt(sbi, INLINE_XATTR); > set_opt(sbi, INLINE_DATA); > @@ -2782,6 +2796,7 @@ static int __f2fs_remount(struct fs_context *fc, struct super_block *sb) > bool no_compress_cache = !test_opt(sbi, COMPRESS_CACHE); > bool block_unit_discard = f2fs_block_unit_discard(sbi); > bool no_nat_bits = !test_opt(sbi, NAT_BITS); > + bool shared_sit_check = test_opt(sbi, SHARED_SIT_CHECK); > #ifdef CONFIG_QUOTA > int i, j; > #endif > @@ -2904,6 +2919,12 @@ static int __f2fs_remount(struct fs_context *fc, struct super_block *sb) > goto restore_opts; > } > > + if (shared_sit_check != !!test_opt(sbi, SHARED_SIT_CHECK)) { > + err = -EINVAL; > + f2fs_warn(sbi, "switch shared_sit_check option is not allowed"); > + goto restore_opts; > + } > + > if ((flags & SB_RDONLY) && test_opt(sbi, DISABLE_CHECKPOINT)) { > err = -EINVAL; > f2fs_warn(sbi, "disabling checkpoint not compatible with read-only");