Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xfs: use separate btree cursor cache for each btree type

Now that we have the infrastructure to track the max possible height of
each btree type, we can create a separate slab cache for cursors of each
type of btree. For smaller indices like the free space btrees, this
means that we can pack more cursors into a slab page, improving slab
utilization.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>

+185 -29
+22 -1
fs/xfs/libxfs/xfs_alloc_btree.c
··· 20 20 #include "xfs_trans.h" 21 21 #include "xfs_ag.h" 22 22 23 + static kmem_zone_t *xfs_allocbt_cur_cache; 23 24 24 25 STATIC struct xfs_btree_cur * 25 26 xfs_allocbt_dup_cursor( ··· 478 477 479 478 ASSERT(btnum == XFS_BTNUM_BNO || btnum == XFS_BTNUM_CNT); 480 479 481 - cur = xfs_btree_alloc_cursor(mp, tp, btnum, mp->m_alloc_maxlevels); 480 + cur = xfs_btree_alloc_cursor(mp, tp, btnum, mp->m_alloc_maxlevels, 481 + xfs_allocbt_cur_cache); 482 482 cur->bc_ag.abt.active = false; 483 483 484 484 if (btnum == XFS_BTNUM_CNT) { ··· 618 616 unsigned long long len) 619 617 { 620 618 return xfs_btree_calc_size(mp->m_alloc_mnr, len); 619 + } 620 + 621 + int __init 622 + xfs_allocbt_init_cur_cache(void) 623 + { 624 + xfs_allocbt_cur_cache = kmem_cache_create("xfs_bnobt_cur", 625 + xfs_btree_cur_sizeof(xfs_allocbt_maxlevels_ondisk()), 626 + 0, 0, NULL); 627 + 628 + if (!xfs_allocbt_cur_cache) 629 + return -ENOMEM; 630 + return 0; 631 + } 632 + 633 + void 634 + xfs_allocbt_destroy_cur_cache(void) 635 + { 636 + kmem_cache_destroy(xfs_allocbt_cur_cache); 637 + xfs_allocbt_cur_cache = NULL; 621 638 }
+3
fs/xfs/libxfs/xfs_alloc_btree.h
··· 62 62 63 63 unsigned int xfs_allocbt_maxlevels_ondisk(void); 64 64 65 + int __init xfs_allocbt_init_cur_cache(void); 66 + void xfs_allocbt_destroy_cur_cache(void); 67 + 65 68 #endif /* __XFS_ALLOC_BTREE_H__ */
+22 -1
fs/xfs/libxfs/xfs_bmap_btree.c
··· 22 22 #include "xfs_trace.h" 23 23 #include "xfs_rmap.h" 24 24 25 + static kmem_zone_t *xfs_bmbt_cur_cache; 26 + 25 27 /* 26 28 * Convert on-disk form of btree root to in-memory form. 27 29 */ ··· 555 553 ASSERT(whichfork != XFS_COW_FORK); 556 554 557 555 cur = xfs_btree_alloc_cursor(mp, tp, XFS_BTNUM_BMAP, 558 - mp->m_bm_maxlevels[whichfork]); 556 + mp->m_bm_maxlevels[whichfork], xfs_bmbt_cur_cache); 559 557 cur->bc_nlevels = be16_to_cpu(ifp->if_broot->bb_level) + 1; 560 558 cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_bmbt_2); 561 559 ··· 676 674 unsigned long long len) 677 675 { 678 676 return xfs_btree_calc_size(mp->m_bmap_dmnr, len); 677 + } 678 + 679 + int __init 680 + xfs_bmbt_init_cur_cache(void) 681 + { 682 + xfs_bmbt_cur_cache = kmem_cache_create("xfs_bmbt_cur", 683 + xfs_btree_cur_sizeof(xfs_bmbt_maxlevels_ondisk()), 684 + 0, 0, NULL); 685 + 686 + if (!xfs_bmbt_cur_cache) 687 + return -ENOMEM; 688 + return 0; 689 + } 690 + 691 + void 692 + xfs_bmbt_destroy_cur_cache(void) 693 + { 694 + kmem_cache_destroy(xfs_bmbt_cur_cache); 695 + xfs_bmbt_cur_cache = NULL; 679 696 }
+3
fs/xfs/libxfs/xfs_bmap_btree.h
··· 112 112 113 113 unsigned int xfs_bmbt_maxlevels_ondisk(void); 114 114 115 + int __init xfs_bmbt_init_cur_cache(void); 116 + void xfs_bmbt_destroy_cur_cache(void); 117 + 115 118 #endif /* __XFS_BMAP_BTREE_H__ */
+45 -6
fs/xfs/libxfs/xfs_btree.c
··· 22 22 #include "xfs_log.h" 23 23 #include "xfs_btree_staging.h" 24 24 #include "xfs_ag.h" 25 - 26 - /* 27 - * Cursor allocation zone. 28 - */ 29 - kmem_zone_t *xfs_btree_cur_zone; 25 + #include "xfs_alloc_btree.h" 26 + #include "xfs_ialloc_btree.h" 27 + #include "xfs_bmap_btree.h" 28 + #include "xfs_rmap_btree.h" 29 + #include "xfs_refcount_btree.h" 30 30 31 31 /* 32 32 * Btree magic numbers. ··· 379 379 kmem_free(cur->bc_ops); 380 380 if (!(cur->bc_flags & XFS_BTREE_LONG_PTRS) && cur->bc_ag.pag) 381 381 xfs_perag_put(cur->bc_ag.pag); 382 - kmem_cache_free(xfs_btree_cur_zone, cur); 382 + kmem_cache_free(cur->bc_cache, cur); 383 383 } 384 384 385 385 /* ··· 4961 4961 return block->bb_u.l.bb_rightsib != cpu_to_be64(NULLFSBLOCK); 4962 4962 else 4963 4963 return block->bb_u.s.bb_rightsib != cpu_to_be32(NULLAGBLOCK); 4964 + } 4965 + 4966 + /* Set up all the btree cursor caches. */ 4967 + int __init 4968 + xfs_btree_init_cur_caches(void) 4969 + { 4970 + int error; 4971 + 4972 + error = xfs_allocbt_init_cur_cache(); 4973 + if (error) 4974 + return error; 4975 + error = xfs_inobt_init_cur_cache(); 4976 + if (error) 4977 + goto err; 4978 + error = xfs_bmbt_init_cur_cache(); 4979 + if (error) 4980 + goto err; 4981 + error = xfs_rmapbt_init_cur_cache(); 4982 + if (error) 4983 + goto err; 4984 + error = xfs_refcountbt_init_cur_cache(); 4985 + if (error) 4986 + goto err; 4987 + 4988 + return 0; 4989 + err: 4990 + xfs_btree_destroy_cur_caches(); 4991 + return error; 4992 + } 4993 + 4994 + /* Destroy all the btree cursor caches, if they've been allocated. */ 4995 + void 4996 + xfs_btree_destroy_cur_caches(void) 4997 + { 4998 + xfs_allocbt_destroy_cur_cache(); 4999 + xfs_inobt_destroy_cur_cache(); 5000 + xfs_bmbt_destroy_cur_cache(); 5001 + xfs_rmapbt_destroy_cur_cache(); 5002 + xfs_refcountbt_destroy_cur_cache(); 4964 5003 }
+8 -12
fs/xfs/libxfs/xfs_btree.h
··· 13 13 struct xfs_ifork; 14 14 struct xfs_perag; 15 15 16 - extern kmem_zone_t *xfs_btree_cur_zone; 17 - 18 16 /* 19 17 * Generic key, ptr and record wrapper structures. 20 18 * ··· 89 91 XFS_STATS_INC_OFF((cur)->bc_mp, (cur)->bc_statoff + __XBTS_ ## stat) 90 92 #define XFS_BTREE_STATS_ADD(cur, stat, val) \ 91 93 XFS_STATS_ADD_OFF((cur)->bc_mp, (cur)->bc_statoff + __XBTS_ ## stat, val) 92 - 93 - /* 94 - * The btree cursor zone hands out cursors that can handle up to this many 95 - * levels. This is the known maximum for all btree types. 96 - */ 97 - #define XFS_BTREE_CUR_CACHE_MAXLEVELS (9) 98 94 99 95 struct xfs_btree_ops { 100 96 /* size of the key and record structures */ ··· 230 238 struct xfs_trans *bc_tp; /* transaction we're in, if any */ 231 239 struct xfs_mount *bc_mp; /* file system mount struct */ 232 240 const struct xfs_btree_ops *bc_ops; 241 + kmem_zone_t *bc_cache; /* cursor cache */ 233 242 unsigned int bc_flags; /* btree features - below */ 234 243 xfs_btnum_t bc_btnum; /* identifies which btree type */ 235 244 union xfs_btree_irec bc_rec; /* current insert/search record value */ ··· 585 592 struct xfs_mount *mp, 586 593 struct xfs_trans *tp, 587 594 xfs_btnum_t btnum, 588 - uint8_t maxlevels) 595 + uint8_t maxlevels, 596 + kmem_zone_t *cache) 589 597 { 590 598 struct xfs_btree_cur *cur; 591 599 592 - ASSERT(maxlevels <= XFS_BTREE_CUR_CACHE_MAXLEVELS); 593 - 594 - cur = kmem_cache_zalloc(xfs_btree_cur_zone, GFP_NOFS | __GFP_NOFAIL); 600 + cur = kmem_cache_zalloc(cache, GFP_NOFS | __GFP_NOFAIL); 595 601 cur->bc_tp = tp; 596 602 cur->bc_mp = mp; 597 603 cur->bc_btnum = btnum; 598 604 cur->bc_maxlevels = maxlevels; 605 + cur->bc_cache = cache; 599 606 600 607 return cur; 601 608 } 609 + 610 + int __init xfs_btree_init_cur_caches(void); 611 + void xfs_btree_destroy_cur_caches(void); 602 612 603 613 #endif /* __XFS_BTREE_H__ */
+22 -1
fs/xfs/libxfs/xfs_ialloc_btree.c
··· 22 22 #include "xfs_rmap.h" 23 23 #include "xfs_ag.h" 24 24 25 + static kmem_zone_t *xfs_inobt_cur_cache; 26 + 25 27 STATIC int 26 28 xfs_inobt_get_minrecs( 27 29 struct xfs_btree_cur *cur, ··· 435 433 struct xfs_btree_cur *cur; 436 434 437 435 cur = xfs_btree_alloc_cursor(mp, tp, btnum, 438 - M_IGEO(mp)->inobt_maxlevels); 436 + M_IGEO(mp)->inobt_maxlevels, xfs_inobt_cur_cache); 439 437 if (btnum == XFS_BTNUM_INO) { 440 438 cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_ibt_2); 441 439 cur->bc_ops = &xfs_inobt_ops; ··· 813 811 unsigned long long len) 814 812 { 815 813 return xfs_btree_calc_size(M_IGEO(mp)->inobt_mnr, len); 814 + } 815 + 816 + int __init 817 + xfs_inobt_init_cur_cache(void) 818 + { 819 + xfs_inobt_cur_cache = kmem_cache_create("xfs_inobt_cur", 820 + xfs_btree_cur_sizeof(xfs_inobt_maxlevels_ondisk()), 821 + 0, 0, NULL); 822 + 823 + if (!xfs_inobt_cur_cache) 824 + return -ENOMEM; 825 + return 0; 826 + } 827 + 828 + void 829 + xfs_inobt_destroy_cur_cache(void) 830 + { 831 + kmem_cache_destroy(xfs_inobt_cur_cache); 832 + xfs_inobt_cur_cache = NULL; 816 833 }
+3
fs/xfs/libxfs/xfs_ialloc_btree.h
··· 77 77 78 78 unsigned int xfs_iallocbt_maxlevels_ondisk(void); 79 79 80 + int __init xfs_inobt_init_cur_cache(void); 81 + void xfs_inobt_destroy_cur_cache(void); 82 + 80 83 #endif /* __XFS_IALLOC_BTREE_H__ */
+22 -1
fs/xfs/libxfs/xfs_refcount_btree.c
··· 21 21 #include "xfs_rmap.h" 22 22 #include "xfs_ag.h" 23 23 24 + static kmem_zone_t *xfs_refcountbt_cur_cache; 25 + 24 26 static struct xfs_btree_cur * 25 27 xfs_refcountbt_dup_cursor( 26 28 struct xfs_btree_cur *cur) ··· 325 323 ASSERT(pag->pag_agno < mp->m_sb.sb_agcount); 326 324 327 325 cur = xfs_btree_alloc_cursor(mp, tp, XFS_BTNUM_REFC, 328 - mp->m_refc_maxlevels); 326 + mp->m_refc_maxlevels, xfs_refcountbt_cur_cache); 329 327 cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_refcbt_2); 330 328 331 329 cur->bc_flags |= XFS_BTREE_CRC_BLOCKS; ··· 515 513 *used += tree_len; 516 514 517 515 return error; 516 + } 517 + 518 + int __init 519 + xfs_refcountbt_init_cur_cache(void) 520 + { 521 + xfs_refcountbt_cur_cache = kmem_cache_create("xfs_refcbt_cur", 522 + xfs_btree_cur_sizeof(xfs_refcountbt_maxlevels_ondisk()), 523 + 0, 0, NULL); 524 + 525 + if (!xfs_refcountbt_cur_cache) 526 + return -ENOMEM; 527 + return 0; 528 + } 529 + 530 + void 531 + xfs_refcountbt_destroy_cur_cache(void) 532 + { 533 + kmem_cache_destroy(xfs_refcountbt_cur_cache); 534 + xfs_refcountbt_cur_cache = NULL; 518 535 }
+3
fs/xfs/libxfs/xfs_refcount_btree.h
··· 67 67 68 68 unsigned int xfs_refcountbt_maxlevels_ondisk(void); 69 69 70 + int __init xfs_refcountbt_init_cur_cache(void); 71 + void xfs_refcountbt_destroy_cur_cache(void); 72 + 70 73 #endif /* __XFS_REFCOUNT_BTREE_H__ */
+22 -1
fs/xfs/libxfs/xfs_rmap_btree.c
··· 22 22 #include "xfs_ag.h" 23 23 #include "xfs_ag_resv.h" 24 24 25 + static kmem_zone_t *xfs_rmapbt_cur_cache; 26 + 25 27 /* 26 28 * Reverse map btree. 27 29 * ··· 455 453 456 454 /* Overlapping btree; 2 keys per pointer. */ 457 455 cur = xfs_btree_alloc_cursor(mp, tp, XFS_BTNUM_RMAP, 458 - mp->m_rmap_maxlevels); 456 + mp->m_rmap_maxlevels, xfs_rmapbt_cur_cache); 459 457 cur->bc_flags = XFS_BTREE_CRC_BLOCKS | XFS_BTREE_OVERLAPPING; 460 458 cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_rmap_2); 461 459 cur->bc_ops = &xfs_rmapbt_ops; ··· 675 673 *used += tree_len; 676 674 677 675 return error; 676 + } 677 + 678 + int __init 679 + xfs_rmapbt_init_cur_cache(void) 680 + { 681 + xfs_rmapbt_cur_cache = kmem_cache_create("xfs_rmapbt_cur", 682 + xfs_btree_cur_sizeof(xfs_rmapbt_maxlevels_ondisk()), 683 + 0, 0, NULL); 684 + 685 + if (!xfs_rmapbt_cur_cache) 686 + return -ENOMEM; 687 + return 0; 688 + } 689 + 690 + void 691 + xfs_rmapbt_destroy_cur_cache(void) 692 + { 693 + kmem_cache_destroy(xfs_rmapbt_cur_cache); 694 + xfs_rmapbt_cur_cache = NULL; 678 695 }
+3
fs/xfs/libxfs/xfs_rmap_btree.h
··· 61 61 62 62 unsigned int xfs_rmapbt_maxlevels_ondisk(void); 63 63 64 + int __init xfs_rmapbt_init_cur_cache(void); 65 + void xfs_rmapbt_destroy_cur_cache(void); 66 + 64 67 #endif /* __XFS_RMAP_BTREE_H__ */
+7 -6
fs/xfs/xfs_super.c
··· 37 37 #include "xfs_reflink.h" 38 38 #include "xfs_pwork.h" 39 39 #include "xfs_ag.h" 40 + #include "xfs_btree.h" 40 41 41 42 #include <linux/magic.h> 42 43 #include <linux/fs_context.h> ··· 1954 1953 STATIC int __init 1955 1954 xfs_init_zones(void) 1956 1955 { 1956 + int error; 1957 + 1957 1958 xfs_log_ticket_zone = kmem_cache_create("xfs_log_ticket", 1958 1959 sizeof(struct xlog_ticket), 1959 1960 0, 0, NULL); ··· 1968 1965 if (!xfs_bmap_free_item_zone) 1969 1966 goto out_destroy_log_ticket_zone; 1970 1967 1971 - xfs_btree_cur_zone = kmem_cache_create("xfs_btree_cur", 1972 - xfs_btree_cur_sizeof(XFS_BTREE_CUR_CACHE_MAXLEVELS), 1973 - 0, 0, NULL); 1974 - if (!xfs_btree_cur_zone) 1968 + error = xfs_btree_init_cur_caches(); 1969 + if (error) 1975 1970 goto out_destroy_bmap_free_item_zone; 1976 1971 1977 1972 xfs_da_state_zone = kmem_cache_create("xfs_da_state", ··· 2107 2106 out_destroy_da_state_zone: 2108 2107 kmem_cache_destroy(xfs_da_state_zone); 2109 2108 out_destroy_btree_cur_zone: 2110 - kmem_cache_destroy(xfs_btree_cur_zone); 2109 + xfs_btree_destroy_cur_caches(); 2111 2110 out_destroy_bmap_free_item_zone: 2112 2111 kmem_cache_destroy(xfs_bmap_free_item_zone); 2113 2112 out_destroy_log_ticket_zone: ··· 2139 2138 kmem_cache_destroy(xfs_trans_zone); 2140 2139 kmem_cache_destroy(xfs_ifork_zone); 2141 2140 kmem_cache_destroy(xfs_da_state_zone); 2142 - kmem_cache_destroy(xfs_btree_cur_zone); 2141 + xfs_btree_destroy_cur_caches(); 2143 2142 kmem_cache_destroy(xfs_bmap_free_item_zone); 2144 2143 kmem_cache_destroy(xfs_log_ticket_zone); 2145 2144 }