Commit d0b9e42a authored by Chao Yu's avatar Chao Yu Committed by Jaegeuk Kim
Browse files

f2fs: introduce inmem curseg



Previous implementation of aligned pinfile allocation will:
- allocate new segment on cold data log no matter whether last used
segment is partially used or not, it makes IOs more random;
- force concurrent cold data/GCed IO going into warm data area, it
can make a bad effect on hot/cold data separation;

In this patch, we introduce a new type of log named 'inmem curseg',
the differents from normal curseg is:
- it reuses existed segment type (CURSEG_XXX_NODE/DATA);
- it only exists in memory, its segno, blkofs, summary will not b
 persisted into checkpoint area;

With this new feature, we can enhance scalability of log, special
allocators can be created for purposes:
- pure lfs allocator for aligned pinfile allocation or file
defragmentation
- pure ssr allocator for later feature

So that, let's update aligned pinfile allocation to use this new
inmem curseg fwk.

Signed-off-by: default avatarChao Yu <yuchao0@huawei.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 376207af
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -1619,11 +1619,16 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)

	f2fs_flush_sit_entries(sbi, cpc);

	/* save inmem log status */
	f2fs_save_inmem_curseg(sbi, CURSEG_COLD_DATA_PINNED);

	err = do_checkpoint(sbi, cpc);
	if (err)
		f2fs_release_discard_addrs(sbi);
	else
		f2fs_clear_prefree_segments(sbi, cpc);

	f2fs_restore_inmem_curseg(sbi, CURSEG_COLD_DATA_PINNED);
stop:
	unblock_operations(sbi);
	stat_inc_cp_count(sbi->stat_info);
@@ -1654,7 +1659,7 @@ void f2fs_init_ino_entry_info(struct f2fs_sb_info *sbi)
	}

	sbi->max_orphans = (sbi->blocks_per_seg - F2FS_CP_PACKS -
			NR_CURSEG_TYPE - __cp_payload(sbi)) *
			NR_CURSEG_PERSIST_TYPE - __cp_payload(sbi)) *
				F2FS_ORPHANS_PER_BLOCK;
}

+5 −1
Original line number Diff line number Diff line
@@ -164,7 +164,7 @@ static void update_general_status(struct f2fs_sb_info *sbi)
		* 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
		/ 2;
	si->util_invalid = 50 - si->util_free - si->util_valid;
	for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_NODE; i++) {
	for (i = CURSEG_HOT_DATA; i < NO_CHECK_TYPE; i++) {
		struct curseg_info *curseg = CURSEG_I(sbi, i);
		si->curseg[i] = curseg->segno;
		si->cursec[i] = GET_SEC_FROM_SEG(sbi, curseg->segno);
@@ -393,6 +393,10 @@ static int stat_show(struct seq_file *s, void *v)
			   si->dirty_seg[CURSEG_COLD_NODE],
			   si->full_seg[CURSEG_COLD_NODE],
			   si->valid_blks[CURSEG_COLD_NODE]);
		seq_printf(s, "  - Pinned file: %8d %8d %8d\n",
			   si->curseg[CURSEG_COLD_DATA_PINNED],
			   si->cursec[CURSEG_COLD_DATA_PINNED],
			   si->curzone[CURSEG_COLD_DATA_PINNED]);
		seq_printf(s, "\n  - Valid: %d\n  - Dirty: %d\n",
			   si->main_area_segs - si->dirty_count -
			   si->prefree_count - si->free_segs,
+9 −3
Original line number Diff line number Diff line
@@ -973,7 +973,9 @@ static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
 */
#define	NR_CURSEG_DATA_TYPE	(3)
#define NR_CURSEG_NODE_TYPE	(3)
#define NR_CURSEG_TYPE	(NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
#define NR_CURSEG_INMEM_TYPE	(1)
#define NR_CURSEG_PERSIST_TYPE	(NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
#define NR_CURSEG_TYPE		(NR_CURSEG_INMEM_TYPE + NR_CURSEG_PERSIST_TYPE)

enum {
	CURSEG_HOT_DATA	= 0,	/* directory entry blocks */
@@ -982,8 +984,10 @@ enum {
	CURSEG_HOT_NODE,	/* direct node blocks of directory files */
	CURSEG_WARM_NODE,	/* direct node blocks of normal files */
	CURSEG_COLD_NODE,	/* indirect node blocks */
	NO_CHECK_TYPE,
	CURSEG_COLD_DATA_PINNED,/* cold data for pinned file */
	NR_PERSISTENT_LOG,	/* number of persistent log */
	CURSEG_COLD_DATA_PINNED = NR_PERSISTENT_LOG,
				/* pinned file that needs consecutive block address */
	NO_CHECK_TYPE,		/* number of persistent & inmem log */
};

struct flush_cmd {
@@ -3333,6 +3337,8 @@ block_t f2fs_get_unusable_blocks(struct f2fs_sb_info *sbi);
int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, block_t unusable);
void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi);
int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra);
void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi, int type);
void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi, int type);
void f2fs_allocate_segment_for_resize(struct f2fs_sb_info *sbi, int type,
					unsigned int start, unsigned int end);
void f2fs_allocate_new_segment(struct f2fs_sb_info *sbi, int type);
+3 −2
Original line number Diff line number Diff line
@@ -1656,13 +1656,14 @@ next_alloc:
		}

		down_write(&sbi->pin_sem);
		map.m_seg_type = CURSEG_COLD_DATA_PINNED;

		f2fs_lock_op(sbi);
		f2fs_allocate_new_segment(sbi, CURSEG_COLD_DATA);
		f2fs_allocate_new_segment(sbi, CURSEG_COLD_DATA_PINNED);
		f2fs_unlock_op(sbi);

		map.m_seg_type = CURSEG_COLD_DATA_PINNED;
		err = f2fs_map_blocks(inode, &map, 1, F2FS_GET_BLOCK_PRE_DIO);

		up_write(&sbi->pin_sem);

		done += map.m_len;
+1 −1
Original line number Diff line number Diff line
@@ -1463,7 +1463,7 @@ static int free_segment_range(struct f2fs_sb_info *sbi,
	mutex_unlock(&DIRTY_I(sbi)->seglist_lock);

	/* Move out cursegs from the target range */
	for (type = CURSEG_HOT_DATA; type < NR_CURSEG_TYPE; type++)
	for (type = CURSEG_HOT_DATA; type < NR_CURSEG_PERSIST_TYPE; type++)
		f2fs_allocate_segment_for_resize(sbi, type, start, end);

	/* do GC to move out valid blocks in the range */
Loading