summaryrefslogtreecommitdiff
path: root/fs/xfs/libxfs
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2021-09-01 11:18:09 -0700
committerDarrick J. Wong <djwong@kernel.org>2021-10-22 16:41:07 -0700
commit79bb2eef5532bbf8a56a5f7dc0024022a16c34df (patch)
treeec92ba7714ce5099ebd1850ffba58cb6123c0565 /fs/xfs/libxfs
parent28ff876207269b69fc0ee35d30d5b874d90b6e7b (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.c135
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. */