18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * fs/f2fs/node.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/f2fs_fs.h>
108c2ecf20Sopenharmony_ci#include <linux/mpage.h>
118c2ecf20Sopenharmony_ci#include <linux/backing-dev.h>
128c2ecf20Sopenharmony_ci#include <linux/blkdev.h>
138c2ecf20Sopenharmony_ci#include <linux/pagevec.h>
148c2ecf20Sopenharmony_ci#include <linux/swap.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include "f2fs.h"
178c2ecf20Sopenharmony_ci#include "node.h"
188c2ecf20Sopenharmony_ci#include "segment.h"
198c2ecf20Sopenharmony_ci#include "xattr.h"
208c2ecf20Sopenharmony_ci#include "trace.h"
218c2ecf20Sopenharmony_ci#include <trace/events/f2fs.h>
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#define on_f2fs_build_free_nids(nmi) mutex_is_locked(&(nm_i)->build_lock)
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_cistatic struct kmem_cache *nat_entry_slab;
268c2ecf20Sopenharmony_cistatic struct kmem_cache *free_nid_slab;
278c2ecf20Sopenharmony_cistatic struct kmem_cache *nat_entry_set_slab;
288c2ecf20Sopenharmony_cistatic struct kmem_cache *fsync_node_entry_slab;
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci/*
318c2ecf20Sopenharmony_ci * Check whether the given nid is within node id range.
328c2ecf20Sopenharmony_ci */
338c2ecf20Sopenharmony_ciint f2fs_check_nid_range(struct f2fs_sb_info *sbi, nid_t nid)
348c2ecf20Sopenharmony_ci{
358c2ecf20Sopenharmony_ci	if (unlikely(nid < F2FS_ROOT_INO(sbi) || nid >= NM_I(sbi)->max_nid)) {
368c2ecf20Sopenharmony_ci		set_sbi_flag(sbi, SBI_NEED_FSCK);
378c2ecf20Sopenharmony_ci		f2fs_warn(sbi, "%s: out-of-range nid=%x, run fsck to fix.",
388c2ecf20Sopenharmony_ci			  __func__, nid);
398c2ecf20Sopenharmony_ci		return -EFSCORRUPTED;
408c2ecf20Sopenharmony_ci	}
418c2ecf20Sopenharmony_ci	return 0;
428c2ecf20Sopenharmony_ci}
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_cibool f2fs_available_free_memory(struct f2fs_sb_info *sbi, int type)
458c2ecf20Sopenharmony_ci{
468c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
478c2ecf20Sopenharmony_ci	struct sysinfo val;
488c2ecf20Sopenharmony_ci	unsigned long avail_ram;
498c2ecf20Sopenharmony_ci	unsigned long mem_size = 0;
508c2ecf20Sopenharmony_ci	bool res = false;
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	si_meminfo(&val);
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	/* only uses low memory */
558c2ecf20Sopenharmony_ci	avail_ram = val.totalram - val.totalhigh;
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	/*
588c2ecf20Sopenharmony_ci	 * give 25%, 25%, 50%, 50%, 50% memory for each components respectively
598c2ecf20Sopenharmony_ci	 */
608c2ecf20Sopenharmony_ci	if (type == FREE_NIDS) {
618c2ecf20Sopenharmony_ci		mem_size = (nm_i->nid_cnt[FREE_NID] *
628c2ecf20Sopenharmony_ci				sizeof(struct free_nid)) >> PAGE_SHIFT;
638c2ecf20Sopenharmony_ci		res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 2);
648c2ecf20Sopenharmony_ci	} else if (type == NAT_ENTRIES) {
658c2ecf20Sopenharmony_ci		mem_size = (nm_i->nat_cnt[TOTAL_NAT] *
668c2ecf20Sopenharmony_ci				sizeof(struct nat_entry)) >> PAGE_SHIFT;
678c2ecf20Sopenharmony_ci		res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 2);
688c2ecf20Sopenharmony_ci		if (excess_cached_nats(sbi))
698c2ecf20Sopenharmony_ci			res = false;
708c2ecf20Sopenharmony_ci	} else if (type == DIRTY_DENTS) {
718c2ecf20Sopenharmony_ci		if (sbi->sb->s_bdi->wb.dirty_exceeded)
728c2ecf20Sopenharmony_ci			return false;
738c2ecf20Sopenharmony_ci		mem_size = get_pages(sbi, F2FS_DIRTY_DENTS);
748c2ecf20Sopenharmony_ci		res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 1);
758c2ecf20Sopenharmony_ci	} else if (type == INO_ENTRIES) {
768c2ecf20Sopenharmony_ci		int i;
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci		for (i = 0; i < MAX_INO_ENTRY; i++)
798c2ecf20Sopenharmony_ci			mem_size += sbi->im[i].ino_num *
808c2ecf20Sopenharmony_ci						sizeof(struct ino_entry);
818c2ecf20Sopenharmony_ci		mem_size >>= PAGE_SHIFT;
828c2ecf20Sopenharmony_ci		res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 1);
838c2ecf20Sopenharmony_ci	} else if (type == EXTENT_CACHE) {
848c2ecf20Sopenharmony_ci		mem_size = (atomic_read(&sbi->total_ext_tree) *
858c2ecf20Sopenharmony_ci				sizeof(struct extent_tree) +
868c2ecf20Sopenharmony_ci				atomic_read(&sbi->total_ext_node) *
878c2ecf20Sopenharmony_ci				sizeof(struct extent_node)) >> PAGE_SHIFT;
888c2ecf20Sopenharmony_ci		res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 1);
898c2ecf20Sopenharmony_ci	} else if (type == INMEM_PAGES) {
908c2ecf20Sopenharmony_ci		/* it allows 20% / total_ram for inmemory pages */
918c2ecf20Sopenharmony_ci		mem_size = get_pages(sbi, F2FS_INMEM_PAGES);
928c2ecf20Sopenharmony_ci		res = mem_size < (val.totalram / 5);
938c2ecf20Sopenharmony_ci	} else {
948c2ecf20Sopenharmony_ci		if (!sbi->sb->s_bdi->wb.dirty_exceeded)
958c2ecf20Sopenharmony_ci			return true;
968c2ecf20Sopenharmony_ci	}
978c2ecf20Sopenharmony_ci	return res;
988c2ecf20Sopenharmony_ci}
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_cistatic void clear_node_page_dirty(struct page *page)
1018c2ecf20Sopenharmony_ci{
1028c2ecf20Sopenharmony_ci	if (PageDirty(page)) {
1038c2ecf20Sopenharmony_ci		f2fs_clear_page_cache_dirty_tag(page);
1048c2ecf20Sopenharmony_ci		clear_page_dirty_for_io(page);
1058c2ecf20Sopenharmony_ci		dec_page_count(F2FS_P_SB(page), F2FS_DIRTY_NODES);
1068c2ecf20Sopenharmony_ci	}
1078c2ecf20Sopenharmony_ci	ClearPageUptodate(page);
1088c2ecf20Sopenharmony_ci}
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_cistatic struct page *get_current_nat_page(struct f2fs_sb_info *sbi, nid_t nid)
1118c2ecf20Sopenharmony_ci{
1128c2ecf20Sopenharmony_ci	return f2fs_get_meta_page_retry(sbi, current_nat_addr(sbi, nid));
1138c2ecf20Sopenharmony_ci}
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_cistatic struct page *get_next_nat_page(struct f2fs_sb_info *sbi, nid_t nid)
1168c2ecf20Sopenharmony_ci{
1178c2ecf20Sopenharmony_ci	struct page *src_page;
1188c2ecf20Sopenharmony_ci	struct page *dst_page;
1198c2ecf20Sopenharmony_ci	pgoff_t dst_off;
1208c2ecf20Sopenharmony_ci	void *src_addr;
1218c2ecf20Sopenharmony_ci	void *dst_addr;
1228c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	dst_off = next_nat_addr(sbi, current_nat_addr(sbi, nid));
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	/* get current nat block page with lock */
1278c2ecf20Sopenharmony_ci	src_page = get_current_nat_page(sbi, nid);
1288c2ecf20Sopenharmony_ci	if (IS_ERR(src_page))
1298c2ecf20Sopenharmony_ci		return src_page;
1308c2ecf20Sopenharmony_ci	dst_page = f2fs_grab_meta_page(sbi, dst_off);
1318c2ecf20Sopenharmony_ci	f2fs_bug_on(sbi, PageDirty(src_page));
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	src_addr = page_address(src_page);
1348c2ecf20Sopenharmony_ci	dst_addr = page_address(dst_page);
1358c2ecf20Sopenharmony_ci	memcpy(dst_addr, src_addr, PAGE_SIZE);
1368c2ecf20Sopenharmony_ci	set_page_dirty(dst_page);
1378c2ecf20Sopenharmony_ci	f2fs_put_page(src_page, 1);
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	set_to_next_nat(nm_i, nid);
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	return dst_page;
1428c2ecf20Sopenharmony_ci}
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_cistatic struct nat_entry *__alloc_nat_entry(nid_t nid, bool no_fail)
1458c2ecf20Sopenharmony_ci{
1468c2ecf20Sopenharmony_ci	struct nat_entry *new;
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	if (no_fail)
1498c2ecf20Sopenharmony_ci		new = f2fs_kmem_cache_alloc(nat_entry_slab, GFP_F2FS_ZERO);
1508c2ecf20Sopenharmony_ci	else
1518c2ecf20Sopenharmony_ci		new = kmem_cache_alloc(nat_entry_slab, GFP_F2FS_ZERO);
1528c2ecf20Sopenharmony_ci	if (new) {
1538c2ecf20Sopenharmony_ci		nat_set_nid(new, nid);
1548c2ecf20Sopenharmony_ci		nat_reset_flag(new);
1558c2ecf20Sopenharmony_ci	}
1568c2ecf20Sopenharmony_ci	return new;
1578c2ecf20Sopenharmony_ci}
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_cistatic void __free_nat_entry(struct nat_entry *e)
1608c2ecf20Sopenharmony_ci{
1618c2ecf20Sopenharmony_ci	kmem_cache_free(nat_entry_slab, e);
1628c2ecf20Sopenharmony_ci}
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci/* must be locked by nat_tree_lock */
1658c2ecf20Sopenharmony_cistatic struct nat_entry *__init_nat_entry(struct f2fs_nm_info *nm_i,
1668c2ecf20Sopenharmony_ci	struct nat_entry *ne, struct f2fs_nat_entry *raw_ne, bool no_fail)
1678c2ecf20Sopenharmony_ci{
1688c2ecf20Sopenharmony_ci	if (no_fail)
1698c2ecf20Sopenharmony_ci		f2fs_radix_tree_insert(&nm_i->nat_root, nat_get_nid(ne), ne);
1708c2ecf20Sopenharmony_ci	else if (radix_tree_insert(&nm_i->nat_root, nat_get_nid(ne), ne))
1718c2ecf20Sopenharmony_ci		return NULL;
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	if (raw_ne)
1748c2ecf20Sopenharmony_ci		node_info_from_raw_nat(&ne->ni, raw_ne);
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	spin_lock(&nm_i->nat_list_lock);
1778c2ecf20Sopenharmony_ci	list_add_tail(&ne->list, &nm_i->nat_entries);
1788c2ecf20Sopenharmony_ci	spin_unlock(&nm_i->nat_list_lock);
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	nm_i->nat_cnt[TOTAL_NAT]++;
1818c2ecf20Sopenharmony_ci	nm_i->nat_cnt[RECLAIMABLE_NAT]++;
1828c2ecf20Sopenharmony_ci	return ne;
1838c2ecf20Sopenharmony_ci}
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_cistatic struct nat_entry *__lookup_nat_cache(struct f2fs_nm_info *nm_i, nid_t n)
1868c2ecf20Sopenharmony_ci{
1878c2ecf20Sopenharmony_ci	struct nat_entry *ne;
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	ne = radix_tree_lookup(&nm_i->nat_root, n);
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	/* for recent accessed nat entry, move it to tail of lru list */
1928c2ecf20Sopenharmony_ci	if (ne && !get_nat_flag(ne, IS_DIRTY)) {
1938c2ecf20Sopenharmony_ci		spin_lock(&nm_i->nat_list_lock);
1948c2ecf20Sopenharmony_ci		if (!list_empty(&ne->list))
1958c2ecf20Sopenharmony_ci			list_move_tail(&ne->list, &nm_i->nat_entries);
1968c2ecf20Sopenharmony_ci		spin_unlock(&nm_i->nat_list_lock);
1978c2ecf20Sopenharmony_ci	}
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	return ne;
2008c2ecf20Sopenharmony_ci}
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_cistatic unsigned int __gang_lookup_nat_cache(struct f2fs_nm_info *nm_i,
2038c2ecf20Sopenharmony_ci		nid_t start, unsigned int nr, struct nat_entry **ep)
2048c2ecf20Sopenharmony_ci{
2058c2ecf20Sopenharmony_ci	return radix_tree_gang_lookup(&nm_i->nat_root, (void **)ep, start, nr);
2068c2ecf20Sopenharmony_ci}
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_cistatic void __del_from_nat_cache(struct f2fs_nm_info *nm_i, struct nat_entry *e)
2098c2ecf20Sopenharmony_ci{
2108c2ecf20Sopenharmony_ci	radix_tree_delete(&nm_i->nat_root, nat_get_nid(e));
2118c2ecf20Sopenharmony_ci	nm_i->nat_cnt[TOTAL_NAT]--;
2128c2ecf20Sopenharmony_ci	nm_i->nat_cnt[RECLAIMABLE_NAT]--;
2138c2ecf20Sopenharmony_ci	__free_nat_entry(e);
2148c2ecf20Sopenharmony_ci}
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_cistatic struct nat_entry_set *__grab_nat_entry_set(struct f2fs_nm_info *nm_i,
2178c2ecf20Sopenharmony_ci							struct nat_entry *ne)
2188c2ecf20Sopenharmony_ci{
2198c2ecf20Sopenharmony_ci	nid_t set = NAT_BLOCK_OFFSET(ne->ni.nid);
2208c2ecf20Sopenharmony_ci	struct nat_entry_set *head;
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	head = radix_tree_lookup(&nm_i->nat_set_root, set);
2238c2ecf20Sopenharmony_ci	if (!head) {
2248c2ecf20Sopenharmony_ci		head = f2fs_kmem_cache_alloc(nat_entry_set_slab, GFP_NOFS);
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci		INIT_LIST_HEAD(&head->entry_list);
2278c2ecf20Sopenharmony_ci		INIT_LIST_HEAD(&head->set_list);
2288c2ecf20Sopenharmony_ci		head->set = set;
2298c2ecf20Sopenharmony_ci		head->entry_cnt = 0;
2308c2ecf20Sopenharmony_ci		f2fs_radix_tree_insert(&nm_i->nat_set_root, set, head);
2318c2ecf20Sopenharmony_ci	}
2328c2ecf20Sopenharmony_ci	return head;
2338c2ecf20Sopenharmony_ci}
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_cistatic void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i,
2368c2ecf20Sopenharmony_ci						struct nat_entry *ne)
2378c2ecf20Sopenharmony_ci{
2388c2ecf20Sopenharmony_ci	struct nat_entry_set *head;
2398c2ecf20Sopenharmony_ci	bool new_ne = nat_get_blkaddr(ne) == NEW_ADDR;
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	if (!new_ne)
2428c2ecf20Sopenharmony_ci		head = __grab_nat_entry_set(nm_i, ne);
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	/*
2458c2ecf20Sopenharmony_ci	 * update entry_cnt in below condition:
2468c2ecf20Sopenharmony_ci	 * 1. update NEW_ADDR to valid block address;
2478c2ecf20Sopenharmony_ci	 * 2. update old block address to new one;
2488c2ecf20Sopenharmony_ci	 */
2498c2ecf20Sopenharmony_ci	if (!new_ne && (get_nat_flag(ne, IS_PREALLOC) ||
2508c2ecf20Sopenharmony_ci				!get_nat_flag(ne, IS_DIRTY)))
2518c2ecf20Sopenharmony_ci		head->entry_cnt++;
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	set_nat_flag(ne, IS_PREALLOC, new_ne);
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	if (get_nat_flag(ne, IS_DIRTY))
2568c2ecf20Sopenharmony_ci		goto refresh_list;
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	nm_i->nat_cnt[DIRTY_NAT]++;
2598c2ecf20Sopenharmony_ci	nm_i->nat_cnt[RECLAIMABLE_NAT]--;
2608c2ecf20Sopenharmony_ci	set_nat_flag(ne, IS_DIRTY, true);
2618c2ecf20Sopenharmony_cirefresh_list:
2628c2ecf20Sopenharmony_ci	spin_lock(&nm_i->nat_list_lock);
2638c2ecf20Sopenharmony_ci	if (new_ne)
2648c2ecf20Sopenharmony_ci		list_del_init(&ne->list);
2658c2ecf20Sopenharmony_ci	else
2668c2ecf20Sopenharmony_ci		list_move_tail(&ne->list, &head->entry_list);
2678c2ecf20Sopenharmony_ci	spin_unlock(&nm_i->nat_list_lock);
2688c2ecf20Sopenharmony_ci}
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_cistatic void __clear_nat_cache_dirty(struct f2fs_nm_info *nm_i,
2718c2ecf20Sopenharmony_ci		struct nat_entry_set *set, struct nat_entry *ne)
2728c2ecf20Sopenharmony_ci{
2738c2ecf20Sopenharmony_ci	spin_lock(&nm_i->nat_list_lock);
2748c2ecf20Sopenharmony_ci	list_move_tail(&ne->list, &nm_i->nat_entries);
2758c2ecf20Sopenharmony_ci	spin_unlock(&nm_i->nat_list_lock);
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	set_nat_flag(ne, IS_DIRTY, false);
2788c2ecf20Sopenharmony_ci	set->entry_cnt--;
2798c2ecf20Sopenharmony_ci	nm_i->nat_cnt[DIRTY_NAT]--;
2808c2ecf20Sopenharmony_ci	nm_i->nat_cnt[RECLAIMABLE_NAT]++;
2818c2ecf20Sopenharmony_ci}
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_cistatic unsigned int __gang_lookup_nat_set(struct f2fs_nm_info *nm_i,
2848c2ecf20Sopenharmony_ci		nid_t start, unsigned int nr, struct nat_entry_set **ep)
2858c2ecf20Sopenharmony_ci{
2868c2ecf20Sopenharmony_ci	return radix_tree_gang_lookup(&nm_i->nat_set_root, (void **)ep,
2878c2ecf20Sopenharmony_ci							start, nr);
2888c2ecf20Sopenharmony_ci}
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_cibool f2fs_in_warm_node_list(struct f2fs_sb_info *sbi, struct page *page)
2918c2ecf20Sopenharmony_ci{
2928c2ecf20Sopenharmony_ci	return NODE_MAPPING(sbi) == page->mapping &&
2938c2ecf20Sopenharmony_ci			IS_DNODE(page) && is_cold_node(page);
2948c2ecf20Sopenharmony_ci}
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_civoid f2fs_init_fsync_node_info(struct f2fs_sb_info *sbi)
2978c2ecf20Sopenharmony_ci{
2988c2ecf20Sopenharmony_ci	spin_lock_init(&sbi->fsync_node_lock);
2998c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&sbi->fsync_node_list);
3008c2ecf20Sopenharmony_ci	sbi->fsync_seg_id = 0;
3018c2ecf20Sopenharmony_ci	sbi->fsync_node_num = 0;
3028c2ecf20Sopenharmony_ci}
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_cistatic unsigned int f2fs_add_fsync_node_entry(struct f2fs_sb_info *sbi,
3058c2ecf20Sopenharmony_ci							struct page *page)
3068c2ecf20Sopenharmony_ci{
3078c2ecf20Sopenharmony_ci	struct fsync_node_entry *fn;
3088c2ecf20Sopenharmony_ci	unsigned long flags;
3098c2ecf20Sopenharmony_ci	unsigned int seq_id;
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	fn = f2fs_kmem_cache_alloc(fsync_node_entry_slab, GFP_NOFS);
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci	get_page(page);
3148c2ecf20Sopenharmony_ci	fn->page = page;
3158c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&fn->list);
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	spin_lock_irqsave(&sbi->fsync_node_lock, flags);
3188c2ecf20Sopenharmony_ci	list_add_tail(&fn->list, &sbi->fsync_node_list);
3198c2ecf20Sopenharmony_ci	fn->seq_id = sbi->fsync_seg_id++;
3208c2ecf20Sopenharmony_ci	seq_id = fn->seq_id;
3218c2ecf20Sopenharmony_ci	sbi->fsync_node_num++;
3228c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&sbi->fsync_node_lock, flags);
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	return seq_id;
3258c2ecf20Sopenharmony_ci}
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_civoid f2fs_del_fsync_node_entry(struct f2fs_sb_info *sbi, struct page *page)
3288c2ecf20Sopenharmony_ci{
3298c2ecf20Sopenharmony_ci	struct fsync_node_entry *fn;
3308c2ecf20Sopenharmony_ci	unsigned long flags;
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	spin_lock_irqsave(&sbi->fsync_node_lock, flags);
3338c2ecf20Sopenharmony_ci	list_for_each_entry(fn, &sbi->fsync_node_list, list) {
3348c2ecf20Sopenharmony_ci		if (fn->page == page) {
3358c2ecf20Sopenharmony_ci			list_del(&fn->list);
3368c2ecf20Sopenharmony_ci			sbi->fsync_node_num--;
3378c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&sbi->fsync_node_lock, flags);
3388c2ecf20Sopenharmony_ci			kmem_cache_free(fsync_node_entry_slab, fn);
3398c2ecf20Sopenharmony_ci			put_page(page);
3408c2ecf20Sopenharmony_ci			return;
3418c2ecf20Sopenharmony_ci		}
3428c2ecf20Sopenharmony_ci	}
3438c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&sbi->fsync_node_lock, flags);
3448c2ecf20Sopenharmony_ci	f2fs_bug_on(sbi, 1);
3458c2ecf20Sopenharmony_ci}
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_civoid f2fs_reset_fsync_node_info(struct f2fs_sb_info *sbi)
3488c2ecf20Sopenharmony_ci{
3498c2ecf20Sopenharmony_ci	unsigned long flags;
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	spin_lock_irqsave(&sbi->fsync_node_lock, flags);
3528c2ecf20Sopenharmony_ci	sbi->fsync_seg_id = 0;
3538c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&sbi->fsync_node_lock, flags);
3548c2ecf20Sopenharmony_ci}
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ciint f2fs_need_dentry_mark(struct f2fs_sb_info *sbi, nid_t nid)
3578c2ecf20Sopenharmony_ci{
3588c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
3598c2ecf20Sopenharmony_ci	struct nat_entry *e;
3608c2ecf20Sopenharmony_ci	bool need = false;
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci	down_read(&nm_i->nat_tree_lock);
3638c2ecf20Sopenharmony_ci	e = __lookup_nat_cache(nm_i, nid);
3648c2ecf20Sopenharmony_ci	if (e) {
3658c2ecf20Sopenharmony_ci		if (!get_nat_flag(e, IS_CHECKPOINTED) &&
3668c2ecf20Sopenharmony_ci				!get_nat_flag(e, HAS_FSYNCED_INODE))
3678c2ecf20Sopenharmony_ci			need = true;
3688c2ecf20Sopenharmony_ci	}
3698c2ecf20Sopenharmony_ci	up_read(&nm_i->nat_tree_lock);
3708c2ecf20Sopenharmony_ci	return need;
3718c2ecf20Sopenharmony_ci}
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_cibool f2fs_is_checkpointed_node(struct f2fs_sb_info *sbi, nid_t nid)
3748c2ecf20Sopenharmony_ci{
3758c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
3768c2ecf20Sopenharmony_ci	struct nat_entry *e;
3778c2ecf20Sopenharmony_ci	bool is_cp = true;
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci	down_read(&nm_i->nat_tree_lock);
3808c2ecf20Sopenharmony_ci	e = __lookup_nat_cache(nm_i, nid);
3818c2ecf20Sopenharmony_ci	if (e && !get_nat_flag(e, IS_CHECKPOINTED))
3828c2ecf20Sopenharmony_ci		is_cp = false;
3838c2ecf20Sopenharmony_ci	up_read(&nm_i->nat_tree_lock);
3848c2ecf20Sopenharmony_ci	return is_cp;
3858c2ecf20Sopenharmony_ci}
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_cibool f2fs_need_inode_block_update(struct f2fs_sb_info *sbi, nid_t ino)
3888c2ecf20Sopenharmony_ci{
3898c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
3908c2ecf20Sopenharmony_ci	struct nat_entry *e;
3918c2ecf20Sopenharmony_ci	bool need_update = true;
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	down_read(&nm_i->nat_tree_lock);
3948c2ecf20Sopenharmony_ci	e = __lookup_nat_cache(nm_i, ino);
3958c2ecf20Sopenharmony_ci	if (e && get_nat_flag(e, HAS_LAST_FSYNC) &&
3968c2ecf20Sopenharmony_ci			(get_nat_flag(e, IS_CHECKPOINTED) ||
3978c2ecf20Sopenharmony_ci			 get_nat_flag(e, HAS_FSYNCED_INODE)))
3988c2ecf20Sopenharmony_ci		need_update = false;
3998c2ecf20Sopenharmony_ci	up_read(&nm_i->nat_tree_lock);
4008c2ecf20Sopenharmony_ci	return need_update;
4018c2ecf20Sopenharmony_ci}
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci/* must be locked by nat_tree_lock */
4048c2ecf20Sopenharmony_cistatic void cache_nat_entry(struct f2fs_sb_info *sbi, nid_t nid,
4058c2ecf20Sopenharmony_ci						struct f2fs_nat_entry *ne)
4068c2ecf20Sopenharmony_ci{
4078c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
4088c2ecf20Sopenharmony_ci	struct nat_entry *new, *e;
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci	new = __alloc_nat_entry(nid, false);
4118c2ecf20Sopenharmony_ci	if (!new)
4128c2ecf20Sopenharmony_ci		return;
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci	down_write(&nm_i->nat_tree_lock);
4158c2ecf20Sopenharmony_ci	e = __lookup_nat_cache(nm_i, nid);
4168c2ecf20Sopenharmony_ci	if (!e)
4178c2ecf20Sopenharmony_ci		e = __init_nat_entry(nm_i, new, ne, false);
4188c2ecf20Sopenharmony_ci	else
4198c2ecf20Sopenharmony_ci		f2fs_bug_on(sbi, nat_get_ino(e) != le32_to_cpu(ne->ino) ||
4208c2ecf20Sopenharmony_ci				nat_get_blkaddr(e) !=
4218c2ecf20Sopenharmony_ci					le32_to_cpu(ne->block_addr) ||
4228c2ecf20Sopenharmony_ci				nat_get_version(e) != ne->version);
4238c2ecf20Sopenharmony_ci	up_write(&nm_i->nat_tree_lock);
4248c2ecf20Sopenharmony_ci	if (e != new)
4258c2ecf20Sopenharmony_ci		__free_nat_entry(new);
4268c2ecf20Sopenharmony_ci}
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_cistatic void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
4298c2ecf20Sopenharmony_ci			block_t new_blkaddr, bool fsync_done)
4308c2ecf20Sopenharmony_ci{
4318c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
4328c2ecf20Sopenharmony_ci	struct nat_entry *e;
4338c2ecf20Sopenharmony_ci	struct nat_entry *new = __alloc_nat_entry(ni->nid, true);
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	down_write(&nm_i->nat_tree_lock);
4368c2ecf20Sopenharmony_ci	e = __lookup_nat_cache(nm_i, ni->nid);
4378c2ecf20Sopenharmony_ci	if (!e) {
4388c2ecf20Sopenharmony_ci		e = __init_nat_entry(nm_i, new, NULL, true);
4398c2ecf20Sopenharmony_ci		copy_node_info(&e->ni, ni);
4408c2ecf20Sopenharmony_ci		f2fs_bug_on(sbi, ni->blk_addr == NEW_ADDR);
4418c2ecf20Sopenharmony_ci	} else if (new_blkaddr == NEW_ADDR) {
4428c2ecf20Sopenharmony_ci		/*
4438c2ecf20Sopenharmony_ci		 * when nid is reallocated,
4448c2ecf20Sopenharmony_ci		 * previous nat entry can be remained in nat cache.
4458c2ecf20Sopenharmony_ci		 * So, reinitialize it with new information.
4468c2ecf20Sopenharmony_ci		 */
4478c2ecf20Sopenharmony_ci		copy_node_info(&e->ni, ni);
4488c2ecf20Sopenharmony_ci		f2fs_bug_on(sbi, ni->blk_addr != NULL_ADDR);
4498c2ecf20Sopenharmony_ci	}
4508c2ecf20Sopenharmony_ci	/* let's free early to reduce memory consumption */
4518c2ecf20Sopenharmony_ci	if (e != new)
4528c2ecf20Sopenharmony_ci		__free_nat_entry(new);
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	/* sanity check */
4558c2ecf20Sopenharmony_ci	f2fs_bug_on(sbi, nat_get_blkaddr(e) != ni->blk_addr);
4568c2ecf20Sopenharmony_ci	f2fs_bug_on(sbi, nat_get_blkaddr(e) == NULL_ADDR &&
4578c2ecf20Sopenharmony_ci			new_blkaddr == NULL_ADDR);
4588c2ecf20Sopenharmony_ci	f2fs_bug_on(sbi, nat_get_blkaddr(e) == NEW_ADDR &&
4598c2ecf20Sopenharmony_ci			new_blkaddr == NEW_ADDR);
4608c2ecf20Sopenharmony_ci	f2fs_bug_on(sbi, __is_valid_data_blkaddr(nat_get_blkaddr(e)) &&
4618c2ecf20Sopenharmony_ci			new_blkaddr == NEW_ADDR);
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ci	/* increment version no as node is removed */
4648c2ecf20Sopenharmony_ci	if (nat_get_blkaddr(e) != NEW_ADDR && new_blkaddr == NULL_ADDR) {
4658c2ecf20Sopenharmony_ci		unsigned char version = nat_get_version(e);
4668c2ecf20Sopenharmony_ci		nat_set_version(e, inc_node_version(version));
4678c2ecf20Sopenharmony_ci	}
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci	/* change address */
4708c2ecf20Sopenharmony_ci	nat_set_blkaddr(e, new_blkaddr);
4718c2ecf20Sopenharmony_ci	if (!__is_valid_data_blkaddr(new_blkaddr))
4728c2ecf20Sopenharmony_ci		set_nat_flag(e, IS_CHECKPOINTED, false);
4738c2ecf20Sopenharmony_ci	__set_nat_cache_dirty(nm_i, e);
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	/* update fsync_mark if its inode nat entry is still alive */
4768c2ecf20Sopenharmony_ci	if (ni->nid != ni->ino)
4778c2ecf20Sopenharmony_ci		e = __lookup_nat_cache(nm_i, ni->ino);
4788c2ecf20Sopenharmony_ci	if (e) {
4798c2ecf20Sopenharmony_ci		if (fsync_done && ni->nid == ni->ino)
4808c2ecf20Sopenharmony_ci			set_nat_flag(e, HAS_FSYNCED_INODE, true);
4818c2ecf20Sopenharmony_ci		set_nat_flag(e, HAS_LAST_FSYNC, fsync_done);
4828c2ecf20Sopenharmony_ci	}
4838c2ecf20Sopenharmony_ci	up_write(&nm_i->nat_tree_lock);
4848c2ecf20Sopenharmony_ci}
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ciint f2fs_try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink)
4878c2ecf20Sopenharmony_ci{
4888c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
4898c2ecf20Sopenharmony_ci	int nr = nr_shrink;
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_ci	if (!down_write_trylock(&nm_i->nat_tree_lock))
4928c2ecf20Sopenharmony_ci		return 0;
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci	spin_lock(&nm_i->nat_list_lock);
4958c2ecf20Sopenharmony_ci	while (nr_shrink) {
4968c2ecf20Sopenharmony_ci		struct nat_entry *ne;
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci		if (list_empty(&nm_i->nat_entries))
4998c2ecf20Sopenharmony_ci			break;
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci		ne = list_first_entry(&nm_i->nat_entries,
5028c2ecf20Sopenharmony_ci					struct nat_entry, list);
5038c2ecf20Sopenharmony_ci		list_del(&ne->list);
5048c2ecf20Sopenharmony_ci		spin_unlock(&nm_i->nat_list_lock);
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci		__del_from_nat_cache(nm_i, ne);
5078c2ecf20Sopenharmony_ci		nr_shrink--;
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci		spin_lock(&nm_i->nat_list_lock);
5108c2ecf20Sopenharmony_ci	}
5118c2ecf20Sopenharmony_ci	spin_unlock(&nm_i->nat_list_lock);
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ci	up_write(&nm_i->nat_tree_lock);
5148c2ecf20Sopenharmony_ci	return nr - nr_shrink;
5158c2ecf20Sopenharmony_ci}
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ciint f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
5188c2ecf20Sopenharmony_ci						struct node_info *ni)
5198c2ecf20Sopenharmony_ci{
5208c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
5218c2ecf20Sopenharmony_ci	struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
5228c2ecf20Sopenharmony_ci	struct f2fs_journal *journal = curseg->journal;
5238c2ecf20Sopenharmony_ci	nid_t start_nid = START_NID(nid);
5248c2ecf20Sopenharmony_ci	struct f2fs_nat_block *nat_blk;
5258c2ecf20Sopenharmony_ci	struct page *page = NULL;
5268c2ecf20Sopenharmony_ci	struct f2fs_nat_entry ne;
5278c2ecf20Sopenharmony_ci	struct nat_entry *e;
5288c2ecf20Sopenharmony_ci	pgoff_t index;
5298c2ecf20Sopenharmony_ci	block_t blkaddr;
5308c2ecf20Sopenharmony_ci	int i;
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci	ni->nid = nid;
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci	/* Check nat cache */
5358c2ecf20Sopenharmony_ci	down_read(&nm_i->nat_tree_lock);
5368c2ecf20Sopenharmony_ci	e = __lookup_nat_cache(nm_i, nid);
5378c2ecf20Sopenharmony_ci	if (e) {
5388c2ecf20Sopenharmony_ci		ni->ino = nat_get_ino(e);
5398c2ecf20Sopenharmony_ci		ni->blk_addr = nat_get_blkaddr(e);
5408c2ecf20Sopenharmony_ci		ni->version = nat_get_version(e);
5418c2ecf20Sopenharmony_ci		up_read(&nm_i->nat_tree_lock);
5428c2ecf20Sopenharmony_ci		return 0;
5438c2ecf20Sopenharmony_ci	}
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci	memset(&ne, 0, sizeof(struct f2fs_nat_entry));
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ci	/* Check current segment summary */
5488c2ecf20Sopenharmony_ci	down_read(&curseg->journal_rwsem);
5498c2ecf20Sopenharmony_ci	i = f2fs_lookup_journal_in_cursum(journal, NAT_JOURNAL, nid, 0);
5508c2ecf20Sopenharmony_ci	if (i >= 0) {
5518c2ecf20Sopenharmony_ci		ne = nat_in_journal(journal, i);
5528c2ecf20Sopenharmony_ci		node_info_from_raw_nat(ni, &ne);
5538c2ecf20Sopenharmony_ci	}
5548c2ecf20Sopenharmony_ci	up_read(&curseg->journal_rwsem);
5558c2ecf20Sopenharmony_ci	if (i >= 0) {
5568c2ecf20Sopenharmony_ci		up_read(&nm_i->nat_tree_lock);
5578c2ecf20Sopenharmony_ci		goto cache;
5588c2ecf20Sopenharmony_ci	}
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_ci	/* Fill node_info from nat page */
5618c2ecf20Sopenharmony_ci	index = current_nat_addr(sbi, nid);
5628c2ecf20Sopenharmony_ci	up_read(&nm_i->nat_tree_lock);
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci	page = f2fs_get_meta_page(sbi, index);
5658c2ecf20Sopenharmony_ci	if (IS_ERR(page))
5668c2ecf20Sopenharmony_ci		return PTR_ERR(page);
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_ci	nat_blk = (struct f2fs_nat_block *)page_address(page);
5698c2ecf20Sopenharmony_ci	ne = nat_blk->entries[nid - start_nid];
5708c2ecf20Sopenharmony_ci	node_info_from_raw_nat(ni, &ne);
5718c2ecf20Sopenharmony_ci	f2fs_put_page(page, 1);
5728c2ecf20Sopenharmony_cicache:
5738c2ecf20Sopenharmony_ci	blkaddr = le32_to_cpu(ne.block_addr);
5748c2ecf20Sopenharmony_ci	if (__is_valid_data_blkaddr(blkaddr) &&
5758c2ecf20Sopenharmony_ci		!f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC_ENHANCE))
5768c2ecf20Sopenharmony_ci		return -EFAULT;
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_ci	/* cache nat entry */
5798c2ecf20Sopenharmony_ci	cache_nat_entry(sbi, nid, &ne);
5808c2ecf20Sopenharmony_ci	return 0;
5818c2ecf20Sopenharmony_ci}
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci/*
5848c2ecf20Sopenharmony_ci * readahead MAX_RA_NODE number of node pages.
5858c2ecf20Sopenharmony_ci */
5868c2ecf20Sopenharmony_cistatic void f2fs_ra_node_pages(struct page *parent, int start, int n)
5878c2ecf20Sopenharmony_ci{
5888c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_P_SB(parent);
5898c2ecf20Sopenharmony_ci	struct blk_plug plug;
5908c2ecf20Sopenharmony_ci	int i, end;
5918c2ecf20Sopenharmony_ci	nid_t nid;
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci	blk_start_plug(&plug);
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	/* Then, try readahead for siblings of the desired node */
5968c2ecf20Sopenharmony_ci	end = start + n;
5978c2ecf20Sopenharmony_ci	end = min(end, NIDS_PER_BLOCK);
5988c2ecf20Sopenharmony_ci	for (i = start; i < end; i++) {
5998c2ecf20Sopenharmony_ci		nid = get_nid(parent, i, false);
6008c2ecf20Sopenharmony_ci		f2fs_ra_node_page(sbi, nid);
6018c2ecf20Sopenharmony_ci	}
6028c2ecf20Sopenharmony_ci
6038c2ecf20Sopenharmony_ci	blk_finish_plug(&plug);
6048c2ecf20Sopenharmony_ci}
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_cipgoff_t f2fs_get_next_page_offset(struct dnode_of_data *dn, pgoff_t pgofs)
6078c2ecf20Sopenharmony_ci{
6088c2ecf20Sopenharmony_ci	const long direct_index = ADDRS_PER_INODE(dn->inode);
6098c2ecf20Sopenharmony_ci	const long direct_blks = ADDRS_PER_BLOCK(dn->inode);
6108c2ecf20Sopenharmony_ci	const long indirect_blks = ADDRS_PER_BLOCK(dn->inode) * NIDS_PER_BLOCK;
6118c2ecf20Sopenharmony_ci	unsigned int skipped_unit = ADDRS_PER_BLOCK(dn->inode);
6128c2ecf20Sopenharmony_ci	int cur_level = dn->cur_level;
6138c2ecf20Sopenharmony_ci	int max_level = dn->max_level;
6148c2ecf20Sopenharmony_ci	pgoff_t base = 0;
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci	if (!dn->max_level)
6178c2ecf20Sopenharmony_ci		return pgofs + 1;
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	while (max_level-- > cur_level)
6208c2ecf20Sopenharmony_ci		skipped_unit *= NIDS_PER_BLOCK;
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci	switch (dn->max_level) {
6238c2ecf20Sopenharmony_ci	case 3:
6248c2ecf20Sopenharmony_ci		base += 2 * indirect_blks;
6258c2ecf20Sopenharmony_ci		fallthrough;
6268c2ecf20Sopenharmony_ci	case 2:
6278c2ecf20Sopenharmony_ci		base += 2 * direct_blks;
6288c2ecf20Sopenharmony_ci		fallthrough;
6298c2ecf20Sopenharmony_ci	case 1:
6308c2ecf20Sopenharmony_ci		base += direct_index;
6318c2ecf20Sopenharmony_ci		break;
6328c2ecf20Sopenharmony_ci	default:
6338c2ecf20Sopenharmony_ci		f2fs_bug_on(F2FS_I_SB(dn->inode), 1);
6348c2ecf20Sopenharmony_ci	}
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_ci	return ((pgofs - base) / skipped_unit + 1) * skipped_unit + base;
6378c2ecf20Sopenharmony_ci}
6388c2ecf20Sopenharmony_ci
6398c2ecf20Sopenharmony_ci/*
6408c2ecf20Sopenharmony_ci * The maximum depth is four.
6418c2ecf20Sopenharmony_ci * Offset[0] will have raw inode offset.
6428c2ecf20Sopenharmony_ci */
6438c2ecf20Sopenharmony_cistatic int get_node_path(struct inode *inode, long block,
6448c2ecf20Sopenharmony_ci				int offset[4], unsigned int noffset[4])
6458c2ecf20Sopenharmony_ci{
6468c2ecf20Sopenharmony_ci	const long direct_index = ADDRS_PER_INODE(inode);
6478c2ecf20Sopenharmony_ci	const long direct_blks = ADDRS_PER_BLOCK(inode);
6488c2ecf20Sopenharmony_ci	const long dptrs_per_blk = NIDS_PER_BLOCK;
6498c2ecf20Sopenharmony_ci	const long indirect_blks = ADDRS_PER_BLOCK(inode) * NIDS_PER_BLOCK;
6508c2ecf20Sopenharmony_ci	const long dindirect_blks = indirect_blks * NIDS_PER_BLOCK;
6518c2ecf20Sopenharmony_ci	int n = 0;
6528c2ecf20Sopenharmony_ci	int level = 0;
6538c2ecf20Sopenharmony_ci
6548c2ecf20Sopenharmony_ci	noffset[0] = 0;
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_ci	if (block < direct_index) {
6578c2ecf20Sopenharmony_ci		offset[n] = block;
6588c2ecf20Sopenharmony_ci		goto got;
6598c2ecf20Sopenharmony_ci	}
6608c2ecf20Sopenharmony_ci	block -= direct_index;
6618c2ecf20Sopenharmony_ci	if (block < direct_blks) {
6628c2ecf20Sopenharmony_ci		offset[n++] = NODE_DIR1_BLOCK;
6638c2ecf20Sopenharmony_ci		noffset[n] = 1;
6648c2ecf20Sopenharmony_ci		offset[n] = block;
6658c2ecf20Sopenharmony_ci		level = 1;
6668c2ecf20Sopenharmony_ci		goto got;
6678c2ecf20Sopenharmony_ci	}
6688c2ecf20Sopenharmony_ci	block -= direct_blks;
6698c2ecf20Sopenharmony_ci	if (block < direct_blks) {
6708c2ecf20Sopenharmony_ci		offset[n++] = NODE_DIR2_BLOCK;
6718c2ecf20Sopenharmony_ci		noffset[n] = 2;
6728c2ecf20Sopenharmony_ci		offset[n] = block;
6738c2ecf20Sopenharmony_ci		level = 1;
6748c2ecf20Sopenharmony_ci		goto got;
6758c2ecf20Sopenharmony_ci	}
6768c2ecf20Sopenharmony_ci	block -= direct_blks;
6778c2ecf20Sopenharmony_ci	if (block < indirect_blks) {
6788c2ecf20Sopenharmony_ci		offset[n++] = NODE_IND1_BLOCK;
6798c2ecf20Sopenharmony_ci		noffset[n] = 3;
6808c2ecf20Sopenharmony_ci		offset[n++] = block / direct_blks;
6818c2ecf20Sopenharmony_ci		noffset[n] = 4 + offset[n - 1];
6828c2ecf20Sopenharmony_ci		offset[n] = block % direct_blks;
6838c2ecf20Sopenharmony_ci		level = 2;
6848c2ecf20Sopenharmony_ci		goto got;
6858c2ecf20Sopenharmony_ci	}
6868c2ecf20Sopenharmony_ci	block -= indirect_blks;
6878c2ecf20Sopenharmony_ci	if (block < indirect_blks) {
6888c2ecf20Sopenharmony_ci		offset[n++] = NODE_IND2_BLOCK;
6898c2ecf20Sopenharmony_ci		noffset[n] = 4 + dptrs_per_blk;
6908c2ecf20Sopenharmony_ci		offset[n++] = block / direct_blks;
6918c2ecf20Sopenharmony_ci		noffset[n] = 5 + dptrs_per_blk + offset[n - 1];
6928c2ecf20Sopenharmony_ci		offset[n] = block % direct_blks;
6938c2ecf20Sopenharmony_ci		level = 2;
6948c2ecf20Sopenharmony_ci		goto got;
6958c2ecf20Sopenharmony_ci	}
6968c2ecf20Sopenharmony_ci	block -= indirect_blks;
6978c2ecf20Sopenharmony_ci	if (block < dindirect_blks) {
6988c2ecf20Sopenharmony_ci		offset[n++] = NODE_DIND_BLOCK;
6998c2ecf20Sopenharmony_ci		noffset[n] = 5 + (dptrs_per_blk * 2);
7008c2ecf20Sopenharmony_ci		offset[n++] = block / indirect_blks;
7018c2ecf20Sopenharmony_ci		noffset[n] = 6 + (dptrs_per_blk * 2) +
7028c2ecf20Sopenharmony_ci			      offset[n - 1] * (dptrs_per_blk + 1);
7038c2ecf20Sopenharmony_ci		offset[n++] = (block / direct_blks) % dptrs_per_blk;
7048c2ecf20Sopenharmony_ci		noffset[n] = 7 + (dptrs_per_blk * 2) +
7058c2ecf20Sopenharmony_ci			      offset[n - 2] * (dptrs_per_blk + 1) +
7068c2ecf20Sopenharmony_ci			      offset[n - 1];
7078c2ecf20Sopenharmony_ci		offset[n] = block % direct_blks;
7088c2ecf20Sopenharmony_ci		level = 3;
7098c2ecf20Sopenharmony_ci		goto got;
7108c2ecf20Sopenharmony_ci	} else {
7118c2ecf20Sopenharmony_ci		return -E2BIG;
7128c2ecf20Sopenharmony_ci	}
7138c2ecf20Sopenharmony_cigot:
7148c2ecf20Sopenharmony_ci	return level;
7158c2ecf20Sopenharmony_ci}
7168c2ecf20Sopenharmony_ci
7178c2ecf20Sopenharmony_ci/*
7188c2ecf20Sopenharmony_ci * Caller should call f2fs_put_dnode(dn).
7198c2ecf20Sopenharmony_ci * Also, it should grab and release a rwsem by calling f2fs_lock_op() and
7208c2ecf20Sopenharmony_ci * f2fs_unlock_op() only if mode is set with ALLOC_NODE.
7218c2ecf20Sopenharmony_ci */
7228c2ecf20Sopenharmony_ciint f2fs_get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode)
7238c2ecf20Sopenharmony_ci{
7248c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
7258c2ecf20Sopenharmony_ci	struct page *npage[4];
7268c2ecf20Sopenharmony_ci	struct page *parent = NULL;
7278c2ecf20Sopenharmony_ci	int offset[4];
7288c2ecf20Sopenharmony_ci	unsigned int noffset[4];
7298c2ecf20Sopenharmony_ci	nid_t nids[4];
7308c2ecf20Sopenharmony_ci	int level, i = 0;
7318c2ecf20Sopenharmony_ci	int err = 0;
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ci	level = get_node_path(dn->inode, index, offset, noffset);
7348c2ecf20Sopenharmony_ci	if (level < 0)
7358c2ecf20Sopenharmony_ci		return level;
7368c2ecf20Sopenharmony_ci
7378c2ecf20Sopenharmony_ci	nids[0] = dn->inode->i_ino;
7388c2ecf20Sopenharmony_ci	npage[0] = dn->inode_page;
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_ci	if (!npage[0]) {
7418c2ecf20Sopenharmony_ci		npage[0] = f2fs_get_node_page(sbi, nids[0]);
7428c2ecf20Sopenharmony_ci		if (IS_ERR(npage[0]))
7438c2ecf20Sopenharmony_ci			return PTR_ERR(npage[0]);
7448c2ecf20Sopenharmony_ci	}
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ci	/* if inline_data is set, should not report any block indices */
7478c2ecf20Sopenharmony_ci	if (f2fs_has_inline_data(dn->inode) && index) {
7488c2ecf20Sopenharmony_ci		err = -ENOENT;
7498c2ecf20Sopenharmony_ci		f2fs_put_page(npage[0], 1);
7508c2ecf20Sopenharmony_ci		goto release_out;
7518c2ecf20Sopenharmony_ci	}
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_ci	parent = npage[0];
7548c2ecf20Sopenharmony_ci	if (level != 0)
7558c2ecf20Sopenharmony_ci		nids[1] = get_nid(parent, offset[0], true);
7568c2ecf20Sopenharmony_ci	dn->inode_page = npage[0];
7578c2ecf20Sopenharmony_ci	dn->inode_page_locked = true;
7588c2ecf20Sopenharmony_ci
7598c2ecf20Sopenharmony_ci	/* get indirect or direct nodes */
7608c2ecf20Sopenharmony_ci	for (i = 1; i <= level; i++) {
7618c2ecf20Sopenharmony_ci		bool done = false;
7628c2ecf20Sopenharmony_ci
7638c2ecf20Sopenharmony_ci		if (!nids[i] && mode == ALLOC_NODE) {
7648c2ecf20Sopenharmony_ci			/* alloc new node */
7658c2ecf20Sopenharmony_ci			if (!f2fs_alloc_nid(sbi, &(nids[i]))) {
7668c2ecf20Sopenharmony_ci				err = -ENOSPC;
7678c2ecf20Sopenharmony_ci				goto release_pages;
7688c2ecf20Sopenharmony_ci			}
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_ci			dn->nid = nids[i];
7718c2ecf20Sopenharmony_ci			npage[i] = f2fs_new_node_page(dn, noffset[i]);
7728c2ecf20Sopenharmony_ci			if (IS_ERR(npage[i])) {
7738c2ecf20Sopenharmony_ci				f2fs_alloc_nid_failed(sbi, nids[i]);
7748c2ecf20Sopenharmony_ci				err = PTR_ERR(npage[i]);
7758c2ecf20Sopenharmony_ci				goto release_pages;
7768c2ecf20Sopenharmony_ci			}
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci			set_nid(parent, offset[i - 1], nids[i], i == 1);
7798c2ecf20Sopenharmony_ci			f2fs_alloc_nid_done(sbi, nids[i]);
7808c2ecf20Sopenharmony_ci			done = true;
7818c2ecf20Sopenharmony_ci		} else if (mode == LOOKUP_NODE_RA && i == level && level > 1) {
7828c2ecf20Sopenharmony_ci			npage[i] = f2fs_get_node_page_ra(parent, offset[i - 1]);
7838c2ecf20Sopenharmony_ci			if (IS_ERR(npage[i])) {
7848c2ecf20Sopenharmony_ci				err = PTR_ERR(npage[i]);
7858c2ecf20Sopenharmony_ci				goto release_pages;
7868c2ecf20Sopenharmony_ci			}
7878c2ecf20Sopenharmony_ci			done = true;
7888c2ecf20Sopenharmony_ci		}
7898c2ecf20Sopenharmony_ci		if (i == 1) {
7908c2ecf20Sopenharmony_ci			dn->inode_page_locked = false;
7918c2ecf20Sopenharmony_ci			unlock_page(parent);
7928c2ecf20Sopenharmony_ci		} else {
7938c2ecf20Sopenharmony_ci			f2fs_put_page(parent, 1);
7948c2ecf20Sopenharmony_ci		}
7958c2ecf20Sopenharmony_ci
7968c2ecf20Sopenharmony_ci		if (!done) {
7978c2ecf20Sopenharmony_ci			npage[i] = f2fs_get_node_page(sbi, nids[i]);
7988c2ecf20Sopenharmony_ci			if (IS_ERR(npage[i])) {
7998c2ecf20Sopenharmony_ci				err = PTR_ERR(npage[i]);
8008c2ecf20Sopenharmony_ci				f2fs_put_page(npage[0], 0);
8018c2ecf20Sopenharmony_ci				goto release_out;
8028c2ecf20Sopenharmony_ci			}
8038c2ecf20Sopenharmony_ci		}
8048c2ecf20Sopenharmony_ci		if (i < level) {
8058c2ecf20Sopenharmony_ci			parent = npage[i];
8068c2ecf20Sopenharmony_ci			nids[i + 1] = get_nid(parent, offset[i], false);
8078c2ecf20Sopenharmony_ci		}
8088c2ecf20Sopenharmony_ci	}
8098c2ecf20Sopenharmony_ci	dn->nid = nids[level];
8108c2ecf20Sopenharmony_ci	dn->ofs_in_node = offset[level];
8118c2ecf20Sopenharmony_ci	dn->node_page = npage[level];
8128c2ecf20Sopenharmony_ci	dn->data_blkaddr = f2fs_data_blkaddr(dn);
8138c2ecf20Sopenharmony_ci	return 0;
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_cirelease_pages:
8168c2ecf20Sopenharmony_ci	f2fs_put_page(parent, 1);
8178c2ecf20Sopenharmony_ci	if (i > 1)
8188c2ecf20Sopenharmony_ci		f2fs_put_page(npage[0], 0);
8198c2ecf20Sopenharmony_cirelease_out:
8208c2ecf20Sopenharmony_ci	dn->inode_page = NULL;
8218c2ecf20Sopenharmony_ci	dn->node_page = NULL;
8228c2ecf20Sopenharmony_ci	if (err == -ENOENT) {
8238c2ecf20Sopenharmony_ci		dn->cur_level = i;
8248c2ecf20Sopenharmony_ci		dn->max_level = level;
8258c2ecf20Sopenharmony_ci		dn->ofs_in_node = offset[level];
8268c2ecf20Sopenharmony_ci	}
8278c2ecf20Sopenharmony_ci	return err;
8288c2ecf20Sopenharmony_ci}
8298c2ecf20Sopenharmony_ci
8308c2ecf20Sopenharmony_cistatic int truncate_node(struct dnode_of_data *dn)
8318c2ecf20Sopenharmony_ci{
8328c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
8338c2ecf20Sopenharmony_ci	struct node_info ni;
8348c2ecf20Sopenharmony_ci	int err;
8358c2ecf20Sopenharmony_ci	pgoff_t index;
8368c2ecf20Sopenharmony_ci
8378c2ecf20Sopenharmony_ci	err = f2fs_get_node_info(sbi, dn->nid, &ni);
8388c2ecf20Sopenharmony_ci	if (err)
8398c2ecf20Sopenharmony_ci		return err;
8408c2ecf20Sopenharmony_ci
8418c2ecf20Sopenharmony_ci	/* Deallocate node address */
8428c2ecf20Sopenharmony_ci	f2fs_invalidate_blocks(sbi, ni.blk_addr);
8438c2ecf20Sopenharmony_ci	dec_valid_node_count(sbi, dn->inode, dn->nid == dn->inode->i_ino);
8448c2ecf20Sopenharmony_ci	set_node_addr(sbi, &ni, NULL_ADDR, false);
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_ci	if (dn->nid == dn->inode->i_ino) {
8478c2ecf20Sopenharmony_ci		f2fs_remove_orphan_inode(sbi, dn->nid);
8488c2ecf20Sopenharmony_ci		dec_valid_inode_count(sbi);
8498c2ecf20Sopenharmony_ci		f2fs_inode_synced(dn->inode);
8508c2ecf20Sopenharmony_ci	}
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci	clear_node_page_dirty(dn->node_page);
8538c2ecf20Sopenharmony_ci	set_sbi_flag(sbi, SBI_IS_DIRTY);
8548c2ecf20Sopenharmony_ci
8558c2ecf20Sopenharmony_ci	index = dn->node_page->index;
8568c2ecf20Sopenharmony_ci	f2fs_put_page(dn->node_page, 1);
8578c2ecf20Sopenharmony_ci
8588c2ecf20Sopenharmony_ci	invalidate_mapping_pages(NODE_MAPPING(sbi),
8598c2ecf20Sopenharmony_ci			index, index);
8608c2ecf20Sopenharmony_ci
8618c2ecf20Sopenharmony_ci	dn->node_page = NULL;
8628c2ecf20Sopenharmony_ci	trace_f2fs_truncate_node(dn->inode, dn->nid, ni.blk_addr);
8638c2ecf20Sopenharmony_ci
8648c2ecf20Sopenharmony_ci	return 0;
8658c2ecf20Sopenharmony_ci}
8668c2ecf20Sopenharmony_ci
8678c2ecf20Sopenharmony_cistatic int truncate_dnode(struct dnode_of_data *dn)
8688c2ecf20Sopenharmony_ci{
8698c2ecf20Sopenharmony_ci	struct page *page;
8708c2ecf20Sopenharmony_ci	int err;
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_ci	if (dn->nid == 0)
8738c2ecf20Sopenharmony_ci		return 1;
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_ci	/* get direct node */
8768c2ecf20Sopenharmony_ci	page = f2fs_get_node_page(F2FS_I_SB(dn->inode), dn->nid);
8778c2ecf20Sopenharmony_ci	if (PTR_ERR(page) == -ENOENT)
8788c2ecf20Sopenharmony_ci		return 1;
8798c2ecf20Sopenharmony_ci	else if (IS_ERR(page))
8808c2ecf20Sopenharmony_ci		return PTR_ERR(page);
8818c2ecf20Sopenharmony_ci
8828c2ecf20Sopenharmony_ci	/* Make dnode_of_data for parameter */
8838c2ecf20Sopenharmony_ci	dn->node_page = page;
8848c2ecf20Sopenharmony_ci	dn->ofs_in_node = 0;
8858c2ecf20Sopenharmony_ci	f2fs_truncate_data_blocks(dn);
8868c2ecf20Sopenharmony_ci	err = truncate_node(dn);
8878c2ecf20Sopenharmony_ci	if (err) {
8888c2ecf20Sopenharmony_ci		f2fs_put_page(page, 1);
8898c2ecf20Sopenharmony_ci		return err;
8908c2ecf20Sopenharmony_ci	}
8918c2ecf20Sopenharmony_ci
8928c2ecf20Sopenharmony_ci	return 1;
8938c2ecf20Sopenharmony_ci}
8948c2ecf20Sopenharmony_ci
8958c2ecf20Sopenharmony_cistatic int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs,
8968c2ecf20Sopenharmony_ci						int ofs, int depth)
8978c2ecf20Sopenharmony_ci{
8988c2ecf20Sopenharmony_ci	struct dnode_of_data rdn = *dn;
8998c2ecf20Sopenharmony_ci	struct page *page;
9008c2ecf20Sopenharmony_ci	struct f2fs_node *rn;
9018c2ecf20Sopenharmony_ci	nid_t child_nid;
9028c2ecf20Sopenharmony_ci	unsigned int child_nofs;
9038c2ecf20Sopenharmony_ci	int freed = 0;
9048c2ecf20Sopenharmony_ci	int i, ret;
9058c2ecf20Sopenharmony_ci
9068c2ecf20Sopenharmony_ci	if (dn->nid == 0)
9078c2ecf20Sopenharmony_ci		return NIDS_PER_BLOCK + 1;
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_ci	trace_f2fs_truncate_nodes_enter(dn->inode, dn->nid, dn->data_blkaddr);
9108c2ecf20Sopenharmony_ci
9118c2ecf20Sopenharmony_ci	page = f2fs_get_node_page(F2FS_I_SB(dn->inode), dn->nid);
9128c2ecf20Sopenharmony_ci	if (IS_ERR(page)) {
9138c2ecf20Sopenharmony_ci		trace_f2fs_truncate_nodes_exit(dn->inode, PTR_ERR(page));
9148c2ecf20Sopenharmony_ci		return PTR_ERR(page);
9158c2ecf20Sopenharmony_ci	}
9168c2ecf20Sopenharmony_ci
9178c2ecf20Sopenharmony_ci	f2fs_ra_node_pages(page, ofs, NIDS_PER_BLOCK);
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_ci	rn = F2FS_NODE(page);
9208c2ecf20Sopenharmony_ci	if (depth < 3) {
9218c2ecf20Sopenharmony_ci		for (i = ofs; i < NIDS_PER_BLOCK; i++, freed++) {
9228c2ecf20Sopenharmony_ci			child_nid = le32_to_cpu(rn->in.nid[i]);
9238c2ecf20Sopenharmony_ci			if (child_nid == 0)
9248c2ecf20Sopenharmony_ci				continue;
9258c2ecf20Sopenharmony_ci			rdn.nid = child_nid;
9268c2ecf20Sopenharmony_ci			ret = truncate_dnode(&rdn);
9278c2ecf20Sopenharmony_ci			if (ret < 0)
9288c2ecf20Sopenharmony_ci				goto out_err;
9298c2ecf20Sopenharmony_ci			if (set_nid(page, i, 0, false))
9308c2ecf20Sopenharmony_ci				dn->node_changed = true;
9318c2ecf20Sopenharmony_ci		}
9328c2ecf20Sopenharmony_ci	} else {
9338c2ecf20Sopenharmony_ci		child_nofs = nofs + ofs * (NIDS_PER_BLOCK + 1) + 1;
9348c2ecf20Sopenharmony_ci		for (i = ofs; i < NIDS_PER_BLOCK; i++) {
9358c2ecf20Sopenharmony_ci			child_nid = le32_to_cpu(rn->in.nid[i]);
9368c2ecf20Sopenharmony_ci			if (child_nid == 0) {
9378c2ecf20Sopenharmony_ci				child_nofs += NIDS_PER_BLOCK + 1;
9388c2ecf20Sopenharmony_ci				continue;
9398c2ecf20Sopenharmony_ci			}
9408c2ecf20Sopenharmony_ci			rdn.nid = child_nid;
9418c2ecf20Sopenharmony_ci			ret = truncate_nodes(&rdn, child_nofs, 0, depth - 1);
9428c2ecf20Sopenharmony_ci			if (ret == (NIDS_PER_BLOCK + 1)) {
9438c2ecf20Sopenharmony_ci				if (set_nid(page, i, 0, false))
9448c2ecf20Sopenharmony_ci					dn->node_changed = true;
9458c2ecf20Sopenharmony_ci				child_nofs += ret;
9468c2ecf20Sopenharmony_ci			} else if (ret < 0 && ret != -ENOENT) {
9478c2ecf20Sopenharmony_ci				goto out_err;
9488c2ecf20Sopenharmony_ci			}
9498c2ecf20Sopenharmony_ci		}
9508c2ecf20Sopenharmony_ci		freed = child_nofs;
9518c2ecf20Sopenharmony_ci	}
9528c2ecf20Sopenharmony_ci
9538c2ecf20Sopenharmony_ci	if (!ofs) {
9548c2ecf20Sopenharmony_ci		/* remove current indirect node */
9558c2ecf20Sopenharmony_ci		dn->node_page = page;
9568c2ecf20Sopenharmony_ci		ret = truncate_node(dn);
9578c2ecf20Sopenharmony_ci		if (ret)
9588c2ecf20Sopenharmony_ci			goto out_err;
9598c2ecf20Sopenharmony_ci		freed++;
9608c2ecf20Sopenharmony_ci	} else {
9618c2ecf20Sopenharmony_ci		f2fs_put_page(page, 1);
9628c2ecf20Sopenharmony_ci	}
9638c2ecf20Sopenharmony_ci	trace_f2fs_truncate_nodes_exit(dn->inode, freed);
9648c2ecf20Sopenharmony_ci	return freed;
9658c2ecf20Sopenharmony_ci
9668c2ecf20Sopenharmony_ciout_err:
9678c2ecf20Sopenharmony_ci	f2fs_put_page(page, 1);
9688c2ecf20Sopenharmony_ci	trace_f2fs_truncate_nodes_exit(dn->inode, ret);
9698c2ecf20Sopenharmony_ci	return ret;
9708c2ecf20Sopenharmony_ci}
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_cistatic int truncate_partial_nodes(struct dnode_of_data *dn,
9738c2ecf20Sopenharmony_ci			struct f2fs_inode *ri, int *offset, int depth)
9748c2ecf20Sopenharmony_ci{
9758c2ecf20Sopenharmony_ci	struct page *pages[2];
9768c2ecf20Sopenharmony_ci	nid_t nid[3];
9778c2ecf20Sopenharmony_ci	nid_t child_nid;
9788c2ecf20Sopenharmony_ci	int err = 0;
9798c2ecf20Sopenharmony_ci	int i;
9808c2ecf20Sopenharmony_ci	int idx = depth - 2;
9818c2ecf20Sopenharmony_ci
9828c2ecf20Sopenharmony_ci	nid[0] = le32_to_cpu(ri->i_nid[offset[0] - NODE_DIR1_BLOCK]);
9838c2ecf20Sopenharmony_ci	if (!nid[0])
9848c2ecf20Sopenharmony_ci		return 0;
9858c2ecf20Sopenharmony_ci
9868c2ecf20Sopenharmony_ci	/* get indirect nodes in the path */
9878c2ecf20Sopenharmony_ci	for (i = 0; i < idx + 1; i++) {
9888c2ecf20Sopenharmony_ci		/* reference count'll be increased */
9898c2ecf20Sopenharmony_ci		pages[i] = f2fs_get_node_page(F2FS_I_SB(dn->inode), nid[i]);
9908c2ecf20Sopenharmony_ci		if (IS_ERR(pages[i])) {
9918c2ecf20Sopenharmony_ci			err = PTR_ERR(pages[i]);
9928c2ecf20Sopenharmony_ci			idx = i - 1;
9938c2ecf20Sopenharmony_ci			goto fail;
9948c2ecf20Sopenharmony_ci		}
9958c2ecf20Sopenharmony_ci		nid[i + 1] = get_nid(pages[i], offset[i + 1], false);
9968c2ecf20Sopenharmony_ci	}
9978c2ecf20Sopenharmony_ci
9988c2ecf20Sopenharmony_ci	f2fs_ra_node_pages(pages[idx], offset[idx + 1], NIDS_PER_BLOCK);
9998c2ecf20Sopenharmony_ci
10008c2ecf20Sopenharmony_ci	/* free direct nodes linked to a partial indirect node */
10018c2ecf20Sopenharmony_ci	for (i = offset[idx + 1]; i < NIDS_PER_BLOCK; i++) {
10028c2ecf20Sopenharmony_ci		child_nid = get_nid(pages[idx], i, false);
10038c2ecf20Sopenharmony_ci		if (!child_nid)
10048c2ecf20Sopenharmony_ci			continue;
10058c2ecf20Sopenharmony_ci		dn->nid = child_nid;
10068c2ecf20Sopenharmony_ci		err = truncate_dnode(dn);
10078c2ecf20Sopenharmony_ci		if (err < 0)
10088c2ecf20Sopenharmony_ci			goto fail;
10098c2ecf20Sopenharmony_ci		if (set_nid(pages[idx], i, 0, false))
10108c2ecf20Sopenharmony_ci			dn->node_changed = true;
10118c2ecf20Sopenharmony_ci	}
10128c2ecf20Sopenharmony_ci
10138c2ecf20Sopenharmony_ci	if (offset[idx + 1] == 0) {
10148c2ecf20Sopenharmony_ci		dn->node_page = pages[idx];
10158c2ecf20Sopenharmony_ci		dn->nid = nid[idx];
10168c2ecf20Sopenharmony_ci		err = truncate_node(dn);
10178c2ecf20Sopenharmony_ci		if (err)
10188c2ecf20Sopenharmony_ci			goto fail;
10198c2ecf20Sopenharmony_ci	} else {
10208c2ecf20Sopenharmony_ci		f2fs_put_page(pages[idx], 1);
10218c2ecf20Sopenharmony_ci	}
10228c2ecf20Sopenharmony_ci	offset[idx]++;
10238c2ecf20Sopenharmony_ci	offset[idx + 1] = 0;
10248c2ecf20Sopenharmony_ci	idx--;
10258c2ecf20Sopenharmony_cifail:
10268c2ecf20Sopenharmony_ci	for (i = idx; i >= 0; i--)
10278c2ecf20Sopenharmony_ci		f2fs_put_page(pages[i], 1);
10288c2ecf20Sopenharmony_ci
10298c2ecf20Sopenharmony_ci	trace_f2fs_truncate_partial_nodes(dn->inode, nid, depth, err);
10308c2ecf20Sopenharmony_ci
10318c2ecf20Sopenharmony_ci	return err;
10328c2ecf20Sopenharmony_ci}
10338c2ecf20Sopenharmony_ci
10348c2ecf20Sopenharmony_ci/*
10358c2ecf20Sopenharmony_ci * All the block addresses of data and nodes should be nullified.
10368c2ecf20Sopenharmony_ci */
10378c2ecf20Sopenharmony_ciint f2fs_truncate_inode_blocks(struct inode *inode, pgoff_t from)
10388c2ecf20Sopenharmony_ci{
10398c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
10408c2ecf20Sopenharmony_ci	int err = 0, cont = 1;
10418c2ecf20Sopenharmony_ci	int level, offset[4], noffset[4];
10428c2ecf20Sopenharmony_ci	unsigned int nofs = 0;
10438c2ecf20Sopenharmony_ci	struct f2fs_inode *ri;
10448c2ecf20Sopenharmony_ci	struct dnode_of_data dn;
10458c2ecf20Sopenharmony_ci	struct page *page;
10468c2ecf20Sopenharmony_ci
10478c2ecf20Sopenharmony_ci	trace_f2fs_truncate_inode_blocks_enter(inode, from);
10488c2ecf20Sopenharmony_ci
10498c2ecf20Sopenharmony_ci	level = get_node_path(inode, from, offset, noffset);
10508c2ecf20Sopenharmony_ci	if (level < 0) {
10518c2ecf20Sopenharmony_ci		trace_f2fs_truncate_inode_blocks_exit(inode, level);
10528c2ecf20Sopenharmony_ci		return level;
10538c2ecf20Sopenharmony_ci	}
10548c2ecf20Sopenharmony_ci
10558c2ecf20Sopenharmony_ci	page = f2fs_get_node_page(sbi, inode->i_ino);
10568c2ecf20Sopenharmony_ci	if (IS_ERR(page)) {
10578c2ecf20Sopenharmony_ci		trace_f2fs_truncate_inode_blocks_exit(inode, PTR_ERR(page));
10588c2ecf20Sopenharmony_ci		return PTR_ERR(page);
10598c2ecf20Sopenharmony_ci	}
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_ci	set_new_dnode(&dn, inode, page, NULL, 0);
10628c2ecf20Sopenharmony_ci	unlock_page(page);
10638c2ecf20Sopenharmony_ci
10648c2ecf20Sopenharmony_ci	ri = F2FS_INODE(page);
10658c2ecf20Sopenharmony_ci	switch (level) {
10668c2ecf20Sopenharmony_ci	case 0:
10678c2ecf20Sopenharmony_ci	case 1:
10688c2ecf20Sopenharmony_ci		nofs = noffset[1];
10698c2ecf20Sopenharmony_ci		break;
10708c2ecf20Sopenharmony_ci	case 2:
10718c2ecf20Sopenharmony_ci		nofs = noffset[1];
10728c2ecf20Sopenharmony_ci		if (!offset[level - 1])
10738c2ecf20Sopenharmony_ci			goto skip_partial;
10748c2ecf20Sopenharmony_ci		err = truncate_partial_nodes(&dn, ri, offset, level);
10758c2ecf20Sopenharmony_ci		if (err < 0 && err != -ENOENT)
10768c2ecf20Sopenharmony_ci			goto fail;
10778c2ecf20Sopenharmony_ci		nofs += 1 + NIDS_PER_BLOCK;
10788c2ecf20Sopenharmony_ci		break;
10798c2ecf20Sopenharmony_ci	case 3:
10808c2ecf20Sopenharmony_ci		nofs = 5 + 2 * NIDS_PER_BLOCK;
10818c2ecf20Sopenharmony_ci		if (!offset[level - 1])
10828c2ecf20Sopenharmony_ci			goto skip_partial;
10838c2ecf20Sopenharmony_ci		err = truncate_partial_nodes(&dn, ri, offset, level);
10848c2ecf20Sopenharmony_ci		if (err < 0 && err != -ENOENT)
10858c2ecf20Sopenharmony_ci			goto fail;
10868c2ecf20Sopenharmony_ci		break;
10878c2ecf20Sopenharmony_ci	default:
10888c2ecf20Sopenharmony_ci		BUG();
10898c2ecf20Sopenharmony_ci	}
10908c2ecf20Sopenharmony_ci
10918c2ecf20Sopenharmony_ciskip_partial:
10928c2ecf20Sopenharmony_ci	while (cont) {
10938c2ecf20Sopenharmony_ci		dn.nid = le32_to_cpu(ri->i_nid[offset[0] - NODE_DIR1_BLOCK]);
10948c2ecf20Sopenharmony_ci		switch (offset[0]) {
10958c2ecf20Sopenharmony_ci		case NODE_DIR1_BLOCK:
10968c2ecf20Sopenharmony_ci		case NODE_DIR2_BLOCK:
10978c2ecf20Sopenharmony_ci			err = truncate_dnode(&dn);
10988c2ecf20Sopenharmony_ci			break;
10998c2ecf20Sopenharmony_ci
11008c2ecf20Sopenharmony_ci		case NODE_IND1_BLOCK:
11018c2ecf20Sopenharmony_ci		case NODE_IND2_BLOCK:
11028c2ecf20Sopenharmony_ci			err = truncate_nodes(&dn, nofs, offset[1], 2);
11038c2ecf20Sopenharmony_ci			break;
11048c2ecf20Sopenharmony_ci
11058c2ecf20Sopenharmony_ci		case NODE_DIND_BLOCK:
11068c2ecf20Sopenharmony_ci			err = truncate_nodes(&dn, nofs, offset[1], 3);
11078c2ecf20Sopenharmony_ci			cont = 0;
11088c2ecf20Sopenharmony_ci			break;
11098c2ecf20Sopenharmony_ci
11108c2ecf20Sopenharmony_ci		default:
11118c2ecf20Sopenharmony_ci			BUG();
11128c2ecf20Sopenharmony_ci		}
11138c2ecf20Sopenharmony_ci		if (err < 0 && err != -ENOENT)
11148c2ecf20Sopenharmony_ci			goto fail;
11158c2ecf20Sopenharmony_ci		if (offset[1] == 0 &&
11168c2ecf20Sopenharmony_ci				ri->i_nid[offset[0] - NODE_DIR1_BLOCK]) {
11178c2ecf20Sopenharmony_ci			lock_page(page);
11188c2ecf20Sopenharmony_ci			BUG_ON(page->mapping != NODE_MAPPING(sbi));
11198c2ecf20Sopenharmony_ci			f2fs_wait_on_page_writeback(page, NODE, true, true);
11208c2ecf20Sopenharmony_ci			ri->i_nid[offset[0] - NODE_DIR1_BLOCK] = 0;
11218c2ecf20Sopenharmony_ci			set_page_dirty(page);
11228c2ecf20Sopenharmony_ci			unlock_page(page);
11238c2ecf20Sopenharmony_ci		}
11248c2ecf20Sopenharmony_ci		offset[1] = 0;
11258c2ecf20Sopenharmony_ci		offset[0]++;
11268c2ecf20Sopenharmony_ci		nofs += err;
11278c2ecf20Sopenharmony_ci	}
11288c2ecf20Sopenharmony_cifail:
11298c2ecf20Sopenharmony_ci	f2fs_put_page(page, 0);
11308c2ecf20Sopenharmony_ci	trace_f2fs_truncate_inode_blocks_exit(inode, err);
11318c2ecf20Sopenharmony_ci	return err > 0 ? 0 : err;
11328c2ecf20Sopenharmony_ci}
11338c2ecf20Sopenharmony_ci
11348c2ecf20Sopenharmony_ci/* caller must lock inode page */
11358c2ecf20Sopenharmony_ciint f2fs_truncate_xattr_node(struct inode *inode)
11368c2ecf20Sopenharmony_ci{
11378c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
11388c2ecf20Sopenharmony_ci	nid_t nid = F2FS_I(inode)->i_xattr_nid;
11398c2ecf20Sopenharmony_ci	struct dnode_of_data dn;
11408c2ecf20Sopenharmony_ci	struct page *npage;
11418c2ecf20Sopenharmony_ci	int err;
11428c2ecf20Sopenharmony_ci
11438c2ecf20Sopenharmony_ci	if (!nid)
11448c2ecf20Sopenharmony_ci		return 0;
11458c2ecf20Sopenharmony_ci
11468c2ecf20Sopenharmony_ci	npage = f2fs_get_node_page(sbi, nid);
11478c2ecf20Sopenharmony_ci	if (IS_ERR(npage))
11488c2ecf20Sopenharmony_ci		return PTR_ERR(npage);
11498c2ecf20Sopenharmony_ci
11508c2ecf20Sopenharmony_ci	set_new_dnode(&dn, inode, NULL, npage, nid);
11518c2ecf20Sopenharmony_ci	err = truncate_node(&dn);
11528c2ecf20Sopenharmony_ci	if (err) {
11538c2ecf20Sopenharmony_ci		f2fs_put_page(npage, 1);
11548c2ecf20Sopenharmony_ci		return err;
11558c2ecf20Sopenharmony_ci	}
11568c2ecf20Sopenharmony_ci
11578c2ecf20Sopenharmony_ci	f2fs_i_xnid_write(inode, 0);
11588c2ecf20Sopenharmony_ci
11598c2ecf20Sopenharmony_ci	return 0;
11608c2ecf20Sopenharmony_ci}
11618c2ecf20Sopenharmony_ci
11628c2ecf20Sopenharmony_ci/*
11638c2ecf20Sopenharmony_ci * Caller should grab and release a rwsem by calling f2fs_lock_op() and
11648c2ecf20Sopenharmony_ci * f2fs_unlock_op().
11658c2ecf20Sopenharmony_ci */
11668c2ecf20Sopenharmony_ciint f2fs_remove_inode_page(struct inode *inode)
11678c2ecf20Sopenharmony_ci{
11688c2ecf20Sopenharmony_ci	struct dnode_of_data dn;
11698c2ecf20Sopenharmony_ci	int err;
11708c2ecf20Sopenharmony_ci
11718c2ecf20Sopenharmony_ci	set_new_dnode(&dn, inode, NULL, NULL, inode->i_ino);
11728c2ecf20Sopenharmony_ci	err = f2fs_get_dnode_of_data(&dn, 0, LOOKUP_NODE);
11738c2ecf20Sopenharmony_ci	if (err)
11748c2ecf20Sopenharmony_ci		return err;
11758c2ecf20Sopenharmony_ci
11768c2ecf20Sopenharmony_ci	err = f2fs_truncate_xattr_node(inode);
11778c2ecf20Sopenharmony_ci	if (err) {
11788c2ecf20Sopenharmony_ci		f2fs_put_dnode(&dn);
11798c2ecf20Sopenharmony_ci		return err;
11808c2ecf20Sopenharmony_ci	}
11818c2ecf20Sopenharmony_ci
11828c2ecf20Sopenharmony_ci	/* remove potential inline_data blocks */
11838c2ecf20Sopenharmony_ci	if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
11848c2ecf20Sopenharmony_ci				S_ISLNK(inode->i_mode))
11858c2ecf20Sopenharmony_ci		f2fs_truncate_data_blocks_range(&dn, 1);
11868c2ecf20Sopenharmony_ci
11878c2ecf20Sopenharmony_ci	/* 0 is possible, after f2fs_new_inode() has failed */
11888c2ecf20Sopenharmony_ci	if (unlikely(f2fs_cp_error(F2FS_I_SB(inode)))) {
11898c2ecf20Sopenharmony_ci		f2fs_put_dnode(&dn);
11908c2ecf20Sopenharmony_ci		return -EIO;
11918c2ecf20Sopenharmony_ci	}
11928c2ecf20Sopenharmony_ci
11938c2ecf20Sopenharmony_ci	if (unlikely(inode->i_blocks != 0 && inode->i_blocks != 8)) {
11948c2ecf20Sopenharmony_ci		f2fs_warn(F2FS_I_SB(inode),
11958c2ecf20Sopenharmony_ci			"f2fs_remove_inode_page: inconsistent i_blocks, ino:%lu, iblocks:%llu",
11968c2ecf20Sopenharmony_ci			inode->i_ino, (unsigned long long)inode->i_blocks);
11978c2ecf20Sopenharmony_ci		set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK);
11988c2ecf20Sopenharmony_ci	}
11998c2ecf20Sopenharmony_ci
12008c2ecf20Sopenharmony_ci	/* will put inode & node pages */
12018c2ecf20Sopenharmony_ci	err = truncate_node(&dn);
12028c2ecf20Sopenharmony_ci	if (err) {
12038c2ecf20Sopenharmony_ci		f2fs_put_dnode(&dn);
12048c2ecf20Sopenharmony_ci		return err;
12058c2ecf20Sopenharmony_ci	}
12068c2ecf20Sopenharmony_ci	return 0;
12078c2ecf20Sopenharmony_ci}
12088c2ecf20Sopenharmony_ci
12098c2ecf20Sopenharmony_cistruct page *f2fs_new_inode_page(struct inode *inode)
12108c2ecf20Sopenharmony_ci{
12118c2ecf20Sopenharmony_ci	struct dnode_of_data dn;
12128c2ecf20Sopenharmony_ci
12138c2ecf20Sopenharmony_ci	/* allocate inode page for new inode */
12148c2ecf20Sopenharmony_ci	set_new_dnode(&dn, inode, NULL, NULL, inode->i_ino);
12158c2ecf20Sopenharmony_ci
12168c2ecf20Sopenharmony_ci	/* caller should f2fs_put_page(page, 1); */
12178c2ecf20Sopenharmony_ci	return f2fs_new_node_page(&dn, 0);
12188c2ecf20Sopenharmony_ci}
12198c2ecf20Sopenharmony_ci
12208c2ecf20Sopenharmony_cistruct page *f2fs_new_node_page(struct dnode_of_data *dn, unsigned int ofs)
12218c2ecf20Sopenharmony_ci{
12228c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
12238c2ecf20Sopenharmony_ci	struct node_info new_ni;
12248c2ecf20Sopenharmony_ci	struct page *page;
12258c2ecf20Sopenharmony_ci	int err;
12268c2ecf20Sopenharmony_ci
12278c2ecf20Sopenharmony_ci	if (unlikely(is_inode_flag_set(dn->inode, FI_NO_ALLOC)))
12288c2ecf20Sopenharmony_ci		return ERR_PTR(-EPERM);
12298c2ecf20Sopenharmony_ci
12308c2ecf20Sopenharmony_ci	page = f2fs_grab_cache_page(NODE_MAPPING(sbi), dn->nid, false);
12318c2ecf20Sopenharmony_ci	if (!page)
12328c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
12338c2ecf20Sopenharmony_ci
12348c2ecf20Sopenharmony_ci	if (unlikely((err = inc_valid_node_count(sbi, dn->inode, !ofs))))
12358c2ecf20Sopenharmony_ci		goto fail;
12368c2ecf20Sopenharmony_ci
12378c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_CHECK_FS
12388c2ecf20Sopenharmony_ci	err = f2fs_get_node_info(sbi, dn->nid, &new_ni);
12398c2ecf20Sopenharmony_ci	if (err) {
12408c2ecf20Sopenharmony_ci		dec_valid_node_count(sbi, dn->inode, !ofs);
12418c2ecf20Sopenharmony_ci		goto fail;
12428c2ecf20Sopenharmony_ci	}
12438c2ecf20Sopenharmony_ci	if (unlikely(new_ni.blk_addr != NULL_ADDR)) {
12448c2ecf20Sopenharmony_ci		err = -EFSCORRUPTED;
12458c2ecf20Sopenharmony_ci		set_sbi_flag(sbi, SBI_NEED_FSCK);
12468c2ecf20Sopenharmony_ci		goto fail;
12478c2ecf20Sopenharmony_ci	}
12488c2ecf20Sopenharmony_ci#endif
12498c2ecf20Sopenharmony_ci	new_ni.nid = dn->nid;
12508c2ecf20Sopenharmony_ci	new_ni.ino = dn->inode->i_ino;
12518c2ecf20Sopenharmony_ci	new_ni.blk_addr = NULL_ADDR;
12528c2ecf20Sopenharmony_ci	new_ni.flag = 0;
12538c2ecf20Sopenharmony_ci	new_ni.version = 0;
12548c2ecf20Sopenharmony_ci	set_node_addr(sbi, &new_ni, NEW_ADDR, false);
12558c2ecf20Sopenharmony_ci
12568c2ecf20Sopenharmony_ci	f2fs_wait_on_page_writeback(page, NODE, true, true);
12578c2ecf20Sopenharmony_ci	fill_node_footer(page, dn->nid, dn->inode->i_ino, ofs, true);
12588c2ecf20Sopenharmony_ci	set_cold_node(page, S_ISDIR(dn->inode->i_mode));
12598c2ecf20Sopenharmony_ci	if (!PageUptodate(page))
12608c2ecf20Sopenharmony_ci		SetPageUptodate(page);
12618c2ecf20Sopenharmony_ci	if (set_page_dirty(page))
12628c2ecf20Sopenharmony_ci		dn->node_changed = true;
12638c2ecf20Sopenharmony_ci
12648c2ecf20Sopenharmony_ci	if (f2fs_has_xattr_block(ofs))
12658c2ecf20Sopenharmony_ci		f2fs_i_xnid_write(dn->inode, dn->nid);
12668c2ecf20Sopenharmony_ci
12678c2ecf20Sopenharmony_ci	if (ofs == 0)
12688c2ecf20Sopenharmony_ci		inc_valid_inode_count(sbi);
12698c2ecf20Sopenharmony_ci	return page;
12708c2ecf20Sopenharmony_ci
12718c2ecf20Sopenharmony_cifail:
12728c2ecf20Sopenharmony_ci	clear_node_page_dirty(page);
12738c2ecf20Sopenharmony_ci	f2fs_put_page(page, 1);
12748c2ecf20Sopenharmony_ci	return ERR_PTR(err);
12758c2ecf20Sopenharmony_ci}
12768c2ecf20Sopenharmony_ci
12778c2ecf20Sopenharmony_ci/*
12788c2ecf20Sopenharmony_ci * Caller should do after getting the following values.
12798c2ecf20Sopenharmony_ci * 0: f2fs_put_page(page, 0)
12808c2ecf20Sopenharmony_ci * LOCKED_PAGE or error: f2fs_put_page(page, 1)
12818c2ecf20Sopenharmony_ci */
12828c2ecf20Sopenharmony_cistatic int read_node_page(struct page *page, int op_flags)
12838c2ecf20Sopenharmony_ci{
12848c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_P_SB(page);
12858c2ecf20Sopenharmony_ci	struct node_info ni;
12868c2ecf20Sopenharmony_ci	struct f2fs_io_info fio = {
12878c2ecf20Sopenharmony_ci		.sbi = sbi,
12888c2ecf20Sopenharmony_ci		.type = NODE,
12898c2ecf20Sopenharmony_ci		.op = REQ_OP_READ,
12908c2ecf20Sopenharmony_ci		.op_flags = op_flags,
12918c2ecf20Sopenharmony_ci		.page = page,
12928c2ecf20Sopenharmony_ci		.encrypted_page = NULL,
12938c2ecf20Sopenharmony_ci	};
12948c2ecf20Sopenharmony_ci	int err;
12958c2ecf20Sopenharmony_ci
12968c2ecf20Sopenharmony_ci	if (PageUptodate(page)) {
12978c2ecf20Sopenharmony_ci		if (!f2fs_inode_chksum_verify(sbi, page)) {
12988c2ecf20Sopenharmony_ci			ClearPageUptodate(page);
12998c2ecf20Sopenharmony_ci			return -EFSBADCRC;
13008c2ecf20Sopenharmony_ci		}
13018c2ecf20Sopenharmony_ci		return LOCKED_PAGE;
13028c2ecf20Sopenharmony_ci	}
13038c2ecf20Sopenharmony_ci
13048c2ecf20Sopenharmony_ci	err = f2fs_get_node_info(sbi, page->index, &ni);
13058c2ecf20Sopenharmony_ci	if (err)
13068c2ecf20Sopenharmony_ci		return err;
13078c2ecf20Sopenharmony_ci
13088c2ecf20Sopenharmony_ci	if (unlikely(ni.blk_addr == NULL_ADDR) ||
13098c2ecf20Sopenharmony_ci			is_sbi_flag_set(sbi, SBI_IS_SHUTDOWN)) {
13108c2ecf20Sopenharmony_ci		ClearPageUptodate(page);
13118c2ecf20Sopenharmony_ci		return -ENOENT;
13128c2ecf20Sopenharmony_ci	}
13138c2ecf20Sopenharmony_ci
13148c2ecf20Sopenharmony_ci	fio.new_blkaddr = fio.old_blkaddr = ni.blk_addr;
13158c2ecf20Sopenharmony_ci
13168c2ecf20Sopenharmony_ci	err = f2fs_submit_page_bio(&fio);
13178c2ecf20Sopenharmony_ci
13188c2ecf20Sopenharmony_ci	if (!err)
13198c2ecf20Sopenharmony_ci		f2fs_update_iostat(sbi, FS_NODE_READ_IO, F2FS_BLKSIZE);
13208c2ecf20Sopenharmony_ci
13218c2ecf20Sopenharmony_ci	return err;
13228c2ecf20Sopenharmony_ci}
13238c2ecf20Sopenharmony_ci
13248c2ecf20Sopenharmony_ci/*
13258c2ecf20Sopenharmony_ci * Readahead a node page
13268c2ecf20Sopenharmony_ci */
13278c2ecf20Sopenharmony_civoid f2fs_ra_node_page(struct f2fs_sb_info *sbi, nid_t nid)
13288c2ecf20Sopenharmony_ci{
13298c2ecf20Sopenharmony_ci	struct page *apage;
13308c2ecf20Sopenharmony_ci	int err;
13318c2ecf20Sopenharmony_ci
13328c2ecf20Sopenharmony_ci	if (!nid)
13338c2ecf20Sopenharmony_ci		return;
13348c2ecf20Sopenharmony_ci	if (f2fs_check_nid_range(sbi, nid))
13358c2ecf20Sopenharmony_ci		return;
13368c2ecf20Sopenharmony_ci
13378c2ecf20Sopenharmony_ci	apage = xa_load(&NODE_MAPPING(sbi)->i_pages, nid);
13388c2ecf20Sopenharmony_ci	if (apage)
13398c2ecf20Sopenharmony_ci		return;
13408c2ecf20Sopenharmony_ci
13418c2ecf20Sopenharmony_ci	apage = f2fs_grab_cache_page(NODE_MAPPING(sbi), nid, false);
13428c2ecf20Sopenharmony_ci	if (!apage)
13438c2ecf20Sopenharmony_ci		return;
13448c2ecf20Sopenharmony_ci
13458c2ecf20Sopenharmony_ci	err = read_node_page(apage, REQ_RAHEAD);
13468c2ecf20Sopenharmony_ci	f2fs_put_page(apage, err ? 1 : 0);
13478c2ecf20Sopenharmony_ci}
13488c2ecf20Sopenharmony_ci
13498c2ecf20Sopenharmony_cistatic struct page *__get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid,
13508c2ecf20Sopenharmony_ci					struct page *parent, int start)
13518c2ecf20Sopenharmony_ci{
13528c2ecf20Sopenharmony_ci	struct page *page;
13538c2ecf20Sopenharmony_ci	int err;
13548c2ecf20Sopenharmony_ci
13558c2ecf20Sopenharmony_ci	if (!nid)
13568c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOENT);
13578c2ecf20Sopenharmony_ci	if (f2fs_check_nid_range(sbi, nid))
13588c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
13598c2ecf20Sopenharmony_cirepeat:
13608c2ecf20Sopenharmony_ci	page = f2fs_grab_cache_page(NODE_MAPPING(sbi), nid, false);
13618c2ecf20Sopenharmony_ci	if (!page)
13628c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
13638c2ecf20Sopenharmony_ci
13648c2ecf20Sopenharmony_ci	err = read_node_page(page, 0);
13658c2ecf20Sopenharmony_ci	if (err < 0) {
13668c2ecf20Sopenharmony_ci		f2fs_put_page(page, 1);
13678c2ecf20Sopenharmony_ci		return ERR_PTR(err);
13688c2ecf20Sopenharmony_ci	} else if (err == LOCKED_PAGE) {
13698c2ecf20Sopenharmony_ci		err = 0;
13708c2ecf20Sopenharmony_ci		goto page_hit;
13718c2ecf20Sopenharmony_ci	}
13728c2ecf20Sopenharmony_ci
13738c2ecf20Sopenharmony_ci	if (parent)
13748c2ecf20Sopenharmony_ci		f2fs_ra_node_pages(parent, start + 1, MAX_RA_NODE);
13758c2ecf20Sopenharmony_ci
13768c2ecf20Sopenharmony_ci	lock_page(page);
13778c2ecf20Sopenharmony_ci
13788c2ecf20Sopenharmony_ci	if (unlikely(page->mapping != NODE_MAPPING(sbi))) {
13798c2ecf20Sopenharmony_ci		f2fs_put_page(page, 1);
13808c2ecf20Sopenharmony_ci		goto repeat;
13818c2ecf20Sopenharmony_ci	}
13828c2ecf20Sopenharmony_ci
13838c2ecf20Sopenharmony_ci	if (unlikely(!PageUptodate(page))) {
13848c2ecf20Sopenharmony_ci		err = -EIO;
13858c2ecf20Sopenharmony_ci		goto out_err;
13868c2ecf20Sopenharmony_ci	}
13878c2ecf20Sopenharmony_ci
13888c2ecf20Sopenharmony_ci	if (!f2fs_inode_chksum_verify(sbi, page)) {
13898c2ecf20Sopenharmony_ci		err = -EFSBADCRC;
13908c2ecf20Sopenharmony_ci		goto out_err;
13918c2ecf20Sopenharmony_ci	}
13928c2ecf20Sopenharmony_cipage_hit:
13938c2ecf20Sopenharmony_ci	if(unlikely(nid != nid_of_node(page))) {
13948c2ecf20Sopenharmony_ci		f2fs_warn(sbi, "inconsistent node block, nid:%lu, node_footer[nid:%u,ino:%u,ofs:%u,cpver:%llu,blkaddr:%u]",
13958c2ecf20Sopenharmony_ci			  nid, nid_of_node(page), ino_of_node(page),
13968c2ecf20Sopenharmony_ci			  ofs_of_node(page), cpver_of_node(page),
13978c2ecf20Sopenharmony_ci			  next_blkaddr_of_node(page));
13988c2ecf20Sopenharmony_ci		set_sbi_flag(sbi, SBI_NEED_FSCK);
13998c2ecf20Sopenharmony_ci		err = -EINVAL;
14008c2ecf20Sopenharmony_ciout_err:
14018c2ecf20Sopenharmony_ci		ClearPageUptodate(page);
14028c2ecf20Sopenharmony_ci		f2fs_put_page(page, 1);
14038c2ecf20Sopenharmony_ci		return ERR_PTR(err);
14048c2ecf20Sopenharmony_ci	}
14058c2ecf20Sopenharmony_ci	return page;
14068c2ecf20Sopenharmony_ci}
14078c2ecf20Sopenharmony_ci
14088c2ecf20Sopenharmony_cistruct page *f2fs_get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid)
14098c2ecf20Sopenharmony_ci{
14108c2ecf20Sopenharmony_ci	return __get_node_page(sbi, nid, NULL, 0);
14118c2ecf20Sopenharmony_ci}
14128c2ecf20Sopenharmony_ci
14138c2ecf20Sopenharmony_cistruct page *f2fs_get_node_page_ra(struct page *parent, int start)
14148c2ecf20Sopenharmony_ci{
14158c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_P_SB(parent);
14168c2ecf20Sopenharmony_ci	nid_t nid = get_nid(parent, start, false);
14178c2ecf20Sopenharmony_ci
14188c2ecf20Sopenharmony_ci	return __get_node_page(sbi, nid, parent, start);
14198c2ecf20Sopenharmony_ci}
14208c2ecf20Sopenharmony_ci
14218c2ecf20Sopenharmony_cistatic void flush_inline_data(struct f2fs_sb_info *sbi, nid_t ino)
14228c2ecf20Sopenharmony_ci{
14238c2ecf20Sopenharmony_ci	struct inode *inode;
14248c2ecf20Sopenharmony_ci	struct page *page;
14258c2ecf20Sopenharmony_ci	int ret;
14268c2ecf20Sopenharmony_ci
14278c2ecf20Sopenharmony_ci	/* should flush inline_data before evict_inode */
14288c2ecf20Sopenharmony_ci	inode = ilookup(sbi->sb, ino);
14298c2ecf20Sopenharmony_ci	if (!inode)
14308c2ecf20Sopenharmony_ci		return;
14318c2ecf20Sopenharmony_ci
14328c2ecf20Sopenharmony_ci	page = f2fs_pagecache_get_page(inode->i_mapping, 0,
14338c2ecf20Sopenharmony_ci					FGP_LOCK|FGP_NOWAIT, 0);
14348c2ecf20Sopenharmony_ci	if (!page)
14358c2ecf20Sopenharmony_ci		goto iput_out;
14368c2ecf20Sopenharmony_ci
14378c2ecf20Sopenharmony_ci	if (!PageUptodate(page))
14388c2ecf20Sopenharmony_ci		goto page_out;
14398c2ecf20Sopenharmony_ci
14408c2ecf20Sopenharmony_ci	if (!PageDirty(page))
14418c2ecf20Sopenharmony_ci		goto page_out;
14428c2ecf20Sopenharmony_ci
14438c2ecf20Sopenharmony_ci	if (!clear_page_dirty_for_io(page))
14448c2ecf20Sopenharmony_ci		goto page_out;
14458c2ecf20Sopenharmony_ci
14468c2ecf20Sopenharmony_ci	ret = f2fs_write_inline_data(inode, page);
14478c2ecf20Sopenharmony_ci	inode_dec_dirty_pages(inode);
14488c2ecf20Sopenharmony_ci	f2fs_remove_dirty_inode(inode);
14498c2ecf20Sopenharmony_ci	if (ret)
14508c2ecf20Sopenharmony_ci		set_page_dirty(page);
14518c2ecf20Sopenharmony_cipage_out:
14528c2ecf20Sopenharmony_ci	f2fs_put_page(page, 1);
14538c2ecf20Sopenharmony_ciiput_out:
14548c2ecf20Sopenharmony_ci	iput(inode);
14558c2ecf20Sopenharmony_ci}
14568c2ecf20Sopenharmony_ci
14578c2ecf20Sopenharmony_cistatic struct page *last_fsync_dnode(struct f2fs_sb_info *sbi, nid_t ino)
14588c2ecf20Sopenharmony_ci{
14598c2ecf20Sopenharmony_ci	pgoff_t index;
14608c2ecf20Sopenharmony_ci	struct pagevec pvec;
14618c2ecf20Sopenharmony_ci	struct page *last_page = NULL;
14628c2ecf20Sopenharmony_ci	int nr_pages;
14638c2ecf20Sopenharmony_ci
14648c2ecf20Sopenharmony_ci	pagevec_init(&pvec);
14658c2ecf20Sopenharmony_ci	index = 0;
14668c2ecf20Sopenharmony_ci
14678c2ecf20Sopenharmony_ci	while ((nr_pages = pagevec_lookup_tag(&pvec, NODE_MAPPING(sbi), &index,
14688c2ecf20Sopenharmony_ci				PAGECACHE_TAG_DIRTY))) {
14698c2ecf20Sopenharmony_ci		int i;
14708c2ecf20Sopenharmony_ci
14718c2ecf20Sopenharmony_ci		for (i = 0; i < nr_pages; i++) {
14728c2ecf20Sopenharmony_ci			struct page *page = pvec.pages[i];
14738c2ecf20Sopenharmony_ci
14748c2ecf20Sopenharmony_ci			if (unlikely(f2fs_cp_error(sbi))) {
14758c2ecf20Sopenharmony_ci				f2fs_put_page(last_page, 0);
14768c2ecf20Sopenharmony_ci				pagevec_release(&pvec);
14778c2ecf20Sopenharmony_ci				return ERR_PTR(-EIO);
14788c2ecf20Sopenharmony_ci			}
14798c2ecf20Sopenharmony_ci
14808c2ecf20Sopenharmony_ci			if (!IS_DNODE(page) || !is_cold_node(page))
14818c2ecf20Sopenharmony_ci				continue;
14828c2ecf20Sopenharmony_ci			if (ino_of_node(page) != ino)
14838c2ecf20Sopenharmony_ci				continue;
14848c2ecf20Sopenharmony_ci
14858c2ecf20Sopenharmony_ci			lock_page(page);
14868c2ecf20Sopenharmony_ci
14878c2ecf20Sopenharmony_ci			if (unlikely(page->mapping != NODE_MAPPING(sbi))) {
14888c2ecf20Sopenharmony_cicontinue_unlock:
14898c2ecf20Sopenharmony_ci				unlock_page(page);
14908c2ecf20Sopenharmony_ci				continue;
14918c2ecf20Sopenharmony_ci			}
14928c2ecf20Sopenharmony_ci			if (ino_of_node(page) != ino)
14938c2ecf20Sopenharmony_ci				goto continue_unlock;
14948c2ecf20Sopenharmony_ci
14958c2ecf20Sopenharmony_ci			if (!PageDirty(page)) {
14968c2ecf20Sopenharmony_ci				/* someone wrote it for us */
14978c2ecf20Sopenharmony_ci				goto continue_unlock;
14988c2ecf20Sopenharmony_ci			}
14998c2ecf20Sopenharmony_ci
15008c2ecf20Sopenharmony_ci			if (last_page)
15018c2ecf20Sopenharmony_ci				f2fs_put_page(last_page, 0);
15028c2ecf20Sopenharmony_ci
15038c2ecf20Sopenharmony_ci			get_page(page);
15048c2ecf20Sopenharmony_ci			last_page = page;
15058c2ecf20Sopenharmony_ci			unlock_page(page);
15068c2ecf20Sopenharmony_ci		}
15078c2ecf20Sopenharmony_ci		pagevec_release(&pvec);
15088c2ecf20Sopenharmony_ci		cond_resched();
15098c2ecf20Sopenharmony_ci	}
15108c2ecf20Sopenharmony_ci	return last_page;
15118c2ecf20Sopenharmony_ci}
15128c2ecf20Sopenharmony_ci
15138c2ecf20Sopenharmony_cistatic int __write_node_page(struct page *page, bool atomic, bool *submitted,
15148c2ecf20Sopenharmony_ci				struct writeback_control *wbc, bool do_balance,
15158c2ecf20Sopenharmony_ci				enum iostat_type io_type, unsigned int *seq_id)
15168c2ecf20Sopenharmony_ci{
15178c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_P_SB(page);
15188c2ecf20Sopenharmony_ci	nid_t nid;
15198c2ecf20Sopenharmony_ci	struct node_info ni;
15208c2ecf20Sopenharmony_ci	struct f2fs_io_info fio = {
15218c2ecf20Sopenharmony_ci		.sbi = sbi,
15228c2ecf20Sopenharmony_ci		.ino = ino_of_node(page),
15238c2ecf20Sopenharmony_ci		.type = NODE,
15248c2ecf20Sopenharmony_ci		.op = REQ_OP_WRITE,
15258c2ecf20Sopenharmony_ci		.op_flags = wbc_to_write_flags(wbc),
15268c2ecf20Sopenharmony_ci		.page = page,
15278c2ecf20Sopenharmony_ci		.encrypted_page = NULL,
15288c2ecf20Sopenharmony_ci		.submitted = false,
15298c2ecf20Sopenharmony_ci		.io_type = io_type,
15308c2ecf20Sopenharmony_ci		.io_wbc = wbc,
15318c2ecf20Sopenharmony_ci	};
15328c2ecf20Sopenharmony_ci	unsigned int seq;
15338c2ecf20Sopenharmony_ci
15348c2ecf20Sopenharmony_ci	trace_f2fs_writepage(page, NODE);
15358c2ecf20Sopenharmony_ci
15368c2ecf20Sopenharmony_ci	if (unlikely(f2fs_cp_error(sbi))) {
15378c2ecf20Sopenharmony_ci		if (is_sbi_flag_set(sbi, SBI_IS_CLOSE)) {
15388c2ecf20Sopenharmony_ci			ClearPageUptodate(page);
15398c2ecf20Sopenharmony_ci			dec_page_count(sbi, F2FS_DIRTY_NODES);
15408c2ecf20Sopenharmony_ci			unlock_page(page);
15418c2ecf20Sopenharmony_ci			return 0;
15428c2ecf20Sopenharmony_ci		}
15438c2ecf20Sopenharmony_ci		goto redirty_out;
15448c2ecf20Sopenharmony_ci	}
15458c2ecf20Sopenharmony_ci
15468c2ecf20Sopenharmony_ci	if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
15478c2ecf20Sopenharmony_ci		goto redirty_out;
15488c2ecf20Sopenharmony_ci
15498c2ecf20Sopenharmony_ci	if (!is_sbi_flag_set(sbi, SBI_CP_DISABLED) &&
15508c2ecf20Sopenharmony_ci			wbc->sync_mode == WB_SYNC_NONE &&
15518c2ecf20Sopenharmony_ci			IS_DNODE(page) && is_cold_node(page))
15528c2ecf20Sopenharmony_ci		goto redirty_out;
15538c2ecf20Sopenharmony_ci
15548c2ecf20Sopenharmony_ci	/* get old block addr of this node page */
15558c2ecf20Sopenharmony_ci	nid = nid_of_node(page);
15568c2ecf20Sopenharmony_ci	f2fs_bug_on(sbi, page->index != nid);
15578c2ecf20Sopenharmony_ci
15588c2ecf20Sopenharmony_ci	if (f2fs_get_node_info(sbi, nid, &ni))
15598c2ecf20Sopenharmony_ci		goto redirty_out;
15608c2ecf20Sopenharmony_ci
15618c2ecf20Sopenharmony_ci	if (wbc->for_reclaim) {
15628c2ecf20Sopenharmony_ci		if (!down_read_trylock(&sbi->node_write))
15638c2ecf20Sopenharmony_ci			goto redirty_out;
15648c2ecf20Sopenharmony_ci	} else {
15658c2ecf20Sopenharmony_ci		down_read(&sbi->node_write);
15668c2ecf20Sopenharmony_ci	}
15678c2ecf20Sopenharmony_ci
15688c2ecf20Sopenharmony_ci	/* This page is already truncated */
15698c2ecf20Sopenharmony_ci	if (unlikely(ni.blk_addr == NULL_ADDR)) {
15708c2ecf20Sopenharmony_ci		ClearPageUptodate(page);
15718c2ecf20Sopenharmony_ci		dec_page_count(sbi, F2FS_DIRTY_NODES);
15728c2ecf20Sopenharmony_ci		up_read(&sbi->node_write);
15738c2ecf20Sopenharmony_ci		unlock_page(page);
15748c2ecf20Sopenharmony_ci		return 0;
15758c2ecf20Sopenharmony_ci	}
15768c2ecf20Sopenharmony_ci
15778c2ecf20Sopenharmony_ci	if (__is_valid_data_blkaddr(ni.blk_addr) &&
15788c2ecf20Sopenharmony_ci		!f2fs_is_valid_blkaddr(sbi, ni.blk_addr,
15798c2ecf20Sopenharmony_ci					DATA_GENERIC_ENHANCE)) {
15808c2ecf20Sopenharmony_ci		up_read(&sbi->node_write);
15818c2ecf20Sopenharmony_ci		goto redirty_out;
15828c2ecf20Sopenharmony_ci	}
15838c2ecf20Sopenharmony_ci
15848c2ecf20Sopenharmony_ci	if (atomic && !test_opt(sbi, NOBARRIER))
15858c2ecf20Sopenharmony_ci		fio.op_flags |= REQ_PREFLUSH | REQ_FUA;
15868c2ecf20Sopenharmony_ci
15878c2ecf20Sopenharmony_ci	/* should add to global list before clearing PAGECACHE status */
15888c2ecf20Sopenharmony_ci	if (f2fs_in_warm_node_list(sbi, page)) {
15898c2ecf20Sopenharmony_ci		seq = f2fs_add_fsync_node_entry(sbi, page);
15908c2ecf20Sopenharmony_ci		if (seq_id)
15918c2ecf20Sopenharmony_ci			*seq_id = seq;
15928c2ecf20Sopenharmony_ci	}
15938c2ecf20Sopenharmony_ci
15948c2ecf20Sopenharmony_ci	set_page_writeback(page);
15958c2ecf20Sopenharmony_ci	ClearPageError(page);
15968c2ecf20Sopenharmony_ci
15978c2ecf20Sopenharmony_ci	fio.old_blkaddr = ni.blk_addr;
15988c2ecf20Sopenharmony_ci	f2fs_do_write_node_page(nid, &fio);
15998c2ecf20Sopenharmony_ci	set_node_addr(sbi, &ni, fio.new_blkaddr, is_fsync_dnode(page));
16008c2ecf20Sopenharmony_ci	dec_page_count(sbi, F2FS_DIRTY_NODES);
16018c2ecf20Sopenharmony_ci	up_read(&sbi->node_write);
16028c2ecf20Sopenharmony_ci
16038c2ecf20Sopenharmony_ci	if (wbc->for_reclaim) {
16048c2ecf20Sopenharmony_ci		f2fs_submit_merged_write_cond(sbi, NULL, page, 0, NODE);
16058c2ecf20Sopenharmony_ci		submitted = NULL;
16068c2ecf20Sopenharmony_ci	}
16078c2ecf20Sopenharmony_ci
16088c2ecf20Sopenharmony_ci	unlock_page(page);
16098c2ecf20Sopenharmony_ci
16108c2ecf20Sopenharmony_ci	if (unlikely(f2fs_cp_error(sbi))) {
16118c2ecf20Sopenharmony_ci		f2fs_submit_merged_write(sbi, NODE);
16128c2ecf20Sopenharmony_ci		submitted = NULL;
16138c2ecf20Sopenharmony_ci	}
16148c2ecf20Sopenharmony_ci	if (submitted)
16158c2ecf20Sopenharmony_ci		*submitted = fio.submitted;
16168c2ecf20Sopenharmony_ci
16178c2ecf20Sopenharmony_ci	if (do_balance)
16188c2ecf20Sopenharmony_ci		f2fs_balance_fs(sbi, false);
16198c2ecf20Sopenharmony_ci	return 0;
16208c2ecf20Sopenharmony_ci
16218c2ecf20Sopenharmony_ciredirty_out:
16228c2ecf20Sopenharmony_ci	redirty_page_for_writepage(wbc, page);
16238c2ecf20Sopenharmony_ci	return AOP_WRITEPAGE_ACTIVATE;
16248c2ecf20Sopenharmony_ci}
16258c2ecf20Sopenharmony_ci
16268c2ecf20Sopenharmony_ciint f2fs_move_node_page(struct page *node_page, int gc_type)
16278c2ecf20Sopenharmony_ci{
16288c2ecf20Sopenharmony_ci	int err = 0;
16298c2ecf20Sopenharmony_ci
16308c2ecf20Sopenharmony_ci	if (gc_type == FG_GC) {
16318c2ecf20Sopenharmony_ci		struct writeback_control wbc = {
16328c2ecf20Sopenharmony_ci			.sync_mode = WB_SYNC_ALL,
16338c2ecf20Sopenharmony_ci			.nr_to_write = 1,
16348c2ecf20Sopenharmony_ci			.for_reclaim = 0,
16358c2ecf20Sopenharmony_ci		};
16368c2ecf20Sopenharmony_ci
16378c2ecf20Sopenharmony_ci		f2fs_wait_on_page_writeback(node_page, NODE, true, true);
16388c2ecf20Sopenharmony_ci
16398c2ecf20Sopenharmony_ci		set_page_dirty(node_page);
16408c2ecf20Sopenharmony_ci
16418c2ecf20Sopenharmony_ci		if (!clear_page_dirty_for_io(node_page)) {
16428c2ecf20Sopenharmony_ci			err = -EAGAIN;
16438c2ecf20Sopenharmony_ci			goto out_page;
16448c2ecf20Sopenharmony_ci		}
16458c2ecf20Sopenharmony_ci
16468c2ecf20Sopenharmony_ci		if (__write_node_page(node_page, false, NULL,
16478c2ecf20Sopenharmony_ci					&wbc, false, FS_GC_NODE_IO, NULL)) {
16488c2ecf20Sopenharmony_ci			err = -EAGAIN;
16498c2ecf20Sopenharmony_ci			unlock_page(node_page);
16508c2ecf20Sopenharmony_ci		}
16518c2ecf20Sopenharmony_ci		goto release_page;
16528c2ecf20Sopenharmony_ci	} else {
16538c2ecf20Sopenharmony_ci		/* set page dirty and write it */
16548c2ecf20Sopenharmony_ci		if (!PageWriteback(node_page))
16558c2ecf20Sopenharmony_ci			set_page_dirty(node_page);
16568c2ecf20Sopenharmony_ci	}
16578c2ecf20Sopenharmony_ciout_page:
16588c2ecf20Sopenharmony_ci	unlock_page(node_page);
16598c2ecf20Sopenharmony_cirelease_page:
16608c2ecf20Sopenharmony_ci	f2fs_put_page(node_page, 0);
16618c2ecf20Sopenharmony_ci	return err;
16628c2ecf20Sopenharmony_ci}
16638c2ecf20Sopenharmony_ci
16648c2ecf20Sopenharmony_cistatic int f2fs_write_node_page(struct page *page,
16658c2ecf20Sopenharmony_ci				struct writeback_control *wbc)
16668c2ecf20Sopenharmony_ci{
16678c2ecf20Sopenharmony_ci	return __write_node_page(page, false, NULL, wbc, false,
16688c2ecf20Sopenharmony_ci						FS_NODE_IO, NULL);
16698c2ecf20Sopenharmony_ci}
16708c2ecf20Sopenharmony_ci
16718c2ecf20Sopenharmony_ciint f2fs_fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode,
16728c2ecf20Sopenharmony_ci			struct writeback_control *wbc, bool atomic,
16738c2ecf20Sopenharmony_ci			unsigned int *seq_id)
16748c2ecf20Sopenharmony_ci{
16758c2ecf20Sopenharmony_ci	pgoff_t index;
16768c2ecf20Sopenharmony_ci	struct pagevec pvec;
16778c2ecf20Sopenharmony_ci	int ret = 0;
16788c2ecf20Sopenharmony_ci	struct page *last_page = NULL;
16798c2ecf20Sopenharmony_ci	bool marked = false;
16808c2ecf20Sopenharmony_ci	nid_t ino = inode->i_ino;
16818c2ecf20Sopenharmony_ci	int nr_pages;
16828c2ecf20Sopenharmony_ci	int nwritten = 0;
16838c2ecf20Sopenharmony_ci
16848c2ecf20Sopenharmony_ci	if (atomic) {
16858c2ecf20Sopenharmony_ci		last_page = last_fsync_dnode(sbi, ino);
16868c2ecf20Sopenharmony_ci		if (IS_ERR_OR_NULL(last_page))
16878c2ecf20Sopenharmony_ci			return PTR_ERR_OR_ZERO(last_page);
16888c2ecf20Sopenharmony_ci	}
16898c2ecf20Sopenharmony_ciretry:
16908c2ecf20Sopenharmony_ci	pagevec_init(&pvec);
16918c2ecf20Sopenharmony_ci	index = 0;
16928c2ecf20Sopenharmony_ci
16938c2ecf20Sopenharmony_ci	while ((nr_pages = pagevec_lookup_tag(&pvec, NODE_MAPPING(sbi), &index,
16948c2ecf20Sopenharmony_ci				PAGECACHE_TAG_DIRTY))) {
16958c2ecf20Sopenharmony_ci		int i;
16968c2ecf20Sopenharmony_ci
16978c2ecf20Sopenharmony_ci		for (i = 0; i < nr_pages; i++) {
16988c2ecf20Sopenharmony_ci			struct page *page = pvec.pages[i];
16998c2ecf20Sopenharmony_ci			bool submitted = false;
17008c2ecf20Sopenharmony_ci
17018c2ecf20Sopenharmony_ci			if (unlikely(f2fs_cp_error(sbi))) {
17028c2ecf20Sopenharmony_ci				f2fs_put_page(last_page, 0);
17038c2ecf20Sopenharmony_ci				pagevec_release(&pvec);
17048c2ecf20Sopenharmony_ci				ret = -EIO;
17058c2ecf20Sopenharmony_ci				goto out;
17068c2ecf20Sopenharmony_ci			}
17078c2ecf20Sopenharmony_ci
17088c2ecf20Sopenharmony_ci			if (!IS_DNODE(page) || !is_cold_node(page))
17098c2ecf20Sopenharmony_ci				continue;
17108c2ecf20Sopenharmony_ci			if (ino_of_node(page) != ino)
17118c2ecf20Sopenharmony_ci				continue;
17128c2ecf20Sopenharmony_ci
17138c2ecf20Sopenharmony_ci			lock_page(page);
17148c2ecf20Sopenharmony_ci
17158c2ecf20Sopenharmony_ci			if (unlikely(page->mapping != NODE_MAPPING(sbi))) {
17168c2ecf20Sopenharmony_cicontinue_unlock:
17178c2ecf20Sopenharmony_ci				unlock_page(page);
17188c2ecf20Sopenharmony_ci				continue;
17198c2ecf20Sopenharmony_ci			}
17208c2ecf20Sopenharmony_ci			if (ino_of_node(page) != ino)
17218c2ecf20Sopenharmony_ci				goto continue_unlock;
17228c2ecf20Sopenharmony_ci
17238c2ecf20Sopenharmony_ci			if (!PageDirty(page) && page != last_page) {
17248c2ecf20Sopenharmony_ci				/* someone wrote it for us */
17258c2ecf20Sopenharmony_ci				goto continue_unlock;
17268c2ecf20Sopenharmony_ci			}
17278c2ecf20Sopenharmony_ci
17288c2ecf20Sopenharmony_ci			f2fs_wait_on_page_writeback(page, NODE, true, true);
17298c2ecf20Sopenharmony_ci
17308c2ecf20Sopenharmony_ci			set_fsync_mark(page, 0);
17318c2ecf20Sopenharmony_ci			set_dentry_mark(page, 0);
17328c2ecf20Sopenharmony_ci
17338c2ecf20Sopenharmony_ci			if (!atomic || page == last_page) {
17348c2ecf20Sopenharmony_ci				set_fsync_mark(page, 1);
17358c2ecf20Sopenharmony_ci				if (IS_INODE(page)) {
17368c2ecf20Sopenharmony_ci					if (is_inode_flag_set(inode,
17378c2ecf20Sopenharmony_ci								FI_DIRTY_INODE))
17388c2ecf20Sopenharmony_ci						f2fs_update_inode(inode, page);
17398c2ecf20Sopenharmony_ci					set_dentry_mark(page,
17408c2ecf20Sopenharmony_ci						f2fs_need_dentry_mark(sbi, ino));
17418c2ecf20Sopenharmony_ci				}
17428c2ecf20Sopenharmony_ci				/* may be written by other thread */
17438c2ecf20Sopenharmony_ci				if (!PageDirty(page))
17448c2ecf20Sopenharmony_ci					set_page_dirty(page);
17458c2ecf20Sopenharmony_ci			}
17468c2ecf20Sopenharmony_ci
17478c2ecf20Sopenharmony_ci			if (!clear_page_dirty_for_io(page))
17488c2ecf20Sopenharmony_ci				goto continue_unlock;
17498c2ecf20Sopenharmony_ci
17508c2ecf20Sopenharmony_ci			ret = __write_node_page(page, atomic &&
17518c2ecf20Sopenharmony_ci						page == last_page,
17528c2ecf20Sopenharmony_ci						&submitted, wbc, true,
17538c2ecf20Sopenharmony_ci						FS_NODE_IO, seq_id);
17548c2ecf20Sopenharmony_ci			if (ret) {
17558c2ecf20Sopenharmony_ci				unlock_page(page);
17568c2ecf20Sopenharmony_ci				f2fs_put_page(last_page, 0);
17578c2ecf20Sopenharmony_ci				break;
17588c2ecf20Sopenharmony_ci			} else if (submitted) {
17598c2ecf20Sopenharmony_ci				nwritten++;
17608c2ecf20Sopenharmony_ci			}
17618c2ecf20Sopenharmony_ci
17628c2ecf20Sopenharmony_ci			if (page == last_page) {
17638c2ecf20Sopenharmony_ci				f2fs_put_page(page, 0);
17648c2ecf20Sopenharmony_ci				marked = true;
17658c2ecf20Sopenharmony_ci				break;
17668c2ecf20Sopenharmony_ci			}
17678c2ecf20Sopenharmony_ci		}
17688c2ecf20Sopenharmony_ci		pagevec_release(&pvec);
17698c2ecf20Sopenharmony_ci		cond_resched();
17708c2ecf20Sopenharmony_ci
17718c2ecf20Sopenharmony_ci		if (ret || marked)
17728c2ecf20Sopenharmony_ci			break;
17738c2ecf20Sopenharmony_ci	}
17748c2ecf20Sopenharmony_ci	if (!ret && atomic && !marked) {
17758c2ecf20Sopenharmony_ci		f2fs_debug(sbi, "Retry to write fsync mark: ino=%u, idx=%lx",
17768c2ecf20Sopenharmony_ci			   ino, last_page->index);
17778c2ecf20Sopenharmony_ci		lock_page(last_page);
17788c2ecf20Sopenharmony_ci		f2fs_wait_on_page_writeback(last_page, NODE, true, true);
17798c2ecf20Sopenharmony_ci		set_page_dirty(last_page);
17808c2ecf20Sopenharmony_ci		unlock_page(last_page);
17818c2ecf20Sopenharmony_ci		goto retry;
17828c2ecf20Sopenharmony_ci	}
17838c2ecf20Sopenharmony_ciout:
17848c2ecf20Sopenharmony_ci	if (nwritten)
17858c2ecf20Sopenharmony_ci		f2fs_submit_merged_write_cond(sbi, NULL, NULL, ino, NODE);
17868c2ecf20Sopenharmony_ci	return ret ? -EIO: 0;
17878c2ecf20Sopenharmony_ci}
17888c2ecf20Sopenharmony_ci
17898c2ecf20Sopenharmony_cistatic int f2fs_match_ino(struct inode *inode, unsigned long ino, void *data)
17908c2ecf20Sopenharmony_ci{
17918c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
17928c2ecf20Sopenharmony_ci	bool clean;
17938c2ecf20Sopenharmony_ci
17948c2ecf20Sopenharmony_ci	if (inode->i_ino != ino)
17958c2ecf20Sopenharmony_ci		return 0;
17968c2ecf20Sopenharmony_ci
17978c2ecf20Sopenharmony_ci	if (!is_inode_flag_set(inode, FI_DIRTY_INODE))
17988c2ecf20Sopenharmony_ci		return 0;
17998c2ecf20Sopenharmony_ci
18008c2ecf20Sopenharmony_ci	spin_lock(&sbi->inode_lock[DIRTY_META]);
18018c2ecf20Sopenharmony_ci	clean = list_empty(&F2FS_I(inode)->gdirty_list);
18028c2ecf20Sopenharmony_ci	spin_unlock(&sbi->inode_lock[DIRTY_META]);
18038c2ecf20Sopenharmony_ci
18048c2ecf20Sopenharmony_ci	if (clean)
18058c2ecf20Sopenharmony_ci		return 0;
18068c2ecf20Sopenharmony_ci
18078c2ecf20Sopenharmony_ci	inode = igrab(inode);
18088c2ecf20Sopenharmony_ci	if (!inode)
18098c2ecf20Sopenharmony_ci		return 0;
18108c2ecf20Sopenharmony_ci	return 1;
18118c2ecf20Sopenharmony_ci}
18128c2ecf20Sopenharmony_ci
18138c2ecf20Sopenharmony_cistatic bool flush_dirty_inode(struct page *page)
18148c2ecf20Sopenharmony_ci{
18158c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_P_SB(page);
18168c2ecf20Sopenharmony_ci	struct inode *inode;
18178c2ecf20Sopenharmony_ci	nid_t ino = ino_of_node(page);
18188c2ecf20Sopenharmony_ci
18198c2ecf20Sopenharmony_ci	inode = find_inode_nowait(sbi->sb, ino, f2fs_match_ino, NULL);
18208c2ecf20Sopenharmony_ci	if (!inode)
18218c2ecf20Sopenharmony_ci		return false;
18228c2ecf20Sopenharmony_ci
18238c2ecf20Sopenharmony_ci	f2fs_update_inode(inode, page);
18248c2ecf20Sopenharmony_ci	unlock_page(page);
18258c2ecf20Sopenharmony_ci
18268c2ecf20Sopenharmony_ci	iput(inode);
18278c2ecf20Sopenharmony_ci	return true;
18288c2ecf20Sopenharmony_ci}
18298c2ecf20Sopenharmony_ci
18308c2ecf20Sopenharmony_civoid f2fs_flush_inline_data(struct f2fs_sb_info *sbi)
18318c2ecf20Sopenharmony_ci{
18328c2ecf20Sopenharmony_ci	pgoff_t index = 0;
18338c2ecf20Sopenharmony_ci	struct pagevec pvec;
18348c2ecf20Sopenharmony_ci	int nr_pages;
18358c2ecf20Sopenharmony_ci
18368c2ecf20Sopenharmony_ci	pagevec_init(&pvec);
18378c2ecf20Sopenharmony_ci
18388c2ecf20Sopenharmony_ci	while ((nr_pages = pagevec_lookup_tag(&pvec,
18398c2ecf20Sopenharmony_ci			NODE_MAPPING(sbi), &index, PAGECACHE_TAG_DIRTY))) {
18408c2ecf20Sopenharmony_ci		int i;
18418c2ecf20Sopenharmony_ci
18428c2ecf20Sopenharmony_ci		for (i = 0; i < nr_pages; i++) {
18438c2ecf20Sopenharmony_ci			struct page *page = pvec.pages[i];
18448c2ecf20Sopenharmony_ci
18458c2ecf20Sopenharmony_ci			if (!IS_DNODE(page))
18468c2ecf20Sopenharmony_ci				continue;
18478c2ecf20Sopenharmony_ci
18488c2ecf20Sopenharmony_ci			lock_page(page);
18498c2ecf20Sopenharmony_ci
18508c2ecf20Sopenharmony_ci			if (unlikely(page->mapping != NODE_MAPPING(sbi))) {
18518c2ecf20Sopenharmony_cicontinue_unlock:
18528c2ecf20Sopenharmony_ci				unlock_page(page);
18538c2ecf20Sopenharmony_ci				continue;
18548c2ecf20Sopenharmony_ci			}
18558c2ecf20Sopenharmony_ci
18568c2ecf20Sopenharmony_ci			if (!PageDirty(page)) {
18578c2ecf20Sopenharmony_ci				/* someone wrote it for us */
18588c2ecf20Sopenharmony_ci				goto continue_unlock;
18598c2ecf20Sopenharmony_ci			}
18608c2ecf20Sopenharmony_ci
18618c2ecf20Sopenharmony_ci			/* flush inline_data, if it's async context. */
18628c2ecf20Sopenharmony_ci			if (is_inline_node(page)) {
18638c2ecf20Sopenharmony_ci				clear_inline_node(page);
18648c2ecf20Sopenharmony_ci				unlock_page(page);
18658c2ecf20Sopenharmony_ci				flush_inline_data(sbi, ino_of_node(page));
18668c2ecf20Sopenharmony_ci				continue;
18678c2ecf20Sopenharmony_ci			}
18688c2ecf20Sopenharmony_ci			unlock_page(page);
18698c2ecf20Sopenharmony_ci		}
18708c2ecf20Sopenharmony_ci		pagevec_release(&pvec);
18718c2ecf20Sopenharmony_ci		cond_resched();
18728c2ecf20Sopenharmony_ci	}
18738c2ecf20Sopenharmony_ci}
18748c2ecf20Sopenharmony_ci
18758c2ecf20Sopenharmony_ciint f2fs_sync_node_pages(struct f2fs_sb_info *sbi,
18768c2ecf20Sopenharmony_ci				struct writeback_control *wbc,
18778c2ecf20Sopenharmony_ci				bool do_balance, enum iostat_type io_type)
18788c2ecf20Sopenharmony_ci{
18798c2ecf20Sopenharmony_ci	pgoff_t index;
18808c2ecf20Sopenharmony_ci	struct pagevec pvec;
18818c2ecf20Sopenharmony_ci	int step = 0;
18828c2ecf20Sopenharmony_ci	int nwritten = 0;
18838c2ecf20Sopenharmony_ci	int ret = 0;
18848c2ecf20Sopenharmony_ci	int nr_pages, done = 0;
18858c2ecf20Sopenharmony_ci
18868c2ecf20Sopenharmony_ci	pagevec_init(&pvec);
18878c2ecf20Sopenharmony_ci
18888c2ecf20Sopenharmony_cinext_step:
18898c2ecf20Sopenharmony_ci	index = 0;
18908c2ecf20Sopenharmony_ci
18918c2ecf20Sopenharmony_ci	while (!done && (nr_pages = pagevec_lookup_tag(&pvec,
18928c2ecf20Sopenharmony_ci			NODE_MAPPING(sbi), &index, PAGECACHE_TAG_DIRTY))) {
18938c2ecf20Sopenharmony_ci		int i;
18948c2ecf20Sopenharmony_ci
18958c2ecf20Sopenharmony_ci		for (i = 0; i < nr_pages; i++) {
18968c2ecf20Sopenharmony_ci			struct page *page = pvec.pages[i];
18978c2ecf20Sopenharmony_ci			bool submitted = false;
18988c2ecf20Sopenharmony_ci			bool may_dirty = true;
18998c2ecf20Sopenharmony_ci
19008c2ecf20Sopenharmony_ci			/* give a priority to WB_SYNC threads */
19018c2ecf20Sopenharmony_ci			if (atomic_read(&sbi->wb_sync_req[NODE]) &&
19028c2ecf20Sopenharmony_ci					wbc->sync_mode == WB_SYNC_NONE) {
19038c2ecf20Sopenharmony_ci				done = 1;
19048c2ecf20Sopenharmony_ci				break;
19058c2ecf20Sopenharmony_ci			}
19068c2ecf20Sopenharmony_ci
19078c2ecf20Sopenharmony_ci			/*
19088c2ecf20Sopenharmony_ci			 * flushing sequence with step:
19098c2ecf20Sopenharmony_ci			 * 0. indirect nodes
19108c2ecf20Sopenharmony_ci			 * 1. dentry dnodes
19118c2ecf20Sopenharmony_ci			 * 2. file dnodes
19128c2ecf20Sopenharmony_ci			 */
19138c2ecf20Sopenharmony_ci			if (step == 0 && IS_DNODE(page))
19148c2ecf20Sopenharmony_ci				continue;
19158c2ecf20Sopenharmony_ci			if (step == 1 && (!IS_DNODE(page) ||
19168c2ecf20Sopenharmony_ci						is_cold_node(page)))
19178c2ecf20Sopenharmony_ci				continue;
19188c2ecf20Sopenharmony_ci			if (step == 2 && (!IS_DNODE(page) ||
19198c2ecf20Sopenharmony_ci						!is_cold_node(page)))
19208c2ecf20Sopenharmony_ci				continue;
19218c2ecf20Sopenharmony_cilock_node:
19228c2ecf20Sopenharmony_ci			if (wbc->sync_mode == WB_SYNC_ALL)
19238c2ecf20Sopenharmony_ci				lock_page(page);
19248c2ecf20Sopenharmony_ci			else if (!trylock_page(page))
19258c2ecf20Sopenharmony_ci				continue;
19268c2ecf20Sopenharmony_ci
19278c2ecf20Sopenharmony_ci			if (unlikely(page->mapping != NODE_MAPPING(sbi))) {
19288c2ecf20Sopenharmony_cicontinue_unlock:
19298c2ecf20Sopenharmony_ci				unlock_page(page);
19308c2ecf20Sopenharmony_ci				continue;
19318c2ecf20Sopenharmony_ci			}
19328c2ecf20Sopenharmony_ci
19338c2ecf20Sopenharmony_ci			if (!PageDirty(page)) {
19348c2ecf20Sopenharmony_ci				/* someone wrote it for us */
19358c2ecf20Sopenharmony_ci				goto continue_unlock;
19368c2ecf20Sopenharmony_ci			}
19378c2ecf20Sopenharmony_ci
19388c2ecf20Sopenharmony_ci			/* flush inline_data/inode, if it's async context. */
19398c2ecf20Sopenharmony_ci			if (!do_balance)
19408c2ecf20Sopenharmony_ci				goto write_node;
19418c2ecf20Sopenharmony_ci
19428c2ecf20Sopenharmony_ci			/* flush inline_data */
19438c2ecf20Sopenharmony_ci			if (is_inline_node(page)) {
19448c2ecf20Sopenharmony_ci				clear_inline_node(page);
19458c2ecf20Sopenharmony_ci				unlock_page(page);
19468c2ecf20Sopenharmony_ci				flush_inline_data(sbi, ino_of_node(page));
19478c2ecf20Sopenharmony_ci				goto lock_node;
19488c2ecf20Sopenharmony_ci			}
19498c2ecf20Sopenharmony_ci
19508c2ecf20Sopenharmony_ci			/* flush dirty inode */
19518c2ecf20Sopenharmony_ci			if (IS_INODE(page) && may_dirty) {
19528c2ecf20Sopenharmony_ci				may_dirty = false;
19538c2ecf20Sopenharmony_ci				if (flush_dirty_inode(page))
19548c2ecf20Sopenharmony_ci					goto lock_node;
19558c2ecf20Sopenharmony_ci			}
19568c2ecf20Sopenharmony_ciwrite_node:
19578c2ecf20Sopenharmony_ci			f2fs_wait_on_page_writeback(page, NODE, true, true);
19588c2ecf20Sopenharmony_ci
19598c2ecf20Sopenharmony_ci			if (!clear_page_dirty_for_io(page))
19608c2ecf20Sopenharmony_ci				goto continue_unlock;
19618c2ecf20Sopenharmony_ci
19628c2ecf20Sopenharmony_ci			set_fsync_mark(page, 0);
19638c2ecf20Sopenharmony_ci			set_dentry_mark(page, 0);
19648c2ecf20Sopenharmony_ci
19658c2ecf20Sopenharmony_ci			ret = __write_node_page(page, false, &submitted,
19668c2ecf20Sopenharmony_ci						wbc, do_balance, io_type, NULL);
19678c2ecf20Sopenharmony_ci			if (ret)
19688c2ecf20Sopenharmony_ci				unlock_page(page);
19698c2ecf20Sopenharmony_ci			else if (submitted)
19708c2ecf20Sopenharmony_ci				nwritten++;
19718c2ecf20Sopenharmony_ci
19728c2ecf20Sopenharmony_ci			if (--wbc->nr_to_write == 0)
19738c2ecf20Sopenharmony_ci				break;
19748c2ecf20Sopenharmony_ci		}
19758c2ecf20Sopenharmony_ci		pagevec_release(&pvec);
19768c2ecf20Sopenharmony_ci		cond_resched();
19778c2ecf20Sopenharmony_ci
19788c2ecf20Sopenharmony_ci		if (wbc->nr_to_write == 0) {
19798c2ecf20Sopenharmony_ci			step = 2;
19808c2ecf20Sopenharmony_ci			break;
19818c2ecf20Sopenharmony_ci		}
19828c2ecf20Sopenharmony_ci	}
19838c2ecf20Sopenharmony_ci
19848c2ecf20Sopenharmony_ci	if (step < 2) {
19858c2ecf20Sopenharmony_ci		if (!is_sbi_flag_set(sbi, SBI_CP_DISABLED) &&
19868c2ecf20Sopenharmony_ci				wbc->sync_mode == WB_SYNC_NONE && step == 1)
19878c2ecf20Sopenharmony_ci			goto out;
19888c2ecf20Sopenharmony_ci		step++;
19898c2ecf20Sopenharmony_ci		goto next_step;
19908c2ecf20Sopenharmony_ci	}
19918c2ecf20Sopenharmony_ciout:
19928c2ecf20Sopenharmony_ci	if (nwritten)
19938c2ecf20Sopenharmony_ci		f2fs_submit_merged_write(sbi, NODE);
19948c2ecf20Sopenharmony_ci
19958c2ecf20Sopenharmony_ci	if (unlikely(f2fs_cp_error(sbi)))
19968c2ecf20Sopenharmony_ci		return -EIO;
19978c2ecf20Sopenharmony_ci	return ret;
19988c2ecf20Sopenharmony_ci}
19998c2ecf20Sopenharmony_ci
20008c2ecf20Sopenharmony_ciint f2fs_wait_on_node_pages_writeback(struct f2fs_sb_info *sbi,
20018c2ecf20Sopenharmony_ci						unsigned int seq_id)
20028c2ecf20Sopenharmony_ci{
20038c2ecf20Sopenharmony_ci	struct fsync_node_entry *fn;
20048c2ecf20Sopenharmony_ci	struct page *page;
20058c2ecf20Sopenharmony_ci	struct list_head *head = &sbi->fsync_node_list;
20068c2ecf20Sopenharmony_ci	unsigned long flags;
20078c2ecf20Sopenharmony_ci	unsigned int cur_seq_id = 0;
20088c2ecf20Sopenharmony_ci	int ret2, ret = 0;
20098c2ecf20Sopenharmony_ci
20108c2ecf20Sopenharmony_ci	while (seq_id && cur_seq_id < seq_id) {
20118c2ecf20Sopenharmony_ci		spin_lock_irqsave(&sbi->fsync_node_lock, flags);
20128c2ecf20Sopenharmony_ci		if (list_empty(head)) {
20138c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&sbi->fsync_node_lock, flags);
20148c2ecf20Sopenharmony_ci			break;
20158c2ecf20Sopenharmony_ci		}
20168c2ecf20Sopenharmony_ci		fn = list_first_entry(head, struct fsync_node_entry, list);
20178c2ecf20Sopenharmony_ci		if (fn->seq_id > seq_id) {
20188c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&sbi->fsync_node_lock, flags);
20198c2ecf20Sopenharmony_ci			break;
20208c2ecf20Sopenharmony_ci		}
20218c2ecf20Sopenharmony_ci		cur_seq_id = fn->seq_id;
20228c2ecf20Sopenharmony_ci		page = fn->page;
20238c2ecf20Sopenharmony_ci		get_page(page);
20248c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&sbi->fsync_node_lock, flags);
20258c2ecf20Sopenharmony_ci
20268c2ecf20Sopenharmony_ci		f2fs_wait_on_page_writeback(page, NODE, true, false);
20278c2ecf20Sopenharmony_ci		if (TestClearPageError(page))
20288c2ecf20Sopenharmony_ci			ret = -EIO;
20298c2ecf20Sopenharmony_ci
20308c2ecf20Sopenharmony_ci		put_page(page);
20318c2ecf20Sopenharmony_ci
20328c2ecf20Sopenharmony_ci		if (ret)
20338c2ecf20Sopenharmony_ci			break;
20348c2ecf20Sopenharmony_ci	}
20358c2ecf20Sopenharmony_ci
20368c2ecf20Sopenharmony_ci	ret2 = filemap_check_errors(NODE_MAPPING(sbi));
20378c2ecf20Sopenharmony_ci	if (!ret)
20388c2ecf20Sopenharmony_ci		ret = ret2;
20398c2ecf20Sopenharmony_ci
20408c2ecf20Sopenharmony_ci	return ret;
20418c2ecf20Sopenharmony_ci}
20428c2ecf20Sopenharmony_ci
20438c2ecf20Sopenharmony_cistatic int f2fs_write_node_pages(struct address_space *mapping,
20448c2ecf20Sopenharmony_ci			    struct writeback_control *wbc)
20458c2ecf20Sopenharmony_ci{
20468c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_M_SB(mapping);
20478c2ecf20Sopenharmony_ci	struct blk_plug plug;
20488c2ecf20Sopenharmony_ci	long diff;
20498c2ecf20Sopenharmony_ci
20508c2ecf20Sopenharmony_ci	if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
20518c2ecf20Sopenharmony_ci		goto skip_write;
20528c2ecf20Sopenharmony_ci
20538c2ecf20Sopenharmony_ci	/* balancing f2fs's metadata in background */
20548c2ecf20Sopenharmony_ci	f2fs_balance_fs_bg(sbi, true);
20558c2ecf20Sopenharmony_ci
20568c2ecf20Sopenharmony_ci	/* collect a number of dirty node pages and write together */
20578c2ecf20Sopenharmony_ci	if (wbc->sync_mode != WB_SYNC_ALL &&
20588c2ecf20Sopenharmony_ci			get_pages(sbi, F2FS_DIRTY_NODES) <
20598c2ecf20Sopenharmony_ci					nr_pages_to_skip(sbi, NODE))
20608c2ecf20Sopenharmony_ci		goto skip_write;
20618c2ecf20Sopenharmony_ci
20628c2ecf20Sopenharmony_ci	if (wbc->sync_mode == WB_SYNC_ALL)
20638c2ecf20Sopenharmony_ci		atomic_inc(&sbi->wb_sync_req[NODE]);
20648c2ecf20Sopenharmony_ci	else if (atomic_read(&sbi->wb_sync_req[NODE])) {
20658c2ecf20Sopenharmony_ci		/* to avoid potential deadlock */
20668c2ecf20Sopenharmony_ci		if (current->plug)
20678c2ecf20Sopenharmony_ci			blk_finish_plug(current->plug);
20688c2ecf20Sopenharmony_ci		goto skip_write;
20698c2ecf20Sopenharmony_ci	}
20708c2ecf20Sopenharmony_ci
20718c2ecf20Sopenharmony_ci	trace_f2fs_writepages(mapping->host, wbc, NODE);
20728c2ecf20Sopenharmony_ci
20738c2ecf20Sopenharmony_ci	diff = nr_pages_to_write(sbi, NODE, wbc);
20748c2ecf20Sopenharmony_ci	blk_start_plug(&plug);
20758c2ecf20Sopenharmony_ci	f2fs_sync_node_pages(sbi, wbc, true, FS_NODE_IO);
20768c2ecf20Sopenharmony_ci	blk_finish_plug(&plug);
20778c2ecf20Sopenharmony_ci	wbc->nr_to_write = max((long)0, wbc->nr_to_write - diff);
20788c2ecf20Sopenharmony_ci
20798c2ecf20Sopenharmony_ci	if (wbc->sync_mode == WB_SYNC_ALL)
20808c2ecf20Sopenharmony_ci		atomic_dec(&sbi->wb_sync_req[NODE]);
20818c2ecf20Sopenharmony_ci	return 0;
20828c2ecf20Sopenharmony_ci
20838c2ecf20Sopenharmony_ciskip_write:
20848c2ecf20Sopenharmony_ci	wbc->pages_skipped += get_pages(sbi, F2FS_DIRTY_NODES);
20858c2ecf20Sopenharmony_ci	trace_f2fs_writepages(mapping->host, wbc, NODE);
20868c2ecf20Sopenharmony_ci	return 0;
20878c2ecf20Sopenharmony_ci}
20888c2ecf20Sopenharmony_ci
20898c2ecf20Sopenharmony_cistatic int f2fs_set_node_page_dirty(struct page *page)
20908c2ecf20Sopenharmony_ci{
20918c2ecf20Sopenharmony_ci	trace_f2fs_set_page_dirty(page, NODE);
20928c2ecf20Sopenharmony_ci
20938c2ecf20Sopenharmony_ci	if (!PageUptodate(page))
20948c2ecf20Sopenharmony_ci		SetPageUptodate(page);
20958c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_CHECK_FS
20968c2ecf20Sopenharmony_ci	if (IS_INODE(page))
20978c2ecf20Sopenharmony_ci		f2fs_inode_chksum_set(F2FS_P_SB(page), page);
20988c2ecf20Sopenharmony_ci#endif
20998c2ecf20Sopenharmony_ci	if (!PageDirty(page)) {
21008c2ecf20Sopenharmony_ci		__set_page_dirty_nobuffers(page);
21018c2ecf20Sopenharmony_ci		inc_page_count(F2FS_P_SB(page), F2FS_DIRTY_NODES);
21028c2ecf20Sopenharmony_ci		f2fs_set_page_private(page, 0);
21038c2ecf20Sopenharmony_ci		f2fs_trace_pid(page);
21048c2ecf20Sopenharmony_ci		return 1;
21058c2ecf20Sopenharmony_ci	}
21068c2ecf20Sopenharmony_ci	return 0;
21078c2ecf20Sopenharmony_ci}
21088c2ecf20Sopenharmony_ci
21098c2ecf20Sopenharmony_ci/*
21108c2ecf20Sopenharmony_ci * Structure of the f2fs node operations
21118c2ecf20Sopenharmony_ci */
21128c2ecf20Sopenharmony_ciconst struct address_space_operations f2fs_node_aops = {
21138c2ecf20Sopenharmony_ci	.writepage	= f2fs_write_node_page,
21148c2ecf20Sopenharmony_ci	.writepages	= f2fs_write_node_pages,
21158c2ecf20Sopenharmony_ci	.set_page_dirty	= f2fs_set_node_page_dirty,
21168c2ecf20Sopenharmony_ci	.invalidatepage	= f2fs_invalidate_page,
21178c2ecf20Sopenharmony_ci	.releasepage	= f2fs_release_page,
21188c2ecf20Sopenharmony_ci#ifdef CONFIG_MIGRATION
21198c2ecf20Sopenharmony_ci	.migratepage	= f2fs_migrate_page,
21208c2ecf20Sopenharmony_ci#endif
21218c2ecf20Sopenharmony_ci};
21228c2ecf20Sopenharmony_ci
21238c2ecf20Sopenharmony_cistatic struct free_nid *__lookup_free_nid_list(struct f2fs_nm_info *nm_i,
21248c2ecf20Sopenharmony_ci						nid_t n)
21258c2ecf20Sopenharmony_ci{
21268c2ecf20Sopenharmony_ci	return radix_tree_lookup(&nm_i->free_nid_root, n);
21278c2ecf20Sopenharmony_ci}
21288c2ecf20Sopenharmony_ci
21298c2ecf20Sopenharmony_cistatic int __insert_free_nid(struct f2fs_sb_info *sbi,
21308c2ecf20Sopenharmony_ci				struct free_nid *i)
21318c2ecf20Sopenharmony_ci{
21328c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
21338c2ecf20Sopenharmony_ci
21348c2ecf20Sopenharmony_ci	int err = radix_tree_insert(&nm_i->free_nid_root, i->nid, i);
21358c2ecf20Sopenharmony_ci	if (err)
21368c2ecf20Sopenharmony_ci		return err;
21378c2ecf20Sopenharmony_ci
21388c2ecf20Sopenharmony_ci	nm_i->nid_cnt[FREE_NID]++;
21398c2ecf20Sopenharmony_ci	list_add_tail(&i->list, &nm_i->free_nid_list);
21408c2ecf20Sopenharmony_ci	return 0;
21418c2ecf20Sopenharmony_ci}
21428c2ecf20Sopenharmony_ci
21438c2ecf20Sopenharmony_cistatic void __remove_free_nid(struct f2fs_sb_info *sbi,
21448c2ecf20Sopenharmony_ci			struct free_nid *i, enum nid_state state)
21458c2ecf20Sopenharmony_ci{
21468c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
21478c2ecf20Sopenharmony_ci
21488c2ecf20Sopenharmony_ci	f2fs_bug_on(sbi, state != i->state);
21498c2ecf20Sopenharmony_ci	nm_i->nid_cnt[state]--;
21508c2ecf20Sopenharmony_ci	if (state == FREE_NID)
21518c2ecf20Sopenharmony_ci		list_del(&i->list);
21528c2ecf20Sopenharmony_ci	radix_tree_delete(&nm_i->free_nid_root, i->nid);
21538c2ecf20Sopenharmony_ci}
21548c2ecf20Sopenharmony_ci
21558c2ecf20Sopenharmony_cistatic void __move_free_nid(struct f2fs_sb_info *sbi, struct free_nid *i,
21568c2ecf20Sopenharmony_ci			enum nid_state org_state, enum nid_state dst_state)
21578c2ecf20Sopenharmony_ci{
21588c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
21598c2ecf20Sopenharmony_ci
21608c2ecf20Sopenharmony_ci	f2fs_bug_on(sbi, org_state != i->state);
21618c2ecf20Sopenharmony_ci	i->state = dst_state;
21628c2ecf20Sopenharmony_ci	nm_i->nid_cnt[org_state]--;
21638c2ecf20Sopenharmony_ci	nm_i->nid_cnt[dst_state]++;
21648c2ecf20Sopenharmony_ci
21658c2ecf20Sopenharmony_ci	switch (dst_state) {
21668c2ecf20Sopenharmony_ci	case PREALLOC_NID:
21678c2ecf20Sopenharmony_ci		list_del(&i->list);
21688c2ecf20Sopenharmony_ci		break;
21698c2ecf20Sopenharmony_ci	case FREE_NID:
21708c2ecf20Sopenharmony_ci		list_add_tail(&i->list, &nm_i->free_nid_list);
21718c2ecf20Sopenharmony_ci		break;
21728c2ecf20Sopenharmony_ci	default:
21738c2ecf20Sopenharmony_ci		BUG_ON(1);
21748c2ecf20Sopenharmony_ci	}
21758c2ecf20Sopenharmony_ci}
21768c2ecf20Sopenharmony_ci
21778c2ecf20Sopenharmony_cistatic void update_free_nid_bitmap(struct f2fs_sb_info *sbi, nid_t nid,
21788c2ecf20Sopenharmony_ci							bool set, bool build)
21798c2ecf20Sopenharmony_ci{
21808c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
21818c2ecf20Sopenharmony_ci	unsigned int nat_ofs = NAT_BLOCK_OFFSET(nid);
21828c2ecf20Sopenharmony_ci	unsigned int nid_ofs = nid - START_NID(nid);
21838c2ecf20Sopenharmony_ci
21848c2ecf20Sopenharmony_ci	if (!test_bit_le(nat_ofs, nm_i->nat_block_bitmap))
21858c2ecf20Sopenharmony_ci		return;
21868c2ecf20Sopenharmony_ci
21878c2ecf20Sopenharmony_ci	if (set) {
21888c2ecf20Sopenharmony_ci		if (test_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs]))
21898c2ecf20Sopenharmony_ci			return;
21908c2ecf20Sopenharmony_ci		__set_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs]);
21918c2ecf20Sopenharmony_ci		nm_i->free_nid_count[nat_ofs]++;
21928c2ecf20Sopenharmony_ci	} else {
21938c2ecf20Sopenharmony_ci		if (!test_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs]))
21948c2ecf20Sopenharmony_ci			return;
21958c2ecf20Sopenharmony_ci		__clear_bit_le(nid_ofs, nm_i->free_nid_bitmap[nat_ofs]);
21968c2ecf20Sopenharmony_ci		if (!build)
21978c2ecf20Sopenharmony_ci			nm_i->free_nid_count[nat_ofs]--;
21988c2ecf20Sopenharmony_ci	}
21998c2ecf20Sopenharmony_ci}
22008c2ecf20Sopenharmony_ci
22018c2ecf20Sopenharmony_ci/* return if the nid is recognized as free */
22028c2ecf20Sopenharmony_cistatic bool add_free_nid(struct f2fs_sb_info *sbi,
22038c2ecf20Sopenharmony_ci				nid_t nid, bool build, bool update)
22048c2ecf20Sopenharmony_ci{
22058c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
22068c2ecf20Sopenharmony_ci	struct free_nid *i, *e;
22078c2ecf20Sopenharmony_ci	struct nat_entry *ne;
22088c2ecf20Sopenharmony_ci	int err = -EINVAL;
22098c2ecf20Sopenharmony_ci	bool ret = false;
22108c2ecf20Sopenharmony_ci
22118c2ecf20Sopenharmony_ci	/* 0 nid should not be used */
22128c2ecf20Sopenharmony_ci	if (unlikely(nid == 0))
22138c2ecf20Sopenharmony_ci		return false;
22148c2ecf20Sopenharmony_ci
22158c2ecf20Sopenharmony_ci	if (unlikely(f2fs_check_nid_range(sbi, nid)))
22168c2ecf20Sopenharmony_ci		return false;
22178c2ecf20Sopenharmony_ci
22188c2ecf20Sopenharmony_ci	i = f2fs_kmem_cache_alloc(free_nid_slab, GFP_NOFS);
22198c2ecf20Sopenharmony_ci	i->nid = nid;
22208c2ecf20Sopenharmony_ci	i->state = FREE_NID;
22218c2ecf20Sopenharmony_ci
22228c2ecf20Sopenharmony_ci	radix_tree_preload(GFP_NOFS | __GFP_NOFAIL);
22238c2ecf20Sopenharmony_ci
22248c2ecf20Sopenharmony_ci	spin_lock(&nm_i->nid_list_lock);
22258c2ecf20Sopenharmony_ci
22268c2ecf20Sopenharmony_ci	if (build) {
22278c2ecf20Sopenharmony_ci		/*
22288c2ecf20Sopenharmony_ci		 *   Thread A             Thread B
22298c2ecf20Sopenharmony_ci		 *  - f2fs_create
22308c2ecf20Sopenharmony_ci		 *   - f2fs_new_inode
22318c2ecf20Sopenharmony_ci		 *    - f2fs_alloc_nid
22328c2ecf20Sopenharmony_ci		 *     - __insert_nid_to_list(PREALLOC_NID)
22338c2ecf20Sopenharmony_ci		 *                     - f2fs_balance_fs_bg
22348c2ecf20Sopenharmony_ci		 *                      - f2fs_build_free_nids
22358c2ecf20Sopenharmony_ci		 *                       - __f2fs_build_free_nids
22368c2ecf20Sopenharmony_ci		 *                        - scan_nat_page
22378c2ecf20Sopenharmony_ci		 *                         - add_free_nid
22388c2ecf20Sopenharmony_ci		 *                          - __lookup_nat_cache
22398c2ecf20Sopenharmony_ci		 *  - f2fs_add_link
22408c2ecf20Sopenharmony_ci		 *   - f2fs_init_inode_metadata
22418c2ecf20Sopenharmony_ci		 *    - f2fs_new_inode_page
22428c2ecf20Sopenharmony_ci		 *     - f2fs_new_node_page
22438c2ecf20Sopenharmony_ci		 *      - set_node_addr
22448c2ecf20Sopenharmony_ci		 *  - f2fs_alloc_nid_done
22458c2ecf20Sopenharmony_ci		 *   - __remove_nid_from_list(PREALLOC_NID)
22468c2ecf20Sopenharmony_ci		 *                         - __insert_nid_to_list(FREE_NID)
22478c2ecf20Sopenharmony_ci		 */
22488c2ecf20Sopenharmony_ci		ne = __lookup_nat_cache(nm_i, nid);
22498c2ecf20Sopenharmony_ci		if (ne && (!get_nat_flag(ne, IS_CHECKPOINTED) ||
22508c2ecf20Sopenharmony_ci				nat_get_blkaddr(ne) != NULL_ADDR))
22518c2ecf20Sopenharmony_ci			goto err_out;
22528c2ecf20Sopenharmony_ci
22538c2ecf20Sopenharmony_ci		e = __lookup_free_nid_list(nm_i, nid);
22548c2ecf20Sopenharmony_ci		if (e) {
22558c2ecf20Sopenharmony_ci			if (e->state == FREE_NID)
22568c2ecf20Sopenharmony_ci				ret = true;
22578c2ecf20Sopenharmony_ci			goto err_out;
22588c2ecf20Sopenharmony_ci		}
22598c2ecf20Sopenharmony_ci	}
22608c2ecf20Sopenharmony_ci	ret = true;
22618c2ecf20Sopenharmony_ci	err = __insert_free_nid(sbi, i);
22628c2ecf20Sopenharmony_cierr_out:
22638c2ecf20Sopenharmony_ci	if (update) {
22648c2ecf20Sopenharmony_ci		update_free_nid_bitmap(sbi, nid, ret, build);
22658c2ecf20Sopenharmony_ci		if (!build)
22668c2ecf20Sopenharmony_ci			nm_i->available_nids++;
22678c2ecf20Sopenharmony_ci	}
22688c2ecf20Sopenharmony_ci	spin_unlock(&nm_i->nid_list_lock);
22698c2ecf20Sopenharmony_ci	radix_tree_preload_end();
22708c2ecf20Sopenharmony_ci
22718c2ecf20Sopenharmony_ci	if (err)
22728c2ecf20Sopenharmony_ci		kmem_cache_free(free_nid_slab, i);
22738c2ecf20Sopenharmony_ci	return ret;
22748c2ecf20Sopenharmony_ci}
22758c2ecf20Sopenharmony_ci
22768c2ecf20Sopenharmony_cistatic void remove_free_nid(struct f2fs_sb_info *sbi, nid_t nid)
22778c2ecf20Sopenharmony_ci{
22788c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
22798c2ecf20Sopenharmony_ci	struct free_nid *i;
22808c2ecf20Sopenharmony_ci	bool need_free = false;
22818c2ecf20Sopenharmony_ci
22828c2ecf20Sopenharmony_ci	spin_lock(&nm_i->nid_list_lock);
22838c2ecf20Sopenharmony_ci	i = __lookup_free_nid_list(nm_i, nid);
22848c2ecf20Sopenharmony_ci	if (i && i->state == FREE_NID) {
22858c2ecf20Sopenharmony_ci		__remove_free_nid(sbi, i, FREE_NID);
22868c2ecf20Sopenharmony_ci		need_free = true;
22878c2ecf20Sopenharmony_ci	}
22888c2ecf20Sopenharmony_ci	spin_unlock(&nm_i->nid_list_lock);
22898c2ecf20Sopenharmony_ci
22908c2ecf20Sopenharmony_ci	if (need_free)
22918c2ecf20Sopenharmony_ci		kmem_cache_free(free_nid_slab, i);
22928c2ecf20Sopenharmony_ci}
22938c2ecf20Sopenharmony_ci
22948c2ecf20Sopenharmony_cistatic int scan_nat_page(struct f2fs_sb_info *sbi,
22958c2ecf20Sopenharmony_ci			struct page *nat_page, nid_t start_nid)
22968c2ecf20Sopenharmony_ci{
22978c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
22988c2ecf20Sopenharmony_ci	struct f2fs_nat_block *nat_blk = page_address(nat_page);
22998c2ecf20Sopenharmony_ci	block_t blk_addr;
23008c2ecf20Sopenharmony_ci	unsigned int nat_ofs = NAT_BLOCK_OFFSET(start_nid);
23018c2ecf20Sopenharmony_ci	int i;
23028c2ecf20Sopenharmony_ci
23038c2ecf20Sopenharmony_ci	__set_bit_le(nat_ofs, nm_i->nat_block_bitmap);
23048c2ecf20Sopenharmony_ci
23058c2ecf20Sopenharmony_ci	i = start_nid % NAT_ENTRY_PER_BLOCK;
23068c2ecf20Sopenharmony_ci
23078c2ecf20Sopenharmony_ci	for (; i < NAT_ENTRY_PER_BLOCK; i++, start_nid++) {
23088c2ecf20Sopenharmony_ci		if (unlikely(start_nid >= nm_i->max_nid))
23098c2ecf20Sopenharmony_ci			break;
23108c2ecf20Sopenharmony_ci
23118c2ecf20Sopenharmony_ci		blk_addr = le32_to_cpu(nat_blk->entries[i].block_addr);
23128c2ecf20Sopenharmony_ci
23138c2ecf20Sopenharmony_ci		if (blk_addr == NEW_ADDR)
23148c2ecf20Sopenharmony_ci			return -EINVAL;
23158c2ecf20Sopenharmony_ci
23168c2ecf20Sopenharmony_ci		if (blk_addr == NULL_ADDR) {
23178c2ecf20Sopenharmony_ci			add_free_nid(sbi, start_nid, true, true);
23188c2ecf20Sopenharmony_ci		} else {
23198c2ecf20Sopenharmony_ci			spin_lock(&NM_I(sbi)->nid_list_lock);
23208c2ecf20Sopenharmony_ci			update_free_nid_bitmap(sbi, start_nid, false, true);
23218c2ecf20Sopenharmony_ci			spin_unlock(&NM_I(sbi)->nid_list_lock);
23228c2ecf20Sopenharmony_ci		}
23238c2ecf20Sopenharmony_ci	}
23248c2ecf20Sopenharmony_ci
23258c2ecf20Sopenharmony_ci	return 0;
23268c2ecf20Sopenharmony_ci}
23278c2ecf20Sopenharmony_ci
23288c2ecf20Sopenharmony_cistatic void scan_curseg_cache(struct f2fs_sb_info *sbi)
23298c2ecf20Sopenharmony_ci{
23308c2ecf20Sopenharmony_ci	struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
23318c2ecf20Sopenharmony_ci	struct f2fs_journal *journal = curseg->journal;
23328c2ecf20Sopenharmony_ci	int i;
23338c2ecf20Sopenharmony_ci
23348c2ecf20Sopenharmony_ci	down_read(&curseg->journal_rwsem);
23358c2ecf20Sopenharmony_ci	for (i = 0; i < nats_in_cursum(journal); i++) {
23368c2ecf20Sopenharmony_ci		block_t addr;
23378c2ecf20Sopenharmony_ci		nid_t nid;
23388c2ecf20Sopenharmony_ci
23398c2ecf20Sopenharmony_ci		addr = le32_to_cpu(nat_in_journal(journal, i).block_addr);
23408c2ecf20Sopenharmony_ci		nid = le32_to_cpu(nid_in_journal(journal, i));
23418c2ecf20Sopenharmony_ci		if (addr == NULL_ADDR)
23428c2ecf20Sopenharmony_ci			add_free_nid(sbi, nid, true, false);
23438c2ecf20Sopenharmony_ci		else
23448c2ecf20Sopenharmony_ci			remove_free_nid(sbi, nid);
23458c2ecf20Sopenharmony_ci	}
23468c2ecf20Sopenharmony_ci	up_read(&curseg->journal_rwsem);
23478c2ecf20Sopenharmony_ci}
23488c2ecf20Sopenharmony_ci
23498c2ecf20Sopenharmony_cistatic void scan_free_nid_bits(struct f2fs_sb_info *sbi)
23508c2ecf20Sopenharmony_ci{
23518c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
23528c2ecf20Sopenharmony_ci	unsigned int i, idx;
23538c2ecf20Sopenharmony_ci	nid_t nid;
23548c2ecf20Sopenharmony_ci
23558c2ecf20Sopenharmony_ci	down_read(&nm_i->nat_tree_lock);
23568c2ecf20Sopenharmony_ci
23578c2ecf20Sopenharmony_ci	for (i = 0; i < nm_i->nat_blocks; i++) {
23588c2ecf20Sopenharmony_ci		if (!test_bit_le(i, nm_i->nat_block_bitmap))
23598c2ecf20Sopenharmony_ci			continue;
23608c2ecf20Sopenharmony_ci		if (!nm_i->free_nid_count[i])
23618c2ecf20Sopenharmony_ci			continue;
23628c2ecf20Sopenharmony_ci		for (idx = 0; idx < NAT_ENTRY_PER_BLOCK; idx++) {
23638c2ecf20Sopenharmony_ci			idx = find_next_bit_le(nm_i->free_nid_bitmap[i],
23648c2ecf20Sopenharmony_ci						NAT_ENTRY_PER_BLOCK, idx);
23658c2ecf20Sopenharmony_ci			if (idx >= NAT_ENTRY_PER_BLOCK)
23668c2ecf20Sopenharmony_ci				break;
23678c2ecf20Sopenharmony_ci
23688c2ecf20Sopenharmony_ci			nid = i * NAT_ENTRY_PER_BLOCK + idx;
23698c2ecf20Sopenharmony_ci			add_free_nid(sbi, nid, true, false);
23708c2ecf20Sopenharmony_ci
23718c2ecf20Sopenharmony_ci			if (nm_i->nid_cnt[FREE_NID] >= MAX_FREE_NIDS)
23728c2ecf20Sopenharmony_ci				goto out;
23738c2ecf20Sopenharmony_ci		}
23748c2ecf20Sopenharmony_ci	}
23758c2ecf20Sopenharmony_ciout:
23768c2ecf20Sopenharmony_ci	scan_curseg_cache(sbi);
23778c2ecf20Sopenharmony_ci
23788c2ecf20Sopenharmony_ci	up_read(&nm_i->nat_tree_lock);
23798c2ecf20Sopenharmony_ci}
23808c2ecf20Sopenharmony_ci
23818c2ecf20Sopenharmony_cistatic int __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
23828c2ecf20Sopenharmony_ci						bool sync, bool mount)
23838c2ecf20Sopenharmony_ci{
23848c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
23858c2ecf20Sopenharmony_ci	int i = 0, ret;
23868c2ecf20Sopenharmony_ci	nid_t nid = nm_i->next_scan_nid;
23878c2ecf20Sopenharmony_ci
23888c2ecf20Sopenharmony_ci	if (unlikely(nid >= nm_i->max_nid))
23898c2ecf20Sopenharmony_ci		nid = 0;
23908c2ecf20Sopenharmony_ci
23918c2ecf20Sopenharmony_ci	if (unlikely(nid % NAT_ENTRY_PER_BLOCK))
23928c2ecf20Sopenharmony_ci		nid = NAT_BLOCK_OFFSET(nid) * NAT_ENTRY_PER_BLOCK;
23938c2ecf20Sopenharmony_ci
23948c2ecf20Sopenharmony_ci	/* Enough entries */
23958c2ecf20Sopenharmony_ci	if (nm_i->nid_cnt[FREE_NID] >= NAT_ENTRY_PER_BLOCK)
23968c2ecf20Sopenharmony_ci		return 0;
23978c2ecf20Sopenharmony_ci
23988c2ecf20Sopenharmony_ci	if (!sync && !f2fs_available_free_memory(sbi, FREE_NIDS))
23998c2ecf20Sopenharmony_ci		return 0;
24008c2ecf20Sopenharmony_ci
24018c2ecf20Sopenharmony_ci	if (!mount) {
24028c2ecf20Sopenharmony_ci		/* try to find free nids in free_nid_bitmap */
24038c2ecf20Sopenharmony_ci		scan_free_nid_bits(sbi);
24048c2ecf20Sopenharmony_ci
24058c2ecf20Sopenharmony_ci		if (nm_i->nid_cnt[FREE_NID] >= NAT_ENTRY_PER_BLOCK)
24068c2ecf20Sopenharmony_ci			return 0;
24078c2ecf20Sopenharmony_ci	}
24088c2ecf20Sopenharmony_ci
24098c2ecf20Sopenharmony_ci	/* readahead nat pages to be scanned */
24108c2ecf20Sopenharmony_ci	f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), FREE_NID_PAGES,
24118c2ecf20Sopenharmony_ci							META_NAT, true);
24128c2ecf20Sopenharmony_ci
24138c2ecf20Sopenharmony_ci	down_read(&nm_i->nat_tree_lock);
24148c2ecf20Sopenharmony_ci
24158c2ecf20Sopenharmony_ci	while (1) {
24168c2ecf20Sopenharmony_ci		if (!test_bit_le(NAT_BLOCK_OFFSET(nid),
24178c2ecf20Sopenharmony_ci						nm_i->nat_block_bitmap)) {
24188c2ecf20Sopenharmony_ci			struct page *page = get_current_nat_page(sbi, nid);
24198c2ecf20Sopenharmony_ci
24208c2ecf20Sopenharmony_ci			if (IS_ERR(page)) {
24218c2ecf20Sopenharmony_ci				ret = PTR_ERR(page);
24228c2ecf20Sopenharmony_ci			} else {
24238c2ecf20Sopenharmony_ci				ret = scan_nat_page(sbi, page, nid);
24248c2ecf20Sopenharmony_ci				f2fs_put_page(page, 1);
24258c2ecf20Sopenharmony_ci			}
24268c2ecf20Sopenharmony_ci
24278c2ecf20Sopenharmony_ci			if (ret) {
24288c2ecf20Sopenharmony_ci				up_read(&nm_i->nat_tree_lock);
24298c2ecf20Sopenharmony_ci				f2fs_err(sbi, "NAT is corrupt, run fsck to fix it");
24308c2ecf20Sopenharmony_ci				return ret;
24318c2ecf20Sopenharmony_ci			}
24328c2ecf20Sopenharmony_ci		}
24338c2ecf20Sopenharmony_ci
24348c2ecf20Sopenharmony_ci		nid += (NAT_ENTRY_PER_BLOCK - (nid % NAT_ENTRY_PER_BLOCK));
24358c2ecf20Sopenharmony_ci		if (unlikely(nid >= nm_i->max_nid))
24368c2ecf20Sopenharmony_ci			nid = 0;
24378c2ecf20Sopenharmony_ci
24388c2ecf20Sopenharmony_ci		if (++i >= FREE_NID_PAGES)
24398c2ecf20Sopenharmony_ci			break;
24408c2ecf20Sopenharmony_ci	}
24418c2ecf20Sopenharmony_ci
24428c2ecf20Sopenharmony_ci	/* go to the next free nat pages to find free nids abundantly */
24438c2ecf20Sopenharmony_ci	nm_i->next_scan_nid = nid;
24448c2ecf20Sopenharmony_ci
24458c2ecf20Sopenharmony_ci	/* find free nids from current sum_pages */
24468c2ecf20Sopenharmony_ci	scan_curseg_cache(sbi);
24478c2ecf20Sopenharmony_ci
24488c2ecf20Sopenharmony_ci	up_read(&nm_i->nat_tree_lock);
24498c2ecf20Sopenharmony_ci
24508c2ecf20Sopenharmony_ci	f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nm_i->next_scan_nid),
24518c2ecf20Sopenharmony_ci					nm_i->ra_nid_pages, META_NAT, false);
24528c2ecf20Sopenharmony_ci
24538c2ecf20Sopenharmony_ci	return 0;
24548c2ecf20Sopenharmony_ci}
24558c2ecf20Sopenharmony_ci
24568c2ecf20Sopenharmony_ciint f2fs_build_free_nids(struct f2fs_sb_info *sbi, bool sync, bool mount)
24578c2ecf20Sopenharmony_ci{
24588c2ecf20Sopenharmony_ci	int ret;
24598c2ecf20Sopenharmony_ci
24608c2ecf20Sopenharmony_ci	mutex_lock(&NM_I(sbi)->build_lock);
24618c2ecf20Sopenharmony_ci	ret = __f2fs_build_free_nids(sbi, sync, mount);
24628c2ecf20Sopenharmony_ci	mutex_unlock(&NM_I(sbi)->build_lock);
24638c2ecf20Sopenharmony_ci
24648c2ecf20Sopenharmony_ci	return ret;
24658c2ecf20Sopenharmony_ci}
24668c2ecf20Sopenharmony_ci
24678c2ecf20Sopenharmony_ci/*
24688c2ecf20Sopenharmony_ci * If this function returns success, caller can obtain a new nid
24698c2ecf20Sopenharmony_ci * from second parameter of this function.
24708c2ecf20Sopenharmony_ci * The returned nid could be used ino as well as nid when inode is created.
24718c2ecf20Sopenharmony_ci */
24728c2ecf20Sopenharmony_cibool f2fs_alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid)
24738c2ecf20Sopenharmony_ci{
24748c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
24758c2ecf20Sopenharmony_ci	struct free_nid *i = NULL;
24768c2ecf20Sopenharmony_ciretry:
24778c2ecf20Sopenharmony_ci	if (time_to_inject(sbi, FAULT_ALLOC_NID)) {
24788c2ecf20Sopenharmony_ci		f2fs_show_injection_info(sbi, FAULT_ALLOC_NID);
24798c2ecf20Sopenharmony_ci		return false;
24808c2ecf20Sopenharmony_ci	}
24818c2ecf20Sopenharmony_ci
24828c2ecf20Sopenharmony_ci	spin_lock(&nm_i->nid_list_lock);
24838c2ecf20Sopenharmony_ci
24848c2ecf20Sopenharmony_ci	if (unlikely(nm_i->available_nids == 0)) {
24858c2ecf20Sopenharmony_ci		spin_unlock(&nm_i->nid_list_lock);
24868c2ecf20Sopenharmony_ci		return false;
24878c2ecf20Sopenharmony_ci	}
24888c2ecf20Sopenharmony_ci
24898c2ecf20Sopenharmony_ci	/* We should not use stale free nids created by f2fs_build_free_nids */
24908c2ecf20Sopenharmony_ci	if (nm_i->nid_cnt[FREE_NID] && !on_f2fs_build_free_nids(nm_i)) {
24918c2ecf20Sopenharmony_ci		f2fs_bug_on(sbi, list_empty(&nm_i->free_nid_list));
24928c2ecf20Sopenharmony_ci		i = list_first_entry(&nm_i->free_nid_list,
24938c2ecf20Sopenharmony_ci					struct free_nid, list);
24948c2ecf20Sopenharmony_ci		*nid = i->nid;
24958c2ecf20Sopenharmony_ci
24968c2ecf20Sopenharmony_ci		__move_free_nid(sbi, i, FREE_NID, PREALLOC_NID);
24978c2ecf20Sopenharmony_ci		nm_i->available_nids--;
24988c2ecf20Sopenharmony_ci
24998c2ecf20Sopenharmony_ci		update_free_nid_bitmap(sbi, *nid, false, false);
25008c2ecf20Sopenharmony_ci
25018c2ecf20Sopenharmony_ci		spin_unlock(&nm_i->nid_list_lock);
25028c2ecf20Sopenharmony_ci		return true;
25038c2ecf20Sopenharmony_ci	}
25048c2ecf20Sopenharmony_ci	spin_unlock(&nm_i->nid_list_lock);
25058c2ecf20Sopenharmony_ci
25068c2ecf20Sopenharmony_ci	/* Let's scan nat pages and its caches to get free nids */
25078c2ecf20Sopenharmony_ci	if (!f2fs_build_free_nids(sbi, true, false))
25088c2ecf20Sopenharmony_ci		goto retry;
25098c2ecf20Sopenharmony_ci	return false;
25108c2ecf20Sopenharmony_ci}
25118c2ecf20Sopenharmony_ci
25128c2ecf20Sopenharmony_ci/*
25138c2ecf20Sopenharmony_ci * f2fs_alloc_nid() should be called prior to this function.
25148c2ecf20Sopenharmony_ci */
25158c2ecf20Sopenharmony_civoid f2fs_alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid)
25168c2ecf20Sopenharmony_ci{
25178c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
25188c2ecf20Sopenharmony_ci	struct free_nid *i;
25198c2ecf20Sopenharmony_ci
25208c2ecf20Sopenharmony_ci	spin_lock(&nm_i->nid_list_lock);
25218c2ecf20Sopenharmony_ci	i = __lookup_free_nid_list(nm_i, nid);
25228c2ecf20Sopenharmony_ci	f2fs_bug_on(sbi, !i);
25238c2ecf20Sopenharmony_ci	__remove_free_nid(sbi, i, PREALLOC_NID);
25248c2ecf20Sopenharmony_ci	spin_unlock(&nm_i->nid_list_lock);
25258c2ecf20Sopenharmony_ci
25268c2ecf20Sopenharmony_ci	kmem_cache_free(free_nid_slab, i);
25278c2ecf20Sopenharmony_ci}
25288c2ecf20Sopenharmony_ci
25298c2ecf20Sopenharmony_ci/*
25308c2ecf20Sopenharmony_ci * f2fs_alloc_nid() should be called prior to this function.
25318c2ecf20Sopenharmony_ci */
25328c2ecf20Sopenharmony_civoid f2fs_alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid)
25338c2ecf20Sopenharmony_ci{
25348c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
25358c2ecf20Sopenharmony_ci	struct free_nid *i;
25368c2ecf20Sopenharmony_ci	bool need_free = false;
25378c2ecf20Sopenharmony_ci
25388c2ecf20Sopenharmony_ci	if (!nid)
25398c2ecf20Sopenharmony_ci		return;
25408c2ecf20Sopenharmony_ci
25418c2ecf20Sopenharmony_ci	spin_lock(&nm_i->nid_list_lock);
25428c2ecf20Sopenharmony_ci	i = __lookup_free_nid_list(nm_i, nid);
25438c2ecf20Sopenharmony_ci	f2fs_bug_on(sbi, !i);
25448c2ecf20Sopenharmony_ci
25458c2ecf20Sopenharmony_ci	if (!f2fs_available_free_memory(sbi, FREE_NIDS)) {
25468c2ecf20Sopenharmony_ci		__remove_free_nid(sbi, i, PREALLOC_NID);
25478c2ecf20Sopenharmony_ci		need_free = true;
25488c2ecf20Sopenharmony_ci	} else {
25498c2ecf20Sopenharmony_ci		__move_free_nid(sbi, i, PREALLOC_NID, FREE_NID);
25508c2ecf20Sopenharmony_ci	}
25518c2ecf20Sopenharmony_ci
25528c2ecf20Sopenharmony_ci	nm_i->available_nids++;
25538c2ecf20Sopenharmony_ci
25548c2ecf20Sopenharmony_ci	update_free_nid_bitmap(sbi, nid, true, false);
25558c2ecf20Sopenharmony_ci
25568c2ecf20Sopenharmony_ci	spin_unlock(&nm_i->nid_list_lock);
25578c2ecf20Sopenharmony_ci
25588c2ecf20Sopenharmony_ci	if (need_free)
25598c2ecf20Sopenharmony_ci		kmem_cache_free(free_nid_slab, i);
25608c2ecf20Sopenharmony_ci}
25618c2ecf20Sopenharmony_ci
25628c2ecf20Sopenharmony_ciint f2fs_try_to_free_nids(struct f2fs_sb_info *sbi, int nr_shrink)
25638c2ecf20Sopenharmony_ci{
25648c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
25658c2ecf20Sopenharmony_ci	int nr = nr_shrink;
25668c2ecf20Sopenharmony_ci
25678c2ecf20Sopenharmony_ci	if (nm_i->nid_cnt[FREE_NID] <= MAX_FREE_NIDS)
25688c2ecf20Sopenharmony_ci		return 0;
25698c2ecf20Sopenharmony_ci
25708c2ecf20Sopenharmony_ci	if (!mutex_trylock(&nm_i->build_lock))
25718c2ecf20Sopenharmony_ci		return 0;
25728c2ecf20Sopenharmony_ci
25738c2ecf20Sopenharmony_ci	while (nr_shrink && nm_i->nid_cnt[FREE_NID] > MAX_FREE_NIDS) {
25748c2ecf20Sopenharmony_ci		struct free_nid *i, *next;
25758c2ecf20Sopenharmony_ci		unsigned int batch = SHRINK_NID_BATCH_SIZE;
25768c2ecf20Sopenharmony_ci
25778c2ecf20Sopenharmony_ci		spin_lock(&nm_i->nid_list_lock);
25788c2ecf20Sopenharmony_ci		list_for_each_entry_safe(i, next, &nm_i->free_nid_list, list) {
25798c2ecf20Sopenharmony_ci			if (!nr_shrink || !batch ||
25808c2ecf20Sopenharmony_ci				nm_i->nid_cnt[FREE_NID] <= MAX_FREE_NIDS)
25818c2ecf20Sopenharmony_ci				break;
25828c2ecf20Sopenharmony_ci			__remove_free_nid(sbi, i, FREE_NID);
25838c2ecf20Sopenharmony_ci			kmem_cache_free(free_nid_slab, i);
25848c2ecf20Sopenharmony_ci			nr_shrink--;
25858c2ecf20Sopenharmony_ci			batch--;
25868c2ecf20Sopenharmony_ci		}
25878c2ecf20Sopenharmony_ci		spin_unlock(&nm_i->nid_list_lock);
25888c2ecf20Sopenharmony_ci	}
25898c2ecf20Sopenharmony_ci
25908c2ecf20Sopenharmony_ci	mutex_unlock(&nm_i->build_lock);
25918c2ecf20Sopenharmony_ci
25928c2ecf20Sopenharmony_ci	return nr - nr_shrink;
25938c2ecf20Sopenharmony_ci}
25948c2ecf20Sopenharmony_ci
25958c2ecf20Sopenharmony_ciint f2fs_recover_inline_xattr(struct inode *inode, struct page *page)
25968c2ecf20Sopenharmony_ci{
25978c2ecf20Sopenharmony_ci	void *src_addr, *dst_addr;
25988c2ecf20Sopenharmony_ci	size_t inline_size;
25998c2ecf20Sopenharmony_ci	struct page *ipage;
26008c2ecf20Sopenharmony_ci	struct f2fs_inode *ri;
26018c2ecf20Sopenharmony_ci
26028c2ecf20Sopenharmony_ci	ipage = f2fs_get_node_page(F2FS_I_SB(inode), inode->i_ino);
26038c2ecf20Sopenharmony_ci	if (IS_ERR(ipage))
26048c2ecf20Sopenharmony_ci		return PTR_ERR(ipage);
26058c2ecf20Sopenharmony_ci
26068c2ecf20Sopenharmony_ci	ri = F2FS_INODE(page);
26078c2ecf20Sopenharmony_ci	if (ri->i_inline & F2FS_INLINE_XATTR) {
26088c2ecf20Sopenharmony_ci		set_inode_flag(inode, FI_INLINE_XATTR);
26098c2ecf20Sopenharmony_ci	} else {
26108c2ecf20Sopenharmony_ci		clear_inode_flag(inode, FI_INLINE_XATTR);
26118c2ecf20Sopenharmony_ci		goto update_inode;
26128c2ecf20Sopenharmony_ci	}
26138c2ecf20Sopenharmony_ci
26148c2ecf20Sopenharmony_ci	dst_addr = inline_xattr_addr(inode, ipage);
26158c2ecf20Sopenharmony_ci	src_addr = inline_xattr_addr(inode, page);
26168c2ecf20Sopenharmony_ci	inline_size = inline_xattr_size(inode);
26178c2ecf20Sopenharmony_ci
26188c2ecf20Sopenharmony_ci	f2fs_wait_on_page_writeback(ipage, NODE, true, true);
26198c2ecf20Sopenharmony_ci	memcpy(dst_addr, src_addr, inline_size);
26208c2ecf20Sopenharmony_ciupdate_inode:
26218c2ecf20Sopenharmony_ci	f2fs_update_inode(inode, ipage);
26228c2ecf20Sopenharmony_ci	f2fs_put_page(ipage, 1);
26238c2ecf20Sopenharmony_ci	return 0;
26248c2ecf20Sopenharmony_ci}
26258c2ecf20Sopenharmony_ci
26268c2ecf20Sopenharmony_ciint f2fs_recover_xattr_data(struct inode *inode, struct page *page)
26278c2ecf20Sopenharmony_ci{
26288c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
26298c2ecf20Sopenharmony_ci	nid_t prev_xnid = F2FS_I(inode)->i_xattr_nid;
26308c2ecf20Sopenharmony_ci	nid_t new_xnid;
26318c2ecf20Sopenharmony_ci	struct dnode_of_data dn;
26328c2ecf20Sopenharmony_ci	struct node_info ni;
26338c2ecf20Sopenharmony_ci	struct page *xpage;
26348c2ecf20Sopenharmony_ci	int err;
26358c2ecf20Sopenharmony_ci
26368c2ecf20Sopenharmony_ci	if (!prev_xnid)
26378c2ecf20Sopenharmony_ci		goto recover_xnid;
26388c2ecf20Sopenharmony_ci
26398c2ecf20Sopenharmony_ci	/* 1: invalidate the previous xattr nid */
26408c2ecf20Sopenharmony_ci	err = f2fs_get_node_info(sbi, prev_xnid, &ni);
26418c2ecf20Sopenharmony_ci	if (err)
26428c2ecf20Sopenharmony_ci		return err;
26438c2ecf20Sopenharmony_ci
26448c2ecf20Sopenharmony_ci	f2fs_invalidate_blocks(sbi, ni.blk_addr);
26458c2ecf20Sopenharmony_ci	dec_valid_node_count(sbi, inode, false);
26468c2ecf20Sopenharmony_ci	set_node_addr(sbi, &ni, NULL_ADDR, false);
26478c2ecf20Sopenharmony_ci
26488c2ecf20Sopenharmony_cirecover_xnid:
26498c2ecf20Sopenharmony_ci	/* 2: update xattr nid in inode */
26508c2ecf20Sopenharmony_ci	if (!f2fs_alloc_nid(sbi, &new_xnid))
26518c2ecf20Sopenharmony_ci		return -ENOSPC;
26528c2ecf20Sopenharmony_ci
26538c2ecf20Sopenharmony_ci	set_new_dnode(&dn, inode, NULL, NULL, new_xnid);
26548c2ecf20Sopenharmony_ci	xpage = f2fs_new_node_page(&dn, XATTR_NODE_OFFSET);
26558c2ecf20Sopenharmony_ci	if (IS_ERR(xpage)) {
26568c2ecf20Sopenharmony_ci		f2fs_alloc_nid_failed(sbi, new_xnid);
26578c2ecf20Sopenharmony_ci		return PTR_ERR(xpage);
26588c2ecf20Sopenharmony_ci	}
26598c2ecf20Sopenharmony_ci
26608c2ecf20Sopenharmony_ci	f2fs_alloc_nid_done(sbi, new_xnid);
26618c2ecf20Sopenharmony_ci	f2fs_update_inode_page(inode);
26628c2ecf20Sopenharmony_ci
26638c2ecf20Sopenharmony_ci	/* 3: update and set xattr node page dirty */
26648c2ecf20Sopenharmony_ci	memcpy(F2FS_NODE(xpage), F2FS_NODE(page), VALID_XATTR_BLOCK_SIZE);
26658c2ecf20Sopenharmony_ci
26668c2ecf20Sopenharmony_ci	set_page_dirty(xpage);
26678c2ecf20Sopenharmony_ci	f2fs_put_page(xpage, 1);
26688c2ecf20Sopenharmony_ci
26698c2ecf20Sopenharmony_ci	return 0;
26708c2ecf20Sopenharmony_ci}
26718c2ecf20Sopenharmony_ci
26728c2ecf20Sopenharmony_ciint f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct page *page)
26738c2ecf20Sopenharmony_ci{
26748c2ecf20Sopenharmony_ci	struct f2fs_inode *src, *dst;
26758c2ecf20Sopenharmony_ci	nid_t ino = ino_of_node(page);
26768c2ecf20Sopenharmony_ci	struct node_info old_ni, new_ni;
26778c2ecf20Sopenharmony_ci	struct page *ipage;
26788c2ecf20Sopenharmony_ci	int err;
26798c2ecf20Sopenharmony_ci
26808c2ecf20Sopenharmony_ci	err = f2fs_get_node_info(sbi, ino, &old_ni);
26818c2ecf20Sopenharmony_ci	if (err)
26828c2ecf20Sopenharmony_ci		return err;
26838c2ecf20Sopenharmony_ci
26848c2ecf20Sopenharmony_ci	if (unlikely(old_ni.blk_addr != NULL_ADDR))
26858c2ecf20Sopenharmony_ci		return -EINVAL;
26868c2ecf20Sopenharmony_ciretry:
26878c2ecf20Sopenharmony_ci	ipage = f2fs_grab_cache_page(NODE_MAPPING(sbi), ino, false);
26888c2ecf20Sopenharmony_ci	if (!ipage) {
26898c2ecf20Sopenharmony_ci		congestion_wait(BLK_RW_ASYNC, DEFAULT_IO_TIMEOUT);
26908c2ecf20Sopenharmony_ci		goto retry;
26918c2ecf20Sopenharmony_ci	}
26928c2ecf20Sopenharmony_ci
26938c2ecf20Sopenharmony_ci	/* Should not use this inode from free nid list */
26948c2ecf20Sopenharmony_ci	remove_free_nid(sbi, ino);
26958c2ecf20Sopenharmony_ci
26968c2ecf20Sopenharmony_ci	if (!PageUptodate(ipage))
26978c2ecf20Sopenharmony_ci		SetPageUptodate(ipage);
26988c2ecf20Sopenharmony_ci	fill_node_footer(ipage, ino, ino, 0, true);
26998c2ecf20Sopenharmony_ci	set_cold_node(ipage, false);
27008c2ecf20Sopenharmony_ci
27018c2ecf20Sopenharmony_ci	src = F2FS_INODE(page);
27028c2ecf20Sopenharmony_ci	dst = F2FS_INODE(ipage);
27038c2ecf20Sopenharmony_ci
27048c2ecf20Sopenharmony_ci	memcpy(dst, src, (unsigned long)&src->i_ext - (unsigned long)src);
27058c2ecf20Sopenharmony_ci	dst->i_size = 0;
27068c2ecf20Sopenharmony_ci	dst->i_blocks = cpu_to_le64(1);
27078c2ecf20Sopenharmony_ci	dst->i_links = cpu_to_le32(1);
27088c2ecf20Sopenharmony_ci	dst->i_xattr_nid = 0;
27098c2ecf20Sopenharmony_ci	dst->i_inline = src->i_inline & (F2FS_INLINE_XATTR | F2FS_EXTRA_ATTR);
27108c2ecf20Sopenharmony_ci	if (dst->i_inline & F2FS_EXTRA_ATTR) {
27118c2ecf20Sopenharmony_ci		dst->i_extra_isize = src->i_extra_isize;
27128c2ecf20Sopenharmony_ci
27138c2ecf20Sopenharmony_ci		if (f2fs_sb_has_flexible_inline_xattr(sbi) &&
27148c2ecf20Sopenharmony_ci			F2FS_FITS_IN_INODE(src, le16_to_cpu(src->i_extra_isize),
27158c2ecf20Sopenharmony_ci							i_inline_xattr_size))
27168c2ecf20Sopenharmony_ci			dst->i_inline_xattr_size = src->i_inline_xattr_size;
27178c2ecf20Sopenharmony_ci
27188c2ecf20Sopenharmony_ci		if (f2fs_sb_has_project_quota(sbi) &&
27198c2ecf20Sopenharmony_ci			F2FS_FITS_IN_INODE(src, le16_to_cpu(src->i_extra_isize),
27208c2ecf20Sopenharmony_ci								i_projid))
27218c2ecf20Sopenharmony_ci			dst->i_projid = src->i_projid;
27228c2ecf20Sopenharmony_ci
27238c2ecf20Sopenharmony_ci		if (f2fs_sb_has_inode_crtime(sbi) &&
27248c2ecf20Sopenharmony_ci			F2FS_FITS_IN_INODE(src, le16_to_cpu(src->i_extra_isize),
27258c2ecf20Sopenharmony_ci							i_crtime_nsec)) {
27268c2ecf20Sopenharmony_ci			dst->i_crtime = src->i_crtime;
27278c2ecf20Sopenharmony_ci			dst->i_crtime_nsec = src->i_crtime_nsec;
27288c2ecf20Sopenharmony_ci		}
27298c2ecf20Sopenharmony_ci	}
27308c2ecf20Sopenharmony_ci
27318c2ecf20Sopenharmony_ci	new_ni = old_ni;
27328c2ecf20Sopenharmony_ci	new_ni.ino = ino;
27338c2ecf20Sopenharmony_ci
27348c2ecf20Sopenharmony_ci	if (unlikely(inc_valid_node_count(sbi, NULL, true)))
27358c2ecf20Sopenharmony_ci		WARN_ON(1);
27368c2ecf20Sopenharmony_ci	set_node_addr(sbi, &new_ni, NEW_ADDR, false);
27378c2ecf20Sopenharmony_ci	inc_valid_inode_count(sbi);
27388c2ecf20Sopenharmony_ci	set_page_dirty(ipage);
27398c2ecf20Sopenharmony_ci	f2fs_put_page(ipage, 1);
27408c2ecf20Sopenharmony_ci	return 0;
27418c2ecf20Sopenharmony_ci}
27428c2ecf20Sopenharmony_ci
27438c2ecf20Sopenharmony_ciint f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
27448c2ecf20Sopenharmony_ci			unsigned int segno, struct f2fs_summary_block *sum)
27458c2ecf20Sopenharmony_ci{
27468c2ecf20Sopenharmony_ci	struct f2fs_node *rn;
27478c2ecf20Sopenharmony_ci	struct f2fs_summary *sum_entry;
27488c2ecf20Sopenharmony_ci	block_t addr;
27498c2ecf20Sopenharmony_ci	int i, idx, last_offset, nrpages;
27508c2ecf20Sopenharmony_ci
27518c2ecf20Sopenharmony_ci	/* scan the node segment */
27528c2ecf20Sopenharmony_ci	last_offset = sbi->blocks_per_seg;
27538c2ecf20Sopenharmony_ci	addr = START_BLOCK(sbi, segno);
27548c2ecf20Sopenharmony_ci	sum_entry = &sum->entries[0];
27558c2ecf20Sopenharmony_ci
27568c2ecf20Sopenharmony_ci	for (i = 0; i < last_offset; i += nrpages, addr += nrpages) {
27578c2ecf20Sopenharmony_ci		nrpages = min(last_offset - i, BIO_MAX_PAGES);
27588c2ecf20Sopenharmony_ci
27598c2ecf20Sopenharmony_ci		/* readahead node pages */
27608c2ecf20Sopenharmony_ci		f2fs_ra_meta_pages(sbi, addr, nrpages, META_POR, true);
27618c2ecf20Sopenharmony_ci
27628c2ecf20Sopenharmony_ci		for (idx = addr; idx < addr + nrpages; idx++) {
27638c2ecf20Sopenharmony_ci			struct page *page = f2fs_get_tmp_page(sbi, idx);
27648c2ecf20Sopenharmony_ci
27658c2ecf20Sopenharmony_ci			if (IS_ERR(page))
27668c2ecf20Sopenharmony_ci				return PTR_ERR(page);
27678c2ecf20Sopenharmony_ci
27688c2ecf20Sopenharmony_ci			rn = F2FS_NODE(page);
27698c2ecf20Sopenharmony_ci			sum_entry->nid = rn->footer.nid;
27708c2ecf20Sopenharmony_ci			sum_entry->version = 0;
27718c2ecf20Sopenharmony_ci			sum_entry->ofs_in_node = 0;
27728c2ecf20Sopenharmony_ci			sum_entry++;
27738c2ecf20Sopenharmony_ci			f2fs_put_page(page, 1);
27748c2ecf20Sopenharmony_ci		}
27758c2ecf20Sopenharmony_ci
27768c2ecf20Sopenharmony_ci		invalidate_mapping_pages(META_MAPPING(sbi), addr,
27778c2ecf20Sopenharmony_ci							addr + nrpages);
27788c2ecf20Sopenharmony_ci	}
27798c2ecf20Sopenharmony_ci	return 0;
27808c2ecf20Sopenharmony_ci}
27818c2ecf20Sopenharmony_ci
27828c2ecf20Sopenharmony_cistatic void remove_nats_in_journal(struct f2fs_sb_info *sbi)
27838c2ecf20Sopenharmony_ci{
27848c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
27858c2ecf20Sopenharmony_ci	struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
27868c2ecf20Sopenharmony_ci	struct f2fs_journal *journal = curseg->journal;
27878c2ecf20Sopenharmony_ci	int i;
27888c2ecf20Sopenharmony_ci
27898c2ecf20Sopenharmony_ci	down_write(&curseg->journal_rwsem);
27908c2ecf20Sopenharmony_ci	for (i = 0; i < nats_in_cursum(journal); i++) {
27918c2ecf20Sopenharmony_ci		struct nat_entry *ne;
27928c2ecf20Sopenharmony_ci		struct f2fs_nat_entry raw_ne;
27938c2ecf20Sopenharmony_ci		nid_t nid = le32_to_cpu(nid_in_journal(journal, i));
27948c2ecf20Sopenharmony_ci
27958c2ecf20Sopenharmony_ci		if (f2fs_check_nid_range(sbi, nid))
27968c2ecf20Sopenharmony_ci			continue;
27978c2ecf20Sopenharmony_ci
27988c2ecf20Sopenharmony_ci		raw_ne = nat_in_journal(journal, i);
27998c2ecf20Sopenharmony_ci
28008c2ecf20Sopenharmony_ci		ne = __lookup_nat_cache(nm_i, nid);
28018c2ecf20Sopenharmony_ci		if (!ne) {
28028c2ecf20Sopenharmony_ci			ne = __alloc_nat_entry(nid, true);
28038c2ecf20Sopenharmony_ci			__init_nat_entry(nm_i, ne, &raw_ne, true);
28048c2ecf20Sopenharmony_ci		}
28058c2ecf20Sopenharmony_ci
28068c2ecf20Sopenharmony_ci		/*
28078c2ecf20Sopenharmony_ci		 * if a free nat in journal has not been used after last
28088c2ecf20Sopenharmony_ci		 * checkpoint, we should remove it from available nids,
28098c2ecf20Sopenharmony_ci		 * since later we will add it again.
28108c2ecf20Sopenharmony_ci		 */
28118c2ecf20Sopenharmony_ci		if (!get_nat_flag(ne, IS_DIRTY) &&
28128c2ecf20Sopenharmony_ci				le32_to_cpu(raw_ne.block_addr) == NULL_ADDR) {
28138c2ecf20Sopenharmony_ci			spin_lock(&nm_i->nid_list_lock);
28148c2ecf20Sopenharmony_ci			nm_i->available_nids--;
28158c2ecf20Sopenharmony_ci			spin_unlock(&nm_i->nid_list_lock);
28168c2ecf20Sopenharmony_ci		}
28178c2ecf20Sopenharmony_ci
28188c2ecf20Sopenharmony_ci		__set_nat_cache_dirty(nm_i, ne);
28198c2ecf20Sopenharmony_ci	}
28208c2ecf20Sopenharmony_ci	update_nats_in_cursum(journal, -i);
28218c2ecf20Sopenharmony_ci	up_write(&curseg->journal_rwsem);
28228c2ecf20Sopenharmony_ci}
28238c2ecf20Sopenharmony_ci
28248c2ecf20Sopenharmony_cistatic void __adjust_nat_entry_set(struct nat_entry_set *nes,
28258c2ecf20Sopenharmony_ci						struct list_head *head, int max)
28268c2ecf20Sopenharmony_ci{
28278c2ecf20Sopenharmony_ci	struct nat_entry_set *cur;
28288c2ecf20Sopenharmony_ci
28298c2ecf20Sopenharmony_ci	if (nes->entry_cnt >= max)
28308c2ecf20Sopenharmony_ci		goto add_out;
28318c2ecf20Sopenharmony_ci
28328c2ecf20Sopenharmony_ci	list_for_each_entry(cur, head, set_list) {
28338c2ecf20Sopenharmony_ci		if (cur->entry_cnt >= nes->entry_cnt) {
28348c2ecf20Sopenharmony_ci			list_add(&nes->set_list, cur->set_list.prev);
28358c2ecf20Sopenharmony_ci			return;
28368c2ecf20Sopenharmony_ci		}
28378c2ecf20Sopenharmony_ci	}
28388c2ecf20Sopenharmony_ciadd_out:
28398c2ecf20Sopenharmony_ci	list_add_tail(&nes->set_list, head);
28408c2ecf20Sopenharmony_ci}
28418c2ecf20Sopenharmony_ci
28428c2ecf20Sopenharmony_cistatic void __update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid,
28438c2ecf20Sopenharmony_ci						struct page *page)
28448c2ecf20Sopenharmony_ci{
28458c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
28468c2ecf20Sopenharmony_ci	unsigned int nat_index = start_nid / NAT_ENTRY_PER_BLOCK;
28478c2ecf20Sopenharmony_ci	struct f2fs_nat_block *nat_blk = page_address(page);
28488c2ecf20Sopenharmony_ci	int valid = 0;
28498c2ecf20Sopenharmony_ci	int i = 0;
28508c2ecf20Sopenharmony_ci
28518c2ecf20Sopenharmony_ci	if (!enabled_nat_bits(sbi, NULL))
28528c2ecf20Sopenharmony_ci		return;
28538c2ecf20Sopenharmony_ci
28548c2ecf20Sopenharmony_ci	if (nat_index == 0) {
28558c2ecf20Sopenharmony_ci		valid = 1;
28568c2ecf20Sopenharmony_ci		i = 1;
28578c2ecf20Sopenharmony_ci	}
28588c2ecf20Sopenharmony_ci	for (; i < NAT_ENTRY_PER_BLOCK; i++) {
28598c2ecf20Sopenharmony_ci		if (le32_to_cpu(nat_blk->entries[i].block_addr) != NULL_ADDR)
28608c2ecf20Sopenharmony_ci			valid++;
28618c2ecf20Sopenharmony_ci	}
28628c2ecf20Sopenharmony_ci	if (valid == 0) {
28638c2ecf20Sopenharmony_ci		__set_bit_le(nat_index, nm_i->empty_nat_bits);
28648c2ecf20Sopenharmony_ci		__clear_bit_le(nat_index, nm_i->full_nat_bits);
28658c2ecf20Sopenharmony_ci		return;
28668c2ecf20Sopenharmony_ci	}
28678c2ecf20Sopenharmony_ci
28688c2ecf20Sopenharmony_ci	__clear_bit_le(nat_index, nm_i->empty_nat_bits);
28698c2ecf20Sopenharmony_ci	if (valid == NAT_ENTRY_PER_BLOCK)
28708c2ecf20Sopenharmony_ci		__set_bit_le(nat_index, nm_i->full_nat_bits);
28718c2ecf20Sopenharmony_ci	else
28728c2ecf20Sopenharmony_ci		__clear_bit_le(nat_index, nm_i->full_nat_bits);
28738c2ecf20Sopenharmony_ci}
28748c2ecf20Sopenharmony_ci
28758c2ecf20Sopenharmony_cistatic int __flush_nat_entry_set(struct f2fs_sb_info *sbi,
28768c2ecf20Sopenharmony_ci		struct nat_entry_set *set, struct cp_control *cpc)
28778c2ecf20Sopenharmony_ci{
28788c2ecf20Sopenharmony_ci	struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
28798c2ecf20Sopenharmony_ci	struct f2fs_journal *journal = curseg->journal;
28808c2ecf20Sopenharmony_ci	nid_t start_nid = set->set * NAT_ENTRY_PER_BLOCK;
28818c2ecf20Sopenharmony_ci	bool to_journal = true;
28828c2ecf20Sopenharmony_ci	struct f2fs_nat_block *nat_blk;
28838c2ecf20Sopenharmony_ci	struct nat_entry *ne, *cur;
28848c2ecf20Sopenharmony_ci	struct page *page = NULL;
28858c2ecf20Sopenharmony_ci
28868c2ecf20Sopenharmony_ci	/*
28878c2ecf20Sopenharmony_ci	 * there are two steps to flush nat entries:
28888c2ecf20Sopenharmony_ci	 * #1, flush nat entries to journal in current hot data summary block.
28898c2ecf20Sopenharmony_ci	 * #2, flush nat entries to nat page.
28908c2ecf20Sopenharmony_ci	 */
28918c2ecf20Sopenharmony_ci	if (enabled_nat_bits(sbi, cpc) ||
28928c2ecf20Sopenharmony_ci		!__has_cursum_space(journal, set->entry_cnt, NAT_JOURNAL))
28938c2ecf20Sopenharmony_ci		to_journal = false;
28948c2ecf20Sopenharmony_ci
28958c2ecf20Sopenharmony_ci	if (to_journal) {
28968c2ecf20Sopenharmony_ci		down_write(&curseg->journal_rwsem);
28978c2ecf20Sopenharmony_ci	} else {
28988c2ecf20Sopenharmony_ci		page = get_next_nat_page(sbi, start_nid);
28998c2ecf20Sopenharmony_ci		if (IS_ERR(page))
29008c2ecf20Sopenharmony_ci			return PTR_ERR(page);
29018c2ecf20Sopenharmony_ci
29028c2ecf20Sopenharmony_ci		nat_blk = page_address(page);
29038c2ecf20Sopenharmony_ci		f2fs_bug_on(sbi, !nat_blk);
29048c2ecf20Sopenharmony_ci	}
29058c2ecf20Sopenharmony_ci
29068c2ecf20Sopenharmony_ci	/* flush dirty nats in nat entry set */
29078c2ecf20Sopenharmony_ci	list_for_each_entry_safe(ne, cur, &set->entry_list, list) {
29088c2ecf20Sopenharmony_ci		struct f2fs_nat_entry *raw_ne;
29098c2ecf20Sopenharmony_ci		nid_t nid = nat_get_nid(ne);
29108c2ecf20Sopenharmony_ci		int offset;
29118c2ecf20Sopenharmony_ci
29128c2ecf20Sopenharmony_ci		f2fs_bug_on(sbi, nat_get_blkaddr(ne) == NEW_ADDR);
29138c2ecf20Sopenharmony_ci
29148c2ecf20Sopenharmony_ci		if (to_journal) {
29158c2ecf20Sopenharmony_ci			offset = f2fs_lookup_journal_in_cursum(journal,
29168c2ecf20Sopenharmony_ci							NAT_JOURNAL, nid, 1);
29178c2ecf20Sopenharmony_ci			f2fs_bug_on(sbi, offset < 0);
29188c2ecf20Sopenharmony_ci			raw_ne = &nat_in_journal(journal, offset);
29198c2ecf20Sopenharmony_ci			nid_in_journal(journal, offset) = cpu_to_le32(nid);
29208c2ecf20Sopenharmony_ci		} else {
29218c2ecf20Sopenharmony_ci			raw_ne = &nat_blk->entries[nid - start_nid];
29228c2ecf20Sopenharmony_ci		}
29238c2ecf20Sopenharmony_ci		raw_nat_from_node_info(raw_ne, &ne->ni);
29248c2ecf20Sopenharmony_ci		nat_reset_flag(ne);
29258c2ecf20Sopenharmony_ci		__clear_nat_cache_dirty(NM_I(sbi), set, ne);
29268c2ecf20Sopenharmony_ci		if (nat_get_blkaddr(ne) == NULL_ADDR) {
29278c2ecf20Sopenharmony_ci			add_free_nid(sbi, nid, false, true);
29288c2ecf20Sopenharmony_ci		} else {
29298c2ecf20Sopenharmony_ci			spin_lock(&NM_I(sbi)->nid_list_lock);
29308c2ecf20Sopenharmony_ci			update_free_nid_bitmap(sbi, nid, false, false);
29318c2ecf20Sopenharmony_ci			spin_unlock(&NM_I(sbi)->nid_list_lock);
29328c2ecf20Sopenharmony_ci		}
29338c2ecf20Sopenharmony_ci	}
29348c2ecf20Sopenharmony_ci
29358c2ecf20Sopenharmony_ci	if (to_journal) {
29368c2ecf20Sopenharmony_ci		up_write(&curseg->journal_rwsem);
29378c2ecf20Sopenharmony_ci	} else {
29388c2ecf20Sopenharmony_ci		__update_nat_bits(sbi, start_nid, page);
29398c2ecf20Sopenharmony_ci		f2fs_put_page(page, 1);
29408c2ecf20Sopenharmony_ci	}
29418c2ecf20Sopenharmony_ci
29428c2ecf20Sopenharmony_ci	/* Allow dirty nats by node block allocation in write_begin */
29438c2ecf20Sopenharmony_ci	if (!set->entry_cnt) {
29448c2ecf20Sopenharmony_ci		radix_tree_delete(&NM_I(sbi)->nat_set_root, set->set);
29458c2ecf20Sopenharmony_ci		kmem_cache_free(nat_entry_set_slab, set);
29468c2ecf20Sopenharmony_ci	}
29478c2ecf20Sopenharmony_ci	return 0;
29488c2ecf20Sopenharmony_ci}
29498c2ecf20Sopenharmony_ci
29508c2ecf20Sopenharmony_ci/*
29518c2ecf20Sopenharmony_ci * This function is called during the checkpointing process.
29528c2ecf20Sopenharmony_ci */
29538c2ecf20Sopenharmony_ciint f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
29548c2ecf20Sopenharmony_ci{
29558c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
29568c2ecf20Sopenharmony_ci	struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
29578c2ecf20Sopenharmony_ci	struct f2fs_journal *journal = curseg->journal;
29588c2ecf20Sopenharmony_ci	struct nat_entry_set *setvec[SETVEC_SIZE];
29598c2ecf20Sopenharmony_ci	struct nat_entry_set *set, *tmp;
29608c2ecf20Sopenharmony_ci	unsigned int found;
29618c2ecf20Sopenharmony_ci	nid_t set_idx = 0;
29628c2ecf20Sopenharmony_ci	LIST_HEAD(sets);
29638c2ecf20Sopenharmony_ci	int err = 0;
29648c2ecf20Sopenharmony_ci
29658c2ecf20Sopenharmony_ci	/*
29668c2ecf20Sopenharmony_ci	 * during unmount, let's flush nat_bits before checking
29678c2ecf20Sopenharmony_ci	 * nat_cnt[DIRTY_NAT].
29688c2ecf20Sopenharmony_ci	 */
29698c2ecf20Sopenharmony_ci	if (enabled_nat_bits(sbi, cpc)) {
29708c2ecf20Sopenharmony_ci		down_write(&nm_i->nat_tree_lock);
29718c2ecf20Sopenharmony_ci		remove_nats_in_journal(sbi);
29728c2ecf20Sopenharmony_ci		up_write(&nm_i->nat_tree_lock);
29738c2ecf20Sopenharmony_ci	}
29748c2ecf20Sopenharmony_ci
29758c2ecf20Sopenharmony_ci	if (!nm_i->nat_cnt[DIRTY_NAT])
29768c2ecf20Sopenharmony_ci		return 0;
29778c2ecf20Sopenharmony_ci
29788c2ecf20Sopenharmony_ci	down_write(&nm_i->nat_tree_lock);
29798c2ecf20Sopenharmony_ci
29808c2ecf20Sopenharmony_ci	/*
29818c2ecf20Sopenharmony_ci	 * if there are no enough space in journal to store dirty nat
29828c2ecf20Sopenharmony_ci	 * entries, remove all entries from journal and merge them
29838c2ecf20Sopenharmony_ci	 * into nat entry set.
29848c2ecf20Sopenharmony_ci	 */
29858c2ecf20Sopenharmony_ci	if (enabled_nat_bits(sbi, cpc) ||
29868c2ecf20Sopenharmony_ci		!__has_cursum_space(journal,
29878c2ecf20Sopenharmony_ci			nm_i->nat_cnt[DIRTY_NAT], NAT_JOURNAL))
29888c2ecf20Sopenharmony_ci		remove_nats_in_journal(sbi);
29898c2ecf20Sopenharmony_ci
29908c2ecf20Sopenharmony_ci	while ((found = __gang_lookup_nat_set(nm_i,
29918c2ecf20Sopenharmony_ci					set_idx, SETVEC_SIZE, setvec))) {
29928c2ecf20Sopenharmony_ci		unsigned idx;
29938c2ecf20Sopenharmony_ci		set_idx = setvec[found - 1]->set + 1;
29948c2ecf20Sopenharmony_ci		for (idx = 0; idx < found; idx++)
29958c2ecf20Sopenharmony_ci			__adjust_nat_entry_set(setvec[idx], &sets,
29968c2ecf20Sopenharmony_ci						MAX_NAT_JENTRIES(journal));
29978c2ecf20Sopenharmony_ci	}
29988c2ecf20Sopenharmony_ci
29998c2ecf20Sopenharmony_ci	/* flush dirty nats in nat entry set */
30008c2ecf20Sopenharmony_ci	list_for_each_entry_safe(set, tmp, &sets, set_list) {
30018c2ecf20Sopenharmony_ci		err = __flush_nat_entry_set(sbi, set, cpc);
30028c2ecf20Sopenharmony_ci		if (err)
30038c2ecf20Sopenharmony_ci			break;
30048c2ecf20Sopenharmony_ci	}
30058c2ecf20Sopenharmony_ci
30068c2ecf20Sopenharmony_ci	up_write(&nm_i->nat_tree_lock);
30078c2ecf20Sopenharmony_ci	/* Allow dirty nats by node block allocation in write_begin */
30088c2ecf20Sopenharmony_ci
30098c2ecf20Sopenharmony_ci	return err;
30108c2ecf20Sopenharmony_ci}
30118c2ecf20Sopenharmony_ci
30128c2ecf20Sopenharmony_cistatic int __get_nat_bitmaps(struct f2fs_sb_info *sbi)
30138c2ecf20Sopenharmony_ci{
30148c2ecf20Sopenharmony_ci	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
30158c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
30168c2ecf20Sopenharmony_ci	unsigned int nat_bits_bytes = nm_i->nat_blocks / BITS_PER_BYTE;
30178c2ecf20Sopenharmony_ci	unsigned int i;
30188c2ecf20Sopenharmony_ci	__u64 cp_ver = cur_cp_version(ckpt);
30198c2ecf20Sopenharmony_ci	block_t nat_bits_addr;
30208c2ecf20Sopenharmony_ci
30218c2ecf20Sopenharmony_ci	if (!enabled_nat_bits(sbi, NULL))
30228c2ecf20Sopenharmony_ci		return 0;
30238c2ecf20Sopenharmony_ci
30248c2ecf20Sopenharmony_ci	nm_i->nat_bits_blocks = F2FS_BLK_ALIGN((nat_bits_bytes << 1) + 8);
30258c2ecf20Sopenharmony_ci	nm_i->nat_bits = f2fs_kvzalloc(sbi,
30268c2ecf20Sopenharmony_ci			nm_i->nat_bits_blocks << F2FS_BLKSIZE_BITS, GFP_KERNEL);
30278c2ecf20Sopenharmony_ci	if (!nm_i->nat_bits)
30288c2ecf20Sopenharmony_ci		return -ENOMEM;
30298c2ecf20Sopenharmony_ci
30308c2ecf20Sopenharmony_ci	nat_bits_addr = __start_cp_addr(sbi) + sbi->blocks_per_seg -
30318c2ecf20Sopenharmony_ci						nm_i->nat_bits_blocks;
30328c2ecf20Sopenharmony_ci	for (i = 0; i < nm_i->nat_bits_blocks; i++) {
30338c2ecf20Sopenharmony_ci		struct page *page;
30348c2ecf20Sopenharmony_ci
30358c2ecf20Sopenharmony_ci		page = f2fs_get_meta_page(sbi, nat_bits_addr++);
30368c2ecf20Sopenharmony_ci		if (IS_ERR(page))
30378c2ecf20Sopenharmony_ci			return PTR_ERR(page);
30388c2ecf20Sopenharmony_ci
30398c2ecf20Sopenharmony_ci		memcpy(nm_i->nat_bits + (i << F2FS_BLKSIZE_BITS),
30408c2ecf20Sopenharmony_ci					page_address(page), F2FS_BLKSIZE);
30418c2ecf20Sopenharmony_ci		f2fs_put_page(page, 1);
30428c2ecf20Sopenharmony_ci	}
30438c2ecf20Sopenharmony_ci
30448c2ecf20Sopenharmony_ci	cp_ver |= (cur_cp_crc(ckpt) << 32);
30458c2ecf20Sopenharmony_ci	if (cpu_to_le64(cp_ver) != *(__le64 *)nm_i->nat_bits) {
30468c2ecf20Sopenharmony_ci		disable_nat_bits(sbi, true);
30478c2ecf20Sopenharmony_ci		return 0;
30488c2ecf20Sopenharmony_ci	}
30498c2ecf20Sopenharmony_ci
30508c2ecf20Sopenharmony_ci	nm_i->full_nat_bits = nm_i->nat_bits + 8;
30518c2ecf20Sopenharmony_ci	nm_i->empty_nat_bits = nm_i->full_nat_bits + nat_bits_bytes;
30528c2ecf20Sopenharmony_ci
30538c2ecf20Sopenharmony_ci	f2fs_notice(sbi, "Found nat_bits in checkpoint");
30548c2ecf20Sopenharmony_ci	return 0;
30558c2ecf20Sopenharmony_ci}
30568c2ecf20Sopenharmony_ci
30578c2ecf20Sopenharmony_cistatic inline void load_free_nid_bitmap(struct f2fs_sb_info *sbi)
30588c2ecf20Sopenharmony_ci{
30598c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
30608c2ecf20Sopenharmony_ci	unsigned int i = 0;
30618c2ecf20Sopenharmony_ci	nid_t nid, last_nid;
30628c2ecf20Sopenharmony_ci
30638c2ecf20Sopenharmony_ci	if (!enabled_nat_bits(sbi, NULL))
30648c2ecf20Sopenharmony_ci		return;
30658c2ecf20Sopenharmony_ci
30668c2ecf20Sopenharmony_ci	for (i = 0; i < nm_i->nat_blocks; i++) {
30678c2ecf20Sopenharmony_ci		i = find_next_bit_le(nm_i->empty_nat_bits, nm_i->nat_blocks, i);
30688c2ecf20Sopenharmony_ci		if (i >= nm_i->nat_blocks)
30698c2ecf20Sopenharmony_ci			break;
30708c2ecf20Sopenharmony_ci
30718c2ecf20Sopenharmony_ci		__set_bit_le(i, nm_i->nat_block_bitmap);
30728c2ecf20Sopenharmony_ci
30738c2ecf20Sopenharmony_ci		nid = i * NAT_ENTRY_PER_BLOCK;
30748c2ecf20Sopenharmony_ci		last_nid = nid + NAT_ENTRY_PER_BLOCK;
30758c2ecf20Sopenharmony_ci
30768c2ecf20Sopenharmony_ci		spin_lock(&NM_I(sbi)->nid_list_lock);
30778c2ecf20Sopenharmony_ci		for (; nid < last_nid; nid++)
30788c2ecf20Sopenharmony_ci			update_free_nid_bitmap(sbi, nid, true, true);
30798c2ecf20Sopenharmony_ci		spin_unlock(&NM_I(sbi)->nid_list_lock);
30808c2ecf20Sopenharmony_ci	}
30818c2ecf20Sopenharmony_ci
30828c2ecf20Sopenharmony_ci	for (i = 0; i < nm_i->nat_blocks; i++) {
30838c2ecf20Sopenharmony_ci		i = find_next_bit_le(nm_i->full_nat_bits, nm_i->nat_blocks, i);
30848c2ecf20Sopenharmony_ci		if (i >= nm_i->nat_blocks)
30858c2ecf20Sopenharmony_ci			break;
30868c2ecf20Sopenharmony_ci
30878c2ecf20Sopenharmony_ci		__set_bit_le(i, nm_i->nat_block_bitmap);
30888c2ecf20Sopenharmony_ci	}
30898c2ecf20Sopenharmony_ci}
30908c2ecf20Sopenharmony_ci
30918c2ecf20Sopenharmony_cistatic int init_node_manager(struct f2fs_sb_info *sbi)
30928c2ecf20Sopenharmony_ci{
30938c2ecf20Sopenharmony_ci	struct f2fs_super_block *sb_raw = F2FS_RAW_SUPER(sbi);
30948c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
30958c2ecf20Sopenharmony_ci	unsigned char *version_bitmap;
30968c2ecf20Sopenharmony_ci	unsigned int nat_segs;
30978c2ecf20Sopenharmony_ci	int err;
30988c2ecf20Sopenharmony_ci
30998c2ecf20Sopenharmony_ci	nm_i->nat_blkaddr = le32_to_cpu(sb_raw->nat_blkaddr);
31008c2ecf20Sopenharmony_ci
31018c2ecf20Sopenharmony_ci	/* segment_count_nat includes pair segment so divide to 2. */
31028c2ecf20Sopenharmony_ci	nat_segs = le32_to_cpu(sb_raw->segment_count_nat) >> 1;
31038c2ecf20Sopenharmony_ci	nm_i->nat_blocks = nat_segs << le32_to_cpu(sb_raw->log_blocks_per_seg);
31048c2ecf20Sopenharmony_ci	nm_i->max_nid = NAT_ENTRY_PER_BLOCK * nm_i->nat_blocks;
31058c2ecf20Sopenharmony_ci
31068c2ecf20Sopenharmony_ci	/* not used nids: 0, node, meta, (and root counted as valid node) */
31078c2ecf20Sopenharmony_ci	nm_i->available_nids = nm_i->max_nid - sbi->total_valid_node_count -
31088c2ecf20Sopenharmony_ci						F2FS_RESERVED_NODE_NUM;
31098c2ecf20Sopenharmony_ci	nm_i->nid_cnt[FREE_NID] = 0;
31108c2ecf20Sopenharmony_ci	nm_i->nid_cnt[PREALLOC_NID] = 0;
31118c2ecf20Sopenharmony_ci	nm_i->ram_thresh = DEF_RAM_THRESHOLD;
31128c2ecf20Sopenharmony_ci	nm_i->ra_nid_pages = DEF_RA_NID_PAGES;
31138c2ecf20Sopenharmony_ci	nm_i->dirty_nats_ratio = DEF_DIRTY_NAT_RATIO_THRESHOLD;
31148c2ecf20Sopenharmony_ci
31158c2ecf20Sopenharmony_ci	INIT_RADIX_TREE(&nm_i->free_nid_root, GFP_ATOMIC);
31168c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&nm_i->free_nid_list);
31178c2ecf20Sopenharmony_ci	INIT_RADIX_TREE(&nm_i->nat_root, GFP_NOIO);
31188c2ecf20Sopenharmony_ci	INIT_RADIX_TREE(&nm_i->nat_set_root, GFP_NOIO);
31198c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&nm_i->nat_entries);
31208c2ecf20Sopenharmony_ci	spin_lock_init(&nm_i->nat_list_lock);
31218c2ecf20Sopenharmony_ci
31228c2ecf20Sopenharmony_ci	mutex_init(&nm_i->build_lock);
31238c2ecf20Sopenharmony_ci	spin_lock_init(&nm_i->nid_list_lock);
31248c2ecf20Sopenharmony_ci	init_rwsem(&nm_i->nat_tree_lock);
31258c2ecf20Sopenharmony_ci
31268c2ecf20Sopenharmony_ci	nm_i->next_scan_nid = le32_to_cpu(sbi->ckpt->next_free_nid);
31278c2ecf20Sopenharmony_ci	nm_i->bitmap_size = __bitmap_size(sbi, NAT_BITMAP);
31288c2ecf20Sopenharmony_ci	version_bitmap = __bitmap_ptr(sbi, NAT_BITMAP);
31298c2ecf20Sopenharmony_ci	nm_i->nat_bitmap = kmemdup(version_bitmap, nm_i->bitmap_size,
31308c2ecf20Sopenharmony_ci					GFP_KERNEL);
31318c2ecf20Sopenharmony_ci	if (!nm_i->nat_bitmap)
31328c2ecf20Sopenharmony_ci		return -ENOMEM;
31338c2ecf20Sopenharmony_ci
31348c2ecf20Sopenharmony_ci	err = __get_nat_bitmaps(sbi);
31358c2ecf20Sopenharmony_ci	if (err)
31368c2ecf20Sopenharmony_ci		return err;
31378c2ecf20Sopenharmony_ci
31388c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_CHECK_FS
31398c2ecf20Sopenharmony_ci	nm_i->nat_bitmap_mir = kmemdup(version_bitmap, nm_i->bitmap_size,
31408c2ecf20Sopenharmony_ci					GFP_KERNEL);
31418c2ecf20Sopenharmony_ci	if (!nm_i->nat_bitmap_mir)
31428c2ecf20Sopenharmony_ci		return -ENOMEM;
31438c2ecf20Sopenharmony_ci#endif
31448c2ecf20Sopenharmony_ci
31458c2ecf20Sopenharmony_ci	return 0;
31468c2ecf20Sopenharmony_ci}
31478c2ecf20Sopenharmony_ci
31488c2ecf20Sopenharmony_cistatic int init_free_nid_cache(struct f2fs_sb_info *sbi)
31498c2ecf20Sopenharmony_ci{
31508c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
31518c2ecf20Sopenharmony_ci	int i;
31528c2ecf20Sopenharmony_ci
31538c2ecf20Sopenharmony_ci	nm_i->free_nid_bitmap =
31548c2ecf20Sopenharmony_ci		f2fs_kvzalloc(sbi, array_size(sizeof(unsigned char *),
31558c2ecf20Sopenharmony_ci					      nm_i->nat_blocks),
31568c2ecf20Sopenharmony_ci			      GFP_KERNEL);
31578c2ecf20Sopenharmony_ci	if (!nm_i->free_nid_bitmap)
31588c2ecf20Sopenharmony_ci		return -ENOMEM;
31598c2ecf20Sopenharmony_ci
31608c2ecf20Sopenharmony_ci	for (i = 0; i < nm_i->nat_blocks; i++) {
31618c2ecf20Sopenharmony_ci		nm_i->free_nid_bitmap[i] = f2fs_kvzalloc(sbi,
31628c2ecf20Sopenharmony_ci			f2fs_bitmap_size(NAT_ENTRY_PER_BLOCK), GFP_KERNEL);
31638c2ecf20Sopenharmony_ci		if (!nm_i->free_nid_bitmap[i])
31648c2ecf20Sopenharmony_ci			return -ENOMEM;
31658c2ecf20Sopenharmony_ci	}
31668c2ecf20Sopenharmony_ci
31678c2ecf20Sopenharmony_ci	nm_i->nat_block_bitmap = f2fs_kvzalloc(sbi, nm_i->nat_blocks / 8,
31688c2ecf20Sopenharmony_ci								GFP_KERNEL);
31698c2ecf20Sopenharmony_ci	if (!nm_i->nat_block_bitmap)
31708c2ecf20Sopenharmony_ci		return -ENOMEM;
31718c2ecf20Sopenharmony_ci
31728c2ecf20Sopenharmony_ci	nm_i->free_nid_count =
31738c2ecf20Sopenharmony_ci		f2fs_kvzalloc(sbi, array_size(sizeof(unsigned short),
31748c2ecf20Sopenharmony_ci					      nm_i->nat_blocks),
31758c2ecf20Sopenharmony_ci			      GFP_KERNEL);
31768c2ecf20Sopenharmony_ci	if (!nm_i->free_nid_count)
31778c2ecf20Sopenharmony_ci		return -ENOMEM;
31788c2ecf20Sopenharmony_ci	return 0;
31798c2ecf20Sopenharmony_ci}
31808c2ecf20Sopenharmony_ci
31818c2ecf20Sopenharmony_ciint f2fs_build_node_manager(struct f2fs_sb_info *sbi)
31828c2ecf20Sopenharmony_ci{
31838c2ecf20Sopenharmony_ci	int err;
31848c2ecf20Sopenharmony_ci
31858c2ecf20Sopenharmony_ci	sbi->nm_info = f2fs_kzalloc(sbi, sizeof(struct f2fs_nm_info),
31868c2ecf20Sopenharmony_ci							GFP_KERNEL);
31878c2ecf20Sopenharmony_ci	if (!sbi->nm_info)
31888c2ecf20Sopenharmony_ci		return -ENOMEM;
31898c2ecf20Sopenharmony_ci
31908c2ecf20Sopenharmony_ci	err = init_node_manager(sbi);
31918c2ecf20Sopenharmony_ci	if (err)
31928c2ecf20Sopenharmony_ci		return err;
31938c2ecf20Sopenharmony_ci
31948c2ecf20Sopenharmony_ci	err = init_free_nid_cache(sbi);
31958c2ecf20Sopenharmony_ci	if (err)
31968c2ecf20Sopenharmony_ci		return err;
31978c2ecf20Sopenharmony_ci
31988c2ecf20Sopenharmony_ci	/* load free nid status from nat_bits table */
31998c2ecf20Sopenharmony_ci	load_free_nid_bitmap(sbi);
32008c2ecf20Sopenharmony_ci
32018c2ecf20Sopenharmony_ci	return f2fs_build_free_nids(sbi, true, true);
32028c2ecf20Sopenharmony_ci}
32038c2ecf20Sopenharmony_ci
32048c2ecf20Sopenharmony_civoid f2fs_destroy_node_manager(struct f2fs_sb_info *sbi)
32058c2ecf20Sopenharmony_ci{
32068c2ecf20Sopenharmony_ci	struct f2fs_nm_info *nm_i = NM_I(sbi);
32078c2ecf20Sopenharmony_ci	struct free_nid *i, *next_i;
32088c2ecf20Sopenharmony_ci	struct nat_entry *natvec[NATVEC_SIZE];
32098c2ecf20Sopenharmony_ci	struct nat_entry_set *setvec[SETVEC_SIZE];
32108c2ecf20Sopenharmony_ci	nid_t nid = 0;
32118c2ecf20Sopenharmony_ci	unsigned int found;
32128c2ecf20Sopenharmony_ci
32138c2ecf20Sopenharmony_ci	if (!nm_i)
32148c2ecf20Sopenharmony_ci		return;
32158c2ecf20Sopenharmony_ci
32168c2ecf20Sopenharmony_ci	/* destroy free nid list */
32178c2ecf20Sopenharmony_ci	spin_lock(&nm_i->nid_list_lock);
32188c2ecf20Sopenharmony_ci	list_for_each_entry_safe(i, next_i, &nm_i->free_nid_list, list) {
32198c2ecf20Sopenharmony_ci		__remove_free_nid(sbi, i, FREE_NID);
32208c2ecf20Sopenharmony_ci		spin_unlock(&nm_i->nid_list_lock);
32218c2ecf20Sopenharmony_ci		kmem_cache_free(free_nid_slab, i);
32228c2ecf20Sopenharmony_ci		spin_lock(&nm_i->nid_list_lock);
32238c2ecf20Sopenharmony_ci	}
32248c2ecf20Sopenharmony_ci	f2fs_bug_on(sbi, nm_i->nid_cnt[FREE_NID]);
32258c2ecf20Sopenharmony_ci	f2fs_bug_on(sbi, nm_i->nid_cnt[PREALLOC_NID]);
32268c2ecf20Sopenharmony_ci	f2fs_bug_on(sbi, !list_empty(&nm_i->free_nid_list));
32278c2ecf20Sopenharmony_ci	spin_unlock(&nm_i->nid_list_lock);
32288c2ecf20Sopenharmony_ci
32298c2ecf20Sopenharmony_ci	/* destroy nat cache */
32308c2ecf20Sopenharmony_ci	down_write(&nm_i->nat_tree_lock);
32318c2ecf20Sopenharmony_ci	while ((found = __gang_lookup_nat_cache(nm_i,
32328c2ecf20Sopenharmony_ci					nid, NATVEC_SIZE, natvec))) {
32338c2ecf20Sopenharmony_ci		unsigned idx;
32348c2ecf20Sopenharmony_ci
32358c2ecf20Sopenharmony_ci		nid = nat_get_nid(natvec[found - 1]) + 1;
32368c2ecf20Sopenharmony_ci		for (idx = 0; idx < found; idx++) {
32378c2ecf20Sopenharmony_ci			spin_lock(&nm_i->nat_list_lock);
32388c2ecf20Sopenharmony_ci			list_del(&natvec[idx]->list);
32398c2ecf20Sopenharmony_ci			spin_unlock(&nm_i->nat_list_lock);
32408c2ecf20Sopenharmony_ci
32418c2ecf20Sopenharmony_ci			__del_from_nat_cache(nm_i, natvec[idx]);
32428c2ecf20Sopenharmony_ci		}
32438c2ecf20Sopenharmony_ci	}
32448c2ecf20Sopenharmony_ci	f2fs_bug_on(sbi, nm_i->nat_cnt[TOTAL_NAT]);
32458c2ecf20Sopenharmony_ci
32468c2ecf20Sopenharmony_ci	/* destroy nat set cache */
32478c2ecf20Sopenharmony_ci	nid = 0;
32488c2ecf20Sopenharmony_ci	while ((found = __gang_lookup_nat_set(nm_i,
32498c2ecf20Sopenharmony_ci					nid, SETVEC_SIZE, setvec))) {
32508c2ecf20Sopenharmony_ci		unsigned idx;
32518c2ecf20Sopenharmony_ci
32528c2ecf20Sopenharmony_ci		nid = setvec[found - 1]->set + 1;
32538c2ecf20Sopenharmony_ci		for (idx = 0; idx < found; idx++) {
32548c2ecf20Sopenharmony_ci			/* entry_cnt is not zero, when cp_error was occurred */
32558c2ecf20Sopenharmony_ci			f2fs_bug_on(sbi, !list_empty(&setvec[idx]->entry_list));
32568c2ecf20Sopenharmony_ci			radix_tree_delete(&nm_i->nat_set_root, setvec[idx]->set);
32578c2ecf20Sopenharmony_ci			kmem_cache_free(nat_entry_set_slab, setvec[idx]);
32588c2ecf20Sopenharmony_ci		}
32598c2ecf20Sopenharmony_ci	}
32608c2ecf20Sopenharmony_ci	up_write(&nm_i->nat_tree_lock);
32618c2ecf20Sopenharmony_ci
32628c2ecf20Sopenharmony_ci	kvfree(nm_i->nat_block_bitmap);
32638c2ecf20Sopenharmony_ci	if (nm_i->free_nid_bitmap) {
32648c2ecf20Sopenharmony_ci		int i;
32658c2ecf20Sopenharmony_ci
32668c2ecf20Sopenharmony_ci		for (i = 0; i < nm_i->nat_blocks; i++)
32678c2ecf20Sopenharmony_ci			kvfree(nm_i->free_nid_bitmap[i]);
32688c2ecf20Sopenharmony_ci		kvfree(nm_i->free_nid_bitmap);
32698c2ecf20Sopenharmony_ci	}
32708c2ecf20Sopenharmony_ci	kvfree(nm_i->free_nid_count);
32718c2ecf20Sopenharmony_ci
32728c2ecf20Sopenharmony_ci	kvfree(nm_i->nat_bitmap);
32738c2ecf20Sopenharmony_ci	kvfree(nm_i->nat_bits);
32748c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_CHECK_FS
32758c2ecf20Sopenharmony_ci	kvfree(nm_i->nat_bitmap_mir);
32768c2ecf20Sopenharmony_ci#endif
32778c2ecf20Sopenharmony_ci	sbi->nm_info = NULL;
32788c2ecf20Sopenharmony_ci	kfree(nm_i);
32798c2ecf20Sopenharmony_ci}
32808c2ecf20Sopenharmony_ci
32818c2ecf20Sopenharmony_ciint __init f2fs_create_node_manager_caches(void)
32828c2ecf20Sopenharmony_ci{
32838c2ecf20Sopenharmony_ci	nat_entry_slab = f2fs_kmem_cache_create("f2fs_nat_entry",
32848c2ecf20Sopenharmony_ci			sizeof(struct nat_entry));
32858c2ecf20Sopenharmony_ci	if (!nat_entry_slab)
32868c2ecf20Sopenharmony_ci		goto fail;
32878c2ecf20Sopenharmony_ci
32888c2ecf20Sopenharmony_ci	free_nid_slab = f2fs_kmem_cache_create("f2fs_free_nid",
32898c2ecf20Sopenharmony_ci			sizeof(struct free_nid));
32908c2ecf20Sopenharmony_ci	if (!free_nid_slab)
32918c2ecf20Sopenharmony_ci		goto destroy_nat_entry;
32928c2ecf20Sopenharmony_ci
32938c2ecf20Sopenharmony_ci	nat_entry_set_slab = f2fs_kmem_cache_create("f2fs_nat_entry_set",
32948c2ecf20Sopenharmony_ci			sizeof(struct nat_entry_set));
32958c2ecf20Sopenharmony_ci	if (!nat_entry_set_slab)
32968c2ecf20Sopenharmony_ci		goto destroy_free_nid;
32978c2ecf20Sopenharmony_ci
32988c2ecf20Sopenharmony_ci	fsync_node_entry_slab = f2fs_kmem_cache_create("f2fs_fsync_node_entry",
32998c2ecf20Sopenharmony_ci			sizeof(struct fsync_node_entry));
33008c2ecf20Sopenharmony_ci	if (!fsync_node_entry_slab)
33018c2ecf20Sopenharmony_ci		goto destroy_nat_entry_set;
33028c2ecf20Sopenharmony_ci	return 0;
33038c2ecf20Sopenharmony_ci
33048c2ecf20Sopenharmony_cidestroy_nat_entry_set:
33058c2ecf20Sopenharmony_ci	kmem_cache_destroy(nat_entry_set_slab);
33068c2ecf20Sopenharmony_cidestroy_free_nid:
33078c2ecf20Sopenharmony_ci	kmem_cache_destroy(free_nid_slab);
33088c2ecf20Sopenharmony_cidestroy_nat_entry:
33098c2ecf20Sopenharmony_ci	kmem_cache_destroy(nat_entry_slab);
33108c2ecf20Sopenharmony_cifail:
33118c2ecf20Sopenharmony_ci	return -ENOMEM;
33128c2ecf20Sopenharmony_ci}
33138c2ecf20Sopenharmony_ci
33148c2ecf20Sopenharmony_civoid f2fs_destroy_node_manager_caches(void)
33158c2ecf20Sopenharmony_ci{
33168c2ecf20Sopenharmony_ci	kmem_cache_destroy(fsync_node_entry_slab);
33178c2ecf20Sopenharmony_ci	kmem_cache_destroy(nat_entry_set_slab);
33188c2ecf20Sopenharmony_ci	kmem_cache_destroy(free_nid_slab);
33198c2ecf20Sopenharmony_ci	kmem_cache_destroy(nat_entry_slab);
33208c2ecf20Sopenharmony_ci}
3321