fs/f2fs/gc.c

Source file repositories/reference/linux-study-clean/fs/f2fs/gc.c

File Facts

System
Linux kernel
Corpus path
fs/f2fs/gc.c
Extension
.c
Size
62258 bytes
Lines
2427
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

if (test_opt(sbi, GC_MERGE) && waitqueue_active(fggc_wq)) {
			foreground = true;
			gc_control.one_time = false;
		} else if (f2fs_sb_has_blkzoned(sbi)) {
			gc_control.one_time = true;
		}

		/* give it a try one time */
		if (gc_th->gc_wake)
			gc_th->gc_wake = false;

		if (f2fs_readonly(sbi->sb)) {
			stat_other_skip_bggc_count(sbi);
			continue;
		}
		if (kthread_should_stop())
			break;

		if (sbi->sb->s_writers.frozen >= SB_FREEZE_WRITE) {
			increase_sleep_time(gc_th, &wait_ms);
			stat_other_skip_bggc_count(sbi);
			continue;
		}

		if (time_to_inject(sbi, FAULT_CHECKPOINT))
			f2fs_stop_checkpoint(sbi, false,
					STOP_CP_REASON_FAULT_INJECT);

		if (!sb_start_write_trylock(sbi->sb)) {
			stat_other_skip_bggc_count(sbi);
			continue;
		}

		/*
		 * [GC triggering condition]
		 * 0. GC is not conducted currently.
		 * 1. There are enough dirty segments.
		 * 2. IO subsystem is idle by checking the # of writeback pages.
		 * 3. IO subsystem is idle by checking the # of requests in
		 *    bdev's request list.
		 *
		 * Note) We have to avoid triggering GCs frequently.
		 * Because it is possible that some segments can be
		 * invalidated soon after by user update or deletion.
		 * So, I'd like to wait some time to collect dirty segments.
		 */
		if (sbi->gc_mode == GC_URGENT_HIGH ||
				sbi->gc_mode == GC_URGENT_MID) {
			wait_ms = gc_th->urgent_sleep_time;
			f2fs_down_write_trace(&sbi->gc_lock, &gc_control.lc);
			goto do_gc;
		}

		if (foreground) {
			f2fs_down_write_trace(&sbi->gc_lock, &gc_control.lc);
			goto do_gc;
		} else if (!f2fs_down_write_trylock_trace(&sbi->gc_lock,
							&gc_control.lc)) {
			stat_other_skip_bggc_count(sbi);
			goto next;
		}

		if (!is_idle(sbi, GC_TIME)) {
			increase_sleep_time(gc_th, &wait_ms);
			f2fs_up_write_trace(&sbi->gc_lock, &gc_control.lc);
			stat_io_skip_bggc_count(sbi);
			goto next;
		}

		if (f2fs_sb_has_blkzoned(sbi)) {
			if (has_enough_free_blocks(sbi,
				gc_th->no_zoned_gc_percent)) {
				wait_ms = gc_th->no_gc_sleep_time;
				f2fs_up_write_trace(&sbi->gc_lock,
							&gc_control.lc);
				goto next;
			}
			if (wait_ms == gc_th->no_gc_sleep_time)
				wait_ms = gc_th->max_sleep_time;
		}

		if (need_to_boost_gc(sbi)) {
			decrease_sleep_time(gc_th, &wait_ms);
			if (f2fs_sb_has_blkzoned(sbi))
				gc_boost = true;
		} else {
			increase_sleep_time(gc_th, &wait_ms);
		}
do_gc:
		stat_inc_gc_call_count(sbi, foreground ?

Annotation

Implementation Notes