1 /* 2 * f2fs extent cache support 3 * 4 * Copyright (c) 2015 Motorola Mobility 5 * Copyright (c) 2015 Samsung Electronics 6 * Authors: Jaegeuk Kim <jaegeuk@kernel.org> 7 * Chao Yu <chao2.yu@samsung.com> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 */ 13 14 #include <linux/fs.h> 15 #include <linux/f2fs_fs.h> 16 17 #include "f2fs.h" 18 #include "node.h" 19 #include <trace/events/f2fs.h> 20 21 static struct kmem_cache *extent_tree_slab; 22 static struct kmem_cache *extent_node_slab; 23 24 static struct extent_node *__attach_extent_node(struct f2fs_sb_info *sbi, 25 struct extent_tree *et, struct extent_info *ei, 26 struct rb_node *parent, struct rb_node **p) 27 { 28 struct extent_node *en; 29 30 en = kmem_cache_alloc(extent_node_slab, GFP_ATOMIC); 31 if (!en) 32 return NULL; 33 34 en->ei = *ei; 35 INIT_LIST_HEAD(&en->list); 36 37 rb_link_node(&en->rb_node, parent, p); 38 rb_insert_color(&en->rb_node, &et->root); 39 et->count++; 40 atomic_inc(&sbi->total_ext_node); 41 return en; 42 } 43 44 static void __detach_extent_node(struct f2fs_sb_info *sbi, 45 struct extent_tree *et, struct extent_node *en) 46 { 47 rb_erase(&en->rb_node, &et->root); 48 et->count--; 49 atomic_dec(&sbi->total_ext_node); 50 51 if (et->cached_en == en) 52 et->cached_en = NULL; 53 } 54 55 static struct extent_tree *__grab_extent_tree(struct inode *inode) 56 { 57 struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 58 struct extent_tree *et; 59 nid_t ino = inode->i_ino; 60 61 down_write(&sbi->extent_tree_lock); 62 et = radix_tree_lookup(&sbi->extent_tree_root, ino); 63 if (!et) { 64 et = f2fs_kmem_cache_alloc(extent_tree_slab, GFP_NOFS); 65 f2fs_radix_tree_insert(&sbi->extent_tree_root, ino, et); 66 memset(et, 0, sizeof(struct extent_tree)); 67 et->ino = ino; 68 et->root = RB_ROOT; 69 et->cached_en = NULL; 70 rwlock_init(&et->lock); 71 atomic_set(&et->refcount, 0); 72 et->count = 0; 73 sbi->total_ext_tree++; 74 } 75 atomic_inc(&et->refcount); 76 up_write(&sbi->extent_tree_lock); 77 78 /* never died until evict_inode */ 79 F2FS_I(inode)->extent_tree = et; 80 81 return et; 82 } 83 84 static struct extent_node *__lookup_extent_tree(struct f2fs_sb_info *sbi, 85 struct extent_tree *et, unsigned int fofs) 86 { 87 struct rb_node *node = et->root.rb_node; 88 struct extent_node *en = et->cached_en; 89 90 if (en) { 91 struct extent_info *cei = &en->ei; 92 93 if (cei->fofs <= fofs && cei->fofs + cei->len > fofs) { 94 stat_inc_cached_node_hit(sbi); 95 return en; 96 } 97 } 98 99 while (node) { 100 en = rb_entry(node, struct extent_node, rb_node); 101 102 if (fofs < en->ei.fofs) { 103 node = node->rb_left; 104 } else if (fofs >= en->ei.fofs + en->ei.len) { 105 node = node->rb_right; 106 } else { 107 stat_inc_rbtree_node_hit(sbi); 108 return en; 109 } 110 } 111 return NULL; 112 } 113 114 static struct extent_node *__init_extent_tree(struct f2fs_sb_info *sbi, 115 struct extent_tree *et, struct extent_info *ei) 116 { 117 struct rb_node **p = &et->root.rb_node; 118 struct extent_node *en; 119 120 en = __attach_extent_node(sbi, et, ei, NULL, p); 121 if (!en) 122 return NULL; 123 124 et->largest = en->ei; 125 et->cached_en = en; 126 return en; 127 } 128 129 static unsigned int __free_extent_tree(struct f2fs_sb_info *sbi, 130 struct extent_tree *et, bool free_all) 131 { 132 struct rb_node *node, *next; 133 struct extent_node *en; 134 unsigned int count = et->count; 135 136 node = rb_first(&et->root); 137 while (node) { 138 next = rb_next(node); 139 en = rb_entry(node, struct extent_node, rb_node); 140 141 if (free_all) { 142 spin_lock(&sbi->extent_lock); 143 if (!list_empty(&en->list)) 144 list_del_init(&en->list); 145 spin_unlock(&sbi->extent_lock); 146 } 147 148 if (free_all || list_empty(&en->list)) { 149 __detach_extent_node(sbi, et, en); 150 kmem_cache_free(extent_node_slab, en); 151 } 152 node = next; 153 } 154 155 return count - et->count; 156 } 157 158 static void __drop_largest_extent(struct inode *inode, 159 pgoff_t fofs, unsigned int len) 160 { 161 struct extent_info *largest = &F2FS_I(inode)->extent_tree->largest; 162 163 if (fofs < largest->fofs + largest->len && fofs + len > largest->fofs) 164 largest->len = 0; 165 } 166 167 void f2fs_drop_largest_extent(struct inode *inode, pgoff_t fofs) 168 { 169 if (!f2fs_may_extent_tree(inode)) 170 return; 171 172 __drop_largest_extent(inode, fofs, 1); 173 } 174 175 void f2fs_init_extent_tree(struct inode *inode, struct f2fs_extent *i_ext) 176 { 177 struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 178 struct extent_tree *et; 179 struct extent_node *en; 180 struct extent_info ei; 181 182 if (!f2fs_may_extent_tree(inode)) 183 return; 184 185 et = __grab_extent_tree(inode); 186 187 if (!i_ext || le32_to_cpu(i_ext->len) < F2FS_MIN_EXTENT_LEN) 188 return; 189 190 set_extent_info(&ei, le32_to_cpu(i_ext->fofs), 191 le32_to_cpu(i_ext->blk), le32_to_cpu(i_ext->len)); 192 193 write_lock(&et->lock); 194 if (et->count) 195 goto out; 196 197 en = __init_extent_tree(sbi, et, &ei); 198 if (en) { 199 spin_lock(&sbi->extent_lock); 200 list_add_tail(&en->list, &sbi->extent_list); 201 spin_unlock(&sbi->extent_lock); 202 } 203 out: 204 write_unlock(&et->lock); 205 } 206 207 static bool f2fs_lookup_extent_tree(struct inode *inode, pgoff_t pgofs, 208 struct extent_info *ei) 209 { 210 struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 211 struct extent_tree *et = F2FS_I(inode)->extent_tree; 212 struct extent_node *en; 213 bool ret = false; 214 215 f2fs_bug_on(sbi, !et); 216 217 trace_f2fs_lookup_extent_tree_start(inode, pgofs); 218 219 read_lock(&et->lock); 220 221 if (et->largest.fofs <= pgofs && 222 et->largest.fofs + et->largest.len > pgofs) { 223 *ei = et->largest; 224 ret = true; 225 stat_inc_largest_node_hit(sbi); 226 goto out; 227 } 228 229 en = __lookup_extent_tree(sbi, et, pgofs); 230 if (en) { 231 *ei = en->ei; 232 spin_lock(&sbi->extent_lock); 233 if (!list_empty(&en->list)) 234 list_move_tail(&en->list, &sbi->extent_list); 235 et->cached_en = en; 236 spin_unlock(&sbi->extent_lock); 237 ret = true; 238 } 239 out: 240 stat_inc_total_hit(sbi); 241 read_unlock(&et->lock); 242 243 trace_f2fs_lookup_extent_tree_end(inode, pgofs, ei); 244 return ret; 245 } 246 247 248 /* 249 * lookup extent at @fofs, if hit, return the extent 250 * if not, return NULL and 251 * @prev_ex: extent before fofs 252 * @next_ex: extent after fofs 253 * @insert_p: insert point for new extent at fofs 254 * in order to simpfy the insertion after. 255 * tree must stay unchanged between lookup and insertion. 256 */ 257 static struct extent_node *__lookup_extent_tree_ret(struct extent_tree *et, 258 unsigned int fofs, 259 struct extent_node **prev_ex, 260 struct extent_node **next_ex, 261 struct rb_node ***insert_p, 262 struct rb_node **insert_parent) 263 { 264 struct rb_node **pnode = &et->root.rb_node; 265 struct rb_node *parent = NULL, *tmp_node; 266 struct extent_node *en = et->cached_en; 267 268 *insert_p = NULL; 269 *insert_parent = NULL; 270 *prev_ex = NULL; 271 *next_ex = NULL; 272 273 if (RB_EMPTY_ROOT(&et->root)) 274 return NULL; 275 276 if (en) { 277 struct extent_info *cei = &en->ei; 278 279 if (cei->fofs <= fofs && cei->fofs + cei->len > fofs) 280 goto lookup_neighbors; 281 } 282 283 while (*pnode) { 284 parent = *pnode; 285 en = rb_entry(*pnode, struct extent_node, rb_node); 286 287 if (fofs < en->ei.fofs) 288 pnode = &(*pnode)->rb_left; 289 else if (fofs >= en->ei.fofs + en->ei.len) 290 pnode = &(*pnode)->rb_right; 291 else 292 goto lookup_neighbors; 293 } 294 295 *insert_p = pnode; 296 *insert_parent = parent; 297 298 en = rb_entry(parent, struct extent_node, rb_node); 299 tmp_node = parent; 300 if (parent && fofs > en->ei.fofs) 301 tmp_node = rb_next(parent); 302 *next_ex = tmp_node ? 303 rb_entry(tmp_node, struct extent_node, rb_node) : NULL; 304 305 tmp_node = parent; 306 if (parent && fofs < en->ei.fofs) 307 tmp_node = rb_prev(parent); 308 *prev_ex = tmp_node ? 309 rb_entry(tmp_node, struct extent_node, rb_node) : NULL; 310 return NULL; 311 312 lookup_neighbors: 313 if (fofs == en->ei.fofs) { 314 /* lookup prev node for merging backward later */ 315 tmp_node = rb_prev(&en->rb_node); 316 *prev_ex = tmp_node ? 317 rb_entry(tmp_node, struct extent_node, rb_node) : NULL; 318 } 319 if (fofs == en->ei.fofs + en->ei.len - 1) { 320 /* lookup next node for merging frontward later */ 321 tmp_node = rb_next(&en->rb_node); 322 *next_ex = tmp_node ? 323 rb_entry(tmp_node, struct extent_node, rb_node) : NULL; 324 } 325 return en; 326 } 327 328 static struct extent_node *__try_merge_extent_node(struct f2fs_sb_info *sbi, 329 struct extent_tree *et, struct extent_info *ei, 330 struct extent_node **den, 331 struct extent_node *prev_ex, 332 struct extent_node *next_ex) 333 { 334 struct extent_node *en = NULL; 335 336 if (prev_ex && __is_back_mergeable(ei, &prev_ex->ei)) { 337 prev_ex->ei.len += ei->len; 338 ei = &prev_ex->ei; 339 en = prev_ex; 340 } 341 342 if (next_ex && __is_front_mergeable(ei, &next_ex->ei)) { 343 if (en) { 344 __detach_extent_node(sbi, et, prev_ex); 345 *den = prev_ex; 346 } 347 next_ex->ei.fofs = ei->fofs; 348 next_ex->ei.blk = ei->blk; 349 next_ex->ei.len += ei->len; 350 en = next_ex; 351 } 352 353 if (en) { 354 __try_update_largest_extent(et, en); 355 et->cached_en = en; 356 } 357 return en; 358 } 359 360 static struct extent_node *__insert_extent_tree(struct f2fs_sb_info *sbi, 361 struct extent_tree *et, struct extent_info *ei, 362 struct rb_node **insert_p, 363 struct rb_node *insert_parent) 364 { 365 struct rb_node **p = &et->root.rb_node; 366 struct rb_node *parent = NULL; 367 struct extent_node *en = NULL; 368 369 if (insert_p && insert_parent) { 370 parent = insert_parent; 371 p = insert_p; 372 goto do_insert; 373 } 374 375 while (*p) { 376 parent = *p; 377 en = rb_entry(parent, struct extent_node, rb_node); 378 379 if (ei->fofs < en->ei.fofs) 380 p = &(*p)->rb_left; 381 else if (ei->fofs >= en->ei.fofs + en->ei.len) 382 p = &(*p)->rb_right; 383 else 384 f2fs_bug_on(sbi, 1); 385 } 386 do_insert: 387 en = __attach_extent_node(sbi, et, ei, parent, p); 388 if (!en) 389 return NULL; 390 391 __try_update_largest_extent(et, en); 392 et->cached_en = en; 393 return en; 394 } 395 396 static unsigned int f2fs_update_extent_tree_range(struct inode *inode, 397 pgoff_t fofs, block_t blkaddr, unsigned int len) 398 { 399 struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 400 struct extent_tree *et = F2FS_I(inode)->extent_tree; 401 struct extent_node *en = NULL, *en1 = NULL; 402 struct extent_node *prev_en = NULL, *next_en = NULL; 403 struct extent_info ei, dei, prev; 404 struct rb_node **insert_p = NULL, *insert_parent = NULL; 405 unsigned int end = fofs + len; 406 unsigned int pos = (unsigned int)fofs; 407 408 if (!et) 409 return false; 410 411 trace_f2fs_update_extent_tree_range(inode, fofs, blkaddr, len); 412 413 write_lock(&et->lock); 414 415 if (is_inode_flag_set(F2FS_I(inode), FI_NO_EXTENT)) { 416 write_unlock(&et->lock); 417 return false; 418 } 419 420 prev = et->largest; 421 dei.len = 0; 422 423 /* 424 * drop largest extent before lookup, in case it's already 425 * been shrunk from extent tree 426 */ 427 __drop_largest_extent(inode, fofs, len); 428 429 /* 1. lookup first extent node in range [fofs, fofs + len - 1] */ 430 en = __lookup_extent_tree_ret(et, fofs, &prev_en, &next_en, 431 &insert_p, &insert_parent); 432 if (!en) 433 en = next_en; 434 435 /* 2. invlidate all extent nodes in range [fofs, fofs + len - 1] */ 436 while (en && en->ei.fofs < end) { 437 unsigned int org_end; 438 int parts = 0; /* # of parts current extent split into */ 439 440 next_en = en1 = NULL; 441 442 dei = en->ei; 443 org_end = dei.fofs + dei.len; 444 f2fs_bug_on(sbi, pos >= org_end); 445 446 if (pos > dei.fofs && pos - dei.fofs >= F2FS_MIN_EXTENT_LEN) { 447 en->ei.len = pos - en->ei.fofs; 448 prev_en = en; 449 parts = 1; 450 } 451 452 if (end < org_end && org_end - end >= F2FS_MIN_EXTENT_LEN) { 453 if (parts) { 454 set_extent_info(&ei, end, 455 end - dei.fofs + dei.blk, 456 org_end - end); 457 en1 = __insert_extent_tree(sbi, et, &ei, 458 NULL, NULL); 459 next_en = en1; 460 } else { 461 en->ei.fofs = end; 462 en->ei.blk += end - dei.fofs; 463 en->ei.len -= end - dei.fofs; 464 next_en = en; 465 } 466 parts++; 467 } 468 469 if (!next_en) { 470 struct rb_node *node = rb_next(&en->rb_node); 471 472 next_en = node ? 473 rb_entry(node, struct extent_node, rb_node) 474 : NULL; 475 } 476 477 if (parts) 478 __try_update_largest_extent(et, en); 479 else 480 __detach_extent_node(sbi, et, en); 481 482 /* 483 * if original extent is split into zero or two parts, extent 484 * tree has been altered by deletion or insertion, therefore 485 * invalidate pointers regard to tree. 486 */ 487 if (parts != 1) { 488 insert_p = NULL; 489 insert_parent = NULL; 490 } 491 492 /* update in global extent list */ 493 spin_lock(&sbi->extent_lock); 494 if (!parts && !list_empty(&en->list)) 495 list_del(&en->list); 496 if (en1) 497 list_add_tail(&en1->list, &sbi->extent_list); 498 spin_unlock(&sbi->extent_lock); 499 500 /* release extent node */ 501 if (!parts) 502 kmem_cache_free(extent_node_slab, en); 503 504 en = next_en; 505 } 506 507 /* 3. update extent in extent cache */ 508 if (blkaddr) { 509 struct extent_node *den = NULL; 510 511 set_extent_info(&ei, fofs, blkaddr, len); 512 en1 = __try_merge_extent_node(sbi, et, &ei, &den, 513 prev_en, next_en); 514 if (!en1) 515 en1 = __insert_extent_tree(sbi, et, &ei, 516 insert_p, insert_parent); 517 518 /* give up extent_cache, if split and small updates happen */ 519 if (dei.len >= 1 && 520 prev.len < F2FS_MIN_EXTENT_LEN && 521 et->largest.len < F2FS_MIN_EXTENT_LEN) { 522 et->largest.len = 0; 523 set_inode_flag(F2FS_I(inode), FI_NO_EXTENT); 524 } 525 526 spin_lock(&sbi->extent_lock); 527 if (en1) { 528 if (list_empty(&en1->list)) 529 list_add_tail(&en1->list, &sbi->extent_list); 530 else 531 list_move_tail(&en1->list, &sbi->extent_list); 532 } 533 if (den && !list_empty(&den->list)) 534 list_del(&den->list); 535 spin_unlock(&sbi->extent_lock); 536 537 if (den) 538 kmem_cache_free(extent_node_slab, den); 539 } 540 541 if (is_inode_flag_set(F2FS_I(inode), FI_NO_EXTENT)) 542 __free_extent_tree(sbi, et, true); 543 544 write_unlock(&et->lock); 545 546 return !__is_extent_same(&prev, &et->largest); 547 } 548 549 unsigned int f2fs_shrink_extent_tree(struct f2fs_sb_info *sbi, int nr_shrink) 550 { 551 struct extent_tree *treevec[EXT_TREE_VEC_SIZE]; 552 struct extent_node *en, *tmp; 553 unsigned long ino = F2FS_ROOT_INO(sbi); 554 struct radix_tree_root *root = &sbi->extent_tree_root; 555 unsigned int found; 556 unsigned int node_cnt = 0, tree_cnt = 0; 557 int remained; 558 559 if (!test_opt(sbi, EXTENT_CACHE)) 560 return 0; 561 562 if (!down_write_trylock(&sbi->extent_tree_lock)) 563 goto out; 564 565 /* 1. remove unreferenced extent tree */ 566 while ((found = radix_tree_gang_lookup(root, 567 (void **)treevec, ino, EXT_TREE_VEC_SIZE))) { 568 unsigned i; 569 570 ino = treevec[found - 1]->ino + 1; 571 for (i = 0; i < found; i++) { 572 struct extent_tree *et = treevec[i]; 573 574 if (!atomic_read(&et->refcount)) { 575 write_lock(&et->lock); 576 node_cnt += __free_extent_tree(sbi, et, true); 577 write_unlock(&et->lock); 578 579 radix_tree_delete(root, et->ino); 580 kmem_cache_free(extent_tree_slab, et); 581 sbi->total_ext_tree--; 582 tree_cnt++; 583 584 if (node_cnt + tree_cnt >= nr_shrink) 585 goto unlock_out; 586 } 587 } 588 } 589 up_write(&sbi->extent_tree_lock); 590 591 /* 2. remove LRU extent entries */ 592 if (!down_write_trylock(&sbi->extent_tree_lock)) 593 goto out; 594 595 remained = nr_shrink - (node_cnt + tree_cnt); 596 597 spin_lock(&sbi->extent_lock); 598 list_for_each_entry_safe(en, tmp, &sbi->extent_list, list) { 599 if (!remained--) 600 break; 601 list_del_init(&en->list); 602 } 603 spin_unlock(&sbi->extent_lock); 604 605 /* 606 * reset ino for searching victims from beginning of global extent tree. 607 */ 608 ino = F2FS_ROOT_INO(sbi); 609 610 while ((found = radix_tree_gang_lookup(root, 611 (void **)treevec, ino, EXT_TREE_VEC_SIZE))) { 612 unsigned i; 613 614 ino = treevec[found - 1]->ino + 1; 615 for (i = 0; i < found; i++) { 616 struct extent_tree *et = treevec[i]; 617 618 write_lock(&et->lock); 619 node_cnt += __free_extent_tree(sbi, et, false); 620 write_unlock(&et->lock); 621 622 if (node_cnt + tree_cnt >= nr_shrink) 623 goto unlock_out; 624 } 625 } 626 unlock_out: 627 up_write(&sbi->extent_tree_lock); 628 out: 629 trace_f2fs_shrink_extent_tree(sbi, node_cnt, tree_cnt); 630 631 return node_cnt + tree_cnt; 632 } 633 634 unsigned int f2fs_destroy_extent_node(struct inode *inode) 635 { 636 struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 637 struct extent_tree *et = F2FS_I(inode)->extent_tree; 638 unsigned int node_cnt = 0; 639 640 if (!et) 641 return 0; 642 643 write_lock(&et->lock); 644 node_cnt = __free_extent_tree(sbi, et, true); 645 write_unlock(&et->lock); 646 647 return node_cnt; 648 } 649 650 void f2fs_destroy_extent_tree(struct inode *inode) 651 { 652 struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 653 struct extent_tree *et = F2FS_I(inode)->extent_tree; 654 unsigned int node_cnt = 0; 655 656 if (!et) 657 return; 658 659 if (inode->i_nlink && !is_bad_inode(inode) && et->count) { 660 atomic_dec(&et->refcount); 661 return; 662 } 663 664 /* free all extent info belong to this extent tree */ 665 node_cnt = f2fs_destroy_extent_node(inode); 666 667 /* delete extent tree entry in radix tree */ 668 down_write(&sbi->extent_tree_lock); 669 atomic_dec(&et->refcount); 670 f2fs_bug_on(sbi, atomic_read(&et->refcount) || et->count); 671 radix_tree_delete(&sbi->extent_tree_root, inode->i_ino); 672 kmem_cache_free(extent_tree_slab, et); 673 sbi->total_ext_tree--; 674 up_write(&sbi->extent_tree_lock); 675 676 F2FS_I(inode)->extent_tree = NULL; 677 678 trace_f2fs_destroy_extent_tree(inode, node_cnt); 679 } 680 681 bool f2fs_lookup_extent_cache(struct inode *inode, pgoff_t pgofs, 682 struct extent_info *ei) 683 { 684 if (!f2fs_may_extent_tree(inode)) 685 return false; 686 687 return f2fs_lookup_extent_tree(inode, pgofs, ei); 688 } 689 690 void f2fs_update_extent_cache(struct dnode_of_data *dn) 691 { 692 struct f2fs_inode_info *fi = F2FS_I(dn->inode); 693 pgoff_t fofs; 694 695 if (!f2fs_may_extent_tree(dn->inode)) 696 return; 697 698 f2fs_bug_on(F2FS_I_SB(dn->inode), dn->data_blkaddr == NEW_ADDR); 699 700 701 fofs = start_bidx_of_node(ofs_of_node(dn->node_page), fi) + 702 dn->ofs_in_node; 703 704 if (f2fs_update_extent_tree_range(dn->inode, fofs, dn->data_blkaddr, 1)) 705 sync_inode_page(dn); 706 } 707 708 void f2fs_update_extent_cache_range(struct dnode_of_data *dn, 709 pgoff_t fofs, block_t blkaddr, unsigned int len) 710 711 { 712 if (!f2fs_may_extent_tree(dn->inode)) 713 return; 714 715 if (f2fs_update_extent_tree_range(dn->inode, fofs, blkaddr, len)) 716 sync_inode_page(dn); 717 } 718 719 void init_extent_cache_info(struct f2fs_sb_info *sbi) 720 { 721 INIT_RADIX_TREE(&sbi->extent_tree_root, GFP_NOIO); 722 init_rwsem(&sbi->extent_tree_lock); 723 INIT_LIST_HEAD(&sbi->extent_list); 724 spin_lock_init(&sbi->extent_lock); 725 sbi->total_ext_tree = 0; 726 atomic_set(&sbi->total_ext_node, 0); 727 } 728 729 int __init create_extent_cache(void) 730 { 731 extent_tree_slab = f2fs_kmem_cache_create("f2fs_extent_tree", 732 sizeof(struct extent_tree)); 733 if (!extent_tree_slab) 734 return -ENOMEM; 735 extent_node_slab = f2fs_kmem_cache_create("f2fs_extent_node", 736 sizeof(struct extent_node)); 737 if (!extent_node_slab) { 738 kmem_cache_destroy(extent_tree_slab); 739 return -ENOMEM; 740 } 741 return 0; 742 } 743 744 void destroy_extent_cache(void) 745 { 746 kmem_cache_destroy(extent_node_slab); 747 kmem_cache_destroy(extent_tree_slab); 748 } 749