18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * f2fs extent cache support
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2015 Motorola Mobility
68c2ecf20Sopenharmony_ci * Copyright (c) 2015 Samsung Electronics
78c2ecf20Sopenharmony_ci * Authors: Jaegeuk Kim <jaegeuk@kernel.org>
88c2ecf20Sopenharmony_ci *          Chao Yu <chao2.yu@samsung.com>
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/fs.h>
128c2ecf20Sopenharmony_ci#include <linux/f2fs_fs.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include "f2fs.h"
158c2ecf20Sopenharmony_ci#include "node.h"
168c2ecf20Sopenharmony_ci#include <trace/events/f2fs.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_cistatic struct rb_entry *__lookup_rb_tree_fast(struct rb_entry *cached_re,
198c2ecf20Sopenharmony_ci							unsigned int ofs)
208c2ecf20Sopenharmony_ci{
218c2ecf20Sopenharmony_ci	if (cached_re) {
228c2ecf20Sopenharmony_ci		if (cached_re->ofs <= ofs &&
238c2ecf20Sopenharmony_ci				cached_re->ofs + cached_re->len > ofs) {
248c2ecf20Sopenharmony_ci			return cached_re;
258c2ecf20Sopenharmony_ci		}
268c2ecf20Sopenharmony_ci	}
278c2ecf20Sopenharmony_ci	return NULL;
288c2ecf20Sopenharmony_ci}
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_cistatic struct rb_entry *__lookup_rb_tree_slow(struct rb_root_cached *root,
318c2ecf20Sopenharmony_ci							unsigned int ofs)
328c2ecf20Sopenharmony_ci{
338c2ecf20Sopenharmony_ci	struct rb_node *node = root->rb_root.rb_node;
348c2ecf20Sopenharmony_ci	struct rb_entry *re;
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	while (node) {
378c2ecf20Sopenharmony_ci		re = rb_entry(node, struct rb_entry, rb_node);
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci		if (ofs < re->ofs)
408c2ecf20Sopenharmony_ci			node = node->rb_left;
418c2ecf20Sopenharmony_ci		else if (ofs >= re->ofs + re->len)
428c2ecf20Sopenharmony_ci			node = node->rb_right;
438c2ecf20Sopenharmony_ci		else
448c2ecf20Sopenharmony_ci			return re;
458c2ecf20Sopenharmony_ci	}
468c2ecf20Sopenharmony_ci	return NULL;
478c2ecf20Sopenharmony_ci}
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_cistruct rb_entry *f2fs_lookup_rb_tree(struct rb_root_cached *root,
508c2ecf20Sopenharmony_ci				struct rb_entry *cached_re, unsigned int ofs)
518c2ecf20Sopenharmony_ci{
528c2ecf20Sopenharmony_ci	struct rb_entry *re;
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	re = __lookup_rb_tree_fast(cached_re, ofs);
558c2ecf20Sopenharmony_ci	if (!re)
568c2ecf20Sopenharmony_ci		return __lookup_rb_tree_slow(root, ofs);
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	return re;
598c2ecf20Sopenharmony_ci}
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_cistruct rb_node **f2fs_lookup_rb_tree_ext(struct f2fs_sb_info *sbi,
628c2ecf20Sopenharmony_ci					struct rb_root_cached *root,
638c2ecf20Sopenharmony_ci					struct rb_node **parent,
648c2ecf20Sopenharmony_ci					unsigned long long key, bool *leftmost)
658c2ecf20Sopenharmony_ci{
668c2ecf20Sopenharmony_ci	struct rb_node **p = &root->rb_root.rb_node;
678c2ecf20Sopenharmony_ci	struct rb_entry *re;
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	while (*p) {
708c2ecf20Sopenharmony_ci		*parent = *p;
718c2ecf20Sopenharmony_ci		re = rb_entry(*parent, struct rb_entry, rb_node);
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci		if (key < re->key) {
748c2ecf20Sopenharmony_ci			p = &(*p)->rb_left;
758c2ecf20Sopenharmony_ci		} else {
768c2ecf20Sopenharmony_ci			p = &(*p)->rb_right;
778c2ecf20Sopenharmony_ci			*leftmost = false;
788c2ecf20Sopenharmony_ci		}
798c2ecf20Sopenharmony_ci	}
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	return p;
828c2ecf20Sopenharmony_ci}
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_cistruct rb_node **f2fs_lookup_rb_tree_for_insert(struct f2fs_sb_info *sbi,
858c2ecf20Sopenharmony_ci				struct rb_root_cached *root,
868c2ecf20Sopenharmony_ci				struct rb_node **parent,
878c2ecf20Sopenharmony_ci				unsigned int ofs, bool *leftmost)
888c2ecf20Sopenharmony_ci{
898c2ecf20Sopenharmony_ci	struct rb_node **p = &root->rb_root.rb_node;
908c2ecf20Sopenharmony_ci	struct rb_entry *re;
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	while (*p) {
938c2ecf20Sopenharmony_ci		*parent = *p;
948c2ecf20Sopenharmony_ci		re = rb_entry(*parent, struct rb_entry, rb_node);
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci		if (ofs < re->ofs) {
978c2ecf20Sopenharmony_ci			p = &(*p)->rb_left;
988c2ecf20Sopenharmony_ci		} else if (ofs >= re->ofs + re->len) {
998c2ecf20Sopenharmony_ci			p = &(*p)->rb_right;
1008c2ecf20Sopenharmony_ci			*leftmost = false;
1018c2ecf20Sopenharmony_ci		} else {
1028c2ecf20Sopenharmony_ci			f2fs_bug_on(sbi, 1);
1038c2ecf20Sopenharmony_ci		}
1048c2ecf20Sopenharmony_ci	}
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci	return p;
1078c2ecf20Sopenharmony_ci}
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci/*
1108c2ecf20Sopenharmony_ci * lookup rb entry in position of @ofs in rb-tree,
1118c2ecf20Sopenharmony_ci * if hit, return the entry, otherwise, return NULL
1128c2ecf20Sopenharmony_ci * @prev_ex: extent before ofs
1138c2ecf20Sopenharmony_ci * @next_ex: extent after ofs
1148c2ecf20Sopenharmony_ci * @insert_p: insert point for new extent at ofs
1158c2ecf20Sopenharmony_ci * in order to simpfy the insertion after.
1168c2ecf20Sopenharmony_ci * tree must stay unchanged between lookup and insertion.
1178c2ecf20Sopenharmony_ci */
1188c2ecf20Sopenharmony_cistruct rb_entry *f2fs_lookup_rb_tree_ret(struct rb_root_cached *root,
1198c2ecf20Sopenharmony_ci				struct rb_entry *cached_re,
1208c2ecf20Sopenharmony_ci				unsigned int ofs,
1218c2ecf20Sopenharmony_ci				struct rb_entry **prev_entry,
1228c2ecf20Sopenharmony_ci				struct rb_entry **next_entry,
1238c2ecf20Sopenharmony_ci				struct rb_node ***insert_p,
1248c2ecf20Sopenharmony_ci				struct rb_node **insert_parent,
1258c2ecf20Sopenharmony_ci				bool force, bool *leftmost)
1268c2ecf20Sopenharmony_ci{
1278c2ecf20Sopenharmony_ci	struct rb_node **pnode = &root->rb_root.rb_node;
1288c2ecf20Sopenharmony_ci	struct rb_node *parent = NULL, *tmp_node;
1298c2ecf20Sopenharmony_ci	struct rb_entry *re = cached_re;
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	*insert_p = NULL;
1328c2ecf20Sopenharmony_ci	*insert_parent = NULL;
1338c2ecf20Sopenharmony_ci	*prev_entry = NULL;
1348c2ecf20Sopenharmony_ci	*next_entry = NULL;
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci	if (RB_EMPTY_ROOT(&root->rb_root))
1378c2ecf20Sopenharmony_ci		return NULL;
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	if (re) {
1408c2ecf20Sopenharmony_ci		if (re->ofs <= ofs && re->ofs + re->len > ofs)
1418c2ecf20Sopenharmony_ci			goto lookup_neighbors;
1428c2ecf20Sopenharmony_ci	}
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	if (leftmost)
1458c2ecf20Sopenharmony_ci		*leftmost = true;
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	while (*pnode) {
1488c2ecf20Sopenharmony_ci		parent = *pnode;
1498c2ecf20Sopenharmony_ci		re = rb_entry(*pnode, struct rb_entry, rb_node);
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci		if (ofs < re->ofs) {
1528c2ecf20Sopenharmony_ci			pnode = &(*pnode)->rb_left;
1538c2ecf20Sopenharmony_ci		} else if (ofs >= re->ofs + re->len) {
1548c2ecf20Sopenharmony_ci			pnode = &(*pnode)->rb_right;
1558c2ecf20Sopenharmony_ci			if (leftmost)
1568c2ecf20Sopenharmony_ci				*leftmost = false;
1578c2ecf20Sopenharmony_ci		} else {
1588c2ecf20Sopenharmony_ci			goto lookup_neighbors;
1598c2ecf20Sopenharmony_ci		}
1608c2ecf20Sopenharmony_ci	}
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	*insert_p = pnode;
1638c2ecf20Sopenharmony_ci	*insert_parent = parent;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	re = rb_entry(parent, struct rb_entry, rb_node);
1668c2ecf20Sopenharmony_ci	tmp_node = parent;
1678c2ecf20Sopenharmony_ci	if (parent && ofs > re->ofs)
1688c2ecf20Sopenharmony_ci		tmp_node = rb_next(parent);
1698c2ecf20Sopenharmony_ci	*next_entry = rb_entry_safe(tmp_node, struct rb_entry, rb_node);
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	tmp_node = parent;
1728c2ecf20Sopenharmony_ci	if (parent && ofs < re->ofs)
1738c2ecf20Sopenharmony_ci		tmp_node = rb_prev(parent);
1748c2ecf20Sopenharmony_ci	*prev_entry = rb_entry_safe(tmp_node, struct rb_entry, rb_node);
1758c2ecf20Sopenharmony_ci	return NULL;
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_cilookup_neighbors:
1788c2ecf20Sopenharmony_ci	if (ofs == re->ofs || force) {
1798c2ecf20Sopenharmony_ci		/* lookup prev node for merging backward later */
1808c2ecf20Sopenharmony_ci		tmp_node = rb_prev(&re->rb_node);
1818c2ecf20Sopenharmony_ci		*prev_entry = rb_entry_safe(tmp_node, struct rb_entry, rb_node);
1828c2ecf20Sopenharmony_ci	}
1838c2ecf20Sopenharmony_ci	if (ofs == re->ofs + re->len - 1 || force) {
1848c2ecf20Sopenharmony_ci		/* lookup next node for merging frontward later */
1858c2ecf20Sopenharmony_ci		tmp_node = rb_next(&re->rb_node);
1868c2ecf20Sopenharmony_ci		*next_entry = rb_entry_safe(tmp_node, struct rb_entry, rb_node);
1878c2ecf20Sopenharmony_ci	}
1888c2ecf20Sopenharmony_ci	return re;
1898c2ecf20Sopenharmony_ci}
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_cibool f2fs_check_rb_tree_consistence(struct f2fs_sb_info *sbi,
1928c2ecf20Sopenharmony_ci				struct rb_root_cached *root, bool check_key)
1938c2ecf20Sopenharmony_ci{
1948c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_CHECK_FS
1958c2ecf20Sopenharmony_ci	struct rb_node *cur = rb_first_cached(root), *next;
1968c2ecf20Sopenharmony_ci	struct rb_entry *cur_re, *next_re;
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	if (!cur)
1998c2ecf20Sopenharmony_ci		return true;
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	while (cur) {
2028c2ecf20Sopenharmony_ci		next = rb_next(cur);
2038c2ecf20Sopenharmony_ci		if (!next)
2048c2ecf20Sopenharmony_ci			return true;
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci		cur_re = rb_entry(cur, struct rb_entry, rb_node);
2078c2ecf20Sopenharmony_ci		next_re = rb_entry(next, struct rb_entry, rb_node);
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci		if (check_key) {
2108c2ecf20Sopenharmony_ci			if (cur_re->key > next_re->key) {
2118c2ecf20Sopenharmony_ci				f2fs_info(sbi, "inconsistent rbtree, "
2128c2ecf20Sopenharmony_ci					"cur(%llu) next(%llu)",
2138c2ecf20Sopenharmony_ci					cur_re->key, next_re->key);
2148c2ecf20Sopenharmony_ci				return false;
2158c2ecf20Sopenharmony_ci			}
2168c2ecf20Sopenharmony_ci			goto next;
2178c2ecf20Sopenharmony_ci		}
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci		if (cur_re->ofs + cur_re->len > next_re->ofs) {
2208c2ecf20Sopenharmony_ci			f2fs_info(sbi, "inconsistent rbtree, cur(%u, %u) next(%u, %u)",
2218c2ecf20Sopenharmony_ci				  cur_re->ofs, cur_re->len,
2228c2ecf20Sopenharmony_ci				  next_re->ofs, next_re->len);
2238c2ecf20Sopenharmony_ci			return false;
2248c2ecf20Sopenharmony_ci		}
2258c2ecf20Sopenharmony_cinext:
2268c2ecf20Sopenharmony_ci		cur = next;
2278c2ecf20Sopenharmony_ci	}
2288c2ecf20Sopenharmony_ci#endif
2298c2ecf20Sopenharmony_ci	return true;
2308c2ecf20Sopenharmony_ci}
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_cistatic struct kmem_cache *extent_tree_slab;
2338c2ecf20Sopenharmony_cistatic struct kmem_cache *extent_node_slab;
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_cistatic struct extent_node *__attach_extent_node(struct f2fs_sb_info *sbi,
2368c2ecf20Sopenharmony_ci				struct extent_tree *et, struct extent_info *ei,
2378c2ecf20Sopenharmony_ci				struct rb_node *parent, struct rb_node **p,
2388c2ecf20Sopenharmony_ci				bool leftmost)
2398c2ecf20Sopenharmony_ci{
2408c2ecf20Sopenharmony_ci	struct extent_node *en;
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	en = kmem_cache_alloc(extent_node_slab, GFP_ATOMIC);
2438c2ecf20Sopenharmony_ci	if (!en)
2448c2ecf20Sopenharmony_ci		return NULL;
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci	en->ei = *ei;
2478c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&en->list);
2488c2ecf20Sopenharmony_ci	en->et = et;
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	rb_link_node(&en->rb_node, parent, p);
2518c2ecf20Sopenharmony_ci	rb_insert_color_cached(&en->rb_node, &et->root, leftmost);
2528c2ecf20Sopenharmony_ci	atomic_inc(&et->node_cnt);
2538c2ecf20Sopenharmony_ci	atomic_inc(&sbi->total_ext_node);
2548c2ecf20Sopenharmony_ci	return en;
2558c2ecf20Sopenharmony_ci}
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_cistatic void __detach_extent_node(struct f2fs_sb_info *sbi,
2588c2ecf20Sopenharmony_ci				struct extent_tree *et, struct extent_node *en)
2598c2ecf20Sopenharmony_ci{
2608c2ecf20Sopenharmony_ci	rb_erase_cached(&en->rb_node, &et->root);
2618c2ecf20Sopenharmony_ci	atomic_dec(&et->node_cnt);
2628c2ecf20Sopenharmony_ci	atomic_dec(&sbi->total_ext_node);
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	if (et->cached_en == en)
2658c2ecf20Sopenharmony_ci		et->cached_en = NULL;
2668c2ecf20Sopenharmony_ci	kmem_cache_free(extent_node_slab, en);
2678c2ecf20Sopenharmony_ci}
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci/*
2708c2ecf20Sopenharmony_ci * Flow to release an extent_node:
2718c2ecf20Sopenharmony_ci * 1. list_del_init
2728c2ecf20Sopenharmony_ci * 2. __detach_extent_node
2738c2ecf20Sopenharmony_ci * 3. kmem_cache_free.
2748c2ecf20Sopenharmony_ci */
2758c2ecf20Sopenharmony_cistatic void __release_extent_node(struct f2fs_sb_info *sbi,
2768c2ecf20Sopenharmony_ci			struct extent_tree *et, struct extent_node *en)
2778c2ecf20Sopenharmony_ci{
2788c2ecf20Sopenharmony_ci	spin_lock(&sbi->extent_lock);
2798c2ecf20Sopenharmony_ci	f2fs_bug_on(sbi, list_empty(&en->list));
2808c2ecf20Sopenharmony_ci	list_del_init(&en->list);
2818c2ecf20Sopenharmony_ci	spin_unlock(&sbi->extent_lock);
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci	__detach_extent_node(sbi, et, en);
2848c2ecf20Sopenharmony_ci}
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_cistatic struct extent_tree *__grab_extent_tree(struct inode *inode)
2878c2ecf20Sopenharmony_ci{
2888c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
2898c2ecf20Sopenharmony_ci	struct extent_tree *et;
2908c2ecf20Sopenharmony_ci	nid_t ino = inode->i_ino;
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	mutex_lock(&sbi->extent_tree_lock);
2938c2ecf20Sopenharmony_ci	et = radix_tree_lookup(&sbi->extent_tree_root, ino);
2948c2ecf20Sopenharmony_ci	if (!et) {
2958c2ecf20Sopenharmony_ci		et = f2fs_kmem_cache_alloc(extent_tree_slab, GFP_NOFS);
2968c2ecf20Sopenharmony_ci		f2fs_radix_tree_insert(&sbi->extent_tree_root, ino, et);
2978c2ecf20Sopenharmony_ci		memset(et, 0, sizeof(struct extent_tree));
2988c2ecf20Sopenharmony_ci		et->ino = ino;
2998c2ecf20Sopenharmony_ci		et->root = RB_ROOT_CACHED;
3008c2ecf20Sopenharmony_ci		et->cached_en = NULL;
3018c2ecf20Sopenharmony_ci		rwlock_init(&et->lock);
3028c2ecf20Sopenharmony_ci		INIT_LIST_HEAD(&et->list);
3038c2ecf20Sopenharmony_ci		atomic_set(&et->node_cnt, 0);
3048c2ecf20Sopenharmony_ci		atomic_inc(&sbi->total_ext_tree);
3058c2ecf20Sopenharmony_ci	} else {
3068c2ecf20Sopenharmony_ci		atomic_dec(&sbi->total_zombie_tree);
3078c2ecf20Sopenharmony_ci		list_del_init(&et->list);
3088c2ecf20Sopenharmony_ci	}
3098c2ecf20Sopenharmony_ci	mutex_unlock(&sbi->extent_tree_lock);
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	/* never died until evict_inode */
3128c2ecf20Sopenharmony_ci	F2FS_I(inode)->extent_tree = et;
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci	return et;
3158c2ecf20Sopenharmony_ci}
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_cistatic struct extent_node *__init_extent_tree(struct f2fs_sb_info *sbi,
3188c2ecf20Sopenharmony_ci				struct extent_tree *et, struct extent_info *ei)
3198c2ecf20Sopenharmony_ci{
3208c2ecf20Sopenharmony_ci	struct rb_node **p = &et->root.rb_root.rb_node;
3218c2ecf20Sopenharmony_ci	struct extent_node *en;
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci	en = __attach_extent_node(sbi, et, ei, NULL, p, true);
3248c2ecf20Sopenharmony_ci	if (!en)
3258c2ecf20Sopenharmony_ci		return NULL;
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	et->largest = en->ei;
3288c2ecf20Sopenharmony_ci	et->cached_en = en;
3298c2ecf20Sopenharmony_ci	return en;
3308c2ecf20Sopenharmony_ci}
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_cistatic unsigned int __free_extent_tree(struct f2fs_sb_info *sbi,
3338c2ecf20Sopenharmony_ci					struct extent_tree *et)
3348c2ecf20Sopenharmony_ci{
3358c2ecf20Sopenharmony_ci	struct rb_node *node, *next;
3368c2ecf20Sopenharmony_ci	struct extent_node *en;
3378c2ecf20Sopenharmony_ci	unsigned int count = atomic_read(&et->node_cnt);
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci	node = rb_first_cached(&et->root);
3408c2ecf20Sopenharmony_ci	while (node) {
3418c2ecf20Sopenharmony_ci		next = rb_next(node);
3428c2ecf20Sopenharmony_ci		en = rb_entry(node, struct extent_node, rb_node);
3438c2ecf20Sopenharmony_ci		__release_extent_node(sbi, et, en);
3448c2ecf20Sopenharmony_ci		node = next;
3458c2ecf20Sopenharmony_ci	}
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	return count - atomic_read(&et->node_cnt);
3488c2ecf20Sopenharmony_ci}
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_cistatic void __drop_largest_extent(struct extent_tree *et,
3518c2ecf20Sopenharmony_ci					pgoff_t fofs, unsigned int len)
3528c2ecf20Sopenharmony_ci{
3538c2ecf20Sopenharmony_ci	if (fofs < et->largest.fofs + et->largest.len &&
3548c2ecf20Sopenharmony_ci			fofs + len > et->largest.fofs) {
3558c2ecf20Sopenharmony_ci		et->largest.len = 0;
3568c2ecf20Sopenharmony_ci		et->largest_updated = true;
3578c2ecf20Sopenharmony_ci	}
3588c2ecf20Sopenharmony_ci}
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci/* return true, if inode page is changed */
3618c2ecf20Sopenharmony_cistatic void __f2fs_init_extent_tree(struct inode *inode, struct page *ipage)
3628c2ecf20Sopenharmony_ci{
3638c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
3648c2ecf20Sopenharmony_ci	struct f2fs_extent *i_ext = ipage ? &F2FS_INODE(ipage)->i_ext : NULL;
3658c2ecf20Sopenharmony_ci	struct extent_tree *et;
3668c2ecf20Sopenharmony_ci	struct extent_node *en;
3678c2ecf20Sopenharmony_ci	struct extent_info ei;
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci	if (!f2fs_may_extent_tree(inode)) {
3708c2ecf20Sopenharmony_ci		/* drop largest extent */
3718c2ecf20Sopenharmony_ci		if (i_ext && i_ext->len) {
3728c2ecf20Sopenharmony_ci			f2fs_wait_on_page_writeback(ipage, NODE, true, true);
3738c2ecf20Sopenharmony_ci			i_ext->len = 0;
3748c2ecf20Sopenharmony_ci			set_page_dirty(ipage);
3758c2ecf20Sopenharmony_ci			return;
3768c2ecf20Sopenharmony_ci		}
3778c2ecf20Sopenharmony_ci		return;
3788c2ecf20Sopenharmony_ci	}
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci	et = __grab_extent_tree(inode);
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	if (!i_ext || !i_ext->len)
3838c2ecf20Sopenharmony_ci		return;
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci	get_extent_info(&ei, i_ext);
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci	write_lock(&et->lock);
3888c2ecf20Sopenharmony_ci	if (atomic_read(&et->node_cnt))
3898c2ecf20Sopenharmony_ci		goto out;
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci	en = __init_extent_tree(sbi, et, &ei);
3928c2ecf20Sopenharmony_ci	if (en) {
3938c2ecf20Sopenharmony_ci		spin_lock(&sbi->extent_lock);
3948c2ecf20Sopenharmony_ci		list_add_tail(&en->list, &sbi->extent_list);
3958c2ecf20Sopenharmony_ci		spin_unlock(&sbi->extent_lock);
3968c2ecf20Sopenharmony_ci	}
3978c2ecf20Sopenharmony_ciout:
3988c2ecf20Sopenharmony_ci	write_unlock(&et->lock);
3998c2ecf20Sopenharmony_ci}
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_civoid f2fs_init_extent_tree(struct inode *inode, struct page *ipage)
4028c2ecf20Sopenharmony_ci{
4038c2ecf20Sopenharmony_ci	__f2fs_init_extent_tree(inode, ipage);
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_ci	if (!F2FS_I(inode)->extent_tree)
4068c2ecf20Sopenharmony_ci		set_inode_flag(inode, FI_NO_EXTENT);
4078c2ecf20Sopenharmony_ci}
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_cistatic bool f2fs_lookup_extent_tree(struct inode *inode, pgoff_t pgofs,
4108c2ecf20Sopenharmony_ci							struct extent_info *ei)
4118c2ecf20Sopenharmony_ci{
4128c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
4138c2ecf20Sopenharmony_ci	struct extent_tree *et = F2FS_I(inode)->extent_tree;
4148c2ecf20Sopenharmony_ci	struct extent_node *en;
4158c2ecf20Sopenharmony_ci	bool ret = false;
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci	if (!et)
4188c2ecf20Sopenharmony_ci		return false;
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci	trace_f2fs_lookup_extent_tree_start(inode, pgofs);
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci	read_lock(&et->lock);
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci	if (et->largest.fofs <= pgofs &&
4258c2ecf20Sopenharmony_ci			et->largest.fofs + et->largest.len > pgofs) {
4268c2ecf20Sopenharmony_ci		*ei = et->largest;
4278c2ecf20Sopenharmony_ci		ret = true;
4288c2ecf20Sopenharmony_ci		stat_inc_largest_node_hit(sbi);
4298c2ecf20Sopenharmony_ci		goto out;
4308c2ecf20Sopenharmony_ci	}
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci	en = (struct extent_node *)f2fs_lookup_rb_tree(&et->root,
4338c2ecf20Sopenharmony_ci				(struct rb_entry *)et->cached_en, pgofs);
4348c2ecf20Sopenharmony_ci	if (!en)
4358c2ecf20Sopenharmony_ci		goto out;
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	if (en == et->cached_en)
4388c2ecf20Sopenharmony_ci		stat_inc_cached_node_hit(sbi);
4398c2ecf20Sopenharmony_ci	else
4408c2ecf20Sopenharmony_ci		stat_inc_rbtree_node_hit(sbi);
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ci	*ei = en->ei;
4438c2ecf20Sopenharmony_ci	spin_lock(&sbi->extent_lock);
4448c2ecf20Sopenharmony_ci	if (!list_empty(&en->list)) {
4458c2ecf20Sopenharmony_ci		list_move_tail(&en->list, &sbi->extent_list);
4468c2ecf20Sopenharmony_ci		et->cached_en = en;
4478c2ecf20Sopenharmony_ci	}
4488c2ecf20Sopenharmony_ci	spin_unlock(&sbi->extent_lock);
4498c2ecf20Sopenharmony_ci	ret = true;
4508c2ecf20Sopenharmony_ciout:
4518c2ecf20Sopenharmony_ci	stat_inc_total_hit(sbi);
4528c2ecf20Sopenharmony_ci	read_unlock(&et->lock);
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	trace_f2fs_lookup_extent_tree_end(inode, pgofs, ei);
4558c2ecf20Sopenharmony_ci	return ret;
4568c2ecf20Sopenharmony_ci}
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_cistatic struct extent_node *__try_merge_extent_node(struct f2fs_sb_info *sbi,
4598c2ecf20Sopenharmony_ci				struct extent_tree *et, struct extent_info *ei,
4608c2ecf20Sopenharmony_ci				struct extent_node *prev_ex,
4618c2ecf20Sopenharmony_ci				struct extent_node *next_ex)
4628c2ecf20Sopenharmony_ci{
4638c2ecf20Sopenharmony_ci	struct extent_node *en = NULL;
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci	if (prev_ex && __is_back_mergeable(ei, &prev_ex->ei)) {
4668c2ecf20Sopenharmony_ci		prev_ex->ei.len += ei->len;
4678c2ecf20Sopenharmony_ci		ei = &prev_ex->ei;
4688c2ecf20Sopenharmony_ci		en = prev_ex;
4698c2ecf20Sopenharmony_ci	}
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	if (next_ex && __is_front_mergeable(ei, &next_ex->ei)) {
4728c2ecf20Sopenharmony_ci		next_ex->ei.fofs = ei->fofs;
4738c2ecf20Sopenharmony_ci		next_ex->ei.blk = ei->blk;
4748c2ecf20Sopenharmony_ci		next_ex->ei.len += ei->len;
4758c2ecf20Sopenharmony_ci		if (en)
4768c2ecf20Sopenharmony_ci			__release_extent_node(sbi, et, prev_ex);
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci		en = next_ex;
4798c2ecf20Sopenharmony_ci	}
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ci	if (!en)
4828c2ecf20Sopenharmony_ci		return NULL;
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ci	__try_update_largest_extent(et, en);
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ci	spin_lock(&sbi->extent_lock);
4878c2ecf20Sopenharmony_ci	if (!list_empty(&en->list)) {
4888c2ecf20Sopenharmony_ci		list_move_tail(&en->list, &sbi->extent_list);
4898c2ecf20Sopenharmony_ci		et->cached_en = en;
4908c2ecf20Sopenharmony_ci	}
4918c2ecf20Sopenharmony_ci	spin_unlock(&sbi->extent_lock);
4928c2ecf20Sopenharmony_ci	return en;
4938c2ecf20Sopenharmony_ci}
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_cistatic struct extent_node *__insert_extent_tree(struct f2fs_sb_info *sbi,
4968c2ecf20Sopenharmony_ci				struct extent_tree *et, struct extent_info *ei,
4978c2ecf20Sopenharmony_ci				struct rb_node **insert_p,
4988c2ecf20Sopenharmony_ci				struct rb_node *insert_parent,
4998c2ecf20Sopenharmony_ci				bool leftmost)
5008c2ecf20Sopenharmony_ci{
5018c2ecf20Sopenharmony_ci	struct rb_node **p;
5028c2ecf20Sopenharmony_ci	struct rb_node *parent = NULL;
5038c2ecf20Sopenharmony_ci	struct extent_node *en = NULL;
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci	if (insert_p && insert_parent) {
5068c2ecf20Sopenharmony_ci		parent = insert_parent;
5078c2ecf20Sopenharmony_ci		p = insert_p;
5088c2ecf20Sopenharmony_ci		goto do_insert;
5098c2ecf20Sopenharmony_ci	}
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	leftmost = true;
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ci	p = f2fs_lookup_rb_tree_for_insert(sbi, &et->root, &parent,
5148c2ecf20Sopenharmony_ci						ei->fofs, &leftmost);
5158c2ecf20Sopenharmony_cido_insert:
5168c2ecf20Sopenharmony_ci	en = __attach_extent_node(sbi, et, ei, parent, p, leftmost);
5178c2ecf20Sopenharmony_ci	if (!en)
5188c2ecf20Sopenharmony_ci		return NULL;
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci	__try_update_largest_extent(et, en);
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci	/* update in global extent list */
5238c2ecf20Sopenharmony_ci	spin_lock(&sbi->extent_lock);
5248c2ecf20Sopenharmony_ci	list_add_tail(&en->list, &sbi->extent_list);
5258c2ecf20Sopenharmony_ci	et->cached_en = en;
5268c2ecf20Sopenharmony_ci	spin_unlock(&sbi->extent_lock);
5278c2ecf20Sopenharmony_ci	return en;
5288c2ecf20Sopenharmony_ci}
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_cistatic void f2fs_update_extent_tree_range(struct inode *inode,
5318c2ecf20Sopenharmony_ci				pgoff_t fofs, block_t blkaddr, unsigned int len)
5328c2ecf20Sopenharmony_ci{
5338c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
5348c2ecf20Sopenharmony_ci	struct extent_tree *et = F2FS_I(inode)->extent_tree;
5358c2ecf20Sopenharmony_ci	struct extent_node *en = NULL, *en1 = NULL;
5368c2ecf20Sopenharmony_ci	struct extent_node *prev_en = NULL, *next_en = NULL;
5378c2ecf20Sopenharmony_ci	struct extent_info ei, dei, prev;
5388c2ecf20Sopenharmony_ci	struct rb_node **insert_p = NULL, *insert_parent = NULL;
5398c2ecf20Sopenharmony_ci	unsigned int end = fofs + len;
5408c2ecf20Sopenharmony_ci	unsigned int pos = (unsigned int)fofs;
5418c2ecf20Sopenharmony_ci	bool updated = false;
5428c2ecf20Sopenharmony_ci	bool leftmost = false;
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci	if (!et)
5458c2ecf20Sopenharmony_ci		return;
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ci	trace_f2fs_update_extent_tree_range(inode, fofs, blkaddr, len);
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	write_lock(&et->lock);
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci	if (is_inode_flag_set(inode, FI_NO_EXTENT)) {
5528c2ecf20Sopenharmony_ci		write_unlock(&et->lock);
5538c2ecf20Sopenharmony_ci		return;
5548c2ecf20Sopenharmony_ci	}
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ci	prev = et->largest;
5578c2ecf20Sopenharmony_ci	dei.len = 0;
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_ci	/*
5608c2ecf20Sopenharmony_ci	 * drop largest extent before lookup, in case it's already
5618c2ecf20Sopenharmony_ci	 * been shrunk from extent tree
5628c2ecf20Sopenharmony_ci	 */
5638c2ecf20Sopenharmony_ci	__drop_largest_extent(et, fofs, len);
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci	/* 1. lookup first extent node in range [fofs, fofs + len - 1] */
5668c2ecf20Sopenharmony_ci	en = (struct extent_node *)f2fs_lookup_rb_tree_ret(&et->root,
5678c2ecf20Sopenharmony_ci					(struct rb_entry *)et->cached_en, fofs,
5688c2ecf20Sopenharmony_ci					(struct rb_entry **)&prev_en,
5698c2ecf20Sopenharmony_ci					(struct rb_entry **)&next_en,
5708c2ecf20Sopenharmony_ci					&insert_p, &insert_parent, false,
5718c2ecf20Sopenharmony_ci					&leftmost);
5728c2ecf20Sopenharmony_ci	if (!en)
5738c2ecf20Sopenharmony_ci		en = next_en;
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci	/* 2. invlidate all extent nodes in range [fofs, fofs + len - 1] */
5768c2ecf20Sopenharmony_ci	while (en && en->ei.fofs < end) {
5778c2ecf20Sopenharmony_ci		unsigned int org_end;
5788c2ecf20Sopenharmony_ci		int parts = 0;	/* # of parts current extent split into */
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_ci		next_en = en1 = NULL;
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_ci		dei = en->ei;
5838c2ecf20Sopenharmony_ci		org_end = dei.fofs + dei.len;
5848c2ecf20Sopenharmony_ci		f2fs_bug_on(sbi, pos >= org_end);
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_ci		if (pos > dei.fofs &&	pos - dei.fofs >= F2FS_MIN_EXTENT_LEN) {
5878c2ecf20Sopenharmony_ci			en->ei.len = pos - en->ei.fofs;
5888c2ecf20Sopenharmony_ci			prev_en = en;
5898c2ecf20Sopenharmony_ci			parts = 1;
5908c2ecf20Sopenharmony_ci		}
5918c2ecf20Sopenharmony_ci
5928c2ecf20Sopenharmony_ci		if (end < org_end && org_end - end >= F2FS_MIN_EXTENT_LEN) {
5938c2ecf20Sopenharmony_ci			if (parts) {
5948c2ecf20Sopenharmony_ci				set_extent_info(&ei, end,
5958c2ecf20Sopenharmony_ci						end - dei.fofs + dei.blk,
5968c2ecf20Sopenharmony_ci						org_end - end);
5978c2ecf20Sopenharmony_ci				en1 = __insert_extent_tree(sbi, et, &ei,
5988c2ecf20Sopenharmony_ci							NULL, NULL, true);
5998c2ecf20Sopenharmony_ci				next_en = en1;
6008c2ecf20Sopenharmony_ci			} else {
6018c2ecf20Sopenharmony_ci				en->ei.fofs = end;
6028c2ecf20Sopenharmony_ci				en->ei.blk += end - dei.fofs;
6038c2ecf20Sopenharmony_ci				en->ei.len -= end - dei.fofs;
6048c2ecf20Sopenharmony_ci				next_en = en;
6058c2ecf20Sopenharmony_ci			}
6068c2ecf20Sopenharmony_ci			parts++;
6078c2ecf20Sopenharmony_ci		}
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci		if (!next_en) {
6108c2ecf20Sopenharmony_ci			struct rb_node *node = rb_next(&en->rb_node);
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci			next_en = rb_entry_safe(node, struct extent_node,
6138c2ecf20Sopenharmony_ci						rb_node);
6148c2ecf20Sopenharmony_ci		}
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci		if (parts)
6178c2ecf20Sopenharmony_ci			__try_update_largest_extent(et, en);
6188c2ecf20Sopenharmony_ci		else
6198c2ecf20Sopenharmony_ci			__release_extent_node(sbi, et, en);
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci		/*
6228c2ecf20Sopenharmony_ci		 * if original extent is split into zero or two parts, extent
6238c2ecf20Sopenharmony_ci		 * tree has been altered by deletion or insertion, therefore
6248c2ecf20Sopenharmony_ci		 * invalidate pointers regard to tree.
6258c2ecf20Sopenharmony_ci		 */
6268c2ecf20Sopenharmony_ci		if (parts != 1) {
6278c2ecf20Sopenharmony_ci			insert_p = NULL;
6288c2ecf20Sopenharmony_ci			insert_parent = NULL;
6298c2ecf20Sopenharmony_ci		}
6308c2ecf20Sopenharmony_ci		en = next_en;
6318c2ecf20Sopenharmony_ci	}
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci	/* 3. update extent in extent cache */
6348c2ecf20Sopenharmony_ci	if (blkaddr) {
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_ci		set_extent_info(&ei, fofs, blkaddr, len);
6378c2ecf20Sopenharmony_ci		if (!__try_merge_extent_node(sbi, et, &ei, prev_en, next_en))
6388c2ecf20Sopenharmony_ci			__insert_extent_tree(sbi, et, &ei,
6398c2ecf20Sopenharmony_ci					insert_p, insert_parent, leftmost);
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci		/* give up extent_cache, if split and small updates happen */
6428c2ecf20Sopenharmony_ci		if (dei.len >= 1 &&
6438c2ecf20Sopenharmony_ci				prev.len < F2FS_MIN_EXTENT_LEN &&
6448c2ecf20Sopenharmony_ci				et->largest.len < F2FS_MIN_EXTENT_LEN) {
6458c2ecf20Sopenharmony_ci			et->largest.len = 0;
6468c2ecf20Sopenharmony_ci			et->largest_updated = true;
6478c2ecf20Sopenharmony_ci			set_inode_flag(inode, FI_NO_EXTENT);
6488c2ecf20Sopenharmony_ci		}
6498c2ecf20Sopenharmony_ci	}
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci	if (is_inode_flag_set(inode, FI_NO_EXTENT))
6528c2ecf20Sopenharmony_ci		__free_extent_tree(sbi, et);
6538c2ecf20Sopenharmony_ci
6548c2ecf20Sopenharmony_ci	if (et->largest_updated) {
6558c2ecf20Sopenharmony_ci		et->largest_updated = false;
6568c2ecf20Sopenharmony_ci		updated = true;
6578c2ecf20Sopenharmony_ci	}
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_ci	write_unlock(&et->lock);
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_ci	if (updated)
6628c2ecf20Sopenharmony_ci		f2fs_mark_inode_dirty_sync(inode, true);
6638c2ecf20Sopenharmony_ci}
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ciunsigned int f2fs_shrink_extent_tree(struct f2fs_sb_info *sbi, int nr_shrink)
6668c2ecf20Sopenharmony_ci{
6678c2ecf20Sopenharmony_ci	struct extent_tree *et, *next;
6688c2ecf20Sopenharmony_ci	struct extent_node *en;
6698c2ecf20Sopenharmony_ci	unsigned int node_cnt = 0, tree_cnt = 0;
6708c2ecf20Sopenharmony_ci	int remained;
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_ci	if (!test_opt(sbi, EXTENT_CACHE))
6738c2ecf20Sopenharmony_ci		return 0;
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_ci	if (!atomic_read(&sbi->total_zombie_tree))
6768c2ecf20Sopenharmony_ci		goto free_node;
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_ci	if (!mutex_trylock(&sbi->extent_tree_lock))
6798c2ecf20Sopenharmony_ci		goto out;
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_ci	/* 1. remove unreferenced extent tree */
6828c2ecf20Sopenharmony_ci	list_for_each_entry_safe(et, next, &sbi->zombie_list, list) {
6838c2ecf20Sopenharmony_ci		if (atomic_read(&et->node_cnt)) {
6848c2ecf20Sopenharmony_ci			write_lock(&et->lock);
6858c2ecf20Sopenharmony_ci			node_cnt += __free_extent_tree(sbi, et);
6868c2ecf20Sopenharmony_ci			write_unlock(&et->lock);
6878c2ecf20Sopenharmony_ci		}
6888c2ecf20Sopenharmony_ci		f2fs_bug_on(sbi, atomic_read(&et->node_cnt));
6898c2ecf20Sopenharmony_ci		list_del_init(&et->list);
6908c2ecf20Sopenharmony_ci		radix_tree_delete(&sbi->extent_tree_root, et->ino);
6918c2ecf20Sopenharmony_ci		kmem_cache_free(extent_tree_slab, et);
6928c2ecf20Sopenharmony_ci		atomic_dec(&sbi->total_ext_tree);
6938c2ecf20Sopenharmony_ci		atomic_dec(&sbi->total_zombie_tree);
6948c2ecf20Sopenharmony_ci		tree_cnt++;
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ci		if (node_cnt + tree_cnt >= nr_shrink)
6978c2ecf20Sopenharmony_ci			goto unlock_out;
6988c2ecf20Sopenharmony_ci		cond_resched();
6998c2ecf20Sopenharmony_ci	}
7008c2ecf20Sopenharmony_ci	mutex_unlock(&sbi->extent_tree_lock);
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_cifree_node:
7038c2ecf20Sopenharmony_ci	/* 2. remove LRU extent entries */
7048c2ecf20Sopenharmony_ci	if (!mutex_trylock(&sbi->extent_tree_lock))
7058c2ecf20Sopenharmony_ci		goto out;
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_ci	remained = nr_shrink - (node_cnt + tree_cnt);
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci	spin_lock(&sbi->extent_lock);
7108c2ecf20Sopenharmony_ci	for (; remained > 0; remained--) {
7118c2ecf20Sopenharmony_ci		if (list_empty(&sbi->extent_list))
7128c2ecf20Sopenharmony_ci			break;
7138c2ecf20Sopenharmony_ci		en = list_first_entry(&sbi->extent_list,
7148c2ecf20Sopenharmony_ci					struct extent_node, list);
7158c2ecf20Sopenharmony_ci		et = en->et;
7168c2ecf20Sopenharmony_ci		if (!write_trylock(&et->lock)) {
7178c2ecf20Sopenharmony_ci			/* refresh this extent node's position in extent list */
7188c2ecf20Sopenharmony_ci			list_move_tail(&en->list, &sbi->extent_list);
7198c2ecf20Sopenharmony_ci			continue;
7208c2ecf20Sopenharmony_ci		}
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_ci		list_del_init(&en->list);
7238c2ecf20Sopenharmony_ci		spin_unlock(&sbi->extent_lock);
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_ci		__detach_extent_node(sbi, et, en);
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci		write_unlock(&et->lock);
7288c2ecf20Sopenharmony_ci		node_cnt++;
7298c2ecf20Sopenharmony_ci		spin_lock(&sbi->extent_lock);
7308c2ecf20Sopenharmony_ci	}
7318c2ecf20Sopenharmony_ci	spin_unlock(&sbi->extent_lock);
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ciunlock_out:
7348c2ecf20Sopenharmony_ci	mutex_unlock(&sbi->extent_tree_lock);
7358c2ecf20Sopenharmony_ciout:
7368c2ecf20Sopenharmony_ci	trace_f2fs_shrink_extent_tree(sbi, node_cnt, tree_cnt);
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci	return node_cnt + tree_cnt;
7398c2ecf20Sopenharmony_ci}
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_ciunsigned int f2fs_destroy_extent_node(struct inode *inode)
7428c2ecf20Sopenharmony_ci{
7438c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
7448c2ecf20Sopenharmony_ci	struct extent_tree *et = F2FS_I(inode)->extent_tree;
7458c2ecf20Sopenharmony_ci	unsigned int node_cnt = 0;
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_ci	if (!et || !atomic_read(&et->node_cnt))
7488c2ecf20Sopenharmony_ci		return 0;
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_ci	write_lock(&et->lock);
7518c2ecf20Sopenharmony_ci	node_cnt = __free_extent_tree(sbi, et);
7528c2ecf20Sopenharmony_ci	write_unlock(&et->lock);
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_ci	return node_cnt;
7558c2ecf20Sopenharmony_ci}
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_civoid f2fs_drop_extent_tree(struct inode *inode)
7588c2ecf20Sopenharmony_ci{
7598c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
7608c2ecf20Sopenharmony_ci	struct extent_tree *et = F2FS_I(inode)->extent_tree;
7618c2ecf20Sopenharmony_ci	bool updated = false;
7628c2ecf20Sopenharmony_ci
7638c2ecf20Sopenharmony_ci	if (!f2fs_may_extent_tree(inode))
7648c2ecf20Sopenharmony_ci		return;
7658c2ecf20Sopenharmony_ci
7668c2ecf20Sopenharmony_ci	write_lock(&et->lock);
7678c2ecf20Sopenharmony_ci	set_inode_flag(inode, FI_NO_EXTENT);
7688c2ecf20Sopenharmony_ci	__free_extent_tree(sbi, et);
7698c2ecf20Sopenharmony_ci	if (et->largest.len) {
7708c2ecf20Sopenharmony_ci		et->largest.len = 0;
7718c2ecf20Sopenharmony_ci		updated = true;
7728c2ecf20Sopenharmony_ci	}
7738c2ecf20Sopenharmony_ci	write_unlock(&et->lock);
7748c2ecf20Sopenharmony_ci	if (updated)
7758c2ecf20Sopenharmony_ci		f2fs_mark_inode_dirty_sync(inode, true);
7768c2ecf20Sopenharmony_ci}
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_civoid f2fs_destroy_extent_tree(struct inode *inode)
7798c2ecf20Sopenharmony_ci{
7808c2ecf20Sopenharmony_ci	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
7818c2ecf20Sopenharmony_ci	struct extent_tree *et = F2FS_I(inode)->extent_tree;
7828c2ecf20Sopenharmony_ci	unsigned int node_cnt = 0;
7838c2ecf20Sopenharmony_ci
7848c2ecf20Sopenharmony_ci	if (!et)
7858c2ecf20Sopenharmony_ci		return;
7868c2ecf20Sopenharmony_ci
7878c2ecf20Sopenharmony_ci	if (inode->i_nlink && !is_bad_inode(inode) &&
7888c2ecf20Sopenharmony_ci					atomic_read(&et->node_cnt)) {
7898c2ecf20Sopenharmony_ci		mutex_lock(&sbi->extent_tree_lock);
7908c2ecf20Sopenharmony_ci		list_add_tail(&et->list, &sbi->zombie_list);
7918c2ecf20Sopenharmony_ci		atomic_inc(&sbi->total_zombie_tree);
7928c2ecf20Sopenharmony_ci		mutex_unlock(&sbi->extent_tree_lock);
7938c2ecf20Sopenharmony_ci		return;
7948c2ecf20Sopenharmony_ci	}
7958c2ecf20Sopenharmony_ci
7968c2ecf20Sopenharmony_ci	/* free all extent info belong to this extent tree */
7978c2ecf20Sopenharmony_ci	node_cnt = f2fs_destroy_extent_node(inode);
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_ci	/* delete extent tree entry in radix tree */
8008c2ecf20Sopenharmony_ci	mutex_lock(&sbi->extent_tree_lock);
8018c2ecf20Sopenharmony_ci	f2fs_bug_on(sbi, atomic_read(&et->node_cnt));
8028c2ecf20Sopenharmony_ci	radix_tree_delete(&sbi->extent_tree_root, inode->i_ino);
8038c2ecf20Sopenharmony_ci	kmem_cache_free(extent_tree_slab, et);
8048c2ecf20Sopenharmony_ci	atomic_dec(&sbi->total_ext_tree);
8058c2ecf20Sopenharmony_ci	mutex_unlock(&sbi->extent_tree_lock);
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_ci	F2FS_I(inode)->extent_tree = NULL;
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci	trace_f2fs_destroy_extent_tree(inode, node_cnt);
8108c2ecf20Sopenharmony_ci}
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_cibool f2fs_lookup_extent_cache(struct inode *inode, pgoff_t pgofs,
8138c2ecf20Sopenharmony_ci					struct extent_info *ei)
8148c2ecf20Sopenharmony_ci{
8158c2ecf20Sopenharmony_ci	if (!f2fs_may_extent_tree(inode))
8168c2ecf20Sopenharmony_ci		return false;
8178c2ecf20Sopenharmony_ci
8188c2ecf20Sopenharmony_ci	return f2fs_lookup_extent_tree(inode, pgofs, ei);
8198c2ecf20Sopenharmony_ci}
8208c2ecf20Sopenharmony_ci
8218c2ecf20Sopenharmony_civoid f2fs_update_extent_cache(struct dnode_of_data *dn)
8228c2ecf20Sopenharmony_ci{
8238c2ecf20Sopenharmony_ci	pgoff_t fofs;
8248c2ecf20Sopenharmony_ci	block_t blkaddr;
8258c2ecf20Sopenharmony_ci
8268c2ecf20Sopenharmony_ci	if (!f2fs_may_extent_tree(dn->inode))
8278c2ecf20Sopenharmony_ci		return;
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_ci	if (dn->data_blkaddr == NEW_ADDR)
8308c2ecf20Sopenharmony_ci		blkaddr = NULL_ADDR;
8318c2ecf20Sopenharmony_ci	else
8328c2ecf20Sopenharmony_ci		blkaddr = dn->data_blkaddr;
8338c2ecf20Sopenharmony_ci
8348c2ecf20Sopenharmony_ci	fofs = f2fs_start_bidx_of_node(ofs_of_node(dn->node_page), dn->inode) +
8358c2ecf20Sopenharmony_ci								dn->ofs_in_node;
8368c2ecf20Sopenharmony_ci	f2fs_update_extent_tree_range(dn->inode, fofs, blkaddr, 1);
8378c2ecf20Sopenharmony_ci}
8388c2ecf20Sopenharmony_ci
8398c2ecf20Sopenharmony_civoid f2fs_update_extent_cache_range(struct dnode_of_data *dn,
8408c2ecf20Sopenharmony_ci				pgoff_t fofs, block_t blkaddr, unsigned int len)
8418c2ecf20Sopenharmony_ci
8428c2ecf20Sopenharmony_ci{
8438c2ecf20Sopenharmony_ci	if (!f2fs_may_extent_tree(dn->inode))
8448c2ecf20Sopenharmony_ci		return;
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_ci	f2fs_update_extent_tree_range(dn->inode, fofs, blkaddr, len);
8478c2ecf20Sopenharmony_ci}
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_civoid f2fs_init_extent_cache_info(struct f2fs_sb_info *sbi)
8508c2ecf20Sopenharmony_ci{
8518c2ecf20Sopenharmony_ci	INIT_RADIX_TREE(&sbi->extent_tree_root, GFP_NOIO);
8528c2ecf20Sopenharmony_ci	mutex_init(&sbi->extent_tree_lock);
8538c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&sbi->extent_list);
8548c2ecf20Sopenharmony_ci	spin_lock_init(&sbi->extent_lock);
8558c2ecf20Sopenharmony_ci	atomic_set(&sbi->total_ext_tree, 0);
8568c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&sbi->zombie_list);
8578c2ecf20Sopenharmony_ci	atomic_set(&sbi->total_zombie_tree, 0);
8588c2ecf20Sopenharmony_ci	atomic_set(&sbi->total_ext_node, 0);
8598c2ecf20Sopenharmony_ci}
8608c2ecf20Sopenharmony_ci
8618c2ecf20Sopenharmony_ciint __init f2fs_create_extent_cache(void)
8628c2ecf20Sopenharmony_ci{
8638c2ecf20Sopenharmony_ci	extent_tree_slab = f2fs_kmem_cache_create("f2fs_extent_tree",
8648c2ecf20Sopenharmony_ci			sizeof(struct extent_tree));
8658c2ecf20Sopenharmony_ci	if (!extent_tree_slab)
8668c2ecf20Sopenharmony_ci		return -ENOMEM;
8678c2ecf20Sopenharmony_ci	extent_node_slab = f2fs_kmem_cache_create("f2fs_extent_node",
8688c2ecf20Sopenharmony_ci			sizeof(struct extent_node));
8698c2ecf20Sopenharmony_ci	if (!extent_node_slab) {
8708c2ecf20Sopenharmony_ci		kmem_cache_destroy(extent_tree_slab);
8718c2ecf20Sopenharmony_ci		return -ENOMEM;
8728c2ecf20Sopenharmony_ci	}
8738c2ecf20Sopenharmony_ci	return 0;
8748c2ecf20Sopenharmony_ci}
8758c2ecf20Sopenharmony_ci
8768c2ecf20Sopenharmony_civoid f2fs_destroy_extent_cache(void)
8778c2ecf20Sopenharmony_ci{
8788c2ecf20Sopenharmony_ci	kmem_cache_destroy(extent_node_slab);
8798c2ecf20Sopenharmony_ci	kmem_cache_destroy(extent_tree_slab);
8808c2ecf20Sopenharmony_ci}
881