diff options
author | Darrick J. Wong <djwong@kernel.org> | 2021-09-01 11:18:09 -0700 |
---|---|---|
committer | Darrick J. Wong <djwong@kernel.org> | 2021-10-22 16:41:07 -0700 |
commit | 79bb2eef5532bbf8a56a5f7dc0024022a16c34df (patch) | |
tree | ec92ba7714ce5099ebd1850ffba58cb6123c0565 /fs/xfs/libxfs | |
parent | 28ff876207269b69fc0ee35d30d5b874d90b6e7b (diff) |
xfs: add realtime refcount btree operations
Implement the generic btree operations needed to manipulate rtrefcount
btree blocks. This is different from the regular refcountbt in that we
allocate space from the filesystem at large, and are neither constrained
to the free space nor any particular AG.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Diffstat (limited to 'fs/xfs/libxfs')
-rw-r--r-- | fs/xfs/libxfs/xfs_rtrefcount_btree.c | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/fs/xfs/libxfs/xfs_rtrefcount_btree.c b/fs/xfs/libxfs/xfs_rtrefcount_btree.c index 3cbd98f36043..24eaffc31632 100644 --- a/fs/xfs/libxfs/xfs_rtrefcount_btree.c +++ b/fs/xfs/libxfs/xfs_rtrefcount_btree.c @@ -49,6 +49,108 @@ xfs_rtrefcountbt_dup_cursor( return new; } +STATIC int +xfs_rtrefcountbt_get_minrecs( + struct xfs_btree_cur *cur, + int level) +{ + if (level == cur->bc_nlevels - 1) { + struct xfs_ifork *ifp = xfs_btree_ifork_ptr(cur); + + return xfs_rtrefcountbt_maxrecs(cur->bc_mp, ifp->if_broot_bytes, + level == 0) / 2; + } + + return cur->bc_mp->m_rtrefc_mnr[level != 0]; +} + +STATIC int +xfs_rtrefcountbt_get_maxrecs( + struct xfs_btree_cur *cur, + int level) +{ + if (level == cur->bc_nlevels - 1) { + struct xfs_ifork *ifp = xfs_btree_ifork_ptr(cur); + + return xfs_rtrefcountbt_maxrecs(cur->bc_mp, ifp->if_broot_bytes, + level == 0); + } + + return cur->bc_mp->m_rtrefc_mxr[level != 0]; +} + +STATIC void +xfs_rtrefcountbt_init_key_from_rec( + union xfs_btree_key *key, + const union xfs_btree_rec *rec) +{ + key->rtrefc.rc_startblock = rec->rtrefc.rc_startblock; +} + +STATIC void +xfs_rtrefcountbt_init_high_key_from_rec( + union xfs_btree_key *key, + const union xfs_btree_rec *rec) +{ + __u64 x; + + x = be64_to_cpu(rec->rtrefc.rc_startblock); + x += be64_to_cpu(rec->rtrefc.rc_blockcount) - 1; + key->rtrefc.rc_startblock = cpu_to_be64(x); +} + +STATIC void +xfs_rtrefcountbt_init_rec_from_cur( + struct xfs_btree_cur *cur, + union xfs_btree_rec *rec) +{ + rec->rtrefc.rc_startblock = cpu_to_be64(cur->bc_rec.rc.rc_startblock); + rec->rtrefc.rc_blockcount = cpu_to_be64(cur->bc_rec.rc.rc_blockcount); + rec->rtrefc.rc_refcount = cpu_to_be32(cur->bc_rec.rc.rc_refcount); +} + +STATIC void +xfs_rtrefcountbt_init_ptr_from_cur( + struct xfs_btree_cur *cur, + union xfs_btree_ptr *ptr) +{ + ptr->l = 0; +} + +STATIC int64_t +xfs_rtrefcountbt_key_diff( + struct xfs_btree_cur *cur, + const union xfs_btree_key *key) +{ + struct xfs_refcount_irec *rec = &cur->bc_rec.rc; + const struct xfs_rtrefcount_key *kp = &key->rtrefc; + uint64_t key_start; + + key_start = be64_to_cpu(kp->rc_startblock); + if (key_start > rec->rc_startblock) + return 1; + else if (key_start < rec->rc_startblock) + return -1; + return 0; +} + +STATIC int64_t +xfs_rtrefcountbt_diff_two_keys( + struct xfs_btree_cur *cur, + const union xfs_btree_key *k1, + const union xfs_btree_key *k2) +{ + uint64_t key1_start, key2_start; + + key1_start = be64_to_cpu(k1->rtrefc.rc_startblock); + key2_start = be64_to_cpu(k2->rtrefc.rc_startblock); + if (key1_start > key2_start) + return 1; + else if (key1_start < key2_start) + return -1; + return 0; +} + static xfs_failaddr_t xfs_rtrefcountbt_verify( struct xfs_buf *bp) @@ -114,12 +216,45 @@ const struct xfs_buf_ops xfs_rtrefcountbt_buf_ops = { .verify_struct = xfs_rtrefcountbt_verify, }; +STATIC int +xfs_rtrefcountbt_keys_inorder( + struct xfs_btree_cur *cur, + const union xfs_btree_key *k1, + const union xfs_btree_key *k2) +{ + return be64_to_cpu(k1->rtrefc.rc_startblock) < + be64_to_cpu(k2->rtrefc.rc_startblock); +} + +STATIC int +xfs_rtrefcountbt_recs_inorder( + struct xfs_btree_cur *cur, + const union xfs_btree_rec *r1, + const union xfs_btree_rec *r2) +{ + return be64_to_cpu(r1->rtrefc.rc_startblock) + + be64_to_cpu(r1->rtrefc.rc_blockcount) <= + be64_to_cpu(r2->rtrefc.rc_startblock); +} + static const struct xfs_btree_ops xfs_rtrefcountbt_ops = { .rec_len = sizeof(struct xfs_rtrefcount_rec), .key_len = sizeof(struct xfs_rtrefcount_key), .dup_cursor = xfs_rtrefcountbt_dup_cursor, + .alloc_block = xfs_btree_alloc_imeta_block, + .free_block = xfs_btree_free_imeta_block, + .get_minrecs = xfs_rtrefcountbt_get_minrecs, + .get_maxrecs = xfs_rtrefcountbt_get_maxrecs, + .init_key_from_rec = xfs_rtrefcountbt_init_key_from_rec, + .init_high_key_from_rec = xfs_rtrefcountbt_init_high_key_from_rec, + .init_rec_from_cur = xfs_rtrefcountbt_init_rec_from_cur, + .init_ptr_from_cur = xfs_rtrefcountbt_init_ptr_from_cur, + .key_diff = xfs_rtrefcountbt_key_diff, .buf_ops = &xfs_rtrefcountbt_buf_ops, + .diff_two_keys = xfs_rtrefcountbt_diff_two_keys, + .keys_inorder = xfs_rtrefcountbt_keys_inorder, + .recs_inorder = xfs_rtrefcountbt_recs_inorder, }; /* Initialize a new rt refcount btree cursor. */ |