aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2016-08-02 21:40:56 -0400
committerDave Chinner <david@fromorbit.com>2016-08-02 21:40:56 -0400
commitcfed56ae5f410cd6c1601712a9ed4645b71b170c (patch)
tree8a55b97d8965e80db51ba4c5319150adbb83f491
parent4b8ed67794fe57b23801c65f4ea5b0f0b1f0dbab (diff)
xfs: support overlapping intervals in the rmap btree
Now that the generic btree code supports overlapping intervals, plug in the rmap btree to this functionality. We will need it to find potential left neighbors in xfs_rmap_{alloc,free} later in the patch set. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
-rw-r--r--fs/xfs/libxfs/xfs_rmap_btree.c68
-rw-r--r--fs/xfs/libxfs/xfs_rmap_btree.h10
2 files changed, 74 insertions, 4 deletions
diff --git a/fs/xfs/libxfs/xfs_rmap_btree.c b/fs/xfs/libxfs/xfs_rmap_btree.c
index 95cb964606d1..232450ce61a8 100644
--- a/fs/xfs/libxfs/xfs_rmap_btree.c
+++ b/fs/xfs/libxfs/xfs_rmap_btree.c
@@ -180,6 +180,35 @@ xfs_rmapbt_init_key_from_rec(
180 key->rmap.rm_offset = rec->rmap.rm_offset; 180 key->rmap.rm_offset = rec->rmap.rm_offset;
181} 181}
182 182
183/*
184 * The high key for a reverse mapping record can be computed by shifting
185 * the startblock and offset to the highest value that would still map
186 * to that record. In practice this means that we add blockcount-1 to
187 * the startblock for all records, and if the record is for a data/attr
188 * fork mapping, we add blockcount-1 to the offset too.
189 */
190STATIC void
191xfs_rmapbt_init_high_key_from_rec(
192 union xfs_btree_key *key,
193 union xfs_btree_rec *rec)
194{
195 __uint64_t off;
196 int adj;
197
198 adj = be32_to_cpu(rec->rmap.rm_blockcount) - 1;
199
200 key->rmap.rm_startblock = rec->rmap.rm_startblock;
201 be32_add_cpu(&key->rmap.rm_startblock, adj);
202 key->rmap.rm_owner = rec->rmap.rm_owner;
203 key->rmap.rm_offset = rec->rmap.rm_offset;
204 if (XFS_RMAP_NON_INODE_OWNER(be64_to_cpu(rec->rmap.rm_owner)) ||
205 XFS_RMAP_IS_BMBT_BLOCK(be64_to_cpu(rec->rmap.rm_offset)))
206 return;
207 off = be64_to_cpu(key->rmap.rm_offset);
208 off = (XFS_RMAP_OFF(off) + adj) | (off & ~XFS_RMAP_OFF_MASK);
209 key->rmap.rm_offset = cpu_to_be64(off);
210}
211
183STATIC void 212STATIC void
184xfs_rmapbt_init_rec_from_cur( 213xfs_rmapbt_init_rec_from_cur(
185 struct xfs_btree_cur *cur, 214 struct xfs_btree_cur *cur,
@@ -235,6 +264,38 @@ xfs_rmapbt_key_diff(
235 return 0; 264 return 0;
236} 265}
237 266
267STATIC __int64_t
268xfs_rmapbt_diff_two_keys(
269 struct xfs_btree_cur *cur,
270 union xfs_btree_key *k1,
271 union xfs_btree_key *k2)
272{
273 struct xfs_rmap_key *kp1 = &k1->rmap;
274 struct xfs_rmap_key *kp2 = &k2->rmap;
275 __int64_t d;
276 __u64 x, y;
277
278 d = (__int64_t)be32_to_cpu(kp1->rm_startblock) -
279 be32_to_cpu(kp2->rm_startblock);
280 if (d)
281 return d;
282
283 x = be64_to_cpu(kp1->rm_owner);
284 y = be64_to_cpu(kp2->rm_owner);
285 if (x > y)
286 return 1;
287 else if (y > x)
288 return -1;
289
290 x = XFS_RMAP_OFF(be64_to_cpu(kp1->rm_offset));
291 y = XFS_RMAP_OFF(be64_to_cpu(kp2->rm_offset));
292 if (x > y)
293 return 1;
294 else if (y > x)
295 return -1;
296 return 0;
297}
298
238static bool 299static bool
239xfs_rmapbt_verify( 300xfs_rmapbt_verify(
240 struct xfs_buf *bp) 301 struct xfs_buf *bp)
@@ -382,10 +443,12 @@ static const struct xfs_btree_ops xfs_rmapbt_ops = {
382 .get_minrecs = xfs_rmapbt_get_minrecs, 443 .get_minrecs = xfs_rmapbt_get_minrecs,
383 .get_maxrecs = xfs_rmapbt_get_maxrecs, 444 .get_maxrecs = xfs_rmapbt_get_maxrecs,
384 .init_key_from_rec = xfs_rmapbt_init_key_from_rec, 445 .init_key_from_rec = xfs_rmapbt_init_key_from_rec,
446 .init_high_key_from_rec = xfs_rmapbt_init_high_key_from_rec,
385 .init_rec_from_cur = xfs_rmapbt_init_rec_from_cur, 447 .init_rec_from_cur = xfs_rmapbt_init_rec_from_cur,
386 .init_ptr_from_cur = xfs_rmapbt_init_ptr_from_cur, 448 .init_ptr_from_cur = xfs_rmapbt_init_ptr_from_cur,
387 .key_diff = xfs_rmapbt_key_diff, 449 .key_diff = xfs_rmapbt_key_diff,
388 .buf_ops = &xfs_rmapbt_buf_ops, 450 .buf_ops = &xfs_rmapbt_buf_ops,
451 .diff_two_keys = xfs_rmapbt_diff_two_keys,
389#if defined(DEBUG) || defined(XFS_WARN) 452#if defined(DEBUG) || defined(XFS_WARN)
390 .keys_inorder = xfs_rmapbt_keys_inorder, 453 .keys_inorder = xfs_rmapbt_keys_inorder,
391 .recs_inorder = xfs_rmapbt_recs_inorder, 454 .recs_inorder = xfs_rmapbt_recs_inorder,
@@ -412,8 +475,9 @@ xfs_rmapbt_init_cursor(
412 cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_NOFS); 475 cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_NOFS);
413 cur->bc_tp = tp; 476 cur->bc_tp = tp;
414 cur->bc_mp = mp; 477 cur->bc_mp = mp;
478 /* Overlapping btree; 2 keys per pointer. */
415 cur->bc_btnum = XFS_BTNUM_RMAP; 479 cur->bc_btnum = XFS_BTNUM_RMAP;
416 cur->bc_flags = XFS_BTREE_CRC_BLOCKS; 480 cur->bc_flags = XFS_BTREE_CRC_BLOCKS | XFS_BTREE_OVERLAPPING;
417 cur->bc_blocklog = mp->m_sb.sb_blocklog; 481 cur->bc_blocklog = mp->m_sb.sb_blocklog;
418 cur->bc_ops = &xfs_rmapbt_ops; 482 cur->bc_ops = &xfs_rmapbt_ops;
419 cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]); 483 cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]);
@@ -438,7 +502,7 @@ xfs_rmapbt_maxrecs(
438 if (leaf) 502 if (leaf)
439 return blocklen / sizeof(struct xfs_rmap_rec); 503 return blocklen / sizeof(struct xfs_rmap_rec);
440 return blocklen / 504 return blocklen /
441 (sizeof(struct xfs_rmap_key) + sizeof(xfs_rmap_ptr_t)); 505 (2 * sizeof(struct xfs_rmap_key) + sizeof(xfs_rmap_ptr_t));
442} 506}
443 507
444/* Compute the maximum height of an rmap btree. */ 508/* Compute the maximum height of an rmap btree. */
diff --git a/fs/xfs/libxfs/xfs_rmap_btree.h b/fs/xfs/libxfs/xfs_rmap_btree.h
index a3a6b7d476c7..e73a55357dab 100644
--- a/fs/xfs/libxfs/xfs_rmap_btree.h
+++ b/fs/xfs/libxfs/xfs_rmap_btree.h
@@ -38,12 +38,18 @@ struct xfs_mount;
38#define XFS_RMAP_KEY_ADDR(block, index) \ 38#define XFS_RMAP_KEY_ADDR(block, index) \
39 ((struct xfs_rmap_key *) \ 39 ((struct xfs_rmap_key *) \
40 ((char *)(block) + XFS_RMAP_BLOCK_LEN + \ 40 ((char *)(block) + XFS_RMAP_BLOCK_LEN + \
41 ((index) - 1) * sizeof(struct xfs_rmap_key))) 41 ((index) - 1) * 2 * sizeof(struct xfs_rmap_key)))
42
43#define XFS_RMAP_HIGH_KEY_ADDR(block, index) \
44 ((struct xfs_rmap_key *) \
45 ((char *)(block) + XFS_RMAP_BLOCK_LEN + \
46 sizeof(struct xfs_rmap_key) + \
47 ((index) - 1) * 2 * sizeof(struct xfs_rmap_key)))
42 48
43#define XFS_RMAP_PTR_ADDR(block, index, maxrecs) \ 49#define XFS_RMAP_PTR_ADDR(block, index, maxrecs) \
44 ((xfs_rmap_ptr_t *) \ 50 ((xfs_rmap_ptr_t *) \
45 ((char *)(block) + XFS_RMAP_BLOCK_LEN + \ 51 ((char *)(block) + XFS_RMAP_BLOCK_LEN + \
46 (maxrecs) * sizeof(struct xfs_rmap_key) + \ 52 (maxrecs) * 2 * sizeof(struct xfs_rmap_key) + \
47 ((index) - 1) * sizeof(xfs_rmap_ptr_t))) 53 ((index) - 1) * sizeof(xfs_rmap_ptr_t)))
48 54
49struct xfs_btree_cur *xfs_rmapbt_init_cursor(struct xfs_mount *mp, 55struct xfs_btree_cur *xfs_rmapbt_init_cursor(struct xfs_mount *mp,