Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 408e9375 authored by Jaegeuk Kim's avatar Jaegeuk Kim
Browse files

f2fs: revisit the f2fs_gc flow



I'd like to revisit the f2fs_gc flow and rewrite as follows.

1. In practical, the nGC parameter of f2fs_gc is meaningless. So, let's
  remove it.
2. Background GC marks victim blocks as dirty one at a time.
3. Foreground GC should do cleaning job until acquiring enough free
  sections. Afterwards, it needs to do checkpoint.

Signed-off-by: default avatarJaegeuk Kim <jaegeuk.kim@samsung.com>
parent c335a869
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -986,7 +986,7 @@ int do_write_data_page(struct page *);
int start_gc_thread(struct f2fs_sb_info *);
void stop_gc_thread(struct f2fs_sb_info *);
block_t start_bidx_of_node(unsigned int);
int f2fs_gc(struct f2fs_sb_info *, int);
int f2fs_gc(struct f2fs_sb_info *);
void build_gc_manager(struct f2fs_sb_info *);
int create_gc_caches(void);
void destroy_gc_caches(void);
+21 −39
Original line number Diff line number Diff line
@@ -78,7 +78,7 @@ static int gc_thread_func(void *data)

		sbi->bg_gc++;

		if (f2fs_gc(sbi, 1) == GC_NONE)
		if (f2fs_gc(sbi) == GC_NONE)
			wait_ms = GC_THREAD_NOGC_SLEEP_TIME;
		else if (wait_ms == GC_THREAD_NOGC_SLEEP_TIME)
			wait_ms = GC_THREAD_MAX_SLEEP_TIME;
@@ -651,37 +651,23 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, unsigned int segno,
	return ret;
}

int f2fs_gc(struct f2fs_sb_info *sbi, int nGC)
int f2fs_gc(struct f2fs_sb_info *sbi)
{
	unsigned int segno;
	int old_free_secs, cur_free_secs;
	int gc_status, nfree;
	struct list_head ilist;
	unsigned int segno, i;
	int gc_type = BG_GC;
	int gc_status = GC_NONE;

	INIT_LIST_HEAD(&ilist);
gc_more:
	nfree = 0;
	gc_status = GC_NONE;
	if (!(sbi->sb->s_flags & MS_ACTIVE))
		goto stop;

	if (has_not_enough_free_secs(sbi))
		old_free_secs = reserved_sections(sbi);
	else
		old_free_secs = free_sections(sbi);

	while (sbi->sb->s_flags & MS_ACTIVE) {
		int i;
	if (has_not_enough_free_secs(sbi))
		gc_type = FG_GC;

		cur_free_secs = free_sections(sbi) + nfree;

		/* We got free space successfully. */
		if (nGC < cur_free_secs - old_free_secs)
			break;

	if (!__get_victim(sbi, &segno, gc_type, NO_CHECK_TYPE))
			break;
		goto stop;

	for (i = 0; i < sbi->segs_per_sec; i++) {
		/*
@@ -690,23 +676,19 @@ int f2fs_gc(struct f2fs_sb_info *sbi, int nGC)
		 * If GC is finished uncleanly, we have to return
		 * the victim to dirty segment list.
		 */
			gc_status = do_garbage_collect(sbi, segno + i,
					&ilist, gc_type);
		gc_status = do_garbage_collect(sbi, segno + i, &ilist, gc_type);
		if (gc_status != GC_DONE)
				goto stop;
			nfree++;
		}
			break;
	}
stop:
	if (has_not_enough_free_secs(sbi) || gc_status == GC_BLOCKED) {
	if (has_not_enough_free_secs(sbi)) {
		write_checkpoint(sbi, (gc_status == GC_BLOCKED), false);
		if (nfree)
		if (has_not_enough_free_secs(sbi))
			goto gc_more;
	}
stop:
	mutex_unlock(&sbi->gc_mutex);

	put_gc_inode(&ilist);
	BUG_ON(!list_empty(&ilist));
	return gc_status;
}

+1 −1
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@ void f2fs_balance_fs(struct f2fs_sb_info *sbi)
	 */
	if (has_not_enough_free_secs(sbi)) {
		mutex_lock(&sbi->gc_mutex);
		f2fs_gc(sbi, 1);
		f2fs_gc(sbi);
	}
}