Commit 7ee8bc39 authored by Daeho Jeong's avatar Daeho Jeong Committed by Jaegeuk Kim
Browse files

f2fs: revert summary entry count from 2048 to 512 in 16kb block support



The recent increase in the number of Segment Summary Area (SSA) entries
from 512 to 2048 was an unintentional change in logic of 16kb block
support. This commit corrects the issue.

To better utilize the space available from the erroneous 2048-entry
calculation, we are implementing a solution to share the currently
unused SSA space with neighboring segments. This enhances overall
SSA utilization without impacting the established 8MB segment size.

Fixes: d7e9a903 ("f2fs: Support Block Size == Page Size")
Signed-off-by: default avatarDaeho Jeong <daehojeong@google.com>
Reviewed-by: default avatarChao Yu <chao@kernel.org>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 68d05693
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -245,6 +245,7 @@ struct f2fs_mount_info {
#define F2FS_FEATURE_COMPRESSION		0x00002000
#define F2FS_FEATURE_RO				0x00004000
#define F2FS_FEATURE_DEVICE_ALIAS		0x00008000
#define F2FS_FEATURE_PACKED_SSA			0x00010000

#define __F2FS_HAS_FEATURE(raw_super, mask)				\
	((raw_super->feature & cpu_to_le32(mask)) != 0)
@@ -4704,6 +4705,7 @@ F2FS_FEATURE_FUNCS(casefold, CASEFOLD);
F2FS_FEATURE_FUNCS(compression, COMPRESSION);
F2FS_FEATURE_FUNCS(readonly, RO);
F2FS_FEATURE_FUNCS(device_alias, DEVICE_ALIAS);
F2FS_FEATURE_FUNCS(packed_ssa, PACKED_SSA);

#ifdef CONFIG_BLK_DEV_ZONED
static inline bool f2fs_zone_is_seq(struct f2fs_sb_info *sbi, int devi,
+69 −48
Original line number Diff line number Diff line
@@ -1735,7 +1735,7 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
	unsigned char type = IS_DATASEG(get_seg_entry(sbi, segno)->type) ?
						SUM_TYPE_DATA : SUM_TYPE_NODE;
	unsigned char data_type = (type == SUM_TYPE_DATA) ? DATA : NODE;
	int submitted = 0;
	int submitted = 0, sum_blk_cnt;

	if (__is_large_section(sbi)) {
		sec_end_segno = rounddown(end_segno, SEGS_PER_SEC(sbi));
@@ -1769,22 +1769,28 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,

	sanity_check_seg_type(sbi, get_seg_entry(sbi, segno)->type);

	segno = rounddown(segno, SUMS_PER_BLOCK);
	sum_blk_cnt = DIV_ROUND_UP(end_segno - segno, SUMS_PER_BLOCK);
	/* readahead multi ssa blocks those have contiguous address */
	if (__is_large_section(sbi))
		f2fs_ra_meta_pages(sbi, GET_SUM_BLOCK(sbi, segno),
					end_segno - segno, META_SSA, true);
					sum_blk_cnt, META_SSA, true);

	/* reference all summary page */
	while (segno < end_segno) {
		struct folio *sum_folio = f2fs_get_sum_folio(sbi, segno++);
		struct folio *sum_folio = f2fs_get_sum_folio(sbi, segno);

		segno += SUMS_PER_BLOCK;
		if (IS_ERR(sum_folio)) {
			int err = PTR_ERR(sum_folio);

			end_segno = segno - 1;
			for (segno = start_segno; segno < end_segno; segno++) {
			end_segno = segno - SUMS_PER_BLOCK;
			segno = rounddown(start_segno, SUMS_PER_BLOCK);
			while (segno < end_segno) {
				sum_folio = filemap_get_folio(META_MAPPING(sbi),
						GET_SUM_BLOCK(sbi, segno));
				folio_put_refs(sum_folio, 2);
				segno += SUMS_PER_BLOCK;
			}
			return err;
		}
@@ -1793,36 +1799,49 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,

	blk_start_plug(&plug);

	for (segno = start_segno; segno < end_segno; segno++) {
		struct f2fs_summary_block *sum;
	segno = start_segno;
	while (segno < end_segno) {
		unsigned int cur_segno;

		/* find segment summary of victim */
		struct folio *sum_folio = filemap_get_folio(META_MAPPING(sbi),
					GET_SUM_BLOCK(sbi, segno));
		unsigned int block_end_segno = rounddown(segno, SUMS_PER_BLOCK)
					+ SUMS_PER_BLOCK;

		if (block_end_segno > end_segno)
			block_end_segno = end_segno;

		if (is_cursec(sbi, GET_SEC_FROM_SEG(sbi, segno))) {
			f2fs_err(sbi, "%s: segment %u is used by log",
							__func__, segno);
			f2fs_bug_on(sbi, 1);
			goto skip;
			goto next_block;
		}

		if (get_valid_blocks(sbi, segno, false) == 0)
		if (!folio_test_uptodate(sum_folio) ||
		    unlikely(f2fs_cp_error(sbi)))
			goto next_block;

		for (cur_segno = segno; cur_segno < block_end_segno;
				cur_segno++) {
			struct f2fs_summary_block *sum;

			if (get_valid_blocks(sbi, cur_segno, false) == 0)
				goto freed;
			if (gc_type == BG_GC && __is_large_section(sbi) &&
					migrated >= sbi->migration_granularity)
			goto skip;
		if (!folio_test_uptodate(sum_folio) ||
		    unlikely(f2fs_cp_error(sbi)))
			goto skip;
				continue;

		sum = folio_address(sum_folio);
			sum = SUM_BLK_PAGE_ADDR(sum_folio, cur_segno);
			if (type != GET_SUM_TYPE((&sum->footer))) {
			f2fs_err(sbi, "Inconsistent segment (%u) type [%d, %d] in SIT and SSA",
				 segno, type, GET_SUM_TYPE((&sum->footer)));
				f2fs_err(sbi, "Inconsistent segment (%u) type "
						"[%d, %d] in SSA and SIT",
						cur_segno, type,
						GET_SUM_TYPE((&sum->footer)));
				f2fs_stop_checkpoint(sbi, false,
						STOP_CP_REASON_CORRUPTED_SUMMARY);
			goto skip;
				continue;
			}

			/*
@@ -1833,12 +1852,12 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
			 *                               - lock_page(sum_page)
			 */
			if (type == SUM_TYPE_NODE)
			submitted += gc_node_segment(sbi, sum->entries, segno,
								gc_type);
				submitted += gc_node_segment(sbi, sum->entries,
						cur_segno, gc_type);
			else
			submitted += gc_data_segment(sbi, sum->entries, gc_list,
							segno, gc_type,
							force_migrate);
				submitted += gc_data_segment(sbi, sum->entries,
						gc_list, cur_segno,
						gc_type, force_migrate);

			stat_inc_gc_seg_count(sbi, data_type, gc_type);
			sbi->gc_reclaimed_segs[sbi->gc_mode]++;
@@ -1846,15 +1865,17 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,

freed:
			if (gc_type == FG_GC &&
				get_valid_blocks(sbi, segno, false) == 0)
					get_valid_blocks(sbi, cur_segno, false) == 0)
				seg_freed++;

			if (__is_large_section(sbi))
				sbi->next_victim_seg[gc_type] =
				(segno + 1 < sec_end_segno) ?
					segno + 1 : NULL_SEGNO;
skip:
					(cur_segno + 1 < sec_end_segno) ?
					cur_segno + 1 : NULL_SEGNO;
		}
next_block:
		folio_put_refs(sum_folio, 2);
		segno = block_end_segno;
	}

	if (submitted)
+1 −1
Original line number Diff line number Diff line
@@ -522,7 +522,7 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
	sum_folio = f2fs_get_sum_folio(sbi, segno);
	if (IS_ERR(sum_folio))
		return PTR_ERR(sum_folio);
	sum_node = folio_address(sum_folio);
	sum_node = SUM_BLK_PAGE_ADDR(sum_folio, segno);
	sum = sum_node->entries[blkoff];
	f2fs_folio_put(sum_folio, true);
got_it:
+28 −10
Original line number Diff line number Diff line
@@ -2712,7 +2712,15 @@ struct folio *f2fs_get_sum_folio(struct f2fs_sb_info *sbi, unsigned int segno)
void f2fs_update_meta_page(struct f2fs_sb_info *sbi,
					void *src, block_t blk_addr)
{
	struct folio *folio = f2fs_grab_meta_folio(sbi, blk_addr);
	struct folio *folio;

	if (SUMS_PER_BLOCK == 1)
		folio = f2fs_grab_meta_folio(sbi, blk_addr);
	else
		folio = f2fs_get_meta_folio_retry(sbi, blk_addr);

	if (IS_ERR(folio))
		return;

	memcpy(folio_address(folio), src, PAGE_SIZE);
	folio_mark_dirty(folio);
@@ -2720,9 +2728,21 @@ void f2fs_update_meta_page(struct f2fs_sb_info *sbi,
}

static void write_sum_page(struct f2fs_sb_info *sbi,
			struct f2fs_summary_block *sum_blk, block_t blk_addr)
		struct f2fs_summary_block *sum_blk, unsigned int segno)
{
	f2fs_update_meta_page(sbi, (void *)sum_blk, blk_addr);
	struct folio *folio;

	if (SUMS_PER_BLOCK == 1)
		return f2fs_update_meta_page(sbi, (void *)sum_blk,
				GET_SUM_BLOCK(sbi, segno));

	folio = f2fs_get_sum_folio(sbi, segno);
	if (IS_ERR(folio))
		return;

	memcpy(SUM_BLK_PAGE_ADDR(folio, segno), sum_blk, sizeof(*sum_blk));
	folio_mark_dirty(folio);
	f2fs_folio_put(folio, true);
}

static void write_current_sum_page(struct f2fs_sb_info *sbi,
@@ -2987,7 +3007,7 @@ static int new_curseg(struct f2fs_sb_info *sbi, int type, bool new_sec)
	int ret;

	if (curseg->inited)
		write_sum_page(sbi, curseg->sum_blk, GET_SUM_BLOCK(sbi, segno));
		write_sum_page(sbi, curseg->sum_blk, segno);

	segno = __get_next_segno(sbi, type);
	ret = get_new_segment(sbi, &segno, new_sec, pinning);
@@ -3046,7 +3066,7 @@ static int change_curseg(struct f2fs_sb_info *sbi, int type)
	struct folio *sum_folio;

	if (curseg->inited)
		write_sum_page(sbi, curseg->sum_blk, GET_SUM_BLOCK(sbi, curseg->segno));
		write_sum_page(sbi, curseg->sum_blk, curseg->segno);

	__set_test_and_inuse(sbi, new_segno);

@@ -3065,7 +3085,7 @@ static int change_curseg(struct f2fs_sb_info *sbi, int type)
		memset(curseg->sum_blk, 0, SUM_ENTRY_SIZE);
		return PTR_ERR(sum_folio);
	}
	sum_node = folio_address(sum_folio);
	sum_node = SUM_BLK_PAGE_ADDR(sum_folio, new_segno);
	memcpy(curseg->sum_blk, sum_node, SUM_ENTRY_SIZE);
	f2fs_folio_put(sum_folio, true);
	return 0;
@@ -3154,8 +3174,7 @@ static void __f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi, int type)
		goto out;

	if (get_valid_blocks(sbi, curseg->segno, false)) {
		write_sum_page(sbi, curseg->sum_blk,
				GET_SUM_BLOCK(sbi, curseg->segno));
		write_sum_page(sbi, curseg->sum_blk, curseg->segno);
	} else {
		mutex_lock(&DIRTY_I(sbi)->seglist_lock);
		__set_test_and_free(sbi, curseg->segno, true);
@@ -3833,8 +3852,7 @@ int f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct folio *folio,
	if (segment_full) {
		if (type == CURSEG_COLD_DATA_PINNED &&
		    !((curseg->segno + 1) % sbi->segs_per_sec)) {
			write_sum_page(sbi, curseg->sum_blk,
					GET_SUM_BLOCK(sbi, curseg->segno));
			write_sum_page(sbi, curseg->sum_blk, curseg->segno);
			reset_curseg_fields(curseg);
			goto skip_new_segment;
		}
+6 −2
Original line number Diff line number Diff line
@@ -85,8 +85,12 @@ static inline void sanity_check_seg_type(struct f2fs_sb_info *sbi,
#define GET_ZONE_FROM_SEG(sbi, segno)				\
	GET_ZONE_FROM_SEC(sbi, GET_SEC_FROM_SEG(sbi, segno))

#define SUMS_PER_BLOCK (F2FS_BLKSIZE / F2FS_SUM_BLKSIZE)
#define GET_SUM_BLOCK(sbi, segno)	\
	((sbi)->sm_info->ssa_blkaddr + (segno))
	(SM_I(sbi)->ssa_blkaddr + (segno / SUMS_PER_BLOCK))
#define GET_SUM_BLKOFF(segno) (segno % SUMS_PER_BLOCK)
#define SUM_BLK_PAGE_ADDR(folio, segno)	\
	(folio_address(folio) + GET_SUM_BLKOFF(segno) * F2FS_SUM_BLKSIZE)

#define GET_SUM_TYPE(footer) ((footer)->entry_type)
#define SET_SUM_TYPE(footer, type) ((footer)->entry_type = (type))
Loading