Skip to content

Commit 4f0cd5a

Browse files
Christoph HellwigDarrick J. Wong
authored andcommitted
xfs: split out a btree type from the btree ops geometry flags
Two of the btree cursor flags are always used together and encode the fundamental btree type. There currently are two such types: 1) an on-disk AG-rooted btree with 32-bit pointers 2) an on-disk inode-rooted btree with 64-bit pointers and we're about to add: 3) an in-memory btree with 64-bit pointers Introduce a new enum and a new type field in struct xfs_btree_geom to encode this type directly instead of using flags and change most code to switch on this enum. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Darrick J. Wong <djwong@kernel.org> [djwong: make the pointer lengths explicit] Signed-off-by: Darrick J. Wong <djwong@kernel.org>
1 parent 1a9d262 commit 4f0cd5a

12 files changed

Lines changed: 74 additions & 52 deletions

fs/xfs/libxfs/xfs_alloc_btree.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,8 @@ xfs_allocbt_keys_contiguous(
455455
}
456456

457457
const struct xfs_btree_ops xfs_bnobt_ops = {
458+
.type = XFS_BTREE_TYPE_AG,
459+
458460
.rec_len = sizeof(xfs_alloc_rec_t),
459461
.key_len = sizeof(xfs_alloc_key_t),
460462
.ptr_len = XFS_BTREE_SHORT_PTR_LEN,
@@ -482,6 +484,7 @@ const struct xfs_btree_ops xfs_bnobt_ops = {
482484
};
483485

484486
const struct xfs_btree_ops xfs_cntbt_ops = {
487+
.type = XFS_BTREE_TYPE_AG,
485488
.geom_flags = XFS_BTGEO_LASTREC_UPDATE,
486489

487490
.rec_len = sizeof(xfs_alloc_rec_t),

fs/xfs/libxfs/xfs_bmap_btree.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ xfs_bmbt_keys_contiguous(
525525
}
526526

527527
const struct xfs_btree_ops xfs_bmbt_ops = {
528-
.geom_flags = XFS_BTGEO_ROOT_IN_INODE,
528+
.type = XFS_BTREE_TYPE_INODE,
529529

530530
.rec_len = sizeof(xfs_bmbt_rec_t),
531531
.key_len = sizeof(xfs_bmbt_key_t),

fs/xfs/libxfs/xfs_btree.c

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -447,10 +447,19 @@ xfs_btree_del_cursor(
447447
*/
448448
ASSERT(cur->bc_btnum != XFS_BTNUM_BMAP || cur->bc_ino.allocated == 0 ||
449449
xfs_is_shutdown(cur->bc_mp) || error != 0);
450+
451+
switch (cur->bc_ops->type) {
452+
case XFS_BTREE_TYPE_AG:
453+
if (cur->bc_ag.pag)
454+
xfs_perag_put(cur->bc_ag.pag);
455+
break;
456+
case XFS_BTREE_TYPE_INODE:
457+
/* nothing to do */
458+
break;
459+
}
460+
450461
if (unlikely(cur->bc_flags & XFS_BTREE_STAGING))
451462
kfree(cur->bc_ops);
452-
if (!(cur->bc_ops->ptr_len == XFS_BTREE_LONG_PTR_LEN) && cur->bc_ag.pag)
453-
xfs_perag_put(cur->bc_ag.pag);
454463
kmem_cache_free(cur->bc_cache, cur);
455464
}
456465

@@ -708,7 +717,7 @@ struct xfs_ifork *
708717
xfs_btree_ifork_ptr(
709718
struct xfs_btree_cur *cur)
710719
{
711-
ASSERT(cur->bc_ops->geom_flags & XFS_BTGEO_ROOT_IN_INODE);
720+
ASSERT(cur->bc_ops->type == XFS_BTREE_TYPE_INODE);
712721

713722
if (cur->bc_flags & XFS_BTREE_STAGING)
714723
return cur->bc_ino.ifake->if_fork;
@@ -740,8 +749,8 @@ xfs_btree_get_block(
740749
int level, /* level in btree */
741750
struct xfs_buf **bpp) /* buffer containing the block */
742751
{
743-
if ((cur->bc_ops->geom_flags & XFS_BTGEO_ROOT_IN_INODE) &&
744-
(level == cur->bc_nlevels - 1)) {
752+
if (cur->bc_ops->type == XFS_BTREE_TYPE_INODE &&
753+
level == cur->bc_nlevels - 1) {
745754
*bpp = NULL;
746755
return xfs_btree_get_iroot(cur);
747756
}
@@ -983,8 +992,8 @@ xfs_btree_readahead(
983992
* No readahead needed if we are at the root level and the
984993
* btree root is stored in the inode.
985994
*/
986-
if ((cur->bc_ops->geom_flags & XFS_BTGEO_ROOT_IN_INODE) &&
987-
(lev == cur->bc_nlevels - 1))
995+
if (cur->bc_ops->type == XFS_BTREE_TYPE_INODE &&
996+
lev == cur->bc_nlevels - 1)
988997
return 0;
989998

990999
if ((cur->bc_levels[lev].ra | lr) == cur->bc_levels[lev].ra)
@@ -1172,14 +1181,12 @@ __xfs_btree_init_block(
11721181
buf->bb_u.l.bb_lsn = 0;
11731182
}
11741183
} else {
1175-
/* owner is a 32 bit value on short blocks */
1176-
__u32 __owner = (__u32)owner;
1177-
11781184
buf->bb_u.s.bb_leftsib = cpu_to_be32(NULLAGBLOCK);
11791185
buf->bb_u.s.bb_rightsib = cpu_to_be32(NULLAGBLOCK);
11801186
if (crc) {
11811187
buf->bb_u.s.bb_blkno = cpu_to_be64(blkno);
1182-
buf->bb_u.s.bb_owner = cpu_to_be32(__owner);
1188+
/* owner is a 32 bit value on short blocks */
1189+
buf->bb_u.s.bb_owner = cpu_to_be32((__u32)owner);
11831190
uuid_copy(&buf->bb_u.s.bb_uuid, &mp->m_sb.sb_meta_uuid);
11841191
buf->bb_u.s.bb_lsn = 0;
11851192
}
@@ -1217,7 +1224,7 @@ static inline __u64
12171224
xfs_btree_owner(
12181225
struct xfs_btree_cur *cur)
12191226
{
1220-
if (cur->bc_ops->geom_flags & XFS_BTGEO_ROOT_IN_INODE)
1227+
if (cur->bc_ops->type == XFS_BTREE_TYPE_INODE)
12211228
return cur->bc_ino.ip->i_ino;
12221229
return cur->bc_ag.pag->pag_agno;
12231230
}
@@ -1638,7 +1645,7 @@ xfs_btree_increment(
16381645
* confused or have the tree root in an inode.
16391646
*/
16401647
if (lev == cur->bc_nlevels) {
1641-
if (cur->bc_ops->geom_flags & XFS_BTGEO_ROOT_IN_INODE)
1648+
if (cur->bc_ops->type == XFS_BTREE_TYPE_INODE)
16421649
goto out0;
16431650
ASSERT(0);
16441651
xfs_btree_mark_sick(cur);
@@ -1732,7 +1739,7 @@ xfs_btree_decrement(
17321739
* or the root of the tree is in an inode.
17331740
*/
17341741
if (lev == cur->bc_nlevels) {
1735-
if (cur->bc_ops->geom_flags & XFS_BTGEO_ROOT_IN_INODE)
1742+
if (cur->bc_ops->type == XFS_BTREE_TYPE_INODE)
17361743
goto out0;
17371744
ASSERT(0);
17381745
xfs_btree_mark_sick(cur);
@@ -1807,8 +1814,8 @@ xfs_btree_lookup_get_block(
18071814
int error = 0;
18081815

18091816
/* special case the root block if in an inode */
1810-
if ((cur->bc_ops->geom_flags & XFS_BTGEO_ROOT_IN_INODE) &&
1811-
(level == cur->bc_nlevels - 1)) {
1817+
if (cur->bc_ops->type == XFS_BTREE_TYPE_INODE &&
1818+
level == cur->bc_nlevels - 1) {
18121819
*blkp = xfs_btree_get_iroot(cur);
18131820
return 0;
18141821
}
@@ -2343,7 +2350,7 @@ xfs_btree_lshift(
23432350
int error; /* error return value */
23442351
int i;
23452352

2346-
if ((cur->bc_ops->geom_flags & XFS_BTGEO_ROOT_IN_INODE) &&
2353+
if ((cur->bc_ops->type == XFS_BTREE_TYPE_INODE) &&
23472354
level == cur->bc_nlevels - 1)
23482355
goto out0;
23492356

@@ -2539,8 +2546,8 @@ xfs_btree_rshift(
25392546
int error; /* error return value */
25402547
int i; /* loop counter */
25412548

2542-
if ((cur->bc_ops->geom_flags & XFS_BTGEO_ROOT_IN_INODE) &&
2543-
(level == cur->bc_nlevels - 1))
2549+
if (cur->bc_ops->type == XFS_BTREE_TYPE_INODE &&
2550+
level == cur->bc_nlevels - 1)
25442551
goto out0;
25452552

25462553
/* Set up variables for this block as "left". */
@@ -2990,7 +2997,6 @@ xfs_btree_split(
29902997
#define xfs_btree_split __xfs_btree_split
29912998
#endif /* __KERNEL__ */
29922999

2993-
29943000
/*
29953001
* Copy the old inode root contents into a real block and make the
29963002
* broot point to it.
@@ -3015,7 +3021,7 @@ xfs_btree_new_iroot(
30153021

30163022
XFS_BTREE_STATS_INC(cur, newroot);
30173023

3018-
ASSERT(cur->bc_ops->geom_flags & XFS_BTGEO_ROOT_IN_INODE);
3024+
ASSERT(cur->bc_ops->type == XFS_BTREE_TYPE_INODE);
30193025

30203026
level = cur->bc_nlevels - 1;
30213027

@@ -3240,7 +3246,7 @@ xfs_btree_make_block_unfull(
32403246
{
32413247
int error = 0;
32423248

3243-
if ((cur->bc_ops->geom_flags & XFS_BTGEO_ROOT_IN_INODE) &&
3249+
if (cur->bc_ops->type == XFS_BTREE_TYPE_INODE &&
32443250
level == cur->bc_nlevels - 1) {
32453251
struct xfs_inode *ip = cur->bc_ino.ip;
32463252

@@ -3326,8 +3332,8 @@ xfs_btree_insrec(
33263332
* If we have an external root pointer, and we've made it to the
33273333
* root level, allocate a new root block and we're done.
33283334
*/
3329-
if (!(cur->bc_ops->geom_flags & XFS_BTGEO_ROOT_IN_INODE) &&
3330-
(level >= cur->bc_nlevels)) {
3335+
if (cur->bc_ops->type != XFS_BTREE_TYPE_INODE &&
3336+
level >= cur->bc_nlevels) {
33313337
error = xfs_btree_new_root(cur, stat);
33323338
xfs_btree_set_ptr_null(cur, ptrp);
33333339

@@ -3614,7 +3620,7 @@ xfs_btree_kill_iroot(
36143620
#endif
36153621
int i;
36163622

3617-
ASSERT(cur->bc_ops->geom_flags & XFS_BTGEO_ROOT_IN_INODE);
3623+
ASSERT(cur->bc_ops->type == XFS_BTREE_TYPE_INODE);
36183624
ASSERT(cur->bc_nlevels > 1);
36193625

36203626
/*
@@ -3851,7 +3857,7 @@ xfs_btree_delrec(
38513857
* nothing left to do.
38523858
*/
38533859
if (level == cur->bc_nlevels - 1) {
3854-
if (cur->bc_ops->geom_flags & XFS_BTGEO_ROOT_IN_INODE) {
3860+
if (cur->bc_ops->type == XFS_BTREE_TYPE_INODE) {
38553861
xfs_iroot_realloc(cur->bc_ino.ip, -1,
38563862
cur->bc_ino.whichfork);
38573863

@@ -3919,7 +3925,7 @@ xfs_btree_delrec(
39193925
xfs_btree_get_sibling(cur, block, &rptr, XFS_BB_RIGHTSIB);
39203926
xfs_btree_get_sibling(cur, block, &lptr, XFS_BB_LEFTSIB);
39213927

3922-
if (cur->bc_ops->geom_flags & XFS_BTGEO_ROOT_IN_INODE) {
3928+
if (cur->bc_ops->type == XFS_BTREE_TYPE_INODE) {
39233929
/*
39243930
* One child of root, need to get a chance to copy its contents
39253931
* into the root and delete it. Can't go up to next level,
@@ -4236,8 +4242,8 @@ xfs_btree_delrec(
42364242
* If we joined with the right neighbor and there's a level above
42374243
* us, increment the cursor at that level.
42384244
*/
4239-
else if ((cur->bc_ops->geom_flags & XFS_BTGEO_ROOT_IN_INODE) ||
4240-
(level + 1 < cur->bc_nlevels)) {
4245+
else if (cur->bc_ops->type == XFS_BTREE_TYPE_INODE ||
4246+
level + 1 < cur->bc_nlevels) {
42414247
error = xfs_btree_increment(cur, level + 1, &i);
42424248
if (error)
42434249
goto error0;
@@ -4528,7 +4534,7 @@ xfs_btree_block_change_owner(
45284534
* though, so everything is consistent in memory.
45294535
*/
45304536
if (!bp) {
4531-
ASSERT(cur->bc_ops->geom_flags & XFS_BTGEO_ROOT_IN_INODE);
4537+
ASSERT(cur->bc_ops->type == XFS_BTREE_TYPE_INODE);
45324538
ASSERT(level == cur->bc_nlevels - 1);
45334539
return 0;
45344540
}

fs/xfs/libxfs/xfs_btree.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,15 @@ static inline enum xbtree_key_contig xbtree_key_contig(uint64_t x, uint64_t y)
117117
#define XFS_BTREE_LONG_PTR_LEN (sizeof(__be64))
118118
#define XFS_BTREE_SHORT_PTR_LEN (sizeof(__be32))
119119

120+
enum xfs_btree_type {
121+
XFS_BTREE_TYPE_AG,
122+
XFS_BTREE_TYPE_INODE,
123+
};
124+
120125
struct xfs_btree_ops {
126+
/* Type of btree - AG-rooted or inode-rooted */
127+
enum xfs_btree_type type;
128+
121129
/* XFS_BTGEO_* flags that determine the geometry of the btree */
122130
unsigned int geom_flags;
123131

@@ -216,9 +224,8 @@ struct xfs_btree_ops {
216224
};
217225

218226
/* btree geometry flags */
219-
#define XFS_BTGEO_ROOT_IN_INODE (1U << 0) /* root may be variable size */
220-
#define XFS_BTGEO_LASTREC_UPDATE (1U << 1) /* track last rec externally */
221-
#define XFS_BTGEO_OVERLAPPING (1U << 2) /* overlapping intervals */
227+
#define XFS_BTGEO_LASTREC_UPDATE (1U << 0) /* track last rec externally */
228+
#define XFS_BTGEO_OVERLAPPING (1U << 1) /* overlapping intervals */
222229

223230
/*
224231
* Reasons for the update_lastrec method to be called.
@@ -292,7 +299,7 @@ struct xfs_btree_cur
292299
/*
293300
* Short btree pointers need an agno to be able to turn the pointers
294301
* into physical addresses for IO, so the btree cursor switches between
295-
* bc_ino and bc_ag based on whether XFS_BTGEO_ROOT_IN_INODE is set for
302+
* bc_ino and bc_ag based on bc_ops->type.
296303
* the cursor.
297304
*/
298305
union {

fs/xfs/libxfs/xfs_btree_staging.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ xfs_btree_stage_afakeroot(
136136
struct xfs_btree_ops *nops;
137137

138138
ASSERT(!(cur->bc_flags & XFS_BTREE_STAGING));
139-
ASSERT(!(cur->bc_ops->geom_flags & XFS_BTGEO_ROOT_IN_INODE));
139+
ASSERT(cur->bc_ops->type != XFS_BTREE_TYPE_INODE);
140140
ASSERT(cur->bc_tp == NULL);
141141

142142
nops = kmalloc(sizeof(struct xfs_btree_ops), GFP_KERNEL | __GFP_NOFAIL);
@@ -217,7 +217,7 @@ xfs_btree_stage_ifakeroot(
217217
struct xfs_btree_ops *nops;
218218

219219
ASSERT(!(cur->bc_flags & XFS_BTREE_STAGING));
220-
ASSERT(cur->bc_ops->geom_flags & XFS_BTGEO_ROOT_IN_INODE);
220+
ASSERT(cur->bc_ops->type == XFS_BTREE_TYPE_INODE);
221221
ASSERT(cur->bc_tp == NULL);
222222

223223
nops = kmalloc(sizeof(struct xfs_btree_ops), GFP_KERNEL | __GFP_NOFAIL);
@@ -397,7 +397,7 @@ xfs_btree_bload_prep_block(
397397
struct xfs_btree_block *new_block;
398398
int ret;
399399

400-
if ((cur->bc_ops->geom_flags & XFS_BTGEO_ROOT_IN_INODE) &&
400+
if (cur->bc_ops->type == XFS_BTREE_TYPE_INODE &&
401401
level == cur->bc_nlevels - 1) {
402402
struct xfs_ifork *ifp = xfs_btree_ifork_ptr(cur);
403403
size_t new_size;
@@ -702,7 +702,7 @@ xfs_btree_bload_compute_geometry(
702702
xfs_btree_bload_level_geometry(cur, bbl, level, nr_this_level,
703703
&avg_per_block, &level_blocks, &dontcare64);
704704

705-
if (cur->bc_ops->geom_flags & XFS_BTGEO_ROOT_IN_INODE) {
705+
if (cur->bc_ops->type == XFS_BTREE_TYPE_INODE) {
706706
/*
707707
* If all the items we want to store at this level
708708
* would fit in the inode root block, then we have our
@@ -761,7 +761,7 @@ xfs_btree_bload_compute_geometry(
761761
return -EOVERFLOW;
762762

763763
bbl->btree_height = cur->bc_nlevels;
764-
if (cur->bc_ops->geom_flags & XFS_BTGEO_ROOT_IN_INODE)
764+
if (cur->bc_ops->type == XFS_BTREE_TYPE_INODE)
765765
bbl->nr_blocks = nr_blocks - 1;
766766
else
767767
bbl->nr_blocks = nr_blocks;
@@ -888,7 +888,7 @@ xfs_btree_bload(
888888
}
889889

890890
/* Initialize the new root. */
891-
if (cur->bc_ops->geom_flags & XFS_BTGEO_ROOT_IN_INODE) {
891+
if (cur->bc_ops->type == XFS_BTREE_TYPE_INODE) {
892892
ASSERT(xfs_btree_ptr_is_null(cur, &ptr));
893893
cur->bc_ino.ifake->if_levels = cur->bc_nlevels;
894894
cur->bc_ino.ifake->if_blocks = total_blocks - 1;

fs/xfs/libxfs/xfs_btree_staging.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,7 @@ struct xfs_btree_bload {
7676

7777
/*
7878
* This function should return the size of the in-core btree root
79-
* block. It is only necessary for XFS_BTGEO_ROOT_IN_INODE btree
80-
* types.
79+
* block. It is only necessary for XFS_BTREE_TYPE_INODE btrees.
8180
*/
8281
xfs_btree_bload_iroot_size_fn iroot_size;
8382

fs/xfs/libxfs/xfs_ialloc_btree.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,8 @@ xfs_inobt_keys_contiguous(
399399
}
400400

401401
const struct xfs_btree_ops xfs_inobt_ops = {
402+
.type = XFS_BTREE_TYPE_AG,
403+
402404
.rec_len = sizeof(xfs_inobt_rec_t),
403405
.key_len = sizeof(xfs_inobt_key_t),
404406
.ptr_len = XFS_BTREE_SHORT_PTR_LEN,
@@ -425,6 +427,8 @@ const struct xfs_btree_ops xfs_inobt_ops = {
425427
};
426428

427429
const struct xfs_btree_ops xfs_finobt_ops = {
430+
.type = XFS_BTREE_TYPE_AG,
431+
428432
.rec_len = sizeof(xfs_inobt_rec_t),
429433
.key_len = sizeof(xfs_inobt_key_t),
430434
.ptr_len = XFS_BTREE_SHORT_PTR_LEN,

fs/xfs/libxfs/xfs_refcount_btree.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,8 @@ xfs_refcountbt_keys_contiguous(
318318
}
319319

320320
const struct xfs_btree_ops xfs_refcountbt_ops = {
321+
.type = XFS_BTREE_TYPE_AG,
322+
321323
.rec_len = sizeof(struct xfs_refcount_rec),
322324
.key_len = sizeof(struct xfs_refcount_key),
323325
.ptr_len = XFS_BTREE_SHORT_PTR_LEN,

fs/xfs/libxfs/xfs_rmap_btree.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,7 @@ xfs_rmapbt_keys_contiguous(
473473
}
474474

475475
const struct xfs_btree_ops xfs_rmapbt_ops = {
476+
.type = XFS_BTREE_TYPE_AG,
476477
.geom_flags = XFS_BTGEO_OVERLAPPING,
477478

478479
.rec_len = sizeof(struct xfs_rmap_rec),

0 commit comments

Comments
 (0)