Commit | Line | Data |
---|---|---|
7c1a000d | 1 | // SPDX-License-Identifier: GPL-2.0 |
a28ef1f5 CY |
2 | /* |
3 | * f2fs extent cache support | |
4 | * | |
5 | * Copyright (c) 2015 Motorola Mobility | |
6 | * Copyright (c) 2015 Samsung Electronics | |
7 | * Authors: Jaegeuk Kim <jaegeuk@kernel.org> | |
8 | * Chao Yu <chao2.yu@samsung.com> | |
71644dff JK |
9 | * |
10 | * block_age-based extent cache added by: | |
11 | * Copyright (c) 2022 xiaomi Co., Ltd. | |
12 | * http://www.xiaomi.com/ | |
a28ef1f5 CY |
13 | */ |
14 | ||
15 | #include <linux/fs.h> | |
16 | #include <linux/f2fs_fs.h> | |
17 | ||
18 | #include "f2fs.h" | |
19 | #include "node.h" | |
20 | #include <trace/events/f2fs.h> | |
21 | ||
d7409b05 | 22 | bool sanity_check_extent_cache(struct inode *inode, struct page *ipage) |
269d1194 CY |
23 | { |
24 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | |
d7409b05 CY |
25 | struct f2fs_extent *i_ext = &F2FS_INODE(ipage)->i_ext; |
26 | struct extent_info ei; | |
128d333f | 27 | int devi; |
269d1194 | 28 | |
d7409b05 | 29 | get_read_extent_info(&ei, i_ext); |
bd90c5cd | 30 | |
d7409b05 | 31 | if (!ei.len) |
bd90c5cd | 32 | return true; |
269d1194 | 33 | |
d7409b05 CY |
34 | if (!f2fs_is_valid_blkaddr(sbi, ei.blk, DATA_GENERIC_ENHANCE) || |
35 | !f2fs_is_valid_blkaddr(sbi, ei.blk + ei.len - 1, | |
bd90c5cd | 36 | DATA_GENERIC_ENHANCE)) { |
269d1194 CY |
37 | f2fs_warn(sbi, "%s: inode (ino=%lx) extent info [%u, %u, %u] is incorrect, run fsck to fix", |
38 | __func__, inode->i_ino, | |
d7409b05 | 39 | ei.blk, ei.fofs, ei.len); |
269d1194 CY |
40 | return false; |
41 | } | |
128d333f DJ |
42 | |
43 | if (!IS_DEVICE_ALIASING(inode)) | |
44 | return true; | |
45 | ||
46 | for (devi = 0; devi < sbi->s_ndevs; devi++) { | |
47 | if (FDEV(devi).start_blk != ei.blk || | |
48 | FDEV(devi).end_blk != ei.blk + ei.len - 1) | |
49 | continue; | |
50 | ||
51 | if (devi == 0) { | |
52 | f2fs_warn(sbi, | |
53 | "%s: inode (ino=%lx) is an alias of meta device", | |
54 | __func__, inode->i_ino); | |
55 | return false; | |
56 | } | |
57 | ||
58 | if (bdev_is_zoned(FDEV(devi).bdev)) { | |
59 | f2fs_warn(sbi, | |
60 | "%s: device alias inode (ino=%lx)'s extent info " | |
61 | "[%u, %u, %u] maps to zoned block device", | |
62 | __func__, inode->i_ino, ei.blk, ei.fofs, ei.len); | |
63 | return false; | |
64 | } | |
65 | return true; | |
66 | } | |
67 | ||
68 | f2fs_warn(sbi, "%s: device alias inode (ino=%lx)'s extent info " | |
69 | "[%u, %u, %u] is inconsistent w/ any devices", | |
70 | __func__, inode->i_ino, ei.blk, ei.fofs, ei.len); | |
71 | return false; | |
269d1194 CY |
72 | } |
73 | ||
3bac20a8 JK |
74 | static void __set_extent_info(struct extent_info *ei, |
75 | unsigned int fofs, unsigned int len, | |
e7547dac | 76 | block_t blk, bool keep_clen, |
71644dff | 77 | unsigned long age, unsigned long last_blocks, |
e7547dac | 78 | enum extent_type type) |
3bac20a8 JK |
79 | { |
80 | ei->fofs = fofs; | |
3bac20a8 JK |
81 | ei->len = len; |
82 | ||
e7547dac JK |
83 | if (type == EX_READ) { |
84 | ei->blk = blk; | |
85 | if (keep_clen) | |
86 | return; | |
3bac20a8 | 87 | #ifdef CONFIG_F2FS_FS_COMPRESSION |
e7547dac | 88 | ei->c_len = 0; |
3bac20a8 | 89 | #endif |
71644dff JK |
90 | } else if (type == EX_BLOCK_AGE) { |
91 | ei->age = age; | |
92 | ei->last_blocks = last_blocks; | |
e7547dac JK |
93 | } |
94 | } | |
95 | ||
72840ccc | 96 | static bool __init_may_extent_tree(struct inode *inode, enum extent_type type) |
3bac20a8 | 97 | { |
72840ccc | 98 | if (type == EX_READ) |
f8039821 JK |
99 | return test_opt(F2FS_I_SB(inode), READ_EXTENT_CACHE) && |
100 | S_ISREG(inode->i_mode); | |
101 | if (type == EX_BLOCK_AGE) | |
102 | return test_opt(F2FS_I_SB(inode), AGE_EXTENT_CACHE) && | |
103 | (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)); | |
72840ccc JK |
104 | return false; |
105 | } | |
3bac20a8 | 106 | |
72840ccc JK |
107 | static bool __may_extent_tree(struct inode *inode, enum extent_type type) |
108 | { | |
128d333f DJ |
109 | if (IS_DEVICE_ALIASING(inode) && type == EX_READ) |
110 | return true; | |
111 | ||
3bac20a8 JK |
112 | /* |
113 | * for recovered files during mount do not create extents | |
114 | * if shrinker is not registered. | |
115 | */ | |
72840ccc | 116 | if (list_empty(&F2FS_I_SB(inode)->s_list)) |
3bac20a8 JK |
117 | return false; |
118 | ||
f8039821 JK |
119 | if (!__init_may_extent_tree(inode, type)) |
120 | return false; | |
121 | ||
122 | if (type == EX_READ) { | |
123 | if (is_inode_flag_set(inode, FI_NO_EXTENT)) | |
124 | return false; | |
125 | if (is_inode_flag_set(inode, FI_COMPRESSED_FILE) && | |
126 | !f2fs_sb_has_readonly(F2FS_I_SB(inode))) | |
127 | return false; | |
128 | } else if (type == EX_BLOCK_AGE) { | |
129 | if (is_inode_flag_set(inode, FI_COMPRESSED_FILE)) | |
130 | return false; | |
131 | if (file_is_cold(inode)) | |
132 | return false; | |
133 | } | |
134 | return true; | |
3bac20a8 JK |
135 | } |
136 | ||
137 | static void __try_update_largest_extent(struct extent_tree *et, | |
138 | struct extent_node *en) | |
139 | { | |
e7547dac JK |
140 | if (et->type != EX_READ) |
141 | return; | |
3bac20a8 JK |
142 | if (en->ei.len <= et->largest.len) |
143 | return; | |
144 | ||
145 | et->largest = en->ei; | |
146 | et->largest_updated = true; | |
147 | } | |
148 | ||
149 | static bool __is_extent_mergeable(struct extent_info *back, | |
e7547dac | 150 | struct extent_info *front, enum extent_type type) |
3bac20a8 | 151 | { |
e7547dac | 152 | if (type == EX_READ) { |
3bac20a8 | 153 | #ifdef CONFIG_F2FS_FS_COMPRESSION |
e7547dac JK |
154 | if (back->c_len && back->len != back->c_len) |
155 | return false; | |
156 | if (front->c_len && front->len != front->c_len) | |
157 | return false; | |
3bac20a8 | 158 | #endif |
e7547dac JK |
159 | return (back->fofs + back->len == front->fofs && |
160 | back->blk + back->len == front->blk); | |
71644dff JK |
161 | } else if (type == EX_BLOCK_AGE) { |
162 | return (back->fofs + back->len == front->fofs && | |
163 | abs(back->age - front->age) <= SAME_AGE_REGION && | |
164 | abs(back->last_blocks - front->last_blocks) <= | |
165 | SAME_AGE_REGION); | |
e7547dac JK |
166 | } |
167 | return false; | |
3bac20a8 JK |
168 | } |
169 | ||
170 | static bool __is_back_mergeable(struct extent_info *cur, | |
e7547dac | 171 | struct extent_info *back, enum extent_type type) |
3bac20a8 | 172 | { |
e7547dac | 173 | return __is_extent_mergeable(back, cur, type); |
3bac20a8 JK |
174 | } |
175 | ||
176 | static bool __is_front_mergeable(struct extent_info *cur, | |
e7547dac | 177 | struct extent_info *front, enum extent_type type) |
3bac20a8 | 178 | { |
e7547dac | 179 | return __is_extent_mergeable(cur, front, type); |
3bac20a8 JK |
180 | } |
181 | ||
bf21acf9 JK |
182 | static struct extent_node *__lookup_extent_node(struct rb_root_cached *root, |
183 | struct extent_node *cached_en, unsigned int fofs) | |
54c2258c | 184 | { |
4dada3fd | 185 | struct rb_node *node = root->rb_root.rb_node; |
bf21acf9 JK |
186 | struct extent_node *en; |
187 | ||
188 | /* check a cached entry */ | |
189 | if (cached_en && cached_en->ei.fofs <= fofs && | |
190 | cached_en->ei.fofs + cached_en->ei.len > fofs) | |
191 | return cached_en; | |
54c2258c | 192 | |
bf21acf9 | 193 | /* check rb_tree */ |
54c2258c | 194 | while (node) { |
bf21acf9 | 195 | en = rb_entry(node, struct extent_node, rb_node); |
54c2258c | 196 | |
bf21acf9 | 197 | if (fofs < en->ei.fofs) |
54c2258c | 198 | node = node->rb_left; |
bf21acf9 | 199 | else if (fofs >= en->ei.fofs + en->ei.len) |
54c2258c CY |
200 | node = node->rb_right; |
201 | else | |
bf21acf9 | 202 | return en; |
54c2258c CY |
203 | } |
204 | return NULL; | |
205 | } | |
206 | ||
54c2258c | 207 | /* |
bf21acf9 | 208 | * lookup rb entry in position of @fofs in rb-tree, |
54c2258c | 209 | * if hit, return the entry, otherwise, return NULL |
bf21acf9 JK |
210 | * @prev_ex: extent before fofs |
211 | * @next_ex: extent after fofs | |
212 | * @insert_p: insert point for new extent at fofs | |
146949de | 213 | * in order to simplify the insertion after. |
54c2258c CY |
214 | * tree must stay unchanged between lookup and insertion. |
215 | */ | |
bf21acf9 JK |
216 | static struct extent_node *__lookup_extent_node_ret(struct rb_root_cached *root, |
217 | struct extent_node *cached_en, | |
218 | unsigned int fofs, | |
219 | struct extent_node **prev_entry, | |
220 | struct extent_node **next_entry, | |
54c2258c | 221 | struct rb_node ***insert_p, |
004b6862 | 222 | struct rb_node **insert_parent, |
bf21acf9 | 223 | bool *leftmost) |
54c2258c | 224 | { |
4dada3fd | 225 | struct rb_node **pnode = &root->rb_root.rb_node; |
54c2258c | 226 | struct rb_node *parent = NULL, *tmp_node; |
bf21acf9 | 227 | struct extent_node *en = cached_en; |
54c2258c CY |
228 | |
229 | *insert_p = NULL; | |
230 | *insert_parent = NULL; | |
231 | *prev_entry = NULL; | |
232 | *next_entry = NULL; | |
233 | ||
4dada3fd | 234 | if (RB_EMPTY_ROOT(&root->rb_root)) |
54c2258c CY |
235 | return NULL; |
236 | ||
bf21acf9 JK |
237 | if (en && en->ei.fofs <= fofs && en->ei.fofs + en->ei.len > fofs) |
238 | goto lookup_neighbors; | |
54c2258c | 239 | |
bf21acf9 | 240 | *leftmost = true; |
4dada3fd | 241 | |
54c2258c CY |
242 | while (*pnode) { |
243 | parent = *pnode; | |
bf21acf9 | 244 | en = rb_entry(*pnode, struct extent_node, rb_node); |
54c2258c | 245 | |
bf21acf9 | 246 | if (fofs < en->ei.fofs) { |
54c2258c | 247 | pnode = &(*pnode)->rb_left; |
bf21acf9 | 248 | } else if (fofs >= en->ei.fofs + en->ei.len) { |
54c2258c | 249 | pnode = &(*pnode)->rb_right; |
bf21acf9 | 250 | *leftmost = false; |
4dada3fd | 251 | } else { |
54c2258c | 252 | goto lookup_neighbors; |
4dada3fd | 253 | } |
54c2258c CY |
254 | } |
255 | ||
256 | *insert_p = pnode; | |
257 | *insert_parent = parent; | |
258 | ||
bf21acf9 | 259 | en = rb_entry(parent, struct extent_node, rb_node); |
54c2258c | 260 | tmp_node = parent; |
bf21acf9 | 261 | if (parent && fofs > en->ei.fofs) |
54c2258c | 262 | tmp_node = rb_next(parent); |
bf21acf9 | 263 | *next_entry = rb_entry_safe(tmp_node, struct extent_node, rb_node); |
54c2258c CY |
264 | |
265 | tmp_node = parent; | |
bf21acf9 | 266 | if (parent && fofs < en->ei.fofs) |
54c2258c | 267 | tmp_node = rb_prev(parent); |
bf21acf9 | 268 | *prev_entry = rb_entry_safe(tmp_node, struct extent_node, rb_node); |
54c2258c CY |
269 | return NULL; |
270 | ||
271 | lookup_neighbors: | |
bf21acf9 | 272 | if (fofs == en->ei.fofs) { |
54c2258c | 273 | /* lookup prev node for merging backward later */ |
bf21acf9 JK |
274 | tmp_node = rb_prev(&en->rb_node); |
275 | *prev_entry = rb_entry_safe(tmp_node, | |
276 | struct extent_node, rb_node); | |
54c2258c | 277 | } |
bf21acf9 | 278 | if (fofs == en->ei.fofs + en->ei.len - 1) { |
54c2258c | 279 | /* lookup next node for merging frontward later */ |
bf21acf9 JK |
280 | tmp_node = rb_next(&en->rb_node); |
281 | *next_entry = rb_entry_safe(tmp_node, | |
282 | struct extent_node, rb_node); | |
54c2258c | 283 | } |
bf21acf9 | 284 | return en; |
54c2258c CY |
285 | } |
286 | ||
a28ef1f5 CY |
287 | static struct kmem_cache *extent_tree_slab; |
288 | static struct kmem_cache *extent_node_slab; | |
289 | ||
290 | static struct extent_node *__attach_extent_node(struct f2fs_sb_info *sbi, | |
291 | struct extent_tree *et, struct extent_info *ei, | |
4dada3fd CY |
292 | struct rb_node *parent, struct rb_node **p, |
293 | bool leftmost) | |
a28ef1f5 | 294 | { |
e7547dac | 295 | struct extent_tree_info *eti = &sbi->extent_tree[et->type]; |
a28ef1f5 CY |
296 | struct extent_node *en; |
297 | ||
32410577 | 298 | en = f2fs_kmem_cache_alloc(extent_node_slab, GFP_ATOMIC, false, sbi); |
a28ef1f5 CY |
299 | if (!en) |
300 | return NULL; | |
301 | ||
302 | en->ei = *ei; | |
303 | INIT_LIST_HEAD(&en->list); | |
201ef5e0 | 304 | en->et = et; |
a28ef1f5 CY |
305 | |
306 | rb_link_node(&en->rb_node, parent, p); | |
4dada3fd | 307 | rb_insert_color_cached(&en->rb_node, &et->root, leftmost); |
68e35385 | 308 | atomic_inc(&et->node_cnt); |
e7547dac | 309 | atomic_inc(&eti->total_ext_node); |
a28ef1f5 CY |
310 | return en; |
311 | } | |
312 | ||
313 | static void __detach_extent_node(struct f2fs_sb_info *sbi, | |
314 | struct extent_tree *et, struct extent_node *en) | |
315 | { | |
e7547dac JK |
316 | struct extent_tree_info *eti = &sbi->extent_tree[et->type]; |
317 | ||
4dada3fd | 318 | rb_erase_cached(&en->rb_node, &et->root); |
68e35385 | 319 | atomic_dec(&et->node_cnt); |
e7547dac | 320 | atomic_dec(&eti->total_ext_node); |
a28ef1f5 CY |
321 | |
322 | if (et->cached_en == en) | |
323 | et->cached_en = NULL; | |
a03f01f2 HP |
324 | kmem_cache_free(extent_node_slab, en); |
325 | } | |
326 | ||
327 | /* | |
328 | * Flow to release an extent_node: | |
329 | * 1. list_del_init | |
330 | * 2. __detach_extent_node | |
331 | * 3. kmem_cache_free. | |
332 | */ | |
333 | static void __release_extent_node(struct f2fs_sb_info *sbi, | |
334 | struct extent_tree *et, struct extent_node *en) | |
335 | { | |
e7547dac JK |
336 | struct extent_tree_info *eti = &sbi->extent_tree[et->type]; |
337 | ||
338 | spin_lock(&eti->extent_lock); | |
201ef5e0 HP |
339 | f2fs_bug_on(sbi, list_empty(&en->list)); |
340 | list_del_init(&en->list); | |
e7547dac | 341 | spin_unlock(&eti->extent_lock); |
a03f01f2 HP |
342 | |
343 | __detach_extent_node(sbi, et, en); | |
a28ef1f5 CY |
344 | } |
345 | ||
e7547dac JK |
346 | static struct extent_tree *__grab_extent_tree(struct inode *inode, |
347 | enum extent_type type) | |
a28ef1f5 CY |
348 | { |
349 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | |
e7547dac | 350 | struct extent_tree_info *eti = &sbi->extent_tree[type]; |
a28ef1f5 CY |
351 | struct extent_tree *et; |
352 | nid_t ino = inode->i_ino; | |
353 | ||
e7547dac JK |
354 | mutex_lock(&eti->extent_tree_lock); |
355 | et = radix_tree_lookup(&eti->extent_tree_root, ino); | |
a28ef1f5 | 356 | if (!et) { |
32410577 CY |
357 | et = f2fs_kmem_cache_alloc(extent_tree_slab, |
358 | GFP_NOFS, true, NULL); | |
e7547dac | 359 | f2fs_radix_tree_insert(&eti->extent_tree_root, ino, et); |
a28ef1f5 CY |
360 | memset(et, 0, sizeof(struct extent_tree)); |
361 | et->ino = ino; | |
e7547dac | 362 | et->type = type; |
4dada3fd | 363 | et->root = RB_ROOT_CACHED; |
a28ef1f5 CY |
364 | et->cached_en = NULL; |
365 | rwlock_init(&et->lock); | |
137d09f0 | 366 | INIT_LIST_HEAD(&et->list); |
68e35385 | 367 | atomic_set(&et->node_cnt, 0); |
e7547dac | 368 | atomic_inc(&eti->total_ext_tree); |
74fd8d99 | 369 | } else { |
e7547dac | 370 | atomic_dec(&eti->total_zombie_tree); |
137d09f0 | 371 | list_del_init(&et->list); |
a28ef1f5 | 372 | } |
e7547dac | 373 | mutex_unlock(&eti->extent_tree_lock); |
a28ef1f5 CY |
374 | |
375 | /* never died until evict_inode */ | |
e7547dac | 376 | F2FS_I(inode)->extent_tree[type] = et; |
a28ef1f5 CY |
377 | |
378 | return et; | |
379 | } | |
380 | ||
a28ef1f5 | 381 | static unsigned int __free_extent_tree(struct f2fs_sb_info *sbi, |
3fc5d5a1 | 382 | struct extent_tree *et, unsigned int nr_shrink) |
a28ef1f5 CY |
383 | { |
384 | struct rb_node *node, *next; | |
385 | struct extent_node *en; | |
3fc5d5a1 | 386 | unsigned int count; |
a28ef1f5 | 387 | |
4dada3fd | 388 | node = rb_first_cached(&et->root); |
3fc5d5a1 CY |
389 | |
390 | for (count = 0; node && count < nr_shrink; count++) { | |
a28ef1f5 CY |
391 | next = rb_next(node); |
392 | en = rb_entry(node, struct extent_node, rb_node); | |
201ef5e0 | 393 | __release_extent_node(sbi, et, en); |
a28ef1f5 CY |
394 | node = next; |
395 | } | |
396 | ||
3fc5d5a1 | 397 | return count; |
a28ef1f5 CY |
398 | } |
399 | ||
b430f726 | 400 | static void __drop_largest_extent(struct extent_tree *et, |
41a099de | 401 | pgoff_t fofs, unsigned int len) |
a28ef1f5 | 402 | { |
1cade98c | 403 | if (fofs < (pgoff_t)et->largest.fofs + et->largest.len && |
b430f726 ZZ |
404 | fofs + len > et->largest.fofs) { |
405 | et->largest.len = 0; | |
406 | et->largest_updated = true; | |
205b9822 | 407 | } |
a28ef1f5 CY |
408 | } |
409 | ||
398c7df7 | 410 | void f2fs_init_read_extent_tree(struct inode *inode, struct folio *ifolio) |
a28ef1f5 CY |
411 | { |
412 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | |
72840ccc | 413 | struct extent_tree_info *eti = &sbi->extent_tree[EX_READ]; |
398c7df7 | 414 | struct f2fs_extent *i_ext = &F2FS_INODE(&ifolio->page)->i_ext; |
a28ef1f5 CY |
415 | struct extent_tree *et; |
416 | struct extent_node *en; | |
417 | struct extent_info ei; | |
418 | ||
72840ccc | 419 | if (!__may_extent_tree(inode, EX_READ)) { |
e7547dac | 420 | /* drop largest read extent */ |
d7409b05 | 421 | if (i_ext->len) { |
398c7df7 | 422 | f2fs_folio_wait_writeback(ifolio, NODE, true, true); |
ed3d1256 | 423 | i_ext->len = 0; |
398c7df7 | 424 | folio_mark_dirty(ifolio); |
ed3d1256 | 425 | } |
d7409b05 CY |
426 | set_inode_flag(inode, FI_NO_EXTENT); |
427 | return; | |
ed3d1256 | 428 | } |
a28ef1f5 | 429 | |
72840ccc | 430 | et = __grab_extent_tree(inode, EX_READ); |
a28ef1f5 | 431 | |
12607c1b | 432 | get_read_extent_info(&ei, i_ext); |
a28ef1f5 CY |
433 | |
434 | write_lock(&et->lock); | |
d7409b05 CY |
435 | if (atomic_read(&et->node_cnt) || !ei.len) |
436 | goto skip; | |
a28ef1f5 | 437 | |
128d333f DJ |
438 | if (IS_DEVICE_ALIASING(inode)) { |
439 | et->largest = ei; | |
440 | goto skip; | |
441 | } | |
442 | ||
749d543c JK |
443 | en = __attach_extent_node(sbi, et, &ei, NULL, |
444 | &et->root.rb_root.rb_node, true); | |
a28ef1f5 | 445 | if (en) { |
749d543c JK |
446 | et->largest = en->ei; |
447 | et->cached_en = en; | |
448 | ||
e7547dac JK |
449 | spin_lock(&eti->extent_lock); |
450 | list_add_tail(&en->list, &eti->extent_list); | |
451 | spin_unlock(&eti->extent_lock); | |
a28ef1f5 | 452 | } |
d7409b05 CY |
453 | skip: |
454 | /* Let's drop, if checkpoint got corrupted. */ | |
455 | if (f2fs_cp_error(sbi)) { | |
456 | et->largest.len = 0; | |
457 | et->largest_updated = true; | |
458 | } | |
a28ef1f5 CY |
459 | write_unlock(&et->lock); |
460 | } | |
461 | ||
71644dff JK |
462 | void f2fs_init_age_extent_tree(struct inode *inode) |
463 | { | |
464 | if (!__init_may_extent_tree(inode, EX_BLOCK_AGE)) | |
465 | return; | |
466 | __grab_extent_tree(inode, EX_BLOCK_AGE); | |
467 | } | |
468 | ||
72840ccc | 469 | void f2fs_init_extent_tree(struct inode *inode) |
dad48e73 | 470 | { |
e7547dac | 471 | /* initialize read cache */ |
72840ccc JK |
472 | if (__init_may_extent_tree(inode, EX_READ)) |
473 | __grab_extent_tree(inode, EX_READ); | |
71644dff JK |
474 | |
475 | /* initialize block age cache */ | |
476 | if (__init_may_extent_tree(inode, EX_BLOCK_AGE)) | |
477 | __grab_extent_tree(inode, EX_BLOCK_AGE); | |
dad48e73 YH |
478 | } |
479 | ||
e7547dac JK |
480 | static bool __lookup_extent_tree(struct inode *inode, pgoff_t pgofs, |
481 | struct extent_info *ei, enum extent_type type) | |
a28ef1f5 CY |
482 | { |
483 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | |
e7547dac JK |
484 | struct extent_tree_info *eti = &sbi->extent_tree[type]; |
485 | struct extent_tree *et = F2FS_I(inode)->extent_tree[type]; | |
a28ef1f5 CY |
486 | struct extent_node *en; |
487 | bool ret = false; | |
488 | ||
df9d44b6 JK |
489 | if (!et) |
490 | return false; | |
a28ef1f5 | 491 | |
e7547dac | 492 | trace_f2fs_lookup_extent_tree_start(inode, pgofs, type); |
a28ef1f5 CY |
493 | |
494 | read_lock(&et->lock); | |
495 | ||
e7547dac JK |
496 | if (type == EX_READ && |
497 | et->largest.fofs <= pgofs && | |
1cade98c | 498 | (pgoff_t)et->largest.fofs + et->largest.len > pgofs) { |
a28ef1f5 CY |
499 | *ei = et->largest; |
500 | ret = true; | |
91c481ff | 501 | stat_inc_largest_node_hit(sbi); |
a28ef1f5 CY |
502 | goto out; |
503 | } | |
504 | ||
128d333f DJ |
505 | if (IS_DEVICE_ALIASING(inode)) { |
506 | ret = false; | |
507 | goto out; | |
508 | } | |
509 | ||
bf21acf9 | 510 | en = __lookup_extent_node(&et->root, et->cached_en, pgofs); |
54c2258c CY |
511 | if (!en) |
512 | goto out; | |
513 | ||
514 | if (en == et->cached_en) | |
e7547dac | 515 | stat_inc_cached_node_hit(sbi, type); |
54c2258c | 516 | else |
e7547dac | 517 | stat_inc_rbtree_node_hit(sbi, type); |
54c2258c CY |
518 | |
519 | *ei = en->ei; | |
e7547dac | 520 | spin_lock(&eti->extent_lock); |
54c2258c | 521 | if (!list_empty(&en->list)) { |
e7547dac | 522 | list_move_tail(&en->list, &eti->extent_list); |
54c2258c | 523 | et->cached_en = en; |
a28ef1f5 | 524 | } |
e7547dac | 525 | spin_unlock(&eti->extent_lock); |
54c2258c | 526 | ret = true; |
a28ef1f5 | 527 | out: |
e7547dac | 528 | stat_inc_total_hit(sbi, type); |
a28ef1f5 CY |
529 | read_unlock(&et->lock); |
530 | ||
e7547dac JK |
531 | if (type == EX_READ) |
532 | trace_f2fs_lookup_read_extent_tree_end(inode, pgofs, ei); | |
71644dff JK |
533 | else if (type == EX_BLOCK_AGE) |
534 | trace_f2fs_lookup_age_extent_tree_end(inode, pgofs, ei); | |
a28ef1f5 CY |
535 | return ret; |
536 | } | |
537 | ||
b430f726 | 538 | static struct extent_node *__try_merge_extent_node(struct f2fs_sb_info *sbi, |
0f825ee6 | 539 | struct extent_tree *et, struct extent_info *ei, |
0f825ee6 | 540 | struct extent_node *prev_ex, |
ef05e221 | 541 | struct extent_node *next_ex) |
0f825ee6 | 542 | { |
e7547dac | 543 | struct extent_tree_info *eti = &sbi->extent_tree[et->type]; |
0f825ee6 | 544 | struct extent_node *en = NULL; |
0f825ee6 | 545 | |
e7547dac | 546 | if (prev_ex && __is_back_mergeable(ei, &prev_ex->ei, et->type)) { |
0f825ee6 FL |
547 | prev_ex->ei.len += ei->len; |
548 | ei = &prev_ex->ei; | |
549 | en = prev_ex; | |
550 | } | |
ef05e221 | 551 | |
e7547dac | 552 | if (next_ex && __is_front_mergeable(ei, &next_ex->ei, et->type)) { |
0f825ee6 | 553 | next_ex->ei.fofs = ei->fofs; |
0f825ee6 | 554 | next_ex->ei.len += ei->len; |
e7547dac JK |
555 | if (et->type == EX_READ) |
556 | next_ex->ei.blk = ei->blk; | |
7855eba4 YH |
557 | if (en) |
558 | __release_extent_node(sbi, et, prev_ex); | |
559 | ||
0f825ee6 FL |
560 | en = next_ex; |
561 | } | |
ef05e221 | 562 | |
43a2fa18 JK |
563 | if (!en) |
564 | return NULL; | |
565 | ||
b430f726 | 566 | __try_update_largest_extent(et, en); |
43a2fa18 | 567 | |
e7547dac | 568 | spin_lock(&eti->extent_lock); |
42926744 | 569 | if (!list_empty(&en->list)) { |
e7547dac | 570 | list_move_tail(&en->list, &eti->extent_list); |
42926744 JK |
571 | et->cached_en = en; |
572 | } | |
e7547dac | 573 | spin_unlock(&eti->extent_lock); |
ef05e221 CY |
574 | return en; |
575 | } | |
576 | ||
b430f726 | 577 | static struct extent_node *__insert_extent_tree(struct f2fs_sb_info *sbi, |
ef05e221 CY |
578 | struct extent_tree *et, struct extent_info *ei, |
579 | struct rb_node **insert_p, | |
4dada3fd CY |
580 | struct rb_node *insert_parent, |
581 | bool leftmost) | |
ef05e221 | 582 | { |
e7547dac | 583 | struct extent_tree_info *eti = &sbi->extent_tree[et->type]; |
bf21acf9 | 584 | struct rb_node **p = &et->root.rb_root.rb_node; |
ef05e221 CY |
585 | struct rb_node *parent = NULL; |
586 | struct extent_node *en = NULL; | |
0f825ee6 FL |
587 | |
588 | if (insert_p && insert_parent) { | |
589 | parent = insert_parent; | |
590 | p = insert_p; | |
591 | goto do_insert; | |
592 | } | |
593 | ||
4dada3fd CY |
594 | leftmost = true; |
595 | ||
bf21acf9 JK |
596 | /* look up extent_node in the rb tree */ |
597 | while (*p) { | |
598 | parent = *p; | |
599 | en = rb_entry(parent, struct extent_node, rb_node); | |
600 | ||
601 | if (ei->fofs < en->ei.fofs) { | |
602 | p = &(*p)->rb_left; | |
603 | } else if (ei->fofs >= en->ei.fofs + en->ei.len) { | |
604 | p = &(*p)->rb_right; | |
605 | leftmost = false; | |
606 | } else { | |
607 | f2fs_bug_on(sbi, 1); | |
608 | } | |
609 | } | |
610 | ||
0f825ee6 | 611 | do_insert: |
4dada3fd | 612 | en = __attach_extent_node(sbi, et, ei, parent, p, leftmost); |
0f825ee6 FL |
613 | if (!en) |
614 | return NULL; | |
ef05e221 | 615 | |
b430f726 | 616 | __try_update_largest_extent(et, en); |
43a2fa18 JK |
617 | |
618 | /* update in global extent list */ | |
e7547dac JK |
619 | spin_lock(&eti->extent_lock); |
620 | list_add_tail(&en->list, &eti->extent_list); | |
42926744 | 621 | et->cached_en = en; |
e7547dac | 622 | spin_unlock(&eti->extent_lock); |
0f825ee6 FL |
623 | return en; |
624 | } | |
625 | ||
3fc5d5a1 CY |
626 | static unsigned int __destroy_extent_node(struct inode *inode, |
627 | enum extent_type type) | |
628 | { | |
629 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | |
630 | struct extent_tree *et = F2FS_I(inode)->extent_tree[type]; | |
631 | unsigned int nr_shrink = type == EX_READ ? | |
632 | READ_EXTENT_CACHE_SHRINK_NUMBER : | |
633 | AGE_EXTENT_CACHE_SHRINK_NUMBER; | |
634 | unsigned int node_cnt = 0; | |
635 | ||
636 | if (!et || !atomic_read(&et->node_cnt)) | |
637 | return 0; | |
638 | ||
639 | while (atomic_read(&et->node_cnt)) { | |
640 | write_lock(&et->lock); | |
641 | node_cnt += __free_extent_tree(sbi, et, nr_shrink); | |
642 | write_unlock(&et->lock); | |
643 | } | |
644 | ||
645 | f2fs_bug_on(sbi, atomic_read(&et->node_cnt)); | |
646 | ||
647 | return node_cnt; | |
648 | } | |
649 | ||
e7547dac JK |
650 | static void __update_extent_tree_range(struct inode *inode, |
651 | struct extent_info *tei, enum extent_type type) | |
a28ef1f5 CY |
652 | { |
653 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | |
e7547dac | 654 | struct extent_tree *et = F2FS_I(inode)->extent_tree[type]; |
4d1fa815 | 655 | struct extent_node *en = NULL, *en1 = NULL; |
19b2c30d | 656 | struct extent_node *prev_en = NULL, *next_en = NULL; |
a28ef1f5 | 657 | struct extent_info ei, dei, prev; |
0f825ee6 | 658 | struct rb_node **insert_p = NULL, *insert_parent = NULL; |
e7547dac | 659 | unsigned int fofs = tei->fofs, len = tei->len; |
19b2c30d | 660 | unsigned int end = fofs + len; |
b430f726 | 661 | bool updated = false; |
f9aa52a8 | 662 | bool leftmost = false; |
a28ef1f5 CY |
663 | |
664 | if (!et) | |
317e1300 | 665 | return; |
a28ef1f5 | 666 | |
e7547dac JK |
667 | if (type == EX_READ) |
668 | trace_f2fs_update_read_extent_tree_range(inode, fofs, len, | |
669 | tei->blk, 0); | |
71644dff JK |
670 | else if (type == EX_BLOCK_AGE) |
671 | trace_f2fs_update_age_extent_tree_range(inode, fofs, len, | |
672 | tei->age, tei->last_blocks); | |
673 | ||
a28ef1f5 CY |
674 | write_lock(&et->lock); |
675 | ||
e7547dac JK |
676 | if (type == EX_READ) { |
677 | if (is_inode_flag_set(inode, FI_NO_EXTENT)) { | |
678 | write_unlock(&et->lock); | |
679 | return; | |
680 | } | |
a28ef1f5 | 681 | |
e7547dac JK |
682 | prev = et->largest; |
683 | dei.len = 0; | |
a28ef1f5 | 684 | |
e7547dac JK |
685 | /* |
686 | * drop largest extent before lookup, in case it's already | |
687 | * been shrunk from extent tree | |
688 | */ | |
689 | __drop_largest_extent(et, fofs, len); | |
690 | } | |
a28ef1f5 | 691 | |
19b2c30d | 692 | /* 1. lookup first extent node in range [fofs, fofs + len - 1] */ |
bf21acf9 JK |
693 | en = __lookup_extent_node_ret(&et->root, |
694 | et->cached_en, fofs, | |
695 | &prev_en, &next_en, | |
696 | &insert_p, &insert_parent, | |
4dada3fd | 697 | &leftmost); |
4d1fa815 FL |
698 | if (!en) |
699 | en = next_en; | |
19b2c30d | 700 | |
146949de | 701 | /* 2. invalidate all extent nodes in range [fofs, fofs + len - 1] */ |
4d1fa815 FL |
702 | while (en && en->ei.fofs < end) { |
703 | unsigned int org_end; | |
704 | int parts = 0; /* # of parts current extent split into */ | |
19b2c30d | 705 | |
4d1fa815 | 706 | next_en = en1 = NULL; |
19b2c30d CY |
707 | |
708 | dei = en->ei; | |
4d1fa815 | 709 | org_end = dei.fofs + dei.len; |
e7547dac | 710 | f2fs_bug_on(sbi, fofs >= org_end); |
19b2c30d | 711 | |
e7547dac JK |
712 | if (fofs > dei.fofs && (type != EX_READ || |
713 | fofs - dei.fofs >= F2FS_MIN_EXTENT_LEN)) { | |
714 | en->ei.len = fofs - en->ei.fofs; | |
4d1fa815 FL |
715 | prev_en = en; |
716 | parts = 1; | |
717 | } | |
19b2c30d | 718 | |
e7547dac | 719 | if (end < org_end && (type != EX_READ || |
009a8241 CY |
720 | (org_end - end >= F2FS_MIN_EXTENT_LEN && |
721 | atomic_read(&et->node_cnt) < | |
722 | sbi->max_read_extent_count))) { | |
4d1fa815 | 723 | if (parts) { |
3bac20a8 JK |
724 | __set_extent_info(&ei, |
725 | end, org_end - end, | |
e7547dac | 726 | end - dei.fofs + dei.blk, false, |
71644dff | 727 | dei.age, dei.last_blocks, |
e7547dac | 728 | type); |
b430f726 | 729 | en1 = __insert_extent_tree(sbi, et, &ei, |
4dada3fd | 730 | NULL, NULL, true); |
4d1fa815 FL |
731 | next_en = en1; |
732 | } else { | |
3bac20a8 JK |
733 | __set_extent_info(&en->ei, |
734 | end, en->ei.len - (end - dei.fofs), | |
e7547dac | 735 | en->ei.blk + (end - dei.fofs), true, |
71644dff | 736 | dei.age, dei.last_blocks, |
e7547dac | 737 | type); |
4d1fa815 | 738 | next_en = en; |
19b2c30d | 739 | } |
4d1fa815 | 740 | parts++; |
19b2c30d CY |
741 | } |
742 | ||
4d1fa815 FL |
743 | if (!next_en) { |
744 | struct rb_node *node = rb_next(&en->rb_node); | |
19b2c30d | 745 | |
ed0b5620 GT |
746 | next_en = rb_entry_safe(node, struct extent_node, |
747 | rb_node); | |
a28ef1f5 CY |
748 | } |
749 | ||
4abd3f5a | 750 | if (parts) |
b430f726 | 751 | __try_update_largest_extent(et, en); |
4abd3f5a | 752 | else |
a03f01f2 | 753 | __release_extent_node(sbi, et, en); |
19b2c30d CY |
754 | |
755 | /* | |
4d1fa815 FL |
756 | * if original extent is split into zero or two parts, extent |
757 | * tree has been altered by deletion or insertion, therefore | |
758 | * invalidate pointers regard to tree. | |
19b2c30d | 759 | */ |
4d1fa815 FL |
760 | if (parts != 1) { |
761 | insert_p = NULL; | |
762 | insert_parent = NULL; | |
a28ef1f5 | 763 | } |
4d1fa815 | 764 | en = next_en; |
a28ef1f5 CY |
765 | } |
766 | ||
71644dff JK |
767 | if (type == EX_BLOCK_AGE) |
768 | goto update_age_extent_cache; | |
769 | ||
e7547dac JK |
770 | /* 3. update extent in read extent cache */ |
771 | BUG_ON(type != EX_READ); | |
772 | ||
773 | if (tei->blk) { | |
71644dff JK |
774 | __set_extent_info(&ei, fofs, len, tei->blk, false, |
775 | 0, 0, EX_READ); | |
b430f726 ZZ |
776 | if (!__try_merge_extent_node(sbi, et, &ei, prev_en, next_en)) |
777 | __insert_extent_tree(sbi, et, &ei, | |
4dada3fd | 778 | insert_p, insert_parent, leftmost); |
a28ef1f5 CY |
779 | |
780 | /* give up extent_cache, if split and small updates happen */ | |
781 | if (dei.len >= 1 && | |
782 | prev.len < F2FS_MIN_EXTENT_LEN && | |
783 | et->largest.len < F2FS_MIN_EXTENT_LEN) { | |
b430f726 ZZ |
784 | et->largest.len = 0; |
785 | et->largest_updated = true; | |
91942321 | 786 | set_inode_flag(inode, FI_NO_EXTENT); |
a28ef1f5 | 787 | } |
19b2c30d | 788 | } |
a28ef1f5 | 789 | |
b430f726 ZZ |
790 | if (et->largest_updated) { |
791 | et->largest_updated = false; | |
792 | updated = true; | |
793 | } | |
71644dff JK |
794 | goto out_read_extent_cache; |
795 | update_age_extent_cache: | |
796 | if (!tei->last_blocks) | |
797 | goto out_read_extent_cache; | |
b430f726 | 798 | |
71644dff JK |
799 | __set_extent_info(&ei, fofs, len, 0, false, |
800 | tei->age, tei->last_blocks, EX_BLOCK_AGE); | |
801 | if (!__try_merge_extent_node(sbi, et, &ei, prev_en, next_en)) | |
802 | __insert_extent_tree(sbi, et, &ei, | |
803 | insert_p, insert_parent, leftmost); | |
804 | out_read_extent_cache: | |
a28ef1f5 | 805 | write_unlock(&et->lock); |
b430f726 | 806 | |
3fc5d5a1 CY |
807 | if (is_inode_flag_set(inode, FI_NO_EXTENT)) |
808 | __destroy_extent_node(inode, EX_READ); | |
809 | ||
b430f726 ZZ |
810 | if (updated) |
811 | f2fs_mark_inode_dirty_sync(inode, true); | |
a28ef1f5 CY |
812 | } |
813 | ||
94afd6d6 | 814 | #ifdef CONFIG_F2FS_FS_COMPRESSION |
e7547dac | 815 | void f2fs_update_read_extent_tree_range_compressed(struct inode *inode, |
94afd6d6 CY |
816 | pgoff_t fofs, block_t blkaddr, unsigned int llen, |
817 | unsigned int c_len) | |
818 | { | |
819 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | |
e7547dac | 820 | struct extent_tree *et = F2FS_I(inode)->extent_tree[EX_READ]; |
94afd6d6 CY |
821 | struct extent_node *en = NULL; |
822 | struct extent_node *prev_en = NULL, *next_en = NULL; | |
823 | struct extent_info ei; | |
824 | struct rb_node **insert_p = NULL, *insert_parent = NULL; | |
825 | bool leftmost = false; | |
826 | ||
e7547dac JK |
827 | trace_f2fs_update_read_extent_tree_range(inode, fofs, llen, |
828 | blkaddr, c_len); | |
94afd6d6 CY |
829 | |
830 | /* it is safe here to check FI_NO_EXTENT w/o et->lock in ro image */ | |
831 | if (is_inode_flag_set(inode, FI_NO_EXTENT)) | |
832 | return; | |
833 | ||
834 | write_lock(&et->lock); | |
835 | ||
bf21acf9 JK |
836 | en = __lookup_extent_node_ret(&et->root, |
837 | et->cached_en, fofs, | |
838 | &prev_en, &next_en, | |
839 | &insert_p, &insert_parent, | |
840 | &leftmost); | |
94afd6d6 CY |
841 | if (en) |
842 | goto unlock_out; | |
843 | ||
71644dff | 844 | __set_extent_info(&ei, fofs, llen, blkaddr, true, 0, 0, EX_READ); |
94afd6d6 CY |
845 | ei.c_len = c_len; |
846 | ||
847 | if (!__try_merge_extent_node(sbi, et, &ei, prev_en, next_en)) | |
848 | __insert_extent_tree(sbi, et, &ei, | |
849 | insert_p, insert_parent, leftmost); | |
850 | unlock_out: | |
851 | write_unlock(&et->lock); | |
852 | } | |
853 | #endif | |
854 | ||
d23be468 | 855 | static unsigned long long __calculate_block_age(struct f2fs_sb_info *sbi, |
856 | unsigned long long new, | |
71644dff JK |
857 | unsigned long long old) |
858 | { | |
b03a41a4 | 859 | unsigned int rem_old, rem_new; |
860 | unsigned long long res; | |
d23be468 | 861 | unsigned int weight = sbi->last_age_weight; |
71644dff | 862 | |
d23be468 | 863 | res = div_u64_rem(new, 100, &rem_new) * (100 - weight) |
864 | + div_u64_rem(old, 100, &rem_old) * weight; | |
71644dff | 865 | |
b03a41a4 | 866 | if (rem_new) |
d23be468 | 867 | res += rem_new * (100 - weight) / 100; |
b03a41a4 | 868 | if (rem_old) |
d23be468 | 869 | res += rem_old * weight / 100; |
b03a41a4 | 870 | |
871 | return res; | |
71644dff JK |
872 | } |
873 | ||
874 | /* This returns a new age and allocated blocks in ei */ | |
ed272476 JK |
875 | static int __get_new_block_age(struct inode *inode, struct extent_info *ei, |
876 | block_t blkaddr) | |
71644dff JK |
877 | { |
878 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | |
879 | loff_t f_size = i_size_read(inode); | |
880 | unsigned long long cur_blocks = | |
881 | atomic64_read(&sbi->allocated_data_blocks); | |
22a341b4 | 882 | struct extent_info tei = *ei; /* only fofs and len are valid */ |
71644dff JK |
883 | |
884 | /* | |
885 | * When I/O is not aligned to a PAGE_SIZE, update will happen to the last | |
886 | * file block even in seq write. So don't record age for newly last file | |
887 | * block here. | |
888 | */ | |
889 | if ((f_size >> PAGE_SHIFT) == ei->fofs && f_size & (PAGE_SIZE - 1) && | |
ed272476 | 890 | blkaddr == NEW_ADDR) |
71644dff JK |
891 | return -EINVAL; |
892 | ||
22a341b4 | 893 | if (__lookup_extent_tree(inode, ei->fofs, &tei, EX_BLOCK_AGE)) { |
71644dff JK |
894 | unsigned long long cur_age; |
895 | ||
22a341b4 JK |
896 | if (cur_blocks >= tei.last_blocks) |
897 | cur_age = cur_blocks - tei.last_blocks; | |
71644dff JK |
898 | else |
899 | /* allocated_data_blocks overflow */ | |
22a341b4 | 900 | cur_age = ULLONG_MAX - tei.last_blocks + cur_blocks; |
71644dff | 901 | |
22a341b4 | 902 | if (tei.age) |
d23be468 | 903 | ei->age = __calculate_block_age(sbi, cur_age, tei.age); |
71644dff JK |
904 | else |
905 | ei->age = cur_age; | |
906 | ei->last_blocks = cur_blocks; | |
907 | WARN_ON(ei->age > cur_blocks); | |
908 | return 0; | |
909 | } | |
910 | ||
ed272476 | 911 | f2fs_bug_on(sbi, blkaddr == NULL_ADDR); |
71644dff JK |
912 | |
913 | /* the data block was allocated for the first time */ | |
ed272476 | 914 | if (blkaddr == NEW_ADDR) |
71644dff JK |
915 | goto out; |
916 | ||
ed272476 | 917 | if (__is_valid_data_blkaddr(blkaddr) && |
31f85ccc | 918 | !f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC_ENHANCE)) |
71644dff | 919 | return -EINVAL; |
71644dff JK |
920 | out: |
921 | /* | |
922 | * init block age with zero, this can happen when the block age extent | |
923 | * was reclaimed due to memory constraint or system reboot | |
924 | */ | |
925 | ei->age = 0; | |
926 | ei->last_blocks = cur_blocks; | |
927 | return 0; | |
928 | } | |
929 | ||
e7547dac | 930 | static void __update_extent_cache(struct dnode_of_data *dn, enum extent_type type) |
a28ef1f5 | 931 | { |
fe59109a | 932 | struct extent_info ei = {}; |
e7547dac JK |
933 | |
934 | if (!__may_extent_tree(dn->inode, type)) | |
935 | return; | |
936 | ||
6f7ec661 | 937 | ei.fofs = f2fs_start_bidx_of_node(ofs_of_node(&dn->node_folio->page), dn->inode) + |
e7547dac JK |
938 | dn->ofs_in_node; |
939 | ei.len = 1; | |
940 | ||
941 | if (type == EX_READ) { | |
942 | if (dn->data_blkaddr == NEW_ADDR) | |
943 | ei.blk = NULL_ADDR; | |
944 | else | |
945 | ei.blk = dn->data_blkaddr; | |
71644dff | 946 | } else if (type == EX_BLOCK_AGE) { |
ed272476 | 947 | if (__get_new_block_age(dn->inode, &ei, dn->data_blkaddr)) |
71644dff | 948 | return; |
e7547dac JK |
949 | } |
950 | __update_extent_tree_range(dn->inode, &ei, type); | |
951 | } | |
952 | ||
953 | static unsigned int __shrink_extent_tree(struct f2fs_sb_info *sbi, int nr_shrink, | |
954 | enum extent_type type) | |
955 | { | |
956 | struct extent_tree_info *eti = &sbi->extent_tree[type]; | |
137d09f0 | 957 | struct extent_tree *et, *next; |
201ef5e0 | 958 | struct extent_node *en; |
a28ef1f5 CY |
959 | unsigned int node_cnt = 0, tree_cnt = 0; |
960 | int remained; | |
961 | ||
e7547dac | 962 | if (!atomic_read(&eti->total_zombie_tree)) |
74fd8d99 JK |
963 | goto free_node; |
964 | ||
e7547dac | 965 | if (!mutex_trylock(&eti->extent_tree_lock)) |
a28ef1f5 CY |
966 | goto out; |
967 | ||
968 | /* 1. remove unreferenced extent tree */ | |
e7547dac | 969 | list_for_each_entry_safe(et, next, &eti->zombie_list, list) { |
9b72a388 CY |
970 | if (atomic_read(&et->node_cnt)) { |
971 | write_lock(&et->lock); | |
3fc5d5a1 CY |
972 | node_cnt += __free_extent_tree(sbi, et, |
973 | nr_shrink - node_cnt - tree_cnt); | |
9b72a388 CY |
974 | write_unlock(&et->lock); |
975 | } | |
3fc5d5a1 CY |
976 | |
977 | if (atomic_read(&et->node_cnt)) | |
978 | goto unlock_out; | |
979 | ||
137d09f0 | 980 | list_del_init(&et->list); |
e7547dac | 981 | radix_tree_delete(&eti->extent_tree_root, et->ino); |
137d09f0 | 982 | kmem_cache_free(extent_tree_slab, et); |
e7547dac JK |
983 | atomic_dec(&eti->total_ext_tree); |
984 | atomic_dec(&eti->total_zombie_tree); | |
137d09f0 | 985 | tree_cnt++; |
a28ef1f5 | 986 | |
137d09f0 JK |
987 | if (node_cnt + tree_cnt >= nr_shrink) |
988 | goto unlock_out; | |
6fe2bc95 | 989 | cond_resched(); |
a28ef1f5 | 990 | } |
e7547dac | 991 | mutex_unlock(&eti->extent_tree_lock); |
a28ef1f5 | 992 | |
74fd8d99 | 993 | free_node: |
a28ef1f5 | 994 | /* 2. remove LRU extent entries */ |
e7547dac | 995 | if (!mutex_trylock(&eti->extent_tree_lock)) |
a28ef1f5 CY |
996 | goto out; |
997 | ||
998 | remained = nr_shrink - (node_cnt + tree_cnt); | |
999 | ||
e7547dac | 1000 | spin_lock(&eti->extent_lock); |
201ef5e0 | 1001 | for (; remained > 0; remained--) { |
e7547dac | 1002 | if (list_empty(&eti->extent_list)) |
a28ef1f5 | 1003 | break; |
e7547dac | 1004 | en = list_first_entry(&eti->extent_list, |
201ef5e0 HP |
1005 | struct extent_node, list); |
1006 | et = en->et; | |
1007 | if (!write_trylock(&et->lock)) { | |
1008 | /* refresh this extent node's position in extent list */ | |
e7547dac | 1009 | list_move_tail(&en->list, &eti->extent_list); |
201ef5e0 HP |
1010 | continue; |
1011 | } | |
a28ef1f5 | 1012 | |
201ef5e0 | 1013 | list_del_init(&en->list); |
e7547dac | 1014 | spin_unlock(&eti->extent_lock); |
9b72a388 | 1015 | |
201ef5e0 | 1016 | __detach_extent_node(sbi, et, en); |
a28ef1f5 | 1017 | |
201ef5e0 HP |
1018 | write_unlock(&et->lock); |
1019 | node_cnt++; | |
e7547dac | 1020 | spin_lock(&eti->extent_lock); |
a28ef1f5 | 1021 | } |
e7547dac | 1022 | spin_unlock(&eti->extent_lock); |
201ef5e0 | 1023 | |
a28ef1f5 | 1024 | unlock_out: |
e7547dac | 1025 | mutex_unlock(&eti->extent_tree_lock); |
a28ef1f5 | 1026 | out: |
e7547dac | 1027 | trace_f2fs_shrink_extent_tree(sbi, node_cnt, tree_cnt, type); |
a28ef1f5 CY |
1028 | |
1029 | return node_cnt + tree_cnt; | |
1030 | } | |
1031 | ||
e7547dac JK |
1032 | /* read extent cache operations */ |
1033 | bool f2fs_lookup_read_extent_cache(struct inode *inode, pgoff_t pgofs, | |
1034 | struct extent_info *ei) | |
1035 | { | |
1036 | if (!__may_extent_tree(inode, EX_READ)) | |
1037 | return false; | |
1038 | ||
1039 | return __lookup_extent_tree(inode, pgofs, ei, EX_READ); | |
1040 | } | |
1041 | ||
04a91ab0 CH |
1042 | bool f2fs_lookup_read_extent_cache_block(struct inode *inode, pgoff_t index, |
1043 | block_t *blkaddr) | |
1044 | { | |
1045 | struct extent_info ei = {}; | |
1046 | ||
1047 | if (!f2fs_lookup_read_extent_cache(inode, index, &ei)) | |
1048 | return false; | |
1049 | *blkaddr = ei.blk + index - ei.fofs; | |
1050 | return true; | |
1051 | } | |
1052 | ||
e7547dac JK |
1053 | void f2fs_update_read_extent_cache(struct dnode_of_data *dn) |
1054 | { | |
1055 | return __update_extent_cache(dn, EX_READ); | |
1056 | } | |
1057 | ||
1058 | void f2fs_update_read_extent_cache_range(struct dnode_of_data *dn, | |
1059 | pgoff_t fofs, block_t blkaddr, unsigned int len) | |
1060 | { | |
1061 | struct extent_info ei = { | |
1062 | .fofs = fofs, | |
1063 | .len = len, | |
1064 | .blk = blkaddr, | |
1065 | }; | |
1066 | ||
1067 | if (!__may_extent_tree(dn->inode, EX_READ)) | |
1068 | return; | |
1069 | ||
1070 | __update_extent_tree_range(dn->inode, &ei, EX_READ); | |
1071 | } | |
1072 | ||
1073 | unsigned int f2fs_shrink_read_extent_tree(struct f2fs_sb_info *sbi, int nr_shrink) | |
1074 | { | |
1075 | if (!test_opt(sbi, READ_EXTENT_CACHE)) | |
1076 | return 0; | |
1077 | ||
1078 | return __shrink_extent_tree(sbi, nr_shrink, EX_READ); | |
1079 | } | |
1080 | ||
71644dff JK |
1081 | /* block age extent cache operations */ |
1082 | bool f2fs_lookup_age_extent_cache(struct inode *inode, pgoff_t pgofs, | |
1083 | struct extent_info *ei) | |
1084 | { | |
1085 | if (!__may_extent_tree(inode, EX_BLOCK_AGE)) | |
1086 | return false; | |
1087 | ||
1088 | return __lookup_extent_tree(inode, pgofs, ei, EX_BLOCK_AGE); | |
1089 | } | |
1090 | ||
1091 | void f2fs_update_age_extent_cache(struct dnode_of_data *dn) | |
1092 | { | |
1093 | return __update_extent_cache(dn, EX_BLOCK_AGE); | |
1094 | } | |
1095 | ||
1096 | void f2fs_update_age_extent_cache_range(struct dnode_of_data *dn, | |
1097 | pgoff_t fofs, unsigned int len) | |
1098 | { | |
1099 | struct extent_info ei = { | |
1100 | .fofs = fofs, | |
1101 | .len = len, | |
1102 | }; | |
1103 | ||
1104 | if (!__may_extent_tree(dn->inode, EX_BLOCK_AGE)) | |
1105 | return; | |
1106 | ||
1107 | __update_extent_tree_range(dn->inode, &ei, EX_BLOCK_AGE); | |
1108 | } | |
1109 | ||
1110 | unsigned int f2fs_shrink_age_extent_tree(struct f2fs_sb_info *sbi, int nr_shrink) | |
1111 | { | |
1112 | if (!test_opt(sbi, AGE_EXTENT_CACHE)) | |
1113 | return 0; | |
1114 | ||
1115 | return __shrink_extent_tree(sbi, nr_shrink, EX_BLOCK_AGE); | |
1116 | } | |
1117 | ||
e7547dac JK |
1118 | void f2fs_destroy_extent_node(struct inode *inode) |
1119 | { | |
1120 | __destroy_extent_node(inode, EX_READ); | |
71644dff | 1121 | __destroy_extent_node(inode, EX_BLOCK_AGE); |
e7547dac JK |
1122 | } |
1123 | ||
1124 | static void __drop_extent_tree(struct inode *inode, enum extent_type type) | |
5f281fab | 1125 | { |
e7547dac | 1126 | struct extent_tree *et = F2FS_I(inode)->extent_tree[type]; |
b430f726 | 1127 | bool updated = false; |
5f281fab | 1128 | |
e7547dac | 1129 | if (!__may_extent_tree(inode, type)) |
bf617f7a CY |
1130 | return; |
1131 | ||
5f281fab | 1132 | write_lock(&et->lock); |
e7547dac JK |
1133 | if (type == EX_READ) { |
1134 | set_inode_flag(inode, FI_NO_EXTENT); | |
1135 | if (et->largest.len) { | |
1136 | et->largest.len = 0; | |
1137 | updated = true; | |
1138 | } | |
b430f726 | 1139 | } |
5f281fab | 1140 | write_unlock(&et->lock); |
3fc5d5a1 CY |
1141 | |
1142 | __destroy_extent_node(inode, type); | |
1143 | ||
b430f726 ZZ |
1144 | if (updated) |
1145 | f2fs_mark_inode_dirty_sync(inode, true); | |
5f281fab JK |
1146 | } |
1147 | ||
e7547dac JK |
1148 | void f2fs_drop_extent_tree(struct inode *inode) |
1149 | { | |
1150 | __drop_extent_tree(inode, EX_READ); | |
71644dff | 1151 | __drop_extent_tree(inode, EX_BLOCK_AGE); |
e7547dac JK |
1152 | } |
1153 | ||
1154 | static void __destroy_extent_tree(struct inode *inode, enum extent_type type) | |
a28ef1f5 CY |
1155 | { |
1156 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | |
e7547dac JK |
1157 | struct extent_tree_info *eti = &sbi->extent_tree[type]; |
1158 | struct extent_tree *et = F2FS_I(inode)->extent_tree[type]; | |
a28ef1f5 CY |
1159 | unsigned int node_cnt = 0; |
1160 | ||
1161 | if (!et) | |
1162 | return; | |
1163 | ||
68e35385 CY |
1164 | if (inode->i_nlink && !is_bad_inode(inode) && |
1165 | atomic_read(&et->node_cnt)) { | |
e7547dac JK |
1166 | mutex_lock(&eti->extent_tree_lock); |
1167 | list_add_tail(&et->list, &eti->zombie_list); | |
1168 | atomic_inc(&eti->total_zombie_tree); | |
1169 | mutex_unlock(&eti->extent_tree_lock); | |
a28ef1f5 CY |
1170 | return; |
1171 | } | |
1172 | ||
1173 | /* free all extent info belong to this extent tree */ | |
e7547dac | 1174 | node_cnt = __destroy_extent_node(inode, type); |
a28ef1f5 CY |
1175 | |
1176 | /* delete extent tree entry in radix tree */ | |
e7547dac | 1177 | mutex_lock(&eti->extent_tree_lock); |
68e35385 | 1178 | f2fs_bug_on(sbi, atomic_read(&et->node_cnt)); |
e7547dac | 1179 | radix_tree_delete(&eti->extent_tree_root, inode->i_ino); |
a28ef1f5 | 1180 | kmem_cache_free(extent_tree_slab, et); |
e7547dac JK |
1181 | atomic_dec(&eti->total_ext_tree); |
1182 | mutex_unlock(&eti->extent_tree_lock); | |
a28ef1f5 | 1183 | |
e7547dac | 1184 | F2FS_I(inode)->extent_tree[type] = NULL; |
a28ef1f5 | 1185 | |
e7547dac | 1186 | trace_f2fs_destroy_extent_tree(inode, node_cnt, type); |
a28ef1f5 CY |
1187 | } |
1188 | ||
e7547dac | 1189 | void f2fs_destroy_extent_tree(struct inode *inode) |
a28ef1f5 | 1190 | { |
e7547dac | 1191 | __destroy_extent_tree(inode, EX_READ); |
71644dff | 1192 | __destroy_extent_tree(inode, EX_BLOCK_AGE); |
19b2c30d CY |
1193 | } |
1194 | ||
e7547dac | 1195 | static void __init_extent_tree_info(struct extent_tree_info *eti) |
19b2c30d | 1196 | { |
e7547dac JK |
1197 | INIT_RADIX_TREE(&eti->extent_tree_root, GFP_NOIO); |
1198 | mutex_init(&eti->extent_tree_lock); | |
1199 | INIT_LIST_HEAD(&eti->extent_list); | |
1200 | spin_lock_init(&eti->extent_lock); | |
1201 | atomic_set(&eti->total_ext_tree, 0); | |
1202 | INIT_LIST_HEAD(&eti->zombie_list); | |
1203 | atomic_set(&eti->total_zombie_tree, 0); | |
1204 | atomic_set(&eti->total_ext_node, 0); | |
a28ef1f5 CY |
1205 | } |
1206 | ||
4d57b86d | 1207 | void f2fs_init_extent_cache_info(struct f2fs_sb_info *sbi) |
a28ef1f5 | 1208 | { |
e7547dac | 1209 | __init_extent_tree_info(&sbi->extent_tree[EX_READ]); |
71644dff JK |
1210 | __init_extent_tree_info(&sbi->extent_tree[EX_BLOCK_AGE]); |
1211 | ||
1212 | /* initialize for block age extents */ | |
1213 | atomic64_set(&sbi->allocated_data_blocks, 0); | |
1214 | sbi->hot_data_age_threshold = DEF_HOT_DATA_AGE_THRESHOLD; | |
1215 | sbi->warm_data_age_threshold = DEF_WARM_DATA_AGE_THRESHOLD; | |
d23be468 | 1216 | sbi->last_age_weight = LAST_AGE_WEIGHT; |
009a8241 | 1217 | sbi->max_read_extent_count = DEF_MAX_READ_EXTENT_COUNT; |
a28ef1f5 CY |
1218 | } |
1219 | ||
4d57b86d | 1220 | int __init f2fs_create_extent_cache(void) |
a28ef1f5 CY |
1221 | { |
1222 | extent_tree_slab = f2fs_kmem_cache_create("f2fs_extent_tree", | |
1223 | sizeof(struct extent_tree)); | |
1224 | if (!extent_tree_slab) | |
1225 | return -ENOMEM; | |
1226 | extent_node_slab = f2fs_kmem_cache_create("f2fs_extent_node", | |
1227 | sizeof(struct extent_node)); | |
1228 | if (!extent_node_slab) { | |
1229 | kmem_cache_destroy(extent_tree_slab); | |
1230 | return -ENOMEM; | |
1231 | } | |
1232 | return 0; | |
1233 | } | |
1234 | ||
4d57b86d | 1235 | void f2fs_destroy_extent_cache(void) |
a28ef1f5 CY |
1236 | { |
1237 | kmem_cache_destroy(extent_node_slab); | |
1238 | kmem_cache_destroy(extent_tree_slab); | |
1239 | } |