18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * fs/f2fs/gc.c
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2012 Samsung Electronics Co., Ltd.
68c2ecf20Sopenharmony_ci *             http://www.samsung.com/
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci#include <linux/fs.h>
98c2ecf20Sopenharmony_ci#include <linux/module.h>
108c2ecf20Sopenharmony_ci#include <linux/mount.h>
118c2ecf20Sopenharmony_ci#include <linux/backing-dev.h>
128c2ecf20Sopenharmony_ci#include <linux/init.h>
138c2ecf20Sopenharmony_ci#include <linux/f2fs_fs.h>
148c2ecf20Sopenharmony_ci#include <linux/kthread.h>
158c2ecf20Sopenharmony_ci#include <linux/delay.h>
168c2ecf20Sopenharmony_ci#include <linux/freezer.h>
178c2ecf20Sopenharmony_ci#include <linux/sched/signal.h>
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#include "f2fs.h"
208c2ecf20Sopenharmony_ci#include "node.h"
218c2ecf20Sopenharmony_ci#include "segment.h"
228c2ecf20Sopenharmony_ci#include "gc.h"
238c2ecf20Sopenharmony_ci#include <trace/events/f2fs.h>
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_cistatic struct kmem_cache *victim_entry_slab;
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_cistatic unsigned int count_bits(const unsigned long *addr,
288c2ecf20Sopenharmony_ci				unsigned int offset, unsigned int len);
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_cistatic int gc_thread_func(void *data)
318c2ecf20Sopenharmony_ci{
328c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = data;
338c2ecf20Sopenharmony_ci	struct f2fs_gc_kthread *gc_th = sbi->gc_thread;
348c2ecf20Sopenharmony_ci	wait_queue_head_t *wq = &sbi->gc_thread->gc_wait_queue_head;
358c2ecf20Sopenharmony_ci	wait_queue_head_t *fggc_wq = &sbi->gc_thread->fggc_wq;
368c2ecf20Sopenharmony_ci	unsigned int wait_ms;
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	wait_ms = gc_th->min_sleep_time;
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	set_freezable();
418c2ecf20Sopenharmony_ci	do {
428c2ecf20Sopenharmony_ci		bool sync_mode, foreground = false;
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci		wait_event_interruptible_timeout(*wq,
458c2ecf20Sopenharmony_ci				kthread_should_stop() || freezing(current) ||
468c2ecf20Sopenharmony_ci				waitqueue_active(fggc_wq) ||
478c2ecf20Sopenharmony_ci				gc_th->gc_wake,
488c2ecf20Sopenharmony_ci				msecs_to_jiffies(wait_ms));
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci		if (test_opt(sbi, GC_MERGE) && waitqueue_active(fggc_wq))
518c2ecf20Sopenharmony_ci			foreground = true;
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci		/* give it a try one time */
548c2ecf20Sopenharmony_ci		if (gc_th->gc_wake)
558c2ecf20Sopenharmony_ci			gc_th->gc_wake = 0;
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci		if (try_to_freeze()) {
588c2ecf20Sopenharmony_ci			stat_other_skip_bggc_count(sbi);
598c2ecf20Sopenharmony_ci			continue;
608c2ecf20Sopenharmony_ci		}
618c2ecf20Sopenharmony_ci		if (kthread_should_stop())
628c2ecf20Sopenharmony_ci			break;
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci		if (sbi->sb->s_writers.frozen >= SB_FREEZE_WRITE) {
658c2ecf20Sopenharmony_ci			increase_sleep_time(gc_th, &wait_ms);
668c2ecf20Sopenharmony_ci			stat_other_skip_bggc_count(sbi);
678c2ecf20Sopenharmony_ci			continue;
688c2ecf20Sopenharmony_ci		}
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci		if (time_to_inject(sbi, FAULT_CHECKPOINT)) {
718c2ecf20Sopenharmony_ci			f2fs_show_injection_info(sbi, FAULT_CHECKPOINT);
728c2ecf20Sopenharmony_ci			f2fs_stop_checkpoint(sbi, false);
738c2ecf20Sopenharmony_ci		}
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci		if (!sb_start_write_trylock(sbi->sb)) {
768c2ecf20Sopenharmony_ci			stat_other_skip_bggc_count(sbi);
778c2ecf20Sopenharmony_ci			continue;
788c2ecf20Sopenharmony_ci		}
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci		/*
818c2ecf20Sopenharmony_ci		 * [GC triggering condition]
828c2ecf20Sopenharmony_ci		 * 0. GC is not conducted currently.
838c2ecf20Sopenharmony_ci		 * 1. There are enough dirty segments.
848c2ecf20Sopenharmony_ci		 * 2. IO subsystem is idle by checking the # of writeback pages.
858c2ecf20Sopenharmony_ci		 * 3. IO subsystem is idle by checking the # of requests in
868c2ecf20Sopenharmony_ci		 *    bdev's request list.
878c2ecf20Sopenharmony_ci		 *
888c2ecf20Sopenharmony_ci		 * Note) We have to avoid triggering GCs frequently.
898c2ecf20Sopenharmony_ci		 * Because it is possible that some segments can be
908c2ecf20Sopenharmony_ci		 * invalidated soon after by user update or deletion.
918c2ecf20Sopenharmony_ci		 * So, I'd like to wait some time to collect dirty segments.
928c2ecf20Sopenharmony_ci		 */
938c2ecf20Sopenharmony_ci		if (sbi->gc_mode == GC_URGENT_HIGH) {
948c2ecf20Sopenharmony_ci			wait_ms = gc_th->urgent_sleep_time;
958c2ecf20Sopenharmony_ci			down_write(&sbi->gc_lock);
968c2ecf20Sopenharmony_ci			goto do_gc;
978c2ecf20Sopenharmony_ci		}
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci		if (foreground) {
1008c2ecf20Sopenharmony_ci			down_write(&sbi->gc_lock);
1018c2ecf20Sopenharmony_ci			goto do_gc;
1028c2ecf20Sopenharmony_ci		} else if (!down_write_trylock(&sbi->gc_lock)) {
1038c2ecf20Sopenharmony_ci			stat_other_skip_bggc_count(sbi);
1048c2ecf20Sopenharmony_ci			goto next;
1058c2ecf20Sopenharmony_ci		}
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci		if (!is_idle(sbi, GC_TIME)) {
1088c2ecf20Sopenharmony_ci			increase_sleep_time(gc_th, &wait_ms);
1098c2ecf20Sopenharmony_ci			up_write(&sbi->gc_lock);
1108c2ecf20Sopenharmony_ci			stat_io_skip_bggc_count(sbi);
1118c2ecf20Sopenharmony_ci			goto next;
1128c2ecf20Sopenharmony_ci		}
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci		if (has_enough_invalid_blocks(sbi))
1158c2ecf20Sopenharmony_ci			decrease_sleep_time(gc_th, &wait_ms);
1168c2ecf20Sopenharmony_ci		else
1178c2ecf20Sopenharmony_ci			increase_sleep_time(gc_th, &wait_ms);
1188c2ecf20Sopenharmony_cido_gc:
1198c2ecf20Sopenharmony_ci		if (!foreground)
1208c2ecf20Sopenharmony_ci			stat_inc_bggc_count(sbi->stat_info);
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci		sync_mode = F2FS_OPTION(sbi).bggc_mode == BGGC_MODE_SYNC;
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci		/* foreground GC was been triggered via f2fs_balance_fs() */
1258c2ecf20Sopenharmony_ci		if (foreground)
1268c2ecf20Sopenharmony_ci			sync_mode = false;
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci		/* if return value is not zero, no victim was selected */
1298c2ecf20Sopenharmony_ci		if (f2fs_gc(sbi, sync_mode, !foreground, false, NULL_SEGNO))
1308c2ecf20Sopenharmony_ci			wait_ms = gc_th->no_gc_sleep_time;
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci		if (foreground)
1338c2ecf20Sopenharmony_ci			wake_up_all(&gc_th->fggc_wq);
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci		trace_f2fs_background_gc(sbi->sb, wait_ms,
1368c2ecf20Sopenharmony_ci				prefree_segments(sbi), free_segments(sbi));
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci		/* balancing f2fs's metadata periodically */
1398c2ecf20Sopenharmony_ci		f2fs_balance_fs_bg(sbi, true);
1408c2ecf20Sopenharmony_cinext:
1418c2ecf20Sopenharmony_ci		sb_end_write(sbi->sb);
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	} while (!kthread_should_stop());
1448c2ecf20Sopenharmony_ci	return 0;
1458c2ecf20Sopenharmony_ci}
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ciint f2fs_start_gc_thread(struct f2fs_sb_info *sbi)
1488c2ecf20Sopenharmony_ci{
1498c2ecf20Sopenharmony_ci	struct f2fs_gc_kthread *gc_th;
1508c2ecf20Sopenharmony_ci	dev_t dev = sbi->sb->s_bdev->bd_dev;
1518c2ecf20Sopenharmony_ci	int err = 0;
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci	gc_th = f2fs_kmalloc(sbi, sizeof(struct f2fs_gc_kthread), GFP_KERNEL);
1548c2ecf20Sopenharmony_ci	if (!gc_th) {
1558c2ecf20Sopenharmony_ci		err = -ENOMEM;
1568c2ecf20Sopenharmony_ci		goto out;
1578c2ecf20Sopenharmony_ci	}
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci	gc_th->urgent_sleep_time = DEF_GC_THREAD_URGENT_SLEEP_TIME;
1608c2ecf20Sopenharmony_ci	gc_th->min_sleep_time = DEF_GC_THREAD_MIN_SLEEP_TIME;
1618c2ecf20Sopenharmony_ci	gc_th->max_sleep_time = DEF_GC_THREAD_MAX_SLEEP_TIME;
1628c2ecf20Sopenharmony_ci	gc_th->no_gc_sleep_time = DEF_GC_THREAD_NOGC_SLEEP_TIME;
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci	gc_th->gc_wake= 0;
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	sbi->gc_thread = gc_th;
1678c2ecf20Sopenharmony_ci	init_waitqueue_head(&sbi->gc_thread->gc_wait_queue_head);
1688c2ecf20Sopenharmony_ci	init_waitqueue_head(&sbi->gc_thread->fggc_wq);
1698c2ecf20Sopenharmony_ci	sbi->gc_thread->f2fs_gc_task = kthread_run(gc_thread_func, sbi,
1708c2ecf20Sopenharmony_ci			"f2fs_gc-%u:%u", MAJOR(dev), MINOR(dev));
1718c2ecf20Sopenharmony_ci	if (IS_ERR(gc_th->f2fs_gc_task)) {
1728c2ecf20Sopenharmony_ci		err = PTR_ERR(gc_th->f2fs_gc_task);
1738c2ecf20Sopenharmony_ci		kfree(gc_th);
1748c2ecf20Sopenharmony_ci		sbi->gc_thread = NULL;
1758c2ecf20Sopenharmony_ci	}
1768c2ecf20Sopenharmony_ciout:
1778c2ecf20Sopenharmony_ci	return err;
1788c2ecf20Sopenharmony_ci}
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_civoid f2fs_stop_gc_thread(struct f2fs_sb_info *sbi)
1818c2ecf20Sopenharmony_ci{
1828c2ecf20Sopenharmony_ci	struct f2fs_gc_kthread *gc_th = sbi->gc_thread;
1838c2ecf20Sopenharmony_ci	if (!gc_th)
1848c2ecf20Sopenharmony_ci		return;
1858c2ecf20Sopenharmony_ci	kthread_stop(gc_th->f2fs_gc_task);
1868c2ecf20Sopenharmony_ci	wake_up_all(&gc_th->fggc_wq);
1878c2ecf20Sopenharmony_ci	kfree(gc_th);
1888c2ecf20Sopenharmony_ci	sbi->gc_thread = NULL;
1898c2ecf20Sopenharmony_ci}
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_cistatic int select_gc_type(struct f2fs_sb_info *sbi, int gc_type)
1928c2ecf20Sopenharmony_ci{
1938c2ecf20Sopenharmony_ci	int gc_mode;
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	if (gc_type == BG_GC) {
1968c2ecf20Sopenharmony_ci		if (sbi->am.atgc_enabled)
1978c2ecf20Sopenharmony_ci			gc_mode = GC_AT;
1988c2ecf20Sopenharmony_ci		else
1998c2ecf20Sopenharmony_ci			gc_mode = GC_CB;
2008c2ecf20Sopenharmony_ci	} else {
2018c2ecf20Sopenharmony_ci		gc_mode = GC_GREEDY;
2028c2ecf20Sopenharmony_ci	}
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	switch (sbi->gc_mode) {
2058c2ecf20Sopenharmony_ci	case GC_IDLE_CB:
2068c2ecf20Sopenharmony_ci		gc_mode = GC_CB;
2078c2ecf20Sopenharmony_ci		break;
2088c2ecf20Sopenharmony_ci	case GC_IDLE_GREEDY:
2098c2ecf20Sopenharmony_ci	case GC_URGENT_HIGH:
2108c2ecf20Sopenharmony_ci		gc_mode = GC_GREEDY;
2118c2ecf20Sopenharmony_ci		break;
2128c2ecf20Sopenharmony_ci	case GC_IDLE_AT:
2138c2ecf20Sopenharmony_ci		gc_mode = GC_AT;
2148c2ecf20Sopenharmony_ci		break;
2158c2ecf20Sopenharmony_ci	}
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	return gc_mode;
2188c2ecf20Sopenharmony_ci}
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_cistatic void select_policy(struct f2fs_sb_info *sbi, int gc_type,
2218c2ecf20Sopenharmony_ci			int type, struct victim_sel_policy *p)
2228c2ecf20Sopenharmony_ci{
2238c2ecf20Sopenharmony_ci	struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	if (p->alloc_mode == SSR) {
2268c2ecf20Sopenharmony_ci		p->gc_mode = GC_GREEDY;
2278c2ecf20Sopenharmony_ci		p->dirty_bitmap = dirty_i->dirty_segmap[type];
2288c2ecf20Sopenharmony_ci		p->max_search = dirty_i->nr_dirty[type];
2298c2ecf20Sopenharmony_ci		p->ofs_unit = 1;
2308c2ecf20Sopenharmony_ci	} else if (p->alloc_mode == AT_SSR) {
2318c2ecf20Sopenharmony_ci		p->gc_mode = GC_GREEDY;
2328c2ecf20Sopenharmony_ci		p->dirty_bitmap = dirty_i->dirty_segmap[type];
2338c2ecf20Sopenharmony_ci		p->max_search = dirty_i->nr_dirty[type];
2348c2ecf20Sopenharmony_ci		p->ofs_unit = 1;
2358c2ecf20Sopenharmony_ci	} else {
2368c2ecf20Sopenharmony_ci		p->gc_mode = select_gc_type(sbi, gc_type);
2378c2ecf20Sopenharmony_ci		p->ofs_unit = sbi->segs_per_sec;
2388c2ecf20Sopenharmony_ci		if (__is_large_section(sbi)) {
2398c2ecf20Sopenharmony_ci			p->dirty_bitmap = dirty_i->dirty_secmap;
2408c2ecf20Sopenharmony_ci			p->max_search = count_bits(p->dirty_bitmap,
2418c2ecf20Sopenharmony_ci						0, MAIN_SECS(sbi));
2428c2ecf20Sopenharmony_ci		} else {
2438c2ecf20Sopenharmony_ci			p->dirty_bitmap = dirty_i->dirty_segmap[DIRTY];
2448c2ecf20Sopenharmony_ci			p->max_search = dirty_i->nr_dirty[DIRTY];
2458c2ecf20Sopenharmony_ci		}
2468c2ecf20Sopenharmony_ci	}
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	/*
2498c2ecf20Sopenharmony_ci	 * adjust candidates range, should select all dirty segments for
2508c2ecf20Sopenharmony_ci	 * foreground GC and urgent GC cases.
2518c2ecf20Sopenharmony_ci	 */
2528c2ecf20Sopenharmony_ci	if (gc_type != FG_GC &&
2538c2ecf20Sopenharmony_ci			(sbi->gc_mode != GC_URGENT_HIGH) &&
2548c2ecf20Sopenharmony_ci			(p->gc_mode != GC_AT && p->alloc_mode != AT_SSR) &&
2558c2ecf20Sopenharmony_ci			p->max_search > sbi->max_victim_search)
2568c2ecf20Sopenharmony_ci		p->max_search = sbi->max_victim_search;
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	/* let's select beginning hot/small space first in no_heap mode*/
2598c2ecf20Sopenharmony_ci	if (test_opt(sbi, NOHEAP) &&
2608c2ecf20Sopenharmony_ci		(type == CURSEG_HOT_DATA || IS_NODESEG(type)))
2618c2ecf20Sopenharmony_ci		p->offset = 0;
2628c2ecf20Sopenharmony_ci	else
2638c2ecf20Sopenharmony_ci		p->offset = SIT_I(sbi)->last_victim[p->gc_mode];
2648c2ecf20Sopenharmony_ci}
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_cistatic unsigned int get_max_cost(struct f2fs_sb_info *sbi,
2678c2ecf20Sopenharmony_ci				struct victim_sel_policy *p)
2688c2ecf20Sopenharmony_ci{
2698c2ecf20Sopenharmony_ci	/* SSR allocates in a segment unit */
2708c2ecf20Sopenharmony_ci	if (p->alloc_mode == SSR)
2718c2ecf20Sopenharmony_ci		return sbi->blocks_per_seg;
2728c2ecf20Sopenharmony_ci	else if (p->alloc_mode == AT_SSR)
2738c2ecf20Sopenharmony_ci		return UINT_MAX;
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci	/* LFS */
2768c2ecf20Sopenharmony_ci	if (p->gc_mode == GC_GREEDY)
2778c2ecf20Sopenharmony_ci		return 2 * sbi->blocks_per_seg * p->ofs_unit;
2788c2ecf20Sopenharmony_ci	else if (p->gc_mode == GC_CB)
2798c2ecf20Sopenharmony_ci		return UINT_MAX;
2808c2ecf20Sopenharmony_ci	else if (p->gc_mode == GC_AT)
2818c2ecf20Sopenharmony_ci		return UINT_MAX;
2828c2ecf20Sopenharmony_ci	else /* No other gc_mode */
2838c2ecf20Sopenharmony_ci		return 0;
2848c2ecf20Sopenharmony_ci}
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_cistatic unsigned int check_bg_victims(struct f2fs_sb_info *sbi)
2878c2ecf20Sopenharmony_ci{
2888c2ecf20Sopenharmony_ci	struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
2898c2ecf20Sopenharmony_ci	unsigned int secno;
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	/*
2928c2ecf20Sopenharmony_ci	 * If the gc_type is FG_GC, we can select victim segments
2938c2ecf20Sopenharmony_ci	 * selected by background GC before.
2948c2ecf20Sopenharmony_ci	 * Those segments guarantee they have small valid blocks.
2958c2ecf20Sopenharmony_ci	 */
2968c2ecf20Sopenharmony_ci	for_each_set_bit(secno, dirty_i->victim_secmap, MAIN_SECS(sbi)) {
2978c2ecf20Sopenharmony_ci		if (sec_usage_check(sbi, secno))
2988c2ecf20Sopenharmony_ci			continue;
2998c2ecf20Sopenharmony_ci		clear_bit(secno, dirty_i->victim_secmap);
3008c2ecf20Sopenharmony_ci		return GET_SEG_FROM_SEC(sbi, secno);
3018c2ecf20Sopenharmony_ci	}
3028c2ecf20Sopenharmony_ci	return NULL_SEGNO;
3038c2ecf20Sopenharmony_ci}
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_cistatic unsigned int get_cb_cost(struct f2fs_sb_info *sbi, unsigned int segno)
3068c2ecf20Sopenharmony_ci{
3078c2ecf20Sopenharmony_ci	struct sit_info *sit_i = SIT_I(sbi);
3088c2ecf20Sopenharmony_ci	unsigned int secno = GET_SEC_FROM_SEG(sbi, segno);
3098c2ecf20Sopenharmony_ci	unsigned int start = GET_SEG_FROM_SEC(sbi, secno);
3108c2ecf20Sopenharmony_ci	unsigned long long mtime = 0;
3118c2ecf20Sopenharmony_ci	unsigned int vblocks;
3128c2ecf20Sopenharmony_ci	unsigned char age = 0;
3138c2ecf20Sopenharmony_ci	unsigned char u;
3148c2ecf20Sopenharmony_ci	unsigned int i;
3158c2ecf20Sopenharmony_ci	unsigned int usable_segs_per_sec = f2fs_usable_segs_in_sec(sbi, segno);
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	for (i = 0; i < usable_segs_per_sec; i++)
3188c2ecf20Sopenharmony_ci		mtime += get_seg_entry(sbi, start + i)->mtime;
3198c2ecf20Sopenharmony_ci	vblocks = get_valid_blocks(sbi, segno, true);
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	mtime = div_u64(mtime, usable_segs_per_sec);
3228c2ecf20Sopenharmony_ci	vblocks = div_u64(vblocks, usable_segs_per_sec);
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	u = (vblocks * 100) >> sbi->log_blocks_per_seg;
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	/* Handle if the system time has changed by the user */
3278c2ecf20Sopenharmony_ci	if (mtime < sit_i->min_mtime)
3288c2ecf20Sopenharmony_ci		sit_i->min_mtime = mtime;
3298c2ecf20Sopenharmony_ci	if (mtime > sit_i->max_mtime)
3308c2ecf20Sopenharmony_ci		sit_i->max_mtime = mtime;
3318c2ecf20Sopenharmony_ci	if (sit_i->max_mtime != sit_i->min_mtime)
3328c2ecf20Sopenharmony_ci		age = 100 - div64_u64(100 * (mtime - sit_i->min_mtime),
3338c2ecf20Sopenharmony_ci				sit_i->max_mtime - sit_i->min_mtime);
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci	return UINT_MAX - ((100 * (100 - u) * age) / (100 + u));
3368c2ecf20Sopenharmony_ci}
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_cistatic inline unsigned int get_gc_cost(struct f2fs_sb_info *sbi,
3398c2ecf20Sopenharmony_ci			unsigned int segno, struct victim_sel_policy *p)
3408c2ecf20Sopenharmony_ci{
3418c2ecf20Sopenharmony_ci	if (p->alloc_mode == SSR)
3428c2ecf20Sopenharmony_ci		return get_seg_entry(sbi, segno)->ckpt_valid_blocks;
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci	/* alloc_mode == LFS */
3458c2ecf20Sopenharmony_ci	if (p->gc_mode == GC_GREEDY)
3468c2ecf20Sopenharmony_ci		return get_valid_blocks(sbi, segno, true);
3478c2ecf20Sopenharmony_ci	else if (p->gc_mode == GC_CB)
3488c2ecf20Sopenharmony_ci		return get_cb_cost(sbi, segno);
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci	f2fs_bug_on(sbi, 1);
3518c2ecf20Sopenharmony_ci	return 0;
3528c2ecf20Sopenharmony_ci}
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_cistatic unsigned int count_bits(const unsigned long *addr,
3558c2ecf20Sopenharmony_ci				unsigned int offset, unsigned int len)
3568c2ecf20Sopenharmony_ci{
3578c2ecf20Sopenharmony_ci	unsigned int end = offset + len, sum = 0;
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci	while (offset < end) {
3608c2ecf20Sopenharmony_ci		if (test_bit(offset++, addr))
3618c2ecf20Sopenharmony_ci			++sum;
3628c2ecf20Sopenharmony_ci	}
3638c2ecf20Sopenharmony_ci	return sum;
3648c2ecf20Sopenharmony_ci}
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_cistatic struct victim_entry *attach_victim_entry(struct f2fs_sb_info *sbi,
3678c2ecf20Sopenharmony_ci				unsigned long long mtime, unsigned int segno,
3688c2ecf20Sopenharmony_ci				struct rb_node *parent, struct rb_node **p,
3698c2ecf20Sopenharmony_ci				bool left_most)
3708c2ecf20Sopenharmony_ci{
3718c2ecf20Sopenharmony_ci	struct atgc_management *am = &sbi->am;
3728c2ecf20Sopenharmony_ci	struct victim_entry *ve;
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci	ve =  f2fs_kmem_cache_alloc(victim_entry_slab, GFP_NOFS);
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci	ve->mtime = mtime;
3778c2ecf20Sopenharmony_ci	ve->segno = segno;
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci	rb_link_node(&ve->rb_node, parent, p);
3808c2ecf20Sopenharmony_ci	rb_insert_color_cached(&ve->rb_node, &am->root, left_most);
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	list_add_tail(&ve->list, &am->victim_list);
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci	am->victim_count++;
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci	return ve;
3878c2ecf20Sopenharmony_ci}
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_cistatic void insert_victim_entry(struct f2fs_sb_info *sbi,
3908c2ecf20Sopenharmony_ci				unsigned long long mtime, unsigned int segno)
3918c2ecf20Sopenharmony_ci{
3928c2ecf20Sopenharmony_ci	struct atgc_management *am = &sbi->am;
3938c2ecf20Sopenharmony_ci	struct rb_node **p;
3948c2ecf20Sopenharmony_ci	struct rb_node *parent = NULL;
3958c2ecf20Sopenharmony_ci	bool left_most = true;
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci	p = f2fs_lookup_rb_tree_ext(sbi, &am->root, &parent, mtime, &left_most);
3988c2ecf20Sopenharmony_ci	attach_victim_entry(sbi, mtime, segno, parent, p, left_most);
3998c2ecf20Sopenharmony_ci}
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_cistatic void add_victim_entry(struct f2fs_sb_info *sbi,
4028c2ecf20Sopenharmony_ci				struct victim_sel_policy *p, unsigned int segno)
4038c2ecf20Sopenharmony_ci{
4048c2ecf20Sopenharmony_ci	struct sit_info *sit_i = SIT_I(sbi);
4058c2ecf20Sopenharmony_ci	unsigned int secno = GET_SEC_FROM_SEG(sbi, segno);
4068c2ecf20Sopenharmony_ci	unsigned int start = GET_SEG_FROM_SEC(sbi, secno);
4078c2ecf20Sopenharmony_ci	unsigned long long mtime = 0;
4088c2ecf20Sopenharmony_ci	unsigned int i;
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci	if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
4118c2ecf20Sopenharmony_ci		if (p->gc_mode == GC_AT &&
4128c2ecf20Sopenharmony_ci			get_valid_blocks(sbi, segno, true) == 0)
4138c2ecf20Sopenharmony_ci			return;
4148c2ecf20Sopenharmony_ci	}
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci	for (i = 0; i < sbi->segs_per_sec; i++)
4178c2ecf20Sopenharmony_ci		mtime += get_seg_entry(sbi, start + i)->mtime;
4188c2ecf20Sopenharmony_ci	mtime = div_u64(mtime, sbi->segs_per_sec);
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci	/* Handle if the system time has changed by the user */
4218c2ecf20Sopenharmony_ci	if (mtime < sit_i->min_mtime)
4228c2ecf20Sopenharmony_ci		sit_i->min_mtime = mtime;
4238c2ecf20Sopenharmony_ci	if (mtime > sit_i->max_mtime)
4248c2ecf20Sopenharmony_ci		sit_i->max_mtime = mtime;
4258c2ecf20Sopenharmony_ci	if (mtime < sit_i->dirty_min_mtime)
4268c2ecf20Sopenharmony_ci		sit_i->dirty_min_mtime = mtime;
4278c2ecf20Sopenharmony_ci	if (mtime > sit_i->dirty_max_mtime)
4288c2ecf20Sopenharmony_ci		sit_i->dirty_max_mtime = mtime;
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ci	/* don't choose young section as candidate */
4318c2ecf20Sopenharmony_ci	if (sit_i->dirty_max_mtime - mtime < p->age_threshold)
4328c2ecf20Sopenharmony_ci		return;
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci	insert_victim_entry(sbi, mtime, segno);
4358c2ecf20Sopenharmony_ci}
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_cistatic struct rb_node *lookup_central_victim(struct f2fs_sb_info *sbi,
4388c2ecf20Sopenharmony_ci						struct victim_sel_policy *p)
4398c2ecf20Sopenharmony_ci{
4408c2ecf20Sopenharmony_ci	struct atgc_management *am = &sbi->am;
4418c2ecf20Sopenharmony_ci	struct rb_node *parent = NULL;
4428c2ecf20Sopenharmony_ci	bool left_most;
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	f2fs_lookup_rb_tree_ext(sbi, &am->root, &parent, p->age, &left_most);
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_ci	return parent;
4478c2ecf20Sopenharmony_ci}
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_cistatic void atgc_lookup_victim(struct f2fs_sb_info *sbi,
4508c2ecf20Sopenharmony_ci						struct victim_sel_policy *p)
4518c2ecf20Sopenharmony_ci{
4528c2ecf20Sopenharmony_ci	struct sit_info *sit_i = SIT_I(sbi);
4538c2ecf20Sopenharmony_ci	struct atgc_management *am = &sbi->am;
4548c2ecf20Sopenharmony_ci	struct rb_root_cached *root = &am->root;
4558c2ecf20Sopenharmony_ci	struct rb_node *node;
4568c2ecf20Sopenharmony_ci	struct rb_entry *re;
4578c2ecf20Sopenharmony_ci	struct victim_entry *ve;
4588c2ecf20Sopenharmony_ci	unsigned long long total_time;
4598c2ecf20Sopenharmony_ci	unsigned long long age, u, accu;
4608c2ecf20Sopenharmony_ci	unsigned long long max_mtime = sit_i->dirty_max_mtime;
4618c2ecf20Sopenharmony_ci	unsigned long long min_mtime = sit_i->dirty_min_mtime;
4628c2ecf20Sopenharmony_ci	unsigned int sec_blocks = BLKS_PER_SEC(sbi);
4638c2ecf20Sopenharmony_ci	unsigned int vblocks;
4648c2ecf20Sopenharmony_ci	unsigned int dirty_threshold = max(am->max_candidate_count,
4658c2ecf20Sopenharmony_ci					am->candidate_ratio *
4668c2ecf20Sopenharmony_ci					am->victim_count / 100);
4678c2ecf20Sopenharmony_ci	unsigned int age_weight = am->age_weight;
4688c2ecf20Sopenharmony_ci	unsigned int cost;
4698c2ecf20Sopenharmony_ci	unsigned int iter = 0;
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	if (max_mtime < min_mtime)
4728c2ecf20Sopenharmony_ci		return;
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_ci	max_mtime += 1;
4758c2ecf20Sopenharmony_ci	total_time = max_mtime - min_mtime;
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	accu = div64_u64(ULLONG_MAX, total_time);
4788c2ecf20Sopenharmony_ci	accu = min_t(unsigned long long, div_u64(accu, 100),
4798c2ecf20Sopenharmony_ci					DEFAULT_ACCURACY_CLASS);
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ci	node = rb_first_cached(root);
4828c2ecf20Sopenharmony_cinext:
4838c2ecf20Sopenharmony_ci	re = rb_entry_safe(node, struct rb_entry, rb_node);
4848c2ecf20Sopenharmony_ci	if (!re)
4858c2ecf20Sopenharmony_ci		return;
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci	ve = (struct victim_entry *)re;
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ci	if (ve->mtime >= max_mtime || ve->mtime < min_mtime)
4908c2ecf20Sopenharmony_ci		goto skip;
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci	/* age = 10000 * x% * 60 */
4938c2ecf20Sopenharmony_ci	age = div64_u64(accu * (max_mtime - ve->mtime), total_time) *
4948c2ecf20Sopenharmony_ci								age_weight;
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	vblocks = get_valid_blocks(sbi, ve->segno, true);
4978c2ecf20Sopenharmony_ci	f2fs_bug_on(sbi, !vblocks || vblocks == sec_blocks);
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci	/* u = 10000 * x% * 40 */
5008c2ecf20Sopenharmony_ci	u = div64_u64(accu * (sec_blocks - vblocks), sec_blocks) *
5018c2ecf20Sopenharmony_ci							(100 - age_weight);
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci	f2fs_bug_on(sbi, age + u >= UINT_MAX);
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci	cost = UINT_MAX - (age + u);
5068c2ecf20Sopenharmony_ci	iter++;
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	if (cost < p->min_cost ||
5098c2ecf20Sopenharmony_ci			(cost == p->min_cost && age > p->oldest_age)) {
5108c2ecf20Sopenharmony_ci		p->min_cost = cost;
5118c2ecf20Sopenharmony_ci		p->oldest_age = age;
5128c2ecf20Sopenharmony_ci		p->min_segno = ve->segno;
5138c2ecf20Sopenharmony_ci	}
5148c2ecf20Sopenharmony_ciskip:
5158c2ecf20Sopenharmony_ci	if (iter < dirty_threshold) {
5168c2ecf20Sopenharmony_ci		node = rb_next(node);
5178c2ecf20Sopenharmony_ci		goto next;
5188c2ecf20Sopenharmony_ci	}
5198c2ecf20Sopenharmony_ci}
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci/*
5228c2ecf20Sopenharmony_ci * select candidates around source section in range of
5238c2ecf20Sopenharmony_ci * [target - dirty_threshold, target + dirty_threshold]
5248c2ecf20Sopenharmony_ci */
5258c2ecf20Sopenharmony_cistatic void atssr_lookup_victim(struct f2fs_sb_info *sbi,
5268c2ecf20Sopenharmony_ci						struct victim_sel_policy *p)
5278c2ecf20Sopenharmony_ci{
5288c2ecf20Sopenharmony_ci	struct sit_info *sit_i = SIT_I(sbi);
5298c2ecf20Sopenharmony_ci	struct atgc_management *am = &sbi->am;
5308c2ecf20Sopenharmony_ci	struct rb_node *node;
5318c2ecf20Sopenharmony_ci	struct rb_entry *re;
5328c2ecf20Sopenharmony_ci	struct victim_entry *ve;
5338c2ecf20Sopenharmony_ci	unsigned long long age;
5348c2ecf20Sopenharmony_ci	unsigned long long max_mtime = sit_i->dirty_max_mtime;
5358c2ecf20Sopenharmony_ci	unsigned long long min_mtime = sit_i->dirty_min_mtime;
5368c2ecf20Sopenharmony_ci	unsigned int seg_blocks = sbi->blocks_per_seg;
5378c2ecf20Sopenharmony_ci	unsigned int vblocks;
5388c2ecf20Sopenharmony_ci	unsigned int dirty_threshold = max(am->max_candidate_count,
5398c2ecf20Sopenharmony_ci					am->candidate_ratio *
5408c2ecf20Sopenharmony_ci					am->victim_count / 100);
5418c2ecf20Sopenharmony_ci	unsigned int cost;
5428c2ecf20Sopenharmony_ci	unsigned int iter = 0;
5438c2ecf20Sopenharmony_ci	int stage = 0;
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci	if (max_mtime < min_mtime)
5468c2ecf20Sopenharmony_ci		return;
5478c2ecf20Sopenharmony_ci	max_mtime += 1;
5488c2ecf20Sopenharmony_cinext_stage:
5498c2ecf20Sopenharmony_ci	node = lookup_central_victim(sbi, p);
5508c2ecf20Sopenharmony_cinext_node:
5518c2ecf20Sopenharmony_ci	re = rb_entry_safe(node, struct rb_entry, rb_node);
5528c2ecf20Sopenharmony_ci	if (!re) {
5538c2ecf20Sopenharmony_ci		if (stage == 0)
5548c2ecf20Sopenharmony_ci			goto skip_stage;
5558c2ecf20Sopenharmony_ci		return;
5568c2ecf20Sopenharmony_ci	}
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci	ve = (struct victim_entry *)re;
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_ci	if (ve->mtime >= max_mtime || ve->mtime < min_mtime)
5618c2ecf20Sopenharmony_ci		goto skip_node;
5628c2ecf20Sopenharmony_ci
5638c2ecf20Sopenharmony_ci	age = max_mtime - ve->mtime;
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci	vblocks = get_seg_entry(sbi, ve->segno)->ckpt_valid_blocks;
5668c2ecf20Sopenharmony_ci	f2fs_bug_on(sbi, !vblocks);
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_ci	/* rare case */
5698c2ecf20Sopenharmony_ci	if (vblocks == seg_blocks)
5708c2ecf20Sopenharmony_ci		goto skip_node;
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci	iter++;
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci	age = max_mtime - abs(p->age - age);
5758c2ecf20Sopenharmony_ci	cost = UINT_MAX - vblocks;
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ci	if (cost < p->min_cost ||
5788c2ecf20Sopenharmony_ci			(cost == p->min_cost && age > p->oldest_age)) {
5798c2ecf20Sopenharmony_ci		p->min_cost = cost;
5808c2ecf20Sopenharmony_ci		p->oldest_age = age;
5818c2ecf20Sopenharmony_ci		p->min_segno = ve->segno;
5828c2ecf20Sopenharmony_ci	}
5838c2ecf20Sopenharmony_ciskip_node:
5848c2ecf20Sopenharmony_ci	if (iter < dirty_threshold) {
5858c2ecf20Sopenharmony_ci		if (stage == 0)
5868c2ecf20Sopenharmony_ci			node = rb_prev(node);
5878c2ecf20Sopenharmony_ci		else if (stage == 1)
5888c2ecf20Sopenharmony_ci			node = rb_next(node);
5898c2ecf20Sopenharmony_ci		goto next_node;
5908c2ecf20Sopenharmony_ci	}
5918c2ecf20Sopenharmony_ciskip_stage:
5928c2ecf20Sopenharmony_ci	if (stage < 1) {
5938c2ecf20Sopenharmony_ci		stage++;
5948c2ecf20Sopenharmony_ci		iter = 0;
5958c2ecf20Sopenharmony_ci		goto next_stage;
5968c2ecf20Sopenharmony_ci	}
5978c2ecf20Sopenharmony_ci}
5988c2ecf20Sopenharmony_cistatic void lookup_victim_by_age(struct f2fs_sb_info *sbi,
5998c2ecf20Sopenharmony_ci						struct victim_sel_policy *p)
6008c2ecf20Sopenharmony_ci{
6018c2ecf20Sopenharmony_ci	f2fs_bug_on(sbi, !f2fs_check_rb_tree_consistence(sbi,
6028c2ecf20Sopenharmony_ci						&sbi->am.root, true));
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci	if (p->gc_mode == GC_AT)
6058c2ecf20Sopenharmony_ci		atgc_lookup_victim(sbi, p);
6068c2ecf20Sopenharmony_ci	else if (p->alloc_mode == AT_SSR)
6078c2ecf20Sopenharmony_ci		atssr_lookup_victim(sbi, p);
6088c2ecf20Sopenharmony_ci	else
6098c2ecf20Sopenharmony_ci		f2fs_bug_on(sbi, 1);
6108c2ecf20Sopenharmony_ci}
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_cistatic void release_victim_entry(struct f2fs_sb_info *sbi)
6138c2ecf20Sopenharmony_ci{
6148c2ecf20Sopenharmony_ci	struct atgc_management *am = &sbi->am;
6158c2ecf20Sopenharmony_ci	struct victim_entry *ve, *tmp;
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci	list_for_each_entry_safe(ve, tmp, &am->victim_list, list) {
6188c2ecf20Sopenharmony_ci		list_del(&ve->list);
6198c2ecf20Sopenharmony_ci		kmem_cache_free(victim_entry_slab, ve);
6208c2ecf20Sopenharmony_ci		am->victim_count--;
6218c2ecf20Sopenharmony_ci	}
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_ci	am->root = RB_ROOT_CACHED;
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_ci	f2fs_bug_on(sbi, am->victim_count);
6268c2ecf20Sopenharmony_ci	f2fs_bug_on(sbi, !list_empty(&am->victim_list));
6278c2ecf20Sopenharmony_ci}
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci/*
6308c2ecf20Sopenharmony_ci * This function is called from two paths.
6318c2ecf20Sopenharmony_ci * One is garbage collection and the other is SSR segment selection.
6328c2ecf20Sopenharmony_ci * When it is called during GC, it just gets a victim segment
6338c2ecf20Sopenharmony_ci * and it does not remove it from dirty seglist.
6348c2ecf20Sopenharmony_ci * When it is called from SSR segment selection, it finds a segment
6358c2ecf20Sopenharmony_ci * which has minimum valid blocks and removes it from dirty seglist.
6368c2ecf20Sopenharmony_ci */
6378c2ecf20Sopenharmony_cistatic int get_victim_by_default(struct f2fs_sb_info *sbi,
6388c2ecf20Sopenharmony_ci			unsigned int *result, int gc_type, int type,
6398c2ecf20Sopenharmony_ci			char alloc_mode, unsigned long long age)
6408c2ecf20Sopenharmony_ci{
6418c2ecf20Sopenharmony_ci	struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
6428c2ecf20Sopenharmony_ci	struct sit_info *sm = SIT_I(sbi);
6438c2ecf20Sopenharmony_ci	struct victim_sel_policy p;
6448c2ecf20Sopenharmony_ci	unsigned int secno, last_victim;
6458c2ecf20Sopenharmony_ci	unsigned int last_segment;
6468c2ecf20Sopenharmony_ci	unsigned int nsearched;
6478c2ecf20Sopenharmony_ci	bool is_atgc;
6488c2ecf20Sopenharmony_ci	int ret = 0;
6498c2ecf20Sopenharmony_ci
6508c2ecf20Sopenharmony_ci	mutex_lock(&dirty_i->seglist_lock);
6518c2ecf20Sopenharmony_ci	last_segment = MAIN_SECS(sbi) * sbi->segs_per_sec;
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci	p.alloc_mode = alloc_mode;
6548c2ecf20Sopenharmony_ci	p.age = age;
6558c2ecf20Sopenharmony_ci	p.age_threshold = sbi->am.age_threshold;
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ciretry:
6588c2ecf20Sopenharmony_ci	select_policy(sbi, gc_type, type, &p);
6598c2ecf20Sopenharmony_ci	p.min_segno = NULL_SEGNO;
6608c2ecf20Sopenharmony_ci	p.oldest_age = 0;
6618c2ecf20Sopenharmony_ci	p.min_cost = get_max_cost(sbi, &p);
6628c2ecf20Sopenharmony_ci
6638c2ecf20Sopenharmony_ci	is_atgc = (p.gc_mode == GC_AT || p.alloc_mode == AT_SSR);
6648c2ecf20Sopenharmony_ci	nsearched = 0;
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci	if (is_atgc)
6678c2ecf20Sopenharmony_ci		SIT_I(sbi)->dirty_min_mtime = ULLONG_MAX;
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci	if (*result != NULL_SEGNO) {
6708c2ecf20Sopenharmony_ci		if (!get_valid_blocks(sbi, *result, false)) {
6718c2ecf20Sopenharmony_ci			ret = -ENODATA;
6728c2ecf20Sopenharmony_ci			goto out;
6738c2ecf20Sopenharmony_ci		}
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_ci		if (sec_usage_check(sbi, GET_SEC_FROM_SEG(sbi, *result)))
6768c2ecf20Sopenharmony_ci			ret = -EBUSY;
6778c2ecf20Sopenharmony_ci		else
6788c2ecf20Sopenharmony_ci			p.min_segno = *result;
6798c2ecf20Sopenharmony_ci		goto out;
6808c2ecf20Sopenharmony_ci	}
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_ci	ret = -ENODATA;
6838c2ecf20Sopenharmony_ci	if (p.max_search == 0)
6848c2ecf20Sopenharmony_ci		goto out;
6858c2ecf20Sopenharmony_ci
6868c2ecf20Sopenharmony_ci	if (__is_large_section(sbi) && p.alloc_mode == LFS) {
6878c2ecf20Sopenharmony_ci		if (sbi->next_victim_seg[BG_GC] != NULL_SEGNO) {
6888c2ecf20Sopenharmony_ci			p.min_segno = sbi->next_victim_seg[BG_GC];
6898c2ecf20Sopenharmony_ci			*result = p.min_segno;
6908c2ecf20Sopenharmony_ci			sbi->next_victim_seg[BG_GC] = NULL_SEGNO;
6918c2ecf20Sopenharmony_ci			goto got_result;
6928c2ecf20Sopenharmony_ci		}
6938c2ecf20Sopenharmony_ci		if (gc_type == FG_GC &&
6948c2ecf20Sopenharmony_ci				sbi->next_victim_seg[FG_GC] != NULL_SEGNO) {
6958c2ecf20Sopenharmony_ci			p.min_segno = sbi->next_victim_seg[FG_GC];
6968c2ecf20Sopenharmony_ci			*result = p.min_segno;
6978c2ecf20Sopenharmony_ci			sbi->next_victim_seg[FG_GC] = NULL_SEGNO;
6988c2ecf20Sopenharmony_ci			goto got_result;
6998c2ecf20Sopenharmony_ci		}
7008c2ecf20Sopenharmony_ci	}
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_ci	last_victim = sm->last_victim[p.gc_mode];
7038c2ecf20Sopenharmony_ci	if (p.alloc_mode == LFS && gc_type == FG_GC) {
7048c2ecf20Sopenharmony_ci		p.min_segno = check_bg_victims(sbi);
7058c2ecf20Sopenharmony_ci		if (p.min_segno != NULL_SEGNO)
7068c2ecf20Sopenharmony_ci			goto got_it;
7078c2ecf20Sopenharmony_ci	}
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci	while (1) {
7108c2ecf20Sopenharmony_ci		unsigned long cost, *dirty_bitmap;
7118c2ecf20Sopenharmony_ci		unsigned int unit_no, segno;
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_ci		dirty_bitmap = p.dirty_bitmap;
7148c2ecf20Sopenharmony_ci		unit_no = find_next_bit(dirty_bitmap,
7158c2ecf20Sopenharmony_ci				last_segment / p.ofs_unit,
7168c2ecf20Sopenharmony_ci				p.offset / p.ofs_unit);
7178c2ecf20Sopenharmony_ci		segno = unit_no * p.ofs_unit;
7188c2ecf20Sopenharmony_ci		if (segno >= last_segment) {
7198c2ecf20Sopenharmony_ci			if (sm->last_victim[p.gc_mode]) {
7208c2ecf20Sopenharmony_ci				last_segment =
7218c2ecf20Sopenharmony_ci					sm->last_victim[p.gc_mode];
7228c2ecf20Sopenharmony_ci				sm->last_victim[p.gc_mode] = 0;
7238c2ecf20Sopenharmony_ci				p.offset = 0;
7248c2ecf20Sopenharmony_ci				continue;
7258c2ecf20Sopenharmony_ci			}
7268c2ecf20Sopenharmony_ci			break;
7278c2ecf20Sopenharmony_ci		}
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci		p.offset = segno + p.ofs_unit;
7308c2ecf20Sopenharmony_ci		nsearched++;
7318c2ecf20Sopenharmony_ci
7328c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_CHECK_FS
7338c2ecf20Sopenharmony_ci		/*
7348c2ecf20Sopenharmony_ci		 * skip selecting the invalid segno (that is failed due to block
7358c2ecf20Sopenharmony_ci		 * validity check failure during GC) to avoid endless GC loop in
7368c2ecf20Sopenharmony_ci		 * such cases.
7378c2ecf20Sopenharmony_ci		 */
7388c2ecf20Sopenharmony_ci		if (test_bit(segno, sm->invalid_segmap))
7398c2ecf20Sopenharmony_ci			goto next;
7408c2ecf20Sopenharmony_ci#endif
7418c2ecf20Sopenharmony_ci
7428c2ecf20Sopenharmony_ci		secno = GET_SEC_FROM_SEG(sbi, segno);
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_ci		if (sec_usage_check(sbi, secno))
7458c2ecf20Sopenharmony_ci			goto next;
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_ci		/* Don't touch checkpointed data */
7488c2ecf20Sopenharmony_ci		if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
7498c2ecf20Sopenharmony_ci			if (p.alloc_mode == LFS) {
7508c2ecf20Sopenharmony_ci				/*
7518c2ecf20Sopenharmony_ci				 * LFS is set to find source section during GC.
7528c2ecf20Sopenharmony_ci				 * The victim should have no checkpointed data.
7538c2ecf20Sopenharmony_ci				 */
7548c2ecf20Sopenharmony_ci				if (get_ckpt_valid_blocks(sbi, segno, true))
7558c2ecf20Sopenharmony_ci					goto next;
7568c2ecf20Sopenharmony_ci			} else {
7578c2ecf20Sopenharmony_ci				/*
7588c2ecf20Sopenharmony_ci				 * SSR | AT_SSR are set to find target segment
7598c2ecf20Sopenharmony_ci				 * for writes which can be full by checkpointed
7608c2ecf20Sopenharmony_ci				 * and newly written blocks.
7618c2ecf20Sopenharmony_ci				 */
7628c2ecf20Sopenharmony_ci				if (!f2fs_segment_has_free_slot(sbi, segno))
7638c2ecf20Sopenharmony_ci					goto next;
7648c2ecf20Sopenharmony_ci			}
7658c2ecf20Sopenharmony_ci		}
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_ci		if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
7688c2ecf20Sopenharmony_ci			goto next;
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_ci		if (is_atgc) {
7718c2ecf20Sopenharmony_ci			add_victim_entry(sbi, &p, segno);
7728c2ecf20Sopenharmony_ci			goto next;
7738c2ecf20Sopenharmony_ci		}
7748c2ecf20Sopenharmony_ci
7758c2ecf20Sopenharmony_ci		cost = get_gc_cost(sbi, segno, &p);
7768c2ecf20Sopenharmony_ci
7778c2ecf20Sopenharmony_ci		if (p.min_cost > cost) {
7788c2ecf20Sopenharmony_ci			p.min_segno = segno;
7798c2ecf20Sopenharmony_ci			p.min_cost = cost;
7808c2ecf20Sopenharmony_ci		}
7818c2ecf20Sopenharmony_cinext:
7828c2ecf20Sopenharmony_ci		if (nsearched >= p.max_search) {
7838c2ecf20Sopenharmony_ci			if (!sm->last_victim[p.gc_mode] && segno <= last_victim)
7848c2ecf20Sopenharmony_ci				sm->last_victim[p.gc_mode] =
7858c2ecf20Sopenharmony_ci					last_victim + p.ofs_unit;
7868c2ecf20Sopenharmony_ci			else
7878c2ecf20Sopenharmony_ci				sm->last_victim[p.gc_mode] = segno + p.ofs_unit;
7888c2ecf20Sopenharmony_ci			sm->last_victim[p.gc_mode] %=
7898c2ecf20Sopenharmony_ci				(MAIN_SECS(sbi) * sbi->segs_per_sec);
7908c2ecf20Sopenharmony_ci			break;
7918c2ecf20Sopenharmony_ci		}
7928c2ecf20Sopenharmony_ci	}
7938c2ecf20Sopenharmony_ci
7948c2ecf20Sopenharmony_ci	/* get victim for GC_AT/AT_SSR */
7958c2ecf20Sopenharmony_ci	if (is_atgc) {
7968c2ecf20Sopenharmony_ci		lookup_victim_by_age(sbi, &p);
7978c2ecf20Sopenharmony_ci		release_victim_entry(sbi);
7988c2ecf20Sopenharmony_ci	}
7998c2ecf20Sopenharmony_ci
8008c2ecf20Sopenharmony_ci	if (is_atgc && p.min_segno == NULL_SEGNO &&
8018c2ecf20Sopenharmony_ci			sm->elapsed_time < p.age_threshold) {
8028c2ecf20Sopenharmony_ci		p.age_threshold = 0;
8038c2ecf20Sopenharmony_ci		goto retry;
8048c2ecf20Sopenharmony_ci	}
8058c2ecf20Sopenharmony_ci
8068c2ecf20Sopenharmony_ci	if (p.min_segno != NULL_SEGNO) {
8078c2ecf20Sopenharmony_cigot_it:
8088c2ecf20Sopenharmony_ci		*result = (p.min_segno / p.ofs_unit) * p.ofs_unit;
8098c2ecf20Sopenharmony_cigot_result:
8108c2ecf20Sopenharmony_ci		if (p.alloc_mode == LFS) {
8118c2ecf20Sopenharmony_ci			secno = GET_SEC_FROM_SEG(sbi, p.min_segno);
8128c2ecf20Sopenharmony_ci			if (gc_type == FG_GC)
8138c2ecf20Sopenharmony_ci				sbi->cur_victim_sec = secno;
8148c2ecf20Sopenharmony_ci			else
8158c2ecf20Sopenharmony_ci				set_bit(secno, dirty_i->victim_secmap);
8168c2ecf20Sopenharmony_ci		}
8178c2ecf20Sopenharmony_ci		ret = 0;
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ci	}
8208c2ecf20Sopenharmony_ciout:
8218c2ecf20Sopenharmony_ci	if (p.min_segno != NULL_SEGNO)
8228c2ecf20Sopenharmony_ci		trace_f2fs_get_victim(sbi->sb, type, gc_type, &p,
8238c2ecf20Sopenharmony_ci				sbi->cur_victim_sec,
8248c2ecf20Sopenharmony_ci				prefree_segments(sbi), free_segments(sbi));
8258c2ecf20Sopenharmony_ci	mutex_unlock(&dirty_i->seglist_lock);
8268c2ecf20Sopenharmony_ci
8278c2ecf20Sopenharmony_ci	return ret;
8288c2ecf20Sopenharmony_ci}
8298c2ecf20Sopenharmony_ci
8308c2ecf20Sopenharmony_cistatic const struct victim_selection default_v_ops = {
8318c2ecf20Sopenharmony_ci	.get_victim = get_victim_by_default,
8328c2ecf20Sopenharmony_ci};
8338c2ecf20Sopenharmony_ci
8348c2ecf20Sopenharmony_cistatic struct inode *find_gc_inode(struct gc_inode_list *gc_list, nid_t ino)
8358c2ecf20Sopenharmony_ci{
8368c2ecf20Sopenharmony_ci	struct inode_entry *ie;
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci	ie = radix_tree_lookup(&gc_list->iroot, ino);
8398c2ecf20Sopenharmony_ci	if (ie)
8408c2ecf20Sopenharmony_ci		return ie->inode;
8418c2ecf20Sopenharmony_ci	return NULL;
8428c2ecf20Sopenharmony_ci}
8438c2ecf20Sopenharmony_ci
8448c2ecf20Sopenharmony_cistatic void add_gc_inode(struct gc_inode_list *gc_list, struct inode *inode)
8458c2ecf20Sopenharmony_ci{
8468c2ecf20Sopenharmony_ci	struct inode_entry *new_ie;
8478c2ecf20Sopenharmony_ci
8488c2ecf20Sopenharmony_ci	if (inode == find_gc_inode(gc_list, inode->i_ino)) {
8498c2ecf20Sopenharmony_ci		iput(inode);
8508c2ecf20Sopenharmony_ci		return;
8518c2ecf20Sopenharmony_ci	}
8528c2ecf20Sopenharmony_ci	new_ie = f2fs_kmem_cache_alloc(f2fs_inode_entry_slab, GFP_NOFS);
8538c2ecf20Sopenharmony_ci	new_ie->inode = inode;
8548c2ecf20Sopenharmony_ci
8558c2ecf20Sopenharmony_ci	f2fs_radix_tree_insert(&gc_list->iroot, inode->i_ino, new_ie);
8568c2ecf20Sopenharmony_ci	list_add_tail(&new_ie->list, &gc_list->ilist);
8578c2ecf20Sopenharmony_ci}
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_cistatic void put_gc_inode(struct gc_inode_list *gc_list)
8608c2ecf20Sopenharmony_ci{
8618c2ecf20Sopenharmony_ci	struct inode_entry *ie, *next_ie;
8628c2ecf20Sopenharmony_ci	list_for_each_entry_safe(ie, next_ie, &gc_list->ilist, list) {
8638c2ecf20Sopenharmony_ci		radix_tree_delete(&gc_list->iroot, ie->inode->i_ino);
8648c2ecf20Sopenharmony_ci		iput(ie->inode);
8658c2ecf20Sopenharmony_ci		list_del(&ie->list);
8668c2ecf20Sopenharmony_ci		kmem_cache_free(f2fs_inode_entry_slab, ie);
8678c2ecf20Sopenharmony_ci	}
8688c2ecf20Sopenharmony_ci}
8698c2ecf20Sopenharmony_ci
8708c2ecf20Sopenharmony_cistatic int check_valid_map(struct f2fs_sb_info *sbi,
8718c2ecf20Sopenharmony_ci				unsigned int segno, int offset)
8728c2ecf20Sopenharmony_ci{
8738c2ecf20Sopenharmony_ci	struct sit_info *sit_i = SIT_I(sbi);
8748c2ecf20Sopenharmony_ci	struct seg_entry *sentry;
8758c2ecf20Sopenharmony_ci	int ret;
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_ci	down_read(&sit_i->sentry_lock);
8788c2ecf20Sopenharmony_ci	sentry = get_seg_entry(sbi, segno);
8798c2ecf20Sopenharmony_ci	ret = f2fs_test_bit(offset, sentry->cur_valid_map);
8808c2ecf20Sopenharmony_ci	up_read(&sit_i->sentry_lock);
8818c2ecf20Sopenharmony_ci	return ret;
8828c2ecf20Sopenharmony_ci}
8838c2ecf20Sopenharmony_ci
8848c2ecf20Sopenharmony_ci/*
8858c2ecf20Sopenharmony_ci * This function compares node address got in summary with that in NAT.
8868c2ecf20Sopenharmony_ci * On validity, copy that node with cold status, otherwise (invalid node)
8878c2ecf20Sopenharmony_ci * ignore that.
8888c2ecf20Sopenharmony_ci */
8898c2ecf20Sopenharmony_cistatic int gc_node_segment(struct f2fs_sb_info *sbi,
8908c2ecf20Sopenharmony_ci		struct f2fs_summary *sum, unsigned int segno, int gc_type)
8918c2ecf20Sopenharmony_ci{
8928c2ecf20Sopenharmony_ci	struct f2fs_summary *entry;
8938c2ecf20Sopenharmony_ci	block_t start_addr;
8948c2ecf20Sopenharmony_ci	int off;
8958c2ecf20Sopenharmony_ci	int phase = 0;
8968c2ecf20Sopenharmony_ci	bool fggc = (gc_type == FG_GC);
8978c2ecf20Sopenharmony_ci	int submitted = 0;
8988c2ecf20Sopenharmony_ci	unsigned int usable_blks_in_seg = f2fs_usable_blks_in_seg(sbi, segno);
8998c2ecf20Sopenharmony_ci
9008c2ecf20Sopenharmony_ci	start_addr = START_BLOCK(sbi, segno);
9018c2ecf20Sopenharmony_ci
9028c2ecf20Sopenharmony_cinext_step:
9038c2ecf20Sopenharmony_ci	entry = sum;
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_ci	if (fggc && phase == 2)
9068c2ecf20Sopenharmony_ci		atomic_inc(&sbi->wb_sync_req[NODE]);
9078c2ecf20Sopenharmony_ci
9088c2ecf20Sopenharmony_ci	for (off = 0; off < usable_blks_in_seg; off++, entry++) {
9098c2ecf20Sopenharmony_ci		nid_t nid = le32_to_cpu(entry->nid);
9108c2ecf20Sopenharmony_ci		struct page *node_page;
9118c2ecf20Sopenharmony_ci		struct node_info ni;
9128c2ecf20Sopenharmony_ci		int err;
9138c2ecf20Sopenharmony_ci
9148c2ecf20Sopenharmony_ci		/* stop BG_GC if there is not enough free sections. */
9158c2ecf20Sopenharmony_ci		if (gc_type == BG_GC && has_not_enough_free_secs(sbi, 0, 0))
9168c2ecf20Sopenharmony_ci			return submitted;
9178c2ecf20Sopenharmony_ci
9188c2ecf20Sopenharmony_ci		if (check_valid_map(sbi, segno, off) == 0)
9198c2ecf20Sopenharmony_ci			continue;
9208c2ecf20Sopenharmony_ci
9218c2ecf20Sopenharmony_ci		if (phase == 0) {
9228c2ecf20Sopenharmony_ci			f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), 1,
9238c2ecf20Sopenharmony_ci							META_NAT, true);
9248c2ecf20Sopenharmony_ci			continue;
9258c2ecf20Sopenharmony_ci		}
9268c2ecf20Sopenharmony_ci
9278c2ecf20Sopenharmony_ci		if (phase == 1) {
9288c2ecf20Sopenharmony_ci			f2fs_ra_node_page(sbi, nid);
9298c2ecf20Sopenharmony_ci			continue;
9308c2ecf20Sopenharmony_ci		}
9318c2ecf20Sopenharmony_ci
9328c2ecf20Sopenharmony_ci		/* phase == 2 */
9338c2ecf20Sopenharmony_ci		node_page = f2fs_get_node_page(sbi, nid);
9348c2ecf20Sopenharmony_ci		if (IS_ERR(node_page))
9358c2ecf20Sopenharmony_ci			continue;
9368c2ecf20Sopenharmony_ci
9378c2ecf20Sopenharmony_ci		/* block may become invalid during f2fs_get_node_page */
9388c2ecf20Sopenharmony_ci		if (check_valid_map(sbi, segno, off) == 0) {
9398c2ecf20Sopenharmony_ci			f2fs_put_page(node_page, 1);
9408c2ecf20Sopenharmony_ci			continue;
9418c2ecf20Sopenharmony_ci		}
9428c2ecf20Sopenharmony_ci
9438c2ecf20Sopenharmony_ci		if (f2fs_get_node_info(sbi, nid, &ni)) {
9448c2ecf20Sopenharmony_ci			f2fs_put_page(node_page, 1);
9458c2ecf20Sopenharmony_ci			continue;
9468c2ecf20Sopenharmony_ci		}
9478c2ecf20Sopenharmony_ci
9488c2ecf20Sopenharmony_ci		if (ni.blk_addr != start_addr + off) {
9498c2ecf20Sopenharmony_ci			f2fs_put_page(node_page, 1);
9508c2ecf20Sopenharmony_ci			continue;
9518c2ecf20Sopenharmony_ci		}
9528c2ecf20Sopenharmony_ci
9538c2ecf20Sopenharmony_ci		err = f2fs_move_node_page(node_page, gc_type);
9548c2ecf20Sopenharmony_ci		if (!err && gc_type == FG_GC)
9558c2ecf20Sopenharmony_ci			submitted++;
9568c2ecf20Sopenharmony_ci		stat_inc_node_blk_count(sbi, 1, gc_type);
9578c2ecf20Sopenharmony_ci	}
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci	if (++phase < 3)
9608c2ecf20Sopenharmony_ci		goto next_step;
9618c2ecf20Sopenharmony_ci
9628c2ecf20Sopenharmony_ci	if (fggc)
9638c2ecf20Sopenharmony_ci		atomic_dec(&sbi->wb_sync_req[NODE]);
9648c2ecf20Sopenharmony_ci	return submitted;
9658c2ecf20Sopenharmony_ci}
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_ci/*
9688c2ecf20Sopenharmony_ci * Calculate start block index indicating the given node offset.
9698c2ecf20Sopenharmony_ci * Be careful, caller should give this node offset only indicating direct node
9708c2ecf20Sopenharmony_ci * blocks. If any node offsets, which point the other types of node blocks such
9718c2ecf20Sopenharmony_ci * as indirect or double indirect node blocks, are given, it must be a caller's
9728c2ecf20Sopenharmony_ci * bug.
9738c2ecf20Sopenharmony_ci */
9748c2ecf20Sopenharmony_ciblock_t f2fs_start_bidx_of_node(unsigned int node_ofs, struct inode *inode)
9758c2ecf20Sopenharmony_ci{
9768c2ecf20Sopenharmony_ci	unsigned int indirect_blks = 2 * NIDS_PER_BLOCK + 4;
9778c2ecf20Sopenharmony_ci	unsigned int bidx;
9788c2ecf20Sopenharmony_ci
9798c2ecf20Sopenharmony_ci	if (node_ofs == 0)
9808c2ecf20Sopenharmony_ci		return 0;
9818c2ecf20Sopenharmony_ci
9828c2ecf20Sopenharmony_ci	if (node_ofs <= 2) {
9838c2ecf20Sopenharmony_ci		bidx = node_ofs - 1;
9848c2ecf20Sopenharmony_ci	} else if (node_ofs <= indirect_blks) {
9858c2ecf20Sopenharmony_ci		int dec = (node_ofs - 4) / (NIDS_PER_BLOCK + 1);
9868c2ecf20Sopenharmony_ci		bidx = node_ofs - 2 - dec;
9878c2ecf20Sopenharmony_ci	} else {
9888c2ecf20Sopenharmony_ci		int dec = (node_ofs - indirect_blks - 3) / (NIDS_PER_BLOCK + 1);
9898c2ecf20Sopenharmony_ci		bidx = node_ofs - 5 - dec;
9908c2ecf20Sopenharmony_ci	}
9918c2ecf20Sopenharmony_ci	return bidx * ADDRS_PER_BLOCK(inode) + ADDRS_PER_INODE(inode);
9928c2ecf20Sopenharmony_ci}
9938c2ecf20Sopenharmony_ci
9948c2ecf20Sopenharmony_cistatic bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
9958c2ecf20Sopenharmony_ci		struct node_info *dni, block_t blkaddr, unsigned int *nofs)
9968c2ecf20Sopenharmony_ci{
9978c2ecf20Sopenharmony_ci	struct page *node_page;
9988c2ecf20Sopenharmony_ci	nid_t nid;
9998c2ecf20Sopenharmony_ci	unsigned int ofs_in_node, max_addrs, base;
10008c2ecf20Sopenharmony_ci	block_t source_blkaddr;
10018c2ecf20Sopenharmony_ci
10028c2ecf20Sopenharmony_ci	nid = le32_to_cpu(sum->nid);
10038c2ecf20Sopenharmony_ci	ofs_in_node = le16_to_cpu(sum->ofs_in_node);
10048c2ecf20Sopenharmony_ci
10058c2ecf20Sopenharmony_ci	node_page = f2fs_get_node_page(sbi, nid);
10068c2ecf20Sopenharmony_ci	if (IS_ERR(node_page))
10078c2ecf20Sopenharmony_ci		return false;
10088c2ecf20Sopenharmony_ci
10098c2ecf20Sopenharmony_ci	if (f2fs_get_node_info(sbi, nid, dni)) {
10108c2ecf20Sopenharmony_ci		f2fs_put_page(node_page, 1);
10118c2ecf20Sopenharmony_ci		return false;
10128c2ecf20Sopenharmony_ci	}
10138c2ecf20Sopenharmony_ci
10148c2ecf20Sopenharmony_ci	if (sum->version != dni->version) {
10158c2ecf20Sopenharmony_ci		f2fs_warn(sbi, "%s: valid data with mismatched node version.",
10168c2ecf20Sopenharmony_ci			  __func__);
10178c2ecf20Sopenharmony_ci		set_sbi_flag(sbi, SBI_NEED_FSCK);
10188c2ecf20Sopenharmony_ci	}
10198c2ecf20Sopenharmony_ci
10208c2ecf20Sopenharmony_ci	if (f2fs_check_nid_range(sbi, dni->ino)) {
10218c2ecf20Sopenharmony_ci		f2fs_put_page(node_page, 1);
10228c2ecf20Sopenharmony_ci		return false;
10238c2ecf20Sopenharmony_ci	}
10248c2ecf20Sopenharmony_ci
10258c2ecf20Sopenharmony_ci	if (IS_INODE(node_page)) {
10268c2ecf20Sopenharmony_ci		base = offset_in_addr(F2FS_INODE(node_page));
10278c2ecf20Sopenharmony_ci		max_addrs = DEF_ADDRS_PER_INODE;
10288c2ecf20Sopenharmony_ci	} else {
10298c2ecf20Sopenharmony_ci		base = 0;
10308c2ecf20Sopenharmony_ci		max_addrs = DEF_ADDRS_PER_BLOCK;
10318c2ecf20Sopenharmony_ci	}
10328c2ecf20Sopenharmony_ci
10338c2ecf20Sopenharmony_ci	if (base + ofs_in_node >= max_addrs) {
10348c2ecf20Sopenharmony_ci		f2fs_err(sbi, "Inconsistent blkaddr offset: base:%u, ofs_in_node:%u, max:%u, ino:%u, nid:%u",
10358c2ecf20Sopenharmony_ci			base, ofs_in_node, max_addrs, dni->ino, dni->nid);
10368c2ecf20Sopenharmony_ci		f2fs_put_page(node_page, 1);
10378c2ecf20Sopenharmony_ci		return false;
10388c2ecf20Sopenharmony_ci	}
10398c2ecf20Sopenharmony_ci
10408c2ecf20Sopenharmony_ci	*nofs = ofs_of_node(node_page);
10418c2ecf20Sopenharmony_ci	source_blkaddr = data_blkaddr(NULL, node_page, ofs_in_node);
10428c2ecf20Sopenharmony_ci	f2fs_put_page(node_page, 1);
10438c2ecf20Sopenharmony_ci
10448c2ecf20Sopenharmony_ci	if (source_blkaddr != blkaddr) {
10458c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_CHECK_FS
10468c2ecf20Sopenharmony_ci		unsigned int segno = GET_SEGNO(sbi, blkaddr);
10478c2ecf20Sopenharmony_ci		unsigned long offset = GET_BLKOFF_FROM_SEG0(sbi, blkaddr);
10488c2ecf20Sopenharmony_ci
10498c2ecf20Sopenharmony_ci		if (unlikely(check_valid_map(sbi, segno, offset))) {
10508c2ecf20Sopenharmony_ci			if (!test_and_set_bit(segno, SIT_I(sbi)->invalid_segmap)) {
10518c2ecf20Sopenharmony_ci				f2fs_err(sbi, "mismatched blkaddr %u (source_blkaddr %u) in seg %u\n",
10528c2ecf20Sopenharmony_ci						blkaddr, source_blkaddr, segno);
10538c2ecf20Sopenharmony_ci				set_sbi_flag(sbi, SBI_NEED_FSCK);
10548c2ecf20Sopenharmony_ci			}
10558c2ecf20Sopenharmony_ci		}
10568c2ecf20Sopenharmony_ci#endif
10578c2ecf20Sopenharmony_ci		return false;
10588c2ecf20Sopenharmony_ci	}
10598c2ecf20Sopenharmony_ci	return true;
10608c2ecf20Sopenharmony_ci}
10618c2ecf20Sopenharmony_ci
10628c2ecf20Sopenharmony_cistatic int ra_data_block(struct inode *inode, pgoff_t index)
10638c2ecf20Sopenharmony_ci{
10648c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
10658c2ecf20Sopenharmony_ci	struct address_space *mapping = inode->i_mapping;
10668c2ecf20Sopenharmony_ci	struct dnode_of_data dn;
10678c2ecf20Sopenharmony_ci	struct page *page;
10688c2ecf20Sopenharmony_ci	struct extent_info ei = {0, 0, 0};
10698c2ecf20Sopenharmony_ci	struct f2fs_io_info fio = {
10708c2ecf20Sopenharmony_ci		.sbi = sbi,
10718c2ecf20Sopenharmony_ci		.ino = inode->i_ino,
10728c2ecf20Sopenharmony_ci		.type = DATA,
10738c2ecf20Sopenharmony_ci		.temp = COLD,
10748c2ecf20Sopenharmony_ci		.op = REQ_OP_READ,
10758c2ecf20Sopenharmony_ci		.op_flags = 0,
10768c2ecf20Sopenharmony_ci		.encrypted_page = NULL,
10778c2ecf20Sopenharmony_ci		.in_list = false,
10788c2ecf20Sopenharmony_ci		.retry = false,
10798c2ecf20Sopenharmony_ci	};
10808c2ecf20Sopenharmony_ci	int err;
10818c2ecf20Sopenharmony_ci
10828c2ecf20Sopenharmony_ci	page = f2fs_grab_cache_page(mapping, index, true);
10838c2ecf20Sopenharmony_ci	if (!page)
10848c2ecf20Sopenharmony_ci		return -ENOMEM;
10858c2ecf20Sopenharmony_ci
10868c2ecf20Sopenharmony_ci	if (f2fs_lookup_extent_cache(inode, index, &ei)) {
10878c2ecf20Sopenharmony_ci		dn.data_blkaddr = ei.blk + index - ei.fofs;
10888c2ecf20Sopenharmony_ci		if (unlikely(!f2fs_is_valid_blkaddr(sbi, dn.data_blkaddr,
10898c2ecf20Sopenharmony_ci						DATA_GENERIC_ENHANCE_READ))) {
10908c2ecf20Sopenharmony_ci			err = -EFSCORRUPTED;
10918c2ecf20Sopenharmony_ci			goto put_page;
10928c2ecf20Sopenharmony_ci		}
10938c2ecf20Sopenharmony_ci		goto got_it;
10948c2ecf20Sopenharmony_ci	}
10958c2ecf20Sopenharmony_ci
10968c2ecf20Sopenharmony_ci	set_new_dnode(&dn, inode, NULL, NULL, 0);
10978c2ecf20Sopenharmony_ci	err = f2fs_get_dnode_of_data(&dn, index, LOOKUP_NODE);
10988c2ecf20Sopenharmony_ci	if (err)
10998c2ecf20Sopenharmony_ci		goto put_page;
11008c2ecf20Sopenharmony_ci	f2fs_put_dnode(&dn);
11018c2ecf20Sopenharmony_ci
11028c2ecf20Sopenharmony_ci	if (!__is_valid_data_blkaddr(dn.data_blkaddr)) {
11038c2ecf20Sopenharmony_ci		err = -ENOENT;
11048c2ecf20Sopenharmony_ci		goto put_page;
11058c2ecf20Sopenharmony_ci	}
11068c2ecf20Sopenharmony_ci	if (unlikely(!f2fs_is_valid_blkaddr(sbi, dn.data_blkaddr,
11078c2ecf20Sopenharmony_ci						DATA_GENERIC_ENHANCE))) {
11088c2ecf20Sopenharmony_ci		err = -EFSCORRUPTED;
11098c2ecf20Sopenharmony_ci		goto put_page;
11108c2ecf20Sopenharmony_ci	}
11118c2ecf20Sopenharmony_cigot_it:
11128c2ecf20Sopenharmony_ci	/* read page */
11138c2ecf20Sopenharmony_ci	fio.page = page;
11148c2ecf20Sopenharmony_ci	fio.new_blkaddr = fio.old_blkaddr = dn.data_blkaddr;
11158c2ecf20Sopenharmony_ci
11168c2ecf20Sopenharmony_ci	/*
11178c2ecf20Sopenharmony_ci	 * don't cache encrypted data into meta inode until previous dirty
11188c2ecf20Sopenharmony_ci	 * data were writebacked to avoid racing between GC and flush.
11198c2ecf20Sopenharmony_ci	 */
11208c2ecf20Sopenharmony_ci	f2fs_wait_on_page_writeback(page, DATA, true, true);
11218c2ecf20Sopenharmony_ci
11228c2ecf20Sopenharmony_ci	f2fs_wait_on_block_writeback(inode, dn.data_blkaddr);
11238c2ecf20Sopenharmony_ci
11248c2ecf20Sopenharmony_ci	fio.encrypted_page = f2fs_pagecache_get_page(META_MAPPING(sbi),
11258c2ecf20Sopenharmony_ci					dn.data_blkaddr,
11268c2ecf20Sopenharmony_ci					FGP_LOCK | FGP_CREAT, GFP_NOFS);
11278c2ecf20Sopenharmony_ci	if (!fio.encrypted_page) {
11288c2ecf20Sopenharmony_ci		err = -ENOMEM;
11298c2ecf20Sopenharmony_ci		goto put_page;
11308c2ecf20Sopenharmony_ci	}
11318c2ecf20Sopenharmony_ci
11328c2ecf20Sopenharmony_ci	err = f2fs_submit_page_bio(&fio);
11338c2ecf20Sopenharmony_ci	if (err)
11348c2ecf20Sopenharmony_ci		goto put_encrypted_page;
11358c2ecf20Sopenharmony_ci	f2fs_put_page(fio.encrypted_page, 0);
11368c2ecf20Sopenharmony_ci	f2fs_put_page(page, 1);
11378c2ecf20Sopenharmony_ci
11388c2ecf20Sopenharmony_ci	f2fs_update_iostat(sbi, FS_DATA_READ_IO, F2FS_BLKSIZE);
11398c2ecf20Sopenharmony_ci	f2fs_update_iostat(sbi, FS_GDATA_READ_IO, F2FS_BLKSIZE);
11408c2ecf20Sopenharmony_ci
11418c2ecf20Sopenharmony_ci	return 0;
11428c2ecf20Sopenharmony_ciput_encrypted_page:
11438c2ecf20Sopenharmony_ci	f2fs_put_page(fio.encrypted_page, 1);
11448c2ecf20Sopenharmony_ciput_page:
11458c2ecf20Sopenharmony_ci	f2fs_put_page(page, 1);
11468c2ecf20Sopenharmony_ci	return err;
11478c2ecf20Sopenharmony_ci}
11488c2ecf20Sopenharmony_ci
11498c2ecf20Sopenharmony_ci/*
11508c2ecf20Sopenharmony_ci * Move data block via META_MAPPING while keeping locked data page.
11518c2ecf20Sopenharmony_ci * This can be used to move blocks, aka LBAs, directly on disk.
11528c2ecf20Sopenharmony_ci */
11538c2ecf20Sopenharmony_cistatic int move_data_block(struct inode *inode, block_t bidx,
11548c2ecf20Sopenharmony_ci				int gc_type, unsigned int segno, int off)
11558c2ecf20Sopenharmony_ci{
11568c2ecf20Sopenharmony_ci	struct f2fs_io_info fio = {
11578c2ecf20Sopenharmony_ci		.sbi = F2FS_I_SB(inode),
11588c2ecf20Sopenharmony_ci		.ino = inode->i_ino,
11598c2ecf20Sopenharmony_ci		.type = DATA,
11608c2ecf20Sopenharmony_ci		.temp = COLD,
11618c2ecf20Sopenharmony_ci		.op = REQ_OP_READ,
11628c2ecf20Sopenharmony_ci		.op_flags = 0,
11638c2ecf20Sopenharmony_ci		.encrypted_page = NULL,
11648c2ecf20Sopenharmony_ci		.in_list = false,
11658c2ecf20Sopenharmony_ci		.retry = false,
11668c2ecf20Sopenharmony_ci	};
11678c2ecf20Sopenharmony_ci	struct dnode_of_data dn;
11688c2ecf20Sopenharmony_ci	struct f2fs_summary sum;
11698c2ecf20Sopenharmony_ci	struct node_info ni;
11708c2ecf20Sopenharmony_ci	struct page *page, *mpage;
11718c2ecf20Sopenharmony_ci	block_t newaddr;
11728c2ecf20Sopenharmony_ci	int err = 0;
11738c2ecf20Sopenharmony_ci	bool lfs_mode = f2fs_lfs_mode(fio.sbi);
11748c2ecf20Sopenharmony_ci	int type = fio.sbi->am.atgc_enabled ?
11758c2ecf20Sopenharmony_ci				CURSEG_ALL_DATA_ATGC : CURSEG_COLD_DATA;
11768c2ecf20Sopenharmony_ci
11778c2ecf20Sopenharmony_ci	/* do not read out */
11788c2ecf20Sopenharmony_ci	page = f2fs_grab_cache_page(inode->i_mapping, bidx, false);
11798c2ecf20Sopenharmony_ci	if (!page)
11808c2ecf20Sopenharmony_ci		return -ENOMEM;
11818c2ecf20Sopenharmony_ci
11828c2ecf20Sopenharmony_ci	if (!check_valid_map(F2FS_I_SB(inode), segno, off)) {
11838c2ecf20Sopenharmony_ci		err = -ENOENT;
11848c2ecf20Sopenharmony_ci		goto out;
11858c2ecf20Sopenharmony_ci	}
11868c2ecf20Sopenharmony_ci
11878c2ecf20Sopenharmony_ci	if (f2fs_is_atomic_file(inode)) {
11888c2ecf20Sopenharmony_ci		F2FS_I(inode)->i_gc_failures[GC_FAILURE_ATOMIC]++;
11898c2ecf20Sopenharmony_ci		F2FS_I_SB(inode)->skipped_atomic_files[gc_type]++;
11908c2ecf20Sopenharmony_ci		err = -EAGAIN;
11918c2ecf20Sopenharmony_ci		goto out;
11928c2ecf20Sopenharmony_ci	}
11938c2ecf20Sopenharmony_ci
11948c2ecf20Sopenharmony_ci	if (f2fs_is_pinned_file(inode)) {
11958c2ecf20Sopenharmony_ci		if (gc_type == FG_GC)
11968c2ecf20Sopenharmony_ci			f2fs_pin_file_control(inode, true);
11978c2ecf20Sopenharmony_ci		err = -EAGAIN;
11988c2ecf20Sopenharmony_ci		goto out;
11998c2ecf20Sopenharmony_ci	}
12008c2ecf20Sopenharmony_ci
12018c2ecf20Sopenharmony_ci	set_new_dnode(&dn, inode, NULL, NULL, 0);
12028c2ecf20Sopenharmony_ci	err = f2fs_get_dnode_of_data(&dn, bidx, LOOKUP_NODE);
12038c2ecf20Sopenharmony_ci	if (err)
12048c2ecf20Sopenharmony_ci		goto out;
12058c2ecf20Sopenharmony_ci
12068c2ecf20Sopenharmony_ci	if (unlikely(dn.data_blkaddr == NULL_ADDR)) {
12078c2ecf20Sopenharmony_ci		ClearPageUptodate(page);
12088c2ecf20Sopenharmony_ci		err = -ENOENT;
12098c2ecf20Sopenharmony_ci		goto put_out;
12108c2ecf20Sopenharmony_ci	}
12118c2ecf20Sopenharmony_ci
12128c2ecf20Sopenharmony_ci	/*
12138c2ecf20Sopenharmony_ci	 * don't cache encrypted data into meta inode until previous dirty
12148c2ecf20Sopenharmony_ci	 * data were writebacked to avoid racing between GC and flush.
12158c2ecf20Sopenharmony_ci	 */
12168c2ecf20Sopenharmony_ci	f2fs_wait_on_page_writeback(page, DATA, true, true);
12178c2ecf20Sopenharmony_ci
12188c2ecf20Sopenharmony_ci	f2fs_wait_on_block_writeback(inode, dn.data_blkaddr);
12198c2ecf20Sopenharmony_ci
12208c2ecf20Sopenharmony_ci	err = f2fs_get_node_info(fio.sbi, dn.nid, &ni);
12218c2ecf20Sopenharmony_ci	if (err)
12228c2ecf20Sopenharmony_ci		goto put_out;
12238c2ecf20Sopenharmony_ci
12248c2ecf20Sopenharmony_ci	set_summary(&sum, dn.nid, dn.ofs_in_node, ni.version);
12258c2ecf20Sopenharmony_ci
12268c2ecf20Sopenharmony_ci	/* read page */
12278c2ecf20Sopenharmony_ci	fio.page = page;
12288c2ecf20Sopenharmony_ci	fio.new_blkaddr = fio.old_blkaddr = dn.data_blkaddr;
12298c2ecf20Sopenharmony_ci
12308c2ecf20Sopenharmony_ci	if (lfs_mode)
12318c2ecf20Sopenharmony_ci		down_write(&fio.sbi->io_order_lock);
12328c2ecf20Sopenharmony_ci
12338c2ecf20Sopenharmony_ci	mpage = f2fs_grab_cache_page(META_MAPPING(fio.sbi),
12348c2ecf20Sopenharmony_ci					fio.old_blkaddr, false);
12358c2ecf20Sopenharmony_ci	if (!mpage) {
12368c2ecf20Sopenharmony_ci		err = -ENOMEM;
12378c2ecf20Sopenharmony_ci		goto up_out;
12388c2ecf20Sopenharmony_ci	}
12398c2ecf20Sopenharmony_ci
12408c2ecf20Sopenharmony_ci	fio.encrypted_page = mpage;
12418c2ecf20Sopenharmony_ci
12428c2ecf20Sopenharmony_ci	/* read source block in mpage */
12438c2ecf20Sopenharmony_ci	if (!PageUptodate(mpage)) {
12448c2ecf20Sopenharmony_ci		err = f2fs_submit_page_bio(&fio);
12458c2ecf20Sopenharmony_ci		if (err) {
12468c2ecf20Sopenharmony_ci			f2fs_put_page(mpage, 1);
12478c2ecf20Sopenharmony_ci			goto up_out;
12488c2ecf20Sopenharmony_ci		}
12498c2ecf20Sopenharmony_ci
12508c2ecf20Sopenharmony_ci		f2fs_update_iostat(fio.sbi, FS_DATA_READ_IO, F2FS_BLKSIZE);
12518c2ecf20Sopenharmony_ci		f2fs_update_iostat(fio.sbi, FS_GDATA_READ_IO, F2FS_BLKSIZE);
12528c2ecf20Sopenharmony_ci
12538c2ecf20Sopenharmony_ci		lock_page(mpage);
12548c2ecf20Sopenharmony_ci		if (unlikely(mpage->mapping != META_MAPPING(fio.sbi) ||
12558c2ecf20Sopenharmony_ci						!PageUptodate(mpage))) {
12568c2ecf20Sopenharmony_ci			err = -EIO;
12578c2ecf20Sopenharmony_ci			f2fs_put_page(mpage, 1);
12588c2ecf20Sopenharmony_ci			goto up_out;
12598c2ecf20Sopenharmony_ci		}
12608c2ecf20Sopenharmony_ci	}
12618c2ecf20Sopenharmony_ci
12628c2ecf20Sopenharmony_ci	f2fs_allocate_data_block(fio.sbi, NULL, fio.old_blkaddr, &newaddr,
12638c2ecf20Sopenharmony_ci				&sum, type, NULL, SEQ_NONE);
12648c2ecf20Sopenharmony_ci
12658c2ecf20Sopenharmony_ci	fio.encrypted_page = f2fs_pagecache_get_page(META_MAPPING(fio.sbi),
12668c2ecf20Sopenharmony_ci				newaddr, FGP_LOCK | FGP_CREAT, GFP_NOFS);
12678c2ecf20Sopenharmony_ci	if (!fio.encrypted_page) {
12688c2ecf20Sopenharmony_ci		err = -ENOMEM;
12698c2ecf20Sopenharmony_ci		f2fs_put_page(mpage, 1);
12708c2ecf20Sopenharmony_ci		goto recover_block;
12718c2ecf20Sopenharmony_ci	}
12728c2ecf20Sopenharmony_ci
12738c2ecf20Sopenharmony_ci	/* write target block */
12748c2ecf20Sopenharmony_ci	f2fs_wait_on_page_writeback(fio.encrypted_page, DATA, true, true);
12758c2ecf20Sopenharmony_ci	memcpy(page_address(fio.encrypted_page),
12768c2ecf20Sopenharmony_ci				page_address(mpage), PAGE_SIZE);
12778c2ecf20Sopenharmony_ci	f2fs_put_page(mpage, 1);
12788c2ecf20Sopenharmony_ci	invalidate_mapping_pages(META_MAPPING(fio.sbi),
12798c2ecf20Sopenharmony_ci				fio.old_blkaddr, fio.old_blkaddr);
12808c2ecf20Sopenharmony_ci
12818c2ecf20Sopenharmony_ci	set_page_dirty(fio.encrypted_page);
12828c2ecf20Sopenharmony_ci	if (clear_page_dirty_for_io(fio.encrypted_page))
12838c2ecf20Sopenharmony_ci		dec_page_count(fio.sbi, F2FS_DIRTY_META);
12848c2ecf20Sopenharmony_ci
12858c2ecf20Sopenharmony_ci	set_page_writeback(fio.encrypted_page);
12868c2ecf20Sopenharmony_ci	ClearPageError(page);
12878c2ecf20Sopenharmony_ci
12888c2ecf20Sopenharmony_ci	/* allocate block address */
12898c2ecf20Sopenharmony_ci	f2fs_wait_on_page_writeback(dn.node_page, NODE, true, true);
12908c2ecf20Sopenharmony_ci
12918c2ecf20Sopenharmony_ci	fio.op = REQ_OP_WRITE;
12928c2ecf20Sopenharmony_ci	fio.op_flags = REQ_SYNC;
12938c2ecf20Sopenharmony_ci	fio.new_blkaddr = newaddr;
12948c2ecf20Sopenharmony_ci	f2fs_submit_page_write(&fio);
12958c2ecf20Sopenharmony_ci	if (fio.retry) {
12968c2ecf20Sopenharmony_ci		err = -EAGAIN;
12978c2ecf20Sopenharmony_ci		if (PageWriteback(fio.encrypted_page))
12988c2ecf20Sopenharmony_ci			end_page_writeback(fio.encrypted_page);
12998c2ecf20Sopenharmony_ci		goto put_page_out;
13008c2ecf20Sopenharmony_ci	}
13018c2ecf20Sopenharmony_ci
13028c2ecf20Sopenharmony_ci	f2fs_update_iostat(fio.sbi, FS_GC_DATA_IO, F2FS_BLKSIZE);
13038c2ecf20Sopenharmony_ci
13048c2ecf20Sopenharmony_ci	f2fs_update_data_blkaddr(&dn, newaddr);
13058c2ecf20Sopenharmony_ci	set_inode_flag(inode, FI_APPEND_WRITE);
13068c2ecf20Sopenharmony_ci	if (page->index == 0)
13078c2ecf20Sopenharmony_ci		set_inode_flag(inode, FI_FIRST_BLOCK_WRITTEN);
13088c2ecf20Sopenharmony_ciput_page_out:
13098c2ecf20Sopenharmony_ci	f2fs_put_page(fio.encrypted_page, 1);
13108c2ecf20Sopenharmony_cirecover_block:
13118c2ecf20Sopenharmony_ci	if (err)
13128c2ecf20Sopenharmony_ci		f2fs_do_replace_block(fio.sbi, &sum, newaddr, fio.old_blkaddr,
13138c2ecf20Sopenharmony_ci							true, true, true);
13148c2ecf20Sopenharmony_ciup_out:
13158c2ecf20Sopenharmony_ci	if (lfs_mode)
13168c2ecf20Sopenharmony_ci		up_write(&fio.sbi->io_order_lock);
13178c2ecf20Sopenharmony_ciput_out:
13188c2ecf20Sopenharmony_ci	f2fs_put_dnode(&dn);
13198c2ecf20Sopenharmony_ciout:
13208c2ecf20Sopenharmony_ci	f2fs_put_page(page, 1);
13218c2ecf20Sopenharmony_ci	return err;
13228c2ecf20Sopenharmony_ci}
13238c2ecf20Sopenharmony_ci
13248c2ecf20Sopenharmony_cistatic int move_data_page(struct inode *inode, block_t bidx, int gc_type,
13258c2ecf20Sopenharmony_ci							unsigned int segno, int off)
13268c2ecf20Sopenharmony_ci{
13278c2ecf20Sopenharmony_ci	struct page *page;
13288c2ecf20Sopenharmony_ci	int err = 0;
13298c2ecf20Sopenharmony_ci
13308c2ecf20Sopenharmony_ci	page = f2fs_get_lock_data_page(inode, bidx, true);
13318c2ecf20Sopenharmony_ci	if (IS_ERR(page))
13328c2ecf20Sopenharmony_ci		return PTR_ERR(page);
13338c2ecf20Sopenharmony_ci
13348c2ecf20Sopenharmony_ci	if (!check_valid_map(F2FS_I_SB(inode), segno, off)) {
13358c2ecf20Sopenharmony_ci		err = -ENOENT;
13368c2ecf20Sopenharmony_ci		goto out;
13378c2ecf20Sopenharmony_ci	}
13388c2ecf20Sopenharmony_ci
13398c2ecf20Sopenharmony_ci	if (f2fs_is_atomic_file(inode)) {
13408c2ecf20Sopenharmony_ci		F2FS_I(inode)->i_gc_failures[GC_FAILURE_ATOMIC]++;
13418c2ecf20Sopenharmony_ci		F2FS_I_SB(inode)->skipped_atomic_files[gc_type]++;
13428c2ecf20Sopenharmony_ci		err = -EAGAIN;
13438c2ecf20Sopenharmony_ci		goto out;
13448c2ecf20Sopenharmony_ci	}
13458c2ecf20Sopenharmony_ci	if (f2fs_is_pinned_file(inode)) {
13468c2ecf20Sopenharmony_ci		if (gc_type == FG_GC)
13478c2ecf20Sopenharmony_ci			f2fs_pin_file_control(inode, true);
13488c2ecf20Sopenharmony_ci		err = -EAGAIN;
13498c2ecf20Sopenharmony_ci		goto out;
13508c2ecf20Sopenharmony_ci	}
13518c2ecf20Sopenharmony_ci
13528c2ecf20Sopenharmony_ci	if (gc_type == BG_GC) {
13538c2ecf20Sopenharmony_ci		if (PageWriteback(page)) {
13548c2ecf20Sopenharmony_ci			err = -EAGAIN;
13558c2ecf20Sopenharmony_ci			goto out;
13568c2ecf20Sopenharmony_ci		}
13578c2ecf20Sopenharmony_ci		set_page_dirty(page);
13588c2ecf20Sopenharmony_ci		set_cold_data(page);
13598c2ecf20Sopenharmony_ci	} else {
13608c2ecf20Sopenharmony_ci		struct f2fs_io_info fio = {
13618c2ecf20Sopenharmony_ci			.sbi = F2FS_I_SB(inode),
13628c2ecf20Sopenharmony_ci			.ino = inode->i_ino,
13638c2ecf20Sopenharmony_ci			.type = DATA,
13648c2ecf20Sopenharmony_ci			.temp = COLD,
13658c2ecf20Sopenharmony_ci			.op = REQ_OP_WRITE,
13668c2ecf20Sopenharmony_ci			.op_flags = REQ_SYNC,
13678c2ecf20Sopenharmony_ci			.old_blkaddr = NULL_ADDR,
13688c2ecf20Sopenharmony_ci			.page = page,
13698c2ecf20Sopenharmony_ci			.encrypted_page = NULL,
13708c2ecf20Sopenharmony_ci			.need_lock = LOCK_REQ,
13718c2ecf20Sopenharmony_ci			.io_type = FS_GC_DATA_IO,
13728c2ecf20Sopenharmony_ci		};
13738c2ecf20Sopenharmony_ci		bool is_dirty = PageDirty(page);
13748c2ecf20Sopenharmony_ci
13758c2ecf20Sopenharmony_ciretry:
13768c2ecf20Sopenharmony_ci		f2fs_wait_on_page_writeback(page, DATA, true, true);
13778c2ecf20Sopenharmony_ci
13788c2ecf20Sopenharmony_ci		set_page_dirty(page);
13798c2ecf20Sopenharmony_ci		if (clear_page_dirty_for_io(page)) {
13808c2ecf20Sopenharmony_ci			inode_dec_dirty_pages(inode);
13818c2ecf20Sopenharmony_ci			f2fs_remove_dirty_inode(inode);
13828c2ecf20Sopenharmony_ci		}
13838c2ecf20Sopenharmony_ci
13848c2ecf20Sopenharmony_ci		set_cold_data(page);
13858c2ecf20Sopenharmony_ci
13868c2ecf20Sopenharmony_ci		err = f2fs_do_write_data_page(&fio);
13878c2ecf20Sopenharmony_ci		if (err) {
13888c2ecf20Sopenharmony_ci			clear_cold_data(page);
13898c2ecf20Sopenharmony_ci			if (err == -ENOMEM) {
13908c2ecf20Sopenharmony_ci				congestion_wait(BLK_RW_ASYNC,
13918c2ecf20Sopenharmony_ci						DEFAULT_IO_TIMEOUT);
13928c2ecf20Sopenharmony_ci				goto retry;
13938c2ecf20Sopenharmony_ci			}
13948c2ecf20Sopenharmony_ci			if (is_dirty)
13958c2ecf20Sopenharmony_ci				set_page_dirty(page);
13968c2ecf20Sopenharmony_ci		}
13978c2ecf20Sopenharmony_ci	}
13988c2ecf20Sopenharmony_ciout:
13998c2ecf20Sopenharmony_ci	f2fs_put_page(page, 1);
14008c2ecf20Sopenharmony_ci	return err;
14018c2ecf20Sopenharmony_ci}
14028c2ecf20Sopenharmony_ci
14038c2ecf20Sopenharmony_ci/*
14048c2ecf20Sopenharmony_ci * This function tries to get parent node of victim data block, and identifies
14058c2ecf20Sopenharmony_ci * data block validity. If the block is valid, copy that with cold status and
14068c2ecf20Sopenharmony_ci * modify parent node.
14078c2ecf20Sopenharmony_ci * If the parent node is not valid or the data block address is different,
14088c2ecf20Sopenharmony_ci * the victim data block is ignored.
14098c2ecf20Sopenharmony_ci */
14108c2ecf20Sopenharmony_cistatic int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
14118c2ecf20Sopenharmony_ci		struct gc_inode_list *gc_list, unsigned int segno, int gc_type,
14128c2ecf20Sopenharmony_ci		bool force_migrate)
14138c2ecf20Sopenharmony_ci{
14148c2ecf20Sopenharmony_ci	struct super_block *sb = sbi->sb;
14158c2ecf20Sopenharmony_ci	struct f2fs_summary *entry;
14168c2ecf20Sopenharmony_ci	block_t start_addr;
14178c2ecf20Sopenharmony_ci	int off;
14188c2ecf20Sopenharmony_ci	int phase = 0;
14198c2ecf20Sopenharmony_ci	int submitted = 0;
14208c2ecf20Sopenharmony_ci	unsigned int usable_blks_in_seg = f2fs_usable_blks_in_seg(sbi, segno);
14218c2ecf20Sopenharmony_ci
14228c2ecf20Sopenharmony_ci	start_addr = START_BLOCK(sbi, segno);
14238c2ecf20Sopenharmony_ci
14248c2ecf20Sopenharmony_cinext_step:
14258c2ecf20Sopenharmony_ci	entry = sum;
14268c2ecf20Sopenharmony_ci
14278c2ecf20Sopenharmony_ci	for (off = 0; off < usable_blks_in_seg; off++, entry++) {
14288c2ecf20Sopenharmony_ci		struct page *data_page;
14298c2ecf20Sopenharmony_ci		struct inode *inode;
14308c2ecf20Sopenharmony_ci		struct node_info dni; /* dnode info for the data */
14318c2ecf20Sopenharmony_ci		unsigned int ofs_in_node, nofs;
14328c2ecf20Sopenharmony_ci		block_t start_bidx;
14338c2ecf20Sopenharmony_ci		nid_t nid = le32_to_cpu(entry->nid);
14348c2ecf20Sopenharmony_ci
14358c2ecf20Sopenharmony_ci		/*
14368c2ecf20Sopenharmony_ci		 * stop BG_GC if there is not enough free sections.
14378c2ecf20Sopenharmony_ci		 * Or, stop GC if the segment becomes fully valid caused by
14388c2ecf20Sopenharmony_ci		 * race condition along with SSR block allocation.
14398c2ecf20Sopenharmony_ci		 */
14408c2ecf20Sopenharmony_ci		if ((gc_type == BG_GC && has_not_enough_free_secs(sbi, 0, 0)) ||
14418c2ecf20Sopenharmony_ci			(!force_migrate && get_valid_blocks(sbi, segno, true) ==
14428c2ecf20Sopenharmony_ci							BLKS_PER_SEC(sbi)))
14438c2ecf20Sopenharmony_ci			return submitted;
14448c2ecf20Sopenharmony_ci
14458c2ecf20Sopenharmony_ci		if (check_valid_map(sbi, segno, off) == 0)
14468c2ecf20Sopenharmony_ci			continue;
14478c2ecf20Sopenharmony_ci
14488c2ecf20Sopenharmony_ci		if (phase == 0) {
14498c2ecf20Sopenharmony_ci			f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), 1,
14508c2ecf20Sopenharmony_ci							META_NAT, true);
14518c2ecf20Sopenharmony_ci			continue;
14528c2ecf20Sopenharmony_ci		}
14538c2ecf20Sopenharmony_ci
14548c2ecf20Sopenharmony_ci		if (phase == 1) {
14558c2ecf20Sopenharmony_ci			f2fs_ra_node_page(sbi, nid);
14568c2ecf20Sopenharmony_ci			continue;
14578c2ecf20Sopenharmony_ci		}
14588c2ecf20Sopenharmony_ci
14598c2ecf20Sopenharmony_ci		/* Get an inode by ino with checking validity */
14608c2ecf20Sopenharmony_ci		if (!is_alive(sbi, entry, &dni, start_addr + off, &nofs))
14618c2ecf20Sopenharmony_ci			continue;
14628c2ecf20Sopenharmony_ci
14638c2ecf20Sopenharmony_ci		if (phase == 2) {
14648c2ecf20Sopenharmony_ci			f2fs_ra_node_page(sbi, dni.ino);
14658c2ecf20Sopenharmony_ci			continue;
14668c2ecf20Sopenharmony_ci		}
14678c2ecf20Sopenharmony_ci
14688c2ecf20Sopenharmony_ci		ofs_in_node = le16_to_cpu(entry->ofs_in_node);
14698c2ecf20Sopenharmony_ci
14708c2ecf20Sopenharmony_ci		if (phase == 3) {
14718c2ecf20Sopenharmony_ci			inode = f2fs_iget(sb, dni.ino);
14728c2ecf20Sopenharmony_ci			if (IS_ERR(inode) || is_bad_inode(inode) ||
14738c2ecf20Sopenharmony_ci					special_file(inode->i_mode)) {
14748c2ecf20Sopenharmony_ci				set_sbi_flag(sbi, SBI_NEED_FSCK);
14758c2ecf20Sopenharmony_ci				continue;
14768c2ecf20Sopenharmony_ci			}
14778c2ecf20Sopenharmony_ci
14788c2ecf20Sopenharmony_ci			if (!down_write_trylock(
14798c2ecf20Sopenharmony_ci				&F2FS_I(inode)->i_gc_rwsem[WRITE])) {
14808c2ecf20Sopenharmony_ci				iput(inode);
14818c2ecf20Sopenharmony_ci				sbi->skipped_gc_rwsem++;
14828c2ecf20Sopenharmony_ci				continue;
14838c2ecf20Sopenharmony_ci			}
14848c2ecf20Sopenharmony_ci
14858c2ecf20Sopenharmony_ci			start_bidx = f2fs_start_bidx_of_node(nofs, inode) +
14868c2ecf20Sopenharmony_ci								ofs_in_node;
14878c2ecf20Sopenharmony_ci
14888c2ecf20Sopenharmony_ci			if (f2fs_post_read_required(inode)) {
14898c2ecf20Sopenharmony_ci				int err = ra_data_block(inode, start_bidx);
14908c2ecf20Sopenharmony_ci
14918c2ecf20Sopenharmony_ci				up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
14928c2ecf20Sopenharmony_ci				if (err) {
14938c2ecf20Sopenharmony_ci					iput(inode);
14948c2ecf20Sopenharmony_ci					continue;
14958c2ecf20Sopenharmony_ci				}
14968c2ecf20Sopenharmony_ci				add_gc_inode(gc_list, inode);
14978c2ecf20Sopenharmony_ci				continue;
14988c2ecf20Sopenharmony_ci			}
14998c2ecf20Sopenharmony_ci
15008c2ecf20Sopenharmony_ci			data_page = f2fs_get_read_data_page(inode,
15018c2ecf20Sopenharmony_ci						start_bidx, REQ_RAHEAD, true);
15028c2ecf20Sopenharmony_ci			up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
15038c2ecf20Sopenharmony_ci			if (IS_ERR(data_page)) {
15048c2ecf20Sopenharmony_ci				iput(inode);
15058c2ecf20Sopenharmony_ci				continue;
15068c2ecf20Sopenharmony_ci			}
15078c2ecf20Sopenharmony_ci
15088c2ecf20Sopenharmony_ci			f2fs_put_page(data_page, 0);
15098c2ecf20Sopenharmony_ci			add_gc_inode(gc_list, inode);
15108c2ecf20Sopenharmony_ci			continue;
15118c2ecf20Sopenharmony_ci		}
15128c2ecf20Sopenharmony_ci
15138c2ecf20Sopenharmony_ci		/* phase 4 */
15148c2ecf20Sopenharmony_ci		inode = find_gc_inode(gc_list, dni.ino);
15158c2ecf20Sopenharmony_ci		if (inode) {
15168c2ecf20Sopenharmony_ci			struct f2fs_inode_info *fi = F2FS_I(inode);
15178c2ecf20Sopenharmony_ci			bool locked = false;
15188c2ecf20Sopenharmony_ci			int err;
15198c2ecf20Sopenharmony_ci
15208c2ecf20Sopenharmony_ci			if (S_ISREG(inode->i_mode)) {
15218c2ecf20Sopenharmony_ci				if (!down_write_trylock(&fi->i_gc_rwsem[READ])) {
15228c2ecf20Sopenharmony_ci					sbi->skipped_gc_rwsem++;
15238c2ecf20Sopenharmony_ci					continue;
15248c2ecf20Sopenharmony_ci				}
15258c2ecf20Sopenharmony_ci				if (!down_write_trylock(
15268c2ecf20Sopenharmony_ci						&fi->i_gc_rwsem[WRITE])) {
15278c2ecf20Sopenharmony_ci					sbi->skipped_gc_rwsem++;
15288c2ecf20Sopenharmony_ci					up_write(&fi->i_gc_rwsem[READ]);
15298c2ecf20Sopenharmony_ci					continue;
15308c2ecf20Sopenharmony_ci				}
15318c2ecf20Sopenharmony_ci				locked = true;
15328c2ecf20Sopenharmony_ci
15338c2ecf20Sopenharmony_ci				/* wait for all inflight aio data */
15348c2ecf20Sopenharmony_ci				inode_dio_wait(inode);
15358c2ecf20Sopenharmony_ci			}
15368c2ecf20Sopenharmony_ci
15378c2ecf20Sopenharmony_ci			start_bidx = f2fs_start_bidx_of_node(nofs, inode)
15388c2ecf20Sopenharmony_ci								+ ofs_in_node;
15398c2ecf20Sopenharmony_ci			if (f2fs_post_read_required(inode))
15408c2ecf20Sopenharmony_ci				err = move_data_block(inode, start_bidx,
15418c2ecf20Sopenharmony_ci							gc_type, segno, off);
15428c2ecf20Sopenharmony_ci			else
15438c2ecf20Sopenharmony_ci				err = move_data_page(inode, start_bidx, gc_type,
15448c2ecf20Sopenharmony_ci								segno, off);
15458c2ecf20Sopenharmony_ci
15468c2ecf20Sopenharmony_ci			if (!err && (gc_type == FG_GC ||
15478c2ecf20Sopenharmony_ci					f2fs_post_read_required(inode)))
15488c2ecf20Sopenharmony_ci				submitted++;
15498c2ecf20Sopenharmony_ci
15508c2ecf20Sopenharmony_ci			if (locked) {
15518c2ecf20Sopenharmony_ci				up_write(&fi->i_gc_rwsem[WRITE]);
15528c2ecf20Sopenharmony_ci				up_write(&fi->i_gc_rwsem[READ]);
15538c2ecf20Sopenharmony_ci			}
15548c2ecf20Sopenharmony_ci
15558c2ecf20Sopenharmony_ci			stat_inc_data_blk_count(sbi, 1, gc_type);
15568c2ecf20Sopenharmony_ci		}
15578c2ecf20Sopenharmony_ci	}
15588c2ecf20Sopenharmony_ci
15598c2ecf20Sopenharmony_ci	if (++phase < 5)
15608c2ecf20Sopenharmony_ci		goto next_step;
15618c2ecf20Sopenharmony_ci
15628c2ecf20Sopenharmony_ci	return submitted;
15638c2ecf20Sopenharmony_ci}
15648c2ecf20Sopenharmony_ci
15658c2ecf20Sopenharmony_cistatic int __get_victim(struct f2fs_sb_info *sbi, unsigned int *victim,
15668c2ecf20Sopenharmony_ci			int gc_type)
15678c2ecf20Sopenharmony_ci{
15688c2ecf20Sopenharmony_ci	struct sit_info *sit_i = SIT_I(sbi);
15698c2ecf20Sopenharmony_ci	int ret;
15708c2ecf20Sopenharmony_ci
15718c2ecf20Sopenharmony_ci	down_write(&sit_i->sentry_lock);
15728c2ecf20Sopenharmony_ci	ret = DIRTY_I(sbi)->v_ops->get_victim(sbi, victim, gc_type,
15738c2ecf20Sopenharmony_ci					      NO_CHECK_TYPE, LFS, 0);
15748c2ecf20Sopenharmony_ci	up_write(&sit_i->sentry_lock);
15758c2ecf20Sopenharmony_ci	return ret;
15768c2ecf20Sopenharmony_ci}
15778c2ecf20Sopenharmony_ci
15788c2ecf20Sopenharmony_cistatic int do_garbage_collect(struct f2fs_sb_info *sbi,
15798c2ecf20Sopenharmony_ci				unsigned int start_segno,
15808c2ecf20Sopenharmony_ci				struct gc_inode_list *gc_list, int gc_type,
15818c2ecf20Sopenharmony_ci				bool force_migrate)
15828c2ecf20Sopenharmony_ci{
15838c2ecf20Sopenharmony_ci	struct page *sum_page;
15848c2ecf20Sopenharmony_ci	struct f2fs_summary_block *sum;
15858c2ecf20Sopenharmony_ci	struct blk_plug plug;
15868c2ecf20Sopenharmony_ci	unsigned int segno = start_segno;
15878c2ecf20Sopenharmony_ci	unsigned int end_segno = start_segno + sbi->segs_per_sec;
15888c2ecf20Sopenharmony_ci	int seg_freed = 0, migrated = 0;
15898c2ecf20Sopenharmony_ci	unsigned char type = IS_DATASEG(get_seg_entry(sbi, segno)->type) ?
15908c2ecf20Sopenharmony_ci						SUM_TYPE_DATA : SUM_TYPE_NODE;
15918c2ecf20Sopenharmony_ci	int submitted = 0;
15928c2ecf20Sopenharmony_ci
15938c2ecf20Sopenharmony_ci	if (__is_large_section(sbi))
15948c2ecf20Sopenharmony_ci		end_segno = rounddown(end_segno, sbi->segs_per_sec);
15958c2ecf20Sopenharmony_ci
15968c2ecf20Sopenharmony_ci	/*
15978c2ecf20Sopenharmony_ci	 * zone-capacity can be less than zone-size in zoned devices,
15988c2ecf20Sopenharmony_ci	 * resulting in less than expected usable segments in the zone,
15998c2ecf20Sopenharmony_ci	 * calculate the end segno in the zone which can be garbage collected
16008c2ecf20Sopenharmony_ci	 */
16018c2ecf20Sopenharmony_ci	if (f2fs_sb_has_blkzoned(sbi))
16028c2ecf20Sopenharmony_ci		end_segno -= sbi->segs_per_sec -
16038c2ecf20Sopenharmony_ci					f2fs_usable_segs_in_sec(sbi, segno);
16048c2ecf20Sopenharmony_ci
16058c2ecf20Sopenharmony_ci	sanity_check_seg_type(sbi, get_seg_entry(sbi, segno)->type);
16068c2ecf20Sopenharmony_ci
16078c2ecf20Sopenharmony_ci	/* readahead multi ssa blocks those have contiguous address */
16088c2ecf20Sopenharmony_ci	if (__is_large_section(sbi))
16098c2ecf20Sopenharmony_ci		f2fs_ra_meta_pages(sbi, GET_SUM_BLOCK(sbi, segno),
16108c2ecf20Sopenharmony_ci					end_segno - segno, META_SSA, true);
16118c2ecf20Sopenharmony_ci
16128c2ecf20Sopenharmony_ci	/* reference all summary page */
16138c2ecf20Sopenharmony_ci	while (segno < end_segno) {
16148c2ecf20Sopenharmony_ci		sum_page = f2fs_get_sum_page(sbi, segno++);
16158c2ecf20Sopenharmony_ci		if (IS_ERR(sum_page)) {
16168c2ecf20Sopenharmony_ci			int err = PTR_ERR(sum_page);
16178c2ecf20Sopenharmony_ci
16188c2ecf20Sopenharmony_ci			end_segno = segno - 1;
16198c2ecf20Sopenharmony_ci			for (segno = start_segno; segno < end_segno; segno++) {
16208c2ecf20Sopenharmony_ci				sum_page = find_get_page(META_MAPPING(sbi),
16218c2ecf20Sopenharmony_ci						GET_SUM_BLOCK(sbi, segno));
16228c2ecf20Sopenharmony_ci				f2fs_put_page(sum_page, 0);
16238c2ecf20Sopenharmony_ci				f2fs_put_page(sum_page, 0);
16248c2ecf20Sopenharmony_ci			}
16258c2ecf20Sopenharmony_ci			return err;
16268c2ecf20Sopenharmony_ci		}
16278c2ecf20Sopenharmony_ci		unlock_page(sum_page);
16288c2ecf20Sopenharmony_ci	}
16298c2ecf20Sopenharmony_ci
16308c2ecf20Sopenharmony_ci	blk_start_plug(&plug);
16318c2ecf20Sopenharmony_ci
16328c2ecf20Sopenharmony_ci	for (segno = start_segno; segno < end_segno; segno++) {
16338c2ecf20Sopenharmony_ci
16348c2ecf20Sopenharmony_ci		/* find segment summary of victim */
16358c2ecf20Sopenharmony_ci		sum_page = find_get_page(META_MAPPING(sbi),
16368c2ecf20Sopenharmony_ci					GET_SUM_BLOCK(sbi, segno));
16378c2ecf20Sopenharmony_ci		f2fs_put_page(sum_page, 0);
16388c2ecf20Sopenharmony_ci
16398c2ecf20Sopenharmony_ci		if (get_valid_blocks(sbi, segno, false) == 0)
16408c2ecf20Sopenharmony_ci			goto freed;
16418c2ecf20Sopenharmony_ci		if (gc_type == BG_GC && __is_large_section(sbi) &&
16428c2ecf20Sopenharmony_ci				migrated >= sbi->migration_granularity)
16438c2ecf20Sopenharmony_ci			goto skip;
16448c2ecf20Sopenharmony_ci		if (!PageUptodate(sum_page) || unlikely(f2fs_cp_error(sbi)))
16458c2ecf20Sopenharmony_ci			goto skip;
16468c2ecf20Sopenharmony_ci
16478c2ecf20Sopenharmony_ci		sum = page_address(sum_page);
16488c2ecf20Sopenharmony_ci		if (type != GET_SUM_TYPE((&sum->footer))) {
16498c2ecf20Sopenharmony_ci			f2fs_err(sbi, "Inconsistent segment (%u) type [%d, %d] in SSA and SIT",
16508c2ecf20Sopenharmony_ci				 segno, type, GET_SUM_TYPE((&sum->footer)));
16518c2ecf20Sopenharmony_ci			set_sbi_flag(sbi, SBI_NEED_FSCK);
16528c2ecf20Sopenharmony_ci			f2fs_stop_checkpoint(sbi, false);
16538c2ecf20Sopenharmony_ci			goto skip;
16548c2ecf20Sopenharmony_ci		}
16558c2ecf20Sopenharmony_ci
16568c2ecf20Sopenharmony_ci		/*
16578c2ecf20Sopenharmony_ci		 * this is to avoid deadlock:
16588c2ecf20Sopenharmony_ci		 * - lock_page(sum_page)         - f2fs_replace_block
16598c2ecf20Sopenharmony_ci		 *  - check_valid_map()            - down_write(sentry_lock)
16608c2ecf20Sopenharmony_ci		 *   - down_read(sentry_lock)     - change_curseg()
16618c2ecf20Sopenharmony_ci		 *                                  - lock_page(sum_page)
16628c2ecf20Sopenharmony_ci		 */
16638c2ecf20Sopenharmony_ci		if (type == SUM_TYPE_NODE)
16648c2ecf20Sopenharmony_ci			submitted += gc_node_segment(sbi, sum->entries, segno,
16658c2ecf20Sopenharmony_ci								gc_type);
16668c2ecf20Sopenharmony_ci		else
16678c2ecf20Sopenharmony_ci			submitted += gc_data_segment(sbi, sum->entries, gc_list,
16688c2ecf20Sopenharmony_ci							segno, gc_type,
16698c2ecf20Sopenharmony_ci							force_migrate);
16708c2ecf20Sopenharmony_ci
16718c2ecf20Sopenharmony_ci		stat_inc_seg_count(sbi, type, gc_type);
16728c2ecf20Sopenharmony_ci		migrated++;
16738c2ecf20Sopenharmony_ci
16748c2ecf20Sopenharmony_cifreed:
16758c2ecf20Sopenharmony_ci		if (gc_type == FG_GC &&
16768c2ecf20Sopenharmony_ci				get_valid_blocks(sbi, segno, false) == 0)
16778c2ecf20Sopenharmony_ci			seg_freed++;
16788c2ecf20Sopenharmony_ci
16798c2ecf20Sopenharmony_ci		if (__is_large_section(sbi))
16808c2ecf20Sopenharmony_ci			sbi->next_victim_seg[gc_type] =
16818c2ecf20Sopenharmony_ci				(segno + 1 < end_segno) ? segno + 1 : NULL_SEGNO;
16828c2ecf20Sopenharmony_ciskip:
16838c2ecf20Sopenharmony_ci		f2fs_put_page(sum_page, 0);
16848c2ecf20Sopenharmony_ci	}
16858c2ecf20Sopenharmony_ci
16868c2ecf20Sopenharmony_ci	if (submitted)
16878c2ecf20Sopenharmony_ci		f2fs_submit_merged_write(sbi,
16888c2ecf20Sopenharmony_ci				(type == SUM_TYPE_NODE) ? NODE : DATA);
16898c2ecf20Sopenharmony_ci
16908c2ecf20Sopenharmony_ci	blk_finish_plug(&plug);
16918c2ecf20Sopenharmony_ci
16928c2ecf20Sopenharmony_ci	stat_inc_call_count(sbi->stat_info);
16938c2ecf20Sopenharmony_ci
16948c2ecf20Sopenharmony_ci	return seg_freed;
16958c2ecf20Sopenharmony_ci}
16968c2ecf20Sopenharmony_ci
16978c2ecf20Sopenharmony_ciint f2fs_gc(struct f2fs_sb_info *sbi, bool sync,
16988c2ecf20Sopenharmony_ci			bool background, bool force, unsigned int segno)
16998c2ecf20Sopenharmony_ci{
17008c2ecf20Sopenharmony_ci	int gc_type = sync ? FG_GC : BG_GC;
17018c2ecf20Sopenharmony_ci	int sec_freed = 0, seg_freed = 0, total_freed = 0;
17028c2ecf20Sopenharmony_ci	int ret = 0;
17038c2ecf20Sopenharmony_ci	struct cp_control cpc;
17048c2ecf20Sopenharmony_ci	unsigned int init_segno = segno;
17058c2ecf20Sopenharmony_ci	struct gc_inode_list gc_list = {
17068c2ecf20Sopenharmony_ci		.ilist = LIST_HEAD_INIT(gc_list.ilist),
17078c2ecf20Sopenharmony_ci		.iroot = RADIX_TREE_INIT(gc_list.iroot, GFP_NOFS),
17088c2ecf20Sopenharmony_ci	};
17098c2ecf20Sopenharmony_ci	unsigned long long last_skipped = sbi->skipped_atomic_files[FG_GC];
17108c2ecf20Sopenharmony_ci	unsigned long long first_skipped;
17118c2ecf20Sopenharmony_ci	unsigned int skipped_round = 0, round = 0;
17128c2ecf20Sopenharmony_ci
17138c2ecf20Sopenharmony_ci	trace_f2fs_gc_begin(sbi->sb, sync, background,
17148c2ecf20Sopenharmony_ci				get_pages(sbi, F2FS_DIRTY_NODES),
17158c2ecf20Sopenharmony_ci				get_pages(sbi, F2FS_DIRTY_DENTS),
17168c2ecf20Sopenharmony_ci				get_pages(sbi, F2FS_DIRTY_IMETA),
17178c2ecf20Sopenharmony_ci				free_sections(sbi),
17188c2ecf20Sopenharmony_ci				free_segments(sbi),
17198c2ecf20Sopenharmony_ci				reserved_segments(sbi),
17208c2ecf20Sopenharmony_ci				prefree_segments(sbi));
17218c2ecf20Sopenharmony_ci
17228c2ecf20Sopenharmony_ci	cpc.reason = __get_cp_reason(sbi);
17238c2ecf20Sopenharmony_ci	sbi->skipped_gc_rwsem = 0;
17248c2ecf20Sopenharmony_ci	first_skipped = last_skipped;
17258c2ecf20Sopenharmony_cigc_more:
17268c2ecf20Sopenharmony_ci	if (unlikely(!(sbi->sb->s_flags & SB_ACTIVE))) {
17278c2ecf20Sopenharmony_ci		ret = -EINVAL;
17288c2ecf20Sopenharmony_ci		goto stop;
17298c2ecf20Sopenharmony_ci	}
17308c2ecf20Sopenharmony_ci	if (unlikely(f2fs_cp_error(sbi))) {
17318c2ecf20Sopenharmony_ci		ret = -EIO;
17328c2ecf20Sopenharmony_ci		goto stop;
17338c2ecf20Sopenharmony_ci	}
17348c2ecf20Sopenharmony_ci
17358c2ecf20Sopenharmony_ci	if (gc_type == BG_GC && has_not_enough_free_secs(sbi, 0, 0)) {
17368c2ecf20Sopenharmony_ci		/*
17378c2ecf20Sopenharmony_ci		 * For example, if there are many prefree_segments below given
17388c2ecf20Sopenharmony_ci		 * threshold, we can make them free by checkpoint. Then, we
17398c2ecf20Sopenharmony_ci		 * secure free segments which doesn't need fggc any more.
17408c2ecf20Sopenharmony_ci		 */
17418c2ecf20Sopenharmony_ci		if (prefree_segments(sbi) &&
17428c2ecf20Sopenharmony_ci				!is_sbi_flag_set(sbi, SBI_CP_DISABLED)) {
17438c2ecf20Sopenharmony_ci			ret = f2fs_write_checkpoint(sbi, &cpc);
17448c2ecf20Sopenharmony_ci			if (ret)
17458c2ecf20Sopenharmony_ci				goto stop;
17468c2ecf20Sopenharmony_ci		}
17478c2ecf20Sopenharmony_ci		if (has_not_enough_free_secs(sbi, 0, 0))
17488c2ecf20Sopenharmony_ci			gc_type = FG_GC;
17498c2ecf20Sopenharmony_ci	}
17508c2ecf20Sopenharmony_ci
17518c2ecf20Sopenharmony_ci	/* f2fs_balance_fs doesn't need to do BG_GC in critical path. */
17528c2ecf20Sopenharmony_ci	if (gc_type == BG_GC && !background) {
17538c2ecf20Sopenharmony_ci		ret = -EINVAL;
17548c2ecf20Sopenharmony_ci		goto stop;
17558c2ecf20Sopenharmony_ci	}
17568c2ecf20Sopenharmony_ci	ret = __get_victim(sbi, &segno, gc_type);
17578c2ecf20Sopenharmony_ci	if (ret)
17588c2ecf20Sopenharmony_ci		goto stop;
17598c2ecf20Sopenharmony_ci
17608c2ecf20Sopenharmony_ci	seg_freed = do_garbage_collect(sbi, segno, &gc_list, gc_type, force);
17618c2ecf20Sopenharmony_ci	if (gc_type == FG_GC &&
17628c2ecf20Sopenharmony_ci		seg_freed == f2fs_usable_segs_in_sec(sbi, segno))
17638c2ecf20Sopenharmony_ci		sec_freed++;
17648c2ecf20Sopenharmony_ci	total_freed += seg_freed;
17658c2ecf20Sopenharmony_ci
17668c2ecf20Sopenharmony_ci	if (gc_type == FG_GC) {
17678c2ecf20Sopenharmony_ci		if (sbi->skipped_atomic_files[FG_GC] > last_skipped ||
17688c2ecf20Sopenharmony_ci						sbi->skipped_gc_rwsem)
17698c2ecf20Sopenharmony_ci			skipped_round++;
17708c2ecf20Sopenharmony_ci		last_skipped = sbi->skipped_atomic_files[FG_GC];
17718c2ecf20Sopenharmony_ci		round++;
17728c2ecf20Sopenharmony_ci	}
17738c2ecf20Sopenharmony_ci
17748c2ecf20Sopenharmony_ci	if (gc_type == FG_GC && seg_freed)
17758c2ecf20Sopenharmony_ci		sbi->cur_victim_sec = NULL_SEGNO;
17768c2ecf20Sopenharmony_ci
17778c2ecf20Sopenharmony_ci	if (sync)
17788c2ecf20Sopenharmony_ci		goto stop;
17798c2ecf20Sopenharmony_ci
17808c2ecf20Sopenharmony_ci	if (!has_not_enough_free_secs(sbi, sec_freed, 0))
17818c2ecf20Sopenharmony_ci		goto stop;
17828c2ecf20Sopenharmony_ci
17838c2ecf20Sopenharmony_ci	if (skipped_round <= MAX_SKIP_GC_COUNT || skipped_round * 2 < round) {
17848c2ecf20Sopenharmony_ci
17858c2ecf20Sopenharmony_ci		/* Write checkpoint to reclaim prefree segments */
17868c2ecf20Sopenharmony_ci		if (free_sections(sbi) < NR_CURSEG_PERSIST_TYPE &&
17878c2ecf20Sopenharmony_ci				prefree_segments(sbi) &&
17888c2ecf20Sopenharmony_ci				!is_sbi_flag_set(sbi, SBI_CP_DISABLED)) {
17898c2ecf20Sopenharmony_ci			ret = f2fs_write_checkpoint(sbi, &cpc);
17908c2ecf20Sopenharmony_ci			if (ret)
17918c2ecf20Sopenharmony_ci				goto stop;
17928c2ecf20Sopenharmony_ci		}
17938c2ecf20Sopenharmony_ci		segno = NULL_SEGNO;
17948c2ecf20Sopenharmony_ci		goto gc_more;
17958c2ecf20Sopenharmony_ci	}
17968c2ecf20Sopenharmony_ci	if (first_skipped < last_skipped &&
17978c2ecf20Sopenharmony_ci			(last_skipped - first_skipped) >
17988c2ecf20Sopenharmony_ci					sbi->skipped_gc_rwsem) {
17998c2ecf20Sopenharmony_ci		f2fs_drop_inmem_pages_all(sbi, true);
18008c2ecf20Sopenharmony_ci		segno = NULL_SEGNO;
18018c2ecf20Sopenharmony_ci		goto gc_more;
18028c2ecf20Sopenharmony_ci	}
18038c2ecf20Sopenharmony_ci	if (gc_type == FG_GC && !is_sbi_flag_set(sbi, SBI_CP_DISABLED))
18048c2ecf20Sopenharmony_ci		ret = f2fs_write_checkpoint(sbi, &cpc);
18058c2ecf20Sopenharmony_cistop:
18068c2ecf20Sopenharmony_ci	SIT_I(sbi)->last_victim[ALLOC_NEXT] = 0;
18078c2ecf20Sopenharmony_ci	SIT_I(sbi)->last_victim[FLUSH_DEVICE] = init_segno;
18088c2ecf20Sopenharmony_ci
18098c2ecf20Sopenharmony_ci	trace_f2fs_gc_end(sbi->sb, ret, total_freed, sec_freed,
18108c2ecf20Sopenharmony_ci				get_pages(sbi, F2FS_DIRTY_NODES),
18118c2ecf20Sopenharmony_ci				get_pages(sbi, F2FS_DIRTY_DENTS),
18128c2ecf20Sopenharmony_ci				get_pages(sbi, F2FS_DIRTY_IMETA),
18138c2ecf20Sopenharmony_ci				free_sections(sbi),
18148c2ecf20Sopenharmony_ci				free_segments(sbi),
18158c2ecf20Sopenharmony_ci				reserved_segments(sbi),
18168c2ecf20Sopenharmony_ci				prefree_segments(sbi));
18178c2ecf20Sopenharmony_ci
18188c2ecf20Sopenharmony_ci	up_write(&sbi->gc_lock);
18198c2ecf20Sopenharmony_ci
18208c2ecf20Sopenharmony_ci	put_gc_inode(&gc_list);
18218c2ecf20Sopenharmony_ci
18228c2ecf20Sopenharmony_ci	if (sync && !ret)
18238c2ecf20Sopenharmony_ci		ret = sec_freed ? 0 : -EAGAIN;
18248c2ecf20Sopenharmony_ci	return ret;
18258c2ecf20Sopenharmony_ci}
18268c2ecf20Sopenharmony_ci
18278c2ecf20Sopenharmony_ciint __init f2fs_create_garbage_collection_cache(void)
18288c2ecf20Sopenharmony_ci{
18298c2ecf20Sopenharmony_ci	victim_entry_slab = f2fs_kmem_cache_create("f2fs_victim_entry",
18308c2ecf20Sopenharmony_ci					sizeof(struct victim_entry));
18318c2ecf20Sopenharmony_ci	if (!victim_entry_slab)
18328c2ecf20Sopenharmony_ci		return -ENOMEM;
18338c2ecf20Sopenharmony_ci	return 0;
18348c2ecf20Sopenharmony_ci}
18358c2ecf20Sopenharmony_ci
18368c2ecf20Sopenharmony_civoid f2fs_destroy_garbage_collection_cache(void)
18378c2ecf20Sopenharmony_ci{
18388c2ecf20Sopenharmony_ci	kmem_cache_destroy(victim_entry_slab);
18398c2ecf20Sopenharmony_ci}
18408c2ecf20Sopenharmony_ci
18418c2ecf20Sopenharmony_cistatic void init_atgc_management(struct f2fs_sb_info *sbi)
18428c2ecf20Sopenharmony_ci{
18438c2ecf20Sopenharmony_ci	struct atgc_management *am = &sbi->am;
18448c2ecf20Sopenharmony_ci
18458c2ecf20Sopenharmony_ci	if (test_opt(sbi, ATGC) &&
18468c2ecf20Sopenharmony_ci		SIT_I(sbi)->elapsed_time >= DEF_GC_THREAD_AGE_THRESHOLD)
18478c2ecf20Sopenharmony_ci		am->atgc_enabled = true;
18488c2ecf20Sopenharmony_ci
18498c2ecf20Sopenharmony_ci	am->root = RB_ROOT_CACHED;
18508c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&am->victim_list);
18518c2ecf20Sopenharmony_ci	am->victim_count = 0;
18528c2ecf20Sopenharmony_ci
18538c2ecf20Sopenharmony_ci	am->candidate_ratio = DEF_GC_THREAD_CANDIDATE_RATIO;
18548c2ecf20Sopenharmony_ci	am->max_candidate_count = DEF_GC_THREAD_MAX_CANDIDATE_COUNT;
18558c2ecf20Sopenharmony_ci	am->age_weight = DEF_GC_THREAD_AGE_WEIGHT;
18568c2ecf20Sopenharmony_ci	am->age_threshold = DEF_GC_THREAD_AGE_THRESHOLD;
18578c2ecf20Sopenharmony_ci}
18588c2ecf20Sopenharmony_ci
18598c2ecf20Sopenharmony_civoid f2fs_build_gc_manager(struct f2fs_sb_info *sbi)
18608c2ecf20Sopenharmony_ci{
18618c2ecf20Sopenharmony_ci	DIRTY_I(sbi)->v_ops = &default_v_ops;
18628c2ecf20Sopenharmony_ci
18638c2ecf20Sopenharmony_ci	sbi->gc_pin_file_threshold = DEF_GC_FAILED_PINNED_FILES;
18648c2ecf20Sopenharmony_ci
18658c2ecf20Sopenharmony_ci	/* give warm/cold data area from slower device */
18668c2ecf20Sopenharmony_ci	if (f2fs_is_multi_device(sbi) && !__is_large_section(sbi))
18678c2ecf20Sopenharmony_ci		SIT_I(sbi)->last_victim[ALLOC_NEXT] =
18688c2ecf20Sopenharmony_ci				GET_SEGNO(sbi, FDEV(0).end_blk) + 1;
18698c2ecf20Sopenharmony_ci
18708c2ecf20Sopenharmony_ci	init_atgc_management(sbi);
18718c2ecf20Sopenharmony_ci}
18728c2ecf20Sopenharmony_ci
18738c2ecf20Sopenharmony_cistatic int free_segment_range(struct f2fs_sb_info *sbi,
18748c2ecf20Sopenharmony_ci				unsigned int secs, bool gc_only)
18758c2ecf20Sopenharmony_ci{
18768c2ecf20Sopenharmony_ci	unsigned int segno, next_inuse, start, end;
18778c2ecf20Sopenharmony_ci	struct cp_control cpc = { CP_RESIZE, 0, 0, 0 };
18788c2ecf20Sopenharmony_ci	int gc_mode, gc_type;
18798c2ecf20Sopenharmony_ci	int err = 0;
18808c2ecf20Sopenharmony_ci	int type;
18818c2ecf20Sopenharmony_ci
18828c2ecf20Sopenharmony_ci	/* Force block allocation for GC */
18838c2ecf20Sopenharmony_ci	MAIN_SECS(sbi) -= secs;
18848c2ecf20Sopenharmony_ci	start = MAIN_SECS(sbi) * sbi->segs_per_sec;
18858c2ecf20Sopenharmony_ci	end = MAIN_SEGS(sbi) - 1;
18868c2ecf20Sopenharmony_ci
18878c2ecf20Sopenharmony_ci	mutex_lock(&DIRTY_I(sbi)->seglist_lock);
18888c2ecf20Sopenharmony_ci	for (gc_mode = 0; gc_mode < MAX_GC_POLICY; gc_mode++)
18898c2ecf20Sopenharmony_ci		if (SIT_I(sbi)->last_victim[gc_mode] >= start)
18908c2ecf20Sopenharmony_ci			SIT_I(sbi)->last_victim[gc_mode] = 0;
18918c2ecf20Sopenharmony_ci
18928c2ecf20Sopenharmony_ci	for (gc_type = BG_GC; gc_type <= FG_GC; gc_type++)
18938c2ecf20Sopenharmony_ci		if (sbi->next_victim_seg[gc_type] >= start)
18948c2ecf20Sopenharmony_ci			sbi->next_victim_seg[gc_type] = NULL_SEGNO;
18958c2ecf20Sopenharmony_ci	mutex_unlock(&DIRTY_I(sbi)->seglist_lock);
18968c2ecf20Sopenharmony_ci
18978c2ecf20Sopenharmony_ci	/* Move out cursegs from the target range */
18988c2ecf20Sopenharmony_ci	for (type = CURSEG_HOT_DATA; type < NR_CURSEG_PERSIST_TYPE; type++)
18998c2ecf20Sopenharmony_ci		f2fs_allocate_segment_for_resize(sbi, type, start, end);
19008c2ecf20Sopenharmony_ci
19018c2ecf20Sopenharmony_ci	/* do GC to move out valid blocks in the range */
19028c2ecf20Sopenharmony_ci	for (segno = start; segno <= end; segno += sbi->segs_per_sec) {
19038c2ecf20Sopenharmony_ci		struct gc_inode_list gc_list = {
19048c2ecf20Sopenharmony_ci			.ilist = LIST_HEAD_INIT(gc_list.ilist),
19058c2ecf20Sopenharmony_ci			.iroot = RADIX_TREE_INIT(gc_list.iroot, GFP_NOFS),
19068c2ecf20Sopenharmony_ci		};
19078c2ecf20Sopenharmony_ci
19088c2ecf20Sopenharmony_ci		do_garbage_collect(sbi, segno, &gc_list, FG_GC, true);
19098c2ecf20Sopenharmony_ci		put_gc_inode(&gc_list);
19108c2ecf20Sopenharmony_ci
19118c2ecf20Sopenharmony_ci		if (!gc_only && get_valid_blocks(sbi, segno, true)) {
19128c2ecf20Sopenharmony_ci			err = -EAGAIN;
19138c2ecf20Sopenharmony_ci			goto out;
19148c2ecf20Sopenharmony_ci		}
19158c2ecf20Sopenharmony_ci		if (fatal_signal_pending(current)) {
19168c2ecf20Sopenharmony_ci			err = -ERESTARTSYS;
19178c2ecf20Sopenharmony_ci			goto out;
19188c2ecf20Sopenharmony_ci		}
19198c2ecf20Sopenharmony_ci	}
19208c2ecf20Sopenharmony_ci	if (gc_only)
19218c2ecf20Sopenharmony_ci		goto out;
19228c2ecf20Sopenharmony_ci
19238c2ecf20Sopenharmony_ci	err = f2fs_write_checkpoint(sbi, &cpc);
19248c2ecf20Sopenharmony_ci	if (err)
19258c2ecf20Sopenharmony_ci		goto out;
19268c2ecf20Sopenharmony_ci
19278c2ecf20Sopenharmony_ci	next_inuse = find_next_inuse(FREE_I(sbi), end + 1, start);
19288c2ecf20Sopenharmony_ci	if (next_inuse <= end) {
19298c2ecf20Sopenharmony_ci		f2fs_err(sbi, "segno %u should be free but still inuse!",
19308c2ecf20Sopenharmony_ci			 next_inuse);
19318c2ecf20Sopenharmony_ci		f2fs_bug_on(sbi, 1);
19328c2ecf20Sopenharmony_ci	}
19338c2ecf20Sopenharmony_ciout:
19348c2ecf20Sopenharmony_ci	MAIN_SECS(sbi) += secs;
19358c2ecf20Sopenharmony_ci	return err;
19368c2ecf20Sopenharmony_ci}
19378c2ecf20Sopenharmony_ci
19388c2ecf20Sopenharmony_cistatic void update_sb_metadata(struct f2fs_sb_info *sbi, int secs)
19398c2ecf20Sopenharmony_ci{
19408c2ecf20Sopenharmony_ci	struct f2fs_super_block *raw_sb = F2FS_RAW_SUPER(sbi);
19418c2ecf20Sopenharmony_ci	int section_count;
19428c2ecf20Sopenharmony_ci	int segment_count;
19438c2ecf20Sopenharmony_ci	int segment_count_main;
19448c2ecf20Sopenharmony_ci	long long block_count;
19458c2ecf20Sopenharmony_ci	int segs = secs * sbi->segs_per_sec;
19468c2ecf20Sopenharmony_ci
19478c2ecf20Sopenharmony_ci	down_write(&sbi->sb_lock);
19488c2ecf20Sopenharmony_ci
19498c2ecf20Sopenharmony_ci	section_count = le32_to_cpu(raw_sb->section_count);
19508c2ecf20Sopenharmony_ci	segment_count = le32_to_cpu(raw_sb->segment_count);
19518c2ecf20Sopenharmony_ci	segment_count_main = le32_to_cpu(raw_sb->segment_count_main);
19528c2ecf20Sopenharmony_ci	block_count = le64_to_cpu(raw_sb->block_count);
19538c2ecf20Sopenharmony_ci
19548c2ecf20Sopenharmony_ci	raw_sb->section_count = cpu_to_le32(section_count + secs);
19558c2ecf20Sopenharmony_ci	raw_sb->segment_count = cpu_to_le32(segment_count + segs);
19568c2ecf20Sopenharmony_ci	raw_sb->segment_count_main = cpu_to_le32(segment_count_main + segs);
19578c2ecf20Sopenharmony_ci	raw_sb->block_count = cpu_to_le64(block_count +
19588c2ecf20Sopenharmony_ci					(long long)segs * sbi->blocks_per_seg);
19598c2ecf20Sopenharmony_ci	if (f2fs_is_multi_device(sbi)) {
19608c2ecf20Sopenharmony_ci		int last_dev = sbi->s_ndevs - 1;
19618c2ecf20Sopenharmony_ci		int dev_segs =
19628c2ecf20Sopenharmony_ci			le32_to_cpu(raw_sb->devs[last_dev].total_segments);
19638c2ecf20Sopenharmony_ci
19648c2ecf20Sopenharmony_ci		raw_sb->devs[last_dev].total_segments =
19658c2ecf20Sopenharmony_ci						cpu_to_le32(dev_segs + segs);
19668c2ecf20Sopenharmony_ci	}
19678c2ecf20Sopenharmony_ci
19688c2ecf20Sopenharmony_ci	up_write(&sbi->sb_lock);
19698c2ecf20Sopenharmony_ci}
19708c2ecf20Sopenharmony_ci
19718c2ecf20Sopenharmony_cistatic void update_fs_metadata(struct f2fs_sb_info *sbi, int secs)
19728c2ecf20Sopenharmony_ci{
19738c2ecf20Sopenharmony_ci	int segs = secs * sbi->segs_per_sec;
19748c2ecf20Sopenharmony_ci	long long blks = (long long)segs * sbi->blocks_per_seg;
19758c2ecf20Sopenharmony_ci	long long user_block_count =
19768c2ecf20Sopenharmony_ci				le64_to_cpu(F2FS_CKPT(sbi)->user_block_count);
19778c2ecf20Sopenharmony_ci
19788c2ecf20Sopenharmony_ci	SM_I(sbi)->segment_count = (int)SM_I(sbi)->segment_count + segs;
19798c2ecf20Sopenharmony_ci	MAIN_SEGS(sbi) = (int)MAIN_SEGS(sbi) + segs;
19808c2ecf20Sopenharmony_ci	MAIN_SECS(sbi) += secs;
19818c2ecf20Sopenharmony_ci	FREE_I(sbi)->free_sections = (int)FREE_I(sbi)->free_sections + secs;
19828c2ecf20Sopenharmony_ci	FREE_I(sbi)->free_segments = (int)FREE_I(sbi)->free_segments + segs;
19838c2ecf20Sopenharmony_ci	F2FS_CKPT(sbi)->user_block_count = cpu_to_le64(user_block_count + blks);
19848c2ecf20Sopenharmony_ci
19858c2ecf20Sopenharmony_ci	if (f2fs_is_multi_device(sbi)) {
19868c2ecf20Sopenharmony_ci		int last_dev = sbi->s_ndevs - 1;
19878c2ecf20Sopenharmony_ci
19888c2ecf20Sopenharmony_ci		FDEV(last_dev).total_segments =
19898c2ecf20Sopenharmony_ci				(int)FDEV(last_dev).total_segments + segs;
19908c2ecf20Sopenharmony_ci		FDEV(last_dev).end_blk =
19918c2ecf20Sopenharmony_ci				(long long)FDEV(last_dev).end_blk + blks;
19928c2ecf20Sopenharmony_ci#ifdef CONFIG_BLK_DEV_ZONED
19938c2ecf20Sopenharmony_ci		FDEV(last_dev).nr_blkz = (int)FDEV(last_dev).nr_blkz +
19948c2ecf20Sopenharmony_ci					(int)(blks >> sbi->log_blocks_per_blkz);
19958c2ecf20Sopenharmony_ci#endif
19968c2ecf20Sopenharmony_ci	}
19978c2ecf20Sopenharmony_ci}
19988c2ecf20Sopenharmony_ci
19998c2ecf20Sopenharmony_ciint f2fs_resize_fs(struct file *filp, __u64 block_count)
20008c2ecf20Sopenharmony_ci{
20018c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_I_SB(file_inode(filp));
20028c2ecf20Sopenharmony_ci	__u64 old_block_count, shrunk_blocks;
20038c2ecf20Sopenharmony_ci	struct cp_control cpc = { CP_RESIZE, 0, 0, 0 };
20048c2ecf20Sopenharmony_ci	unsigned int secs;
20058c2ecf20Sopenharmony_ci	int err = 0;
20068c2ecf20Sopenharmony_ci	__u32 rem;
20078c2ecf20Sopenharmony_ci
20088c2ecf20Sopenharmony_ci	old_block_count = le64_to_cpu(F2FS_RAW_SUPER(sbi)->block_count);
20098c2ecf20Sopenharmony_ci	if (block_count > old_block_count)
20108c2ecf20Sopenharmony_ci		return -EINVAL;
20118c2ecf20Sopenharmony_ci
20128c2ecf20Sopenharmony_ci	if (f2fs_is_multi_device(sbi)) {
20138c2ecf20Sopenharmony_ci		int last_dev = sbi->s_ndevs - 1;
20148c2ecf20Sopenharmony_ci		__u64 last_segs = FDEV(last_dev).total_segments;
20158c2ecf20Sopenharmony_ci
20168c2ecf20Sopenharmony_ci		if (block_count + last_segs * sbi->blocks_per_seg <=
20178c2ecf20Sopenharmony_ci								old_block_count)
20188c2ecf20Sopenharmony_ci			return -EINVAL;
20198c2ecf20Sopenharmony_ci	}
20208c2ecf20Sopenharmony_ci
20218c2ecf20Sopenharmony_ci	/* new fs size should align to section size */
20228c2ecf20Sopenharmony_ci	div_u64_rem(block_count, BLKS_PER_SEC(sbi), &rem);
20238c2ecf20Sopenharmony_ci	if (rem)
20248c2ecf20Sopenharmony_ci		return -EINVAL;
20258c2ecf20Sopenharmony_ci
20268c2ecf20Sopenharmony_ci	if (block_count == old_block_count)
20278c2ecf20Sopenharmony_ci		return 0;
20288c2ecf20Sopenharmony_ci
20298c2ecf20Sopenharmony_ci	if (is_sbi_flag_set(sbi, SBI_NEED_FSCK)) {
20308c2ecf20Sopenharmony_ci		f2fs_err(sbi, "Should run fsck to repair first.");
20318c2ecf20Sopenharmony_ci		return -EFSCORRUPTED;
20328c2ecf20Sopenharmony_ci	}
20338c2ecf20Sopenharmony_ci
20348c2ecf20Sopenharmony_ci	if (test_opt(sbi, DISABLE_CHECKPOINT)) {
20358c2ecf20Sopenharmony_ci		f2fs_err(sbi, "Checkpoint should be enabled.");
20368c2ecf20Sopenharmony_ci		return -EINVAL;
20378c2ecf20Sopenharmony_ci	}
20388c2ecf20Sopenharmony_ci
20398c2ecf20Sopenharmony_ci	err = mnt_want_write_file(filp);
20408c2ecf20Sopenharmony_ci	if (err)
20418c2ecf20Sopenharmony_ci		return err;
20428c2ecf20Sopenharmony_ci
20438c2ecf20Sopenharmony_ci	shrunk_blocks = old_block_count - block_count;
20448c2ecf20Sopenharmony_ci	secs = div_u64(shrunk_blocks, BLKS_PER_SEC(sbi));
20458c2ecf20Sopenharmony_ci
20468c2ecf20Sopenharmony_ci	/* stop other GC */
20478c2ecf20Sopenharmony_ci	if (!down_write_trylock(&sbi->gc_lock)) {
20488c2ecf20Sopenharmony_ci		err = -EAGAIN;
20498c2ecf20Sopenharmony_ci		goto out_drop_write;
20508c2ecf20Sopenharmony_ci	}
20518c2ecf20Sopenharmony_ci
20528c2ecf20Sopenharmony_ci	/* stop CP to protect MAIN_SEC in free_segment_range */
20538c2ecf20Sopenharmony_ci	f2fs_lock_op(sbi);
20548c2ecf20Sopenharmony_ci
20558c2ecf20Sopenharmony_ci	spin_lock(&sbi->stat_lock);
20568c2ecf20Sopenharmony_ci	if (shrunk_blocks + valid_user_blocks(sbi) +
20578c2ecf20Sopenharmony_ci		sbi->current_reserved_blocks + sbi->unusable_block_count +
20588c2ecf20Sopenharmony_ci		F2FS_OPTION(sbi).root_reserved_blocks > sbi->user_block_count)
20598c2ecf20Sopenharmony_ci		err = -ENOSPC;
20608c2ecf20Sopenharmony_ci	spin_unlock(&sbi->stat_lock);
20618c2ecf20Sopenharmony_ci
20628c2ecf20Sopenharmony_ci	if (err)
20638c2ecf20Sopenharmony_ci		goto out_unlock;
20648c2ecf20Sopenharmony_ci
20658c2ecf20Sopenharmony_ci	err = free_segment_range(sbi, secs, true);
20668c2ecf20Sopenharmony_ci
20678c2ecf20Sopenharmony_ciout_unlock:
20688c2ecf20Sopenharmony_ci	f2fs_unlock_op(sbi);
20698c2ecf20Sopenharmony_ci	up_write(&sbi->gc_lock);
20708c2ecf20Sopenharmony_ciout_drop_write:
20718c2ecf20Sopenharmony_ci	mnt_drop_write_file(filp);
20728c2ecf20Sopenharmony_ci	if (err)
20738c2ecf20Sopenharmony_ci		return err;
20748c2ecf20Sopenharmony_ci
20758c2ecf20Sopenharmony_ci	freeze_super(sbi->sb);
20768c2ecf20Sopenharmony_ci
20778c2ecf20Sopenharmony_ci	if (f2fs_readonly(sbi->sb)) {
20788c2ecf20Sopenharmony_ci		thaw_super(sbi->sb);
20798c2ecf20Sopenharmony_ci		return -EROFS;
20808c2ecf20Sopenharmony_ci	}
20818c2ecf20Sopenharmony_ci
20828c2ecf20Sopenharmony_ci	down_write(&sbi->gc_lock);
20838c2ecf20Sopenharmony_ci	mutex_lock(&sbi->cp_mutex);
20848c2ecf20Sopenharmony_ci
20858c2ecf20Sopenharmony_ci	spin_lock(&sbi->stat_lock);
20868c2ecf20Sopenharmony_ci	if (shrunk_blocks + valid_user_blocks(sbi) +
20878c2ecf20Sopenharmony_ci		sbi->current_reserved_blocks + sbi->unusable_block_count +
20888c2ecf20Sopenharmony_ci		F2FS_OPTION(sbi).root_reserved_blocks > sbi->user_block_count)
20898c2ecf20Sopenharmony_ci		err = -ENOSPC;
20908c2ecf20Sopenharmony_ci	else
20918c2ecf20Sopenharmony_ci		sbi->user_block_count -= shrunk_blocks;
20928c2ecf20Sopenharmony_ci	spin_unlock(&sbi->stat_lock);
20938c2ecf20Sopenharmony_ci	if (err)
20948c2ecf20Sopenharmony_ci		goto out_err;
20958c2ecf20Sopenharmony_ci
20968c2ecf20Sopenharmony_ci	set_sbi_flag(sbi, SBI_IS_RESIZEFS);
20978c2ecf20Sopenharmony_ci	err = free_segment_range(sbi, secs, false);
20988c2ecf20Sopenharmony_ci	if (err)
20998c2ecf20Sopenharmony_ci		goto recover_out;
21008c2ecf20Sopenharmony_ci
21018c2ecf20Sopenharmony_ci	update_sb_metadata(sbi, -secs);
21028c2ecf20Sopenharmony_ci
21038c2ecf20Sopenharmony_ci	err = f2fs_commit_super(sbi, false);
21048c2ecf20Sopenharmony_ci	if (err) {
21058c2ecf20Sopenharmony_ci		update_sb_metadata(sbi, secs);
21068c2ecf20Sopenharmony_ci		goto recover_out;
21078c2ecf20Sopenharmony_ci	}
21088c2ecf20Sopenharmony_ci
21098c2ecf20Sopenharmony_ci	update_fs_metadata(sbi, -secs);
21108c2ecf20Sopenharmony_ci	clear_sbi_flag(sbi, SBI_IS_RESIZEFS);
21118c2ecf20Sopenharmony_ci	set_sbi_flag(sbi, SBI_IS_DIRTY);
21128c2ecf20Sopenharmony_ci
21138c2ecf20Sopenharmony_ci	err = f2fs_write_checkpoint(sbi, &cpc);
21148c2ecf20Sopenharmony_ci	if (err) {
21158c2ecf20Sopenharmony_ci		update_fs_metadata(sbi, secs);
21168c2ecf20Sopenharmony_ci		update_sb_metadata(sbi, secs);
21178c2ecf20Sopenharmony_ci		f2fs_commit_super(sbi, false);
21188c2ecf20Sopenharmony_ci	}
21198c2ecf20Sopenharmony_cirecover_out:
21208c2ecf20Sopenharmony_ci	clear_sbi_flag(sbi, SBI_IS_RESIZEFS);
21218c2ecf20Sopenharmony_ci	if (err) {
21228c2ecf20Sopenharmony_ci		set_sbi_flag(sbi, SBI_NEED_FSCK);
21238c2ecf20Sopenharmony_ci		f2fs_err(sbi, "resize_fs failed, should run fsck to repair!");
21248c2ecf20Sopenharmony_ci
21258c2ecf20Sopenharmony_ci		spin_lock(&sbi->stat_lock);
21268c2ecf20Sopenharmony_ci		sbi->user_block_count += shrunk_blocks;
21278c2ecf20Sopenharmony_ci		spin_unlock(&sbi->stat_lock);
21288c2ecf20Sopenharmony_ci	}
21298c2ecf20Sopenharmony_ciout_err:
21308c2ecf20Sopenharmony_ci	mutex_unlock(&sbi->cp_mutex);
21318c2ecf20Sopenharmony_ci	up_write(&sbi->gc_lock);
21328c2ecf20Sopenharmony_ci	thaw_super(sbi->sb);
21338c2ecf20Sopenharmony_ci	return err;
21348c2ecf20Sopenharmony_ci}
2135