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