diff options
-rw-r--r-- | fs/xfs/libxfs/xfs_rmap_btree.c | 68 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_rmap_btree.h | 10 |
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 | */ | ||
190 | STATIC void | ||
191 | xfs_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 | |||
183 | STATIC void | 212 | STATIC void |
184 | xfs_rmapbt_init_rec_from_cur( | 213 | xfs_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 | ||
267 | STATIC __int64_t | ||
268 | xfs_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 | |||
238 | static bool | 299 | static bool |
239 | xfs_rmapbt_verify( | 300 | xfs_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 | ||
49 | struct xfs_btree_cur *xfs_rmapbt_init_cursor(struct xfs_mount *mp, | 55 | struct xfs_btree_cur *xfs_rmapbt_init_cursor(struct xfs_mount *mp, |