| .. | .. |
|---|
| 12 | 12 | #include "xfs_sb.h" |
|---|
| 13 | 13 | #include "xfs_mount.h" |
|---|
| 14 | 14 | #include "xfs_btree.h" |
|---|
| 15 | | -#include "xfs_bmap.h" |
|---|
| 15 | +#include "xfs_btree_staging.h" |
|---|
| 16 | 16 | #include "xfs_refcount_btree.h" |
|---|
| 17 | 17 | #include "xfs_alloc.h" |
|---|
| 18 | 18 | #include "xfs_error.h" |
|---|
| 19 | 19 | #include "xfs_trace.h" |
|---|
| 20 | | -#include "xfs_cksum.h" |
|---|
| 21 | 20 | #include "xfs_trans.h" |
|---|
| 22 | 21 | #include "xfs_bit.h" |
|---|
| 23 | 22 | #include "xfs_rmap.h" |
|---|
| .. | .. |
|---|
| 27 | 26 | struct xfs_btree_cur *cur) |
|---|
| 28 | 27 | { |
|---|
| 29 | 28 | return xfs_refcountbt_init_cursor(cur->bc_mp, cur->bc_tp, |
|---|
| 30 | | - cur->bc_private.a.agbp, cur->bc_private.a.agno); |
|---|
| 29 | + cur->bc_ag.agbp, cur->bc_ag.agno); |
|---|
| 31 | 30 | } |
|---|
| 32 | 31 | |
|---|
| 33 | 32 | STATIC void |
|---|
| .. | .. |
|---|
| 36 | 35 | union xfs_btree_ptr *ptr, |
|---|
| 37 | 36 | int inc) |
|---|
| 38 | 37 | { |
|---|
| 39 | | - struct xfs_buf *agbp = cur->bc_private.a.agbp; |
|---|
| 40 | | - struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); |
|---|
| 41 | | - xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); |
|---|
| 42 | | - struct xfs_perag *pag = xfs_perag_get(cur->bc_mp, seqno); |
|---|
| 38 | + struct xfs_buf *agbp = cur->bc_ag.agbp; |
|---|
| 39 | + struct xfs_agf *agf = agbp->b_addr; |
|---|
| 40 | + struct xfs_perag *pag = agbp->b_pag; |
|---|
| 43 | 41 | |
|---|
| 44 | 42 | ASSERT(ptr->s != 0); |
|---|
| 45 | 43 | |
|---|
| 46 | 44 | agf->agf_refcount_root = ptr->s; |
|---|
| 47 | 45 | be32_add_cpu(&agf->agf_refcount_level, inc); |
|---|
| 48 | 46 | pag->pagf_refcount_level += inc; |
|---|
| 49 | | - xfs_perag_put(pag); |
|---|
| 50 | 47 | |
|---|
| 51 | 48 | xfs_alloc_log_agf(cur->bc_tp, agbp, |
|---|
| 52 | 49 | XFS_AGF_REFCOUNT_ROOT | XFS_AGF_REFCOUNT_LEVEL); |
|---|
| .. | .. |
|---|
| 59 | 56 | union xfs_btree_ptr *new, |
|---|
| 60 | 57 | int *stat) |
|---|
| 61 | 58 | { |
|---|
| 62 | | - struct xfs_buf *agbp = cur->bc_private.a.agbp; |
|---|
| 63 | | - struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); |
|---|
| 59 | + struct xfs_buf *agbp = cur->bc_ag.agbp; |
|---|
| 60 | + struct xfs_agf *agf = agbp->b_addr; |
|---|
| 64 | 61 | struct xfs_alloc_arg args; /* block allocation args */ |
|---|
| 65 | 62 | int error; /* error return value */ |
|---|
| 66 | 63 | |
|---|
| .. | .. |
|---|
| 68 | 65 | args.tp = cur->bc_tp; |
|---|
| 69 | 66 | args.mp = cur->bc_mp; |
|---|
| 70 | 67 | args.type = XFS_ALLOCTYPE_NEAR_BNO; |
|---|
| 71 | | - args.fsbno = XFS_AGB_TO_FSB(cur->bc_mp, cur->bc_private.a.agno, |
|---|
| 68 | + args.fsbno = XFS_AGB_TO_FSB(cur->bc_mp, cur->bc_ag.agno, |
|---|
| 72 | 69 | xfs_refc_block(args.mp)); |
|---|
| 73 | | - xfs_rmap_ag_owner(&args.oinfo, XFS_RMAP_OWN_REFC); |
|---|
| 70 | + args.oinfo = XFS_RMAP_OINFO_REFC; |
|---|
| 74 | 71 | args.minlen = args.maxlen = args.prod = 1; |
|---|
| 75 | 72 | args.resv = XFS_AG_RESV_METADATA; |
|---|
| 76 | 73 | |
|---|
| 77 | 74 | error = xfs_alloc_vextent(&args); |
|---|
| 78 | 75 | if (error) |
|---|
| 79 | 76 | goto out_error; |
|---|
| 80 | | - trace_xfs_refcountbt_alloc_block(cur->bc_mp, cur->bc_private.a.agno, |
|---|
| 77 | + trace_xfs_refcountbt_alloc_block(cur->bc_mp, cur->bc_ag.agno, |
|---|
| 81 | 78 | args.agbno, 1); |
|---|
| 82 | 79 | if (args.fsbno == NULLFSBLOCK) { |
|---|
| 83 | 80 | *stat = 0; |
|---|
| 84 | 81 | return 0; |
|---|
| 85 | 82 | } |
|---|
| 86 | | - ASSERT(args.agno == cur->bc_private.a.agno); |
|---|
| 83 | + ASSERT(args.agno == cur->bc_ag.agno); |
|---|
| 87 | 84 | ASSERT(args.len == 1); |
|---|
| 88 | 85 | |
|---|
| 89 | 86 | new->s = cpu_to_be32(args.agbno); |
|---|
| .. | .. |
|---|
| 103 | 100 | struct xfs_buf *bp) |
|---|
| 104 | 101 | { |
|---|
| 105 | 102 | struct xfs_mount *mp = cur->bc_mp; |
|---|
| 106 | | - struct xfs_buf *agbp = cur->bc_private.a.agbp; |
|---|
| 107 | | - struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); |
|---|
| 103 | + struct xfs_buf *agbp = cur->bc_ag.agbp; |
|---|
| 104 | + struct xfs_agf *agf = agbp->b_addr; |
|---|
| 108 | 105 | xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp)); |
|---|
| 109 | | - struct xfs_owner_info oinfo; |
|---|
| 110 | 106 | int error; |
|---|
| 111 | 107 | |
|---|
| 112 | | - trace_xfs_refcountbt_free_block(cur->bc_mp, cur->bc_private.a.agno, |
|---|
| 108 | + trace_xfs_refcountbt_free_block(cur->bc_mp, cur->bc_ag.agno, |
|---|
| 113 | 109 | XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno), 1); |
|---|
| 114 | | - xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_REFC); |
|---|
| 115 | 110 | be32_add_cpu(&agf->agf_refcount_blocks, -1); |
|---|
| 116 | 111 | xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_REFCOUNT_BLOCKS); |
|---|
| 117 | | - error = xfs_free_extent(cur->bc_tp, fsbno, 1, &oinfo, |
|---|
| 112 | + error = xfs_free_extent(cur->bc_tp, fsbno, 1, &XFS_RMAP_OINFO_REFC, |
|---|
| 118 | 113 | XFS_AG_RESV_METADATA); |
|---|
| 119 | 114 | if (error) |
|---|
| 120 | 115 | return error; |
|---|
| .. | .. |
|---|
| 173 | 168 | struct xfs_btree_cur *cur, |
|---|
| 174 | 169 | union xfs_btree_ptr *ptr) |
|---|
| 175 | 170 | { |
|---|
| 176 | | - struct xfs_agf *agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); |
|---|
| 171 | + struct xfs_agf *agf = cur->bc_ag.agbp->b_addr; |
|---|
| 177 | 172 | |
|---|
| 178 | | - ASSERT(cur->bc_private.a.agno == be32_to_cpu(agf->agf_seqno)); |
|---|
| 173 | + ASSERT(cur->bc_ag.agno == be32_to_cpu(agf->agf_seqno)); |
|---|
| 179 | 174 | |
|---|
| 180 | 175 | ptr->s = agf->agf_refcount_root; |
|---|
| 181 | 176 | } |
|---|
| .. | .. |
|---|
| 205 | 200 | xfs_refcountbt_verify( |
|---|
| 206 | 201 | struct xfs_buf *bp) |
|---|
| 207 | 202 | { |
|---|
| 208 | | - struct xfs_mount *mp = bp->b_target->bt_mount; |
|---|
| 203 | + struct xfs_mount *mp = bp->b_mount; |
|---|
| 209 | 204 | struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); |
|---|
| 210 | 205 | struct xfs_perag *pag = bp->b_pag; |
|---|
| 211 | 206 | xfs_failaddr_t fa; |
|---|
| 212 | 207 | unsigned int level; |
|---|
| 213 | 208 | |
|---|
| 214 | | - if (block->bb_magic != cpu_to_be32(XFS_REFC_CRC_MAGIC)) |
|---|
| 209 | + if (!xfs_verify_magic(bp, block->bb_magic)) |
|---|
| 215 | 210 | return __this_address; |
|---|
| 216 | 211 | |
|---|
| 217 | 212 | if (!xfs_sb_version_hasreflink(&mp->m_sb)) |
|---|
| .. | .. |
|---|
| 266 | 261 | |
|---|
| 267 | 262 | const struct xfs_buf_ops xfs_refcountbt_buf_ops = { |
|---|
| 268 | 263 | .name = "xfs_refcountbt", |
|---|
| 264 | + .magic = { 0, cpu_to_be32(XFS_REFC_CRC_MAGIC) }, |
|---|
| 269 | 265 | .verify_read = xfs_refcountbt_read_verify, |
|---|
| 270 | 266 | .verify_write = xfs_refcountbt_write_verify, |
|---|
| 271 | 267 | .verify_struct = xfs_refcountbt_verify, |
|---|
| .. | .. |
|---|
| 314 | 310 | }; |
|---|
| 315 | 311 | |
|---|
| 316 | 312 | /* |
|---|
| 317 | | - * Allocate a new refcount btree cursor. |
|---|
| 313 | + * Initialize a new refcount btree cursor. |
|---|
| 318 | 314 | */ |
|---|
| 315 | +static struct xfs_btree_cur * |
|---|
| 316 | +xfs_refcountbt_init_common( |
|---|
| 317 | + struct xfs_mount *mp, |
|---|
| 318 | + struct xfs_trans *tp, |
|---|
| 319 | + xfs_agnumber_t agno) |
|---|
| 320 | +{ |
|---|
| 321 | + struct xfs_btree_cur *cur; |
|---|
| 322 | + |
|---|
| 323 | + ASSERT(agno != NULLAGNUMBER); |
|---|
| 324 | + ASSERT(agno < mp->m_sb.sb_agcount); |
|---|
| 325 | + |
|---|
| 326 | + cur = kmem_cache_zalloc(xfs_btree_cur_zone, GFP_NOFS | __GFP_NOFAIL); |
|---|
| 327 | + cur->bc_tp = tp; |
|---|
| 328 | + cur->bc_mp = mp; |
|---|
| 329 | + cur->bc_btnum = XFS_BTNUM_REFC; |
|---|
| 330 | + cur->bc_blocklog = mp->m_sb.sb_blocklog; |
|---|
| 331 | + cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_refcbt_2); |
|---|
| 332 | + |
|---|
| 333 | + cur->bc_ag.agno = agno; |
|---|
| 334 | + cur->bc_flags |= XFS_BTREE_CRC_BLOCKS; |
|---|
| 335 | + |
|---|
| 336 | + cur->bc_ag.refc.nr_ops = 0; |
|---|
| 337 | + cur->bc_ag.refc.shape_changes = 0; |
|---|
| 338 | + cur->bc_ops = &xfs_refcountbt_ops; |
|---|
| 339 | + return cur; |
|---|
| 340 | +} |
|---|
| 341 | + |
|---|
| 342 | +/* Create a btree cursor. */ |
|---|
| 319 | 343 | struct xfs_btree_cur * |
|---|
| 320 | 344 | xfs_refcountbt_init_cursor( |
|---|
| 321 | 345 | struct xfs_mount *mp, |
|---|
| .. | .. |
|---|
| 323 | 347 | struct xfs_buf *agbp, |
|---|
| 324 | 348 | xfs_agnumber_t agno) |
|---|
| 325 | 349 | { |
|---|
| 326 | | - struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); |
|---|
| 350 | + struct xfs_agf *agf = agbp->b_addr; |
|---|
| 327 | 351 | struct xfs_btree_cur *cur; |
|---|
| 328 | 352 | |
|---|
| 329 | | - ASSERT(agno != NULLAGNUMBER); |
|---|
| 330 | | - ASSERT(agno < mp->m_sb.sb_agcount); |
|---|
| 331 | | - cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_NOFS); |
|---|
| 332 | | - |
|---|
| 333 | | - cur->bc_tp = tp; |
|---|
| 334 | | - cur->bc_mp = mp; |
|---|
| 335 | | - cur->bc_btnum = XFS_BTNUM_REFC; |
|---|
| 336 | | - cur->bc_blocklog = mp->m_sb.sb_blocklog; |
|---|
| 337 | | - cur->bc_ops = &xfs_refcountbt_ops; |
|---|
| 338 | | - cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_refcbt_2); |
|---|
| 339 | | - |
|---|
| 353 | + cur = xfs_refcountbt_init_common(mp, tp, agno); |
|---|
| 340 | 354 | cur->bc_nlevels = be32_to_cpu(agf->agf_refcount_level); |
|---|
| 341 | | - |
|---|
| 342 | | - cur->bc_private.a.agbp = agbp; |
|---|
| 343 | | - cur->bc_private.a.agno = agno; |
|---|
| 344 | | - cur->bc_flags |= XFS_BTREE_CRC_BLOCKS; |
|---|
| 345 | | - |
|---|
| 346 | | - cur->bc_private.a.priv.refc.nr_ops = 0; |
|---|
| 347 | | - cur->bc_private.a.priv.refc.shape_changes = 0; |
|---|
| 348 | | - |
|---|
| 355 | + cur->bc_ag.agbp = agbp; |
|---|
| 349 | 356 | return cur; |
|---|
| 357 | +} |
|---|
| 358 | + |
|---|
| 359 | +/* Create a btree cursor with a fake root for staging. */ |
|---|
| 360 | +struct xfs_btree_cur * |
|---|
| 361 | +xfs_refcountbt_stage_cursor( |
|---|
| 362 | + struct xfs_mount *mp, |
|---|
| 363 | + struct xbtree_afakeroot *afake, |
|---|
| 364 | + xfs_agnumber_t agno) |
|---|
| 365 | +{ |
|---|
| 366 | + struct xfs_btree_cur *cur; |
|---|
| 367 | + |
|---|
| 368 | + cur = xfs_refcountbt_init_common(mp, NULL, agno); |
|---|
| 369 | + xfs_btree_stage_afakeroot(cur, afake); |
|---|
| 370 | + return cur; |
|---|
| 371 | +} |
|---|
| 372 | + |
|---|
| 373 | +/* |
|---|
| 374 | + * Swap in the new btree root. Once we pass this point the newly rebuilt btree |
|---|
| 375 | + * is in place and we have to kill off all the old btree blocks. |
|---|
| 376 | + */ |
|---|
| 377 | +void |
|---|
| 378 | +xfs_refcountbt_commit_staged_btree( |
|---|
| 379 | + struct xfs_btree_cur *cur, |
|---|
| 380 | + struct xfs_trans *tp, |
|---|
| 381 | + struct xfs_buf *agbp) |
|---|
| 382 | +{ |
|---|
| 383 | + struct xfs_agf *agf = agbp->b_addr; |
|---|
| 384 | + struct xbtree_afakeroot *afake = cur->bc_ag.afake; |
|---|
| 385 | + |
|---|
| 386 | + ASSERT(cur->bc_flags & XFS_BTREE_STAGING); |
|---|
| 387 | + |
|---|
| 388 | + agf->agf_refcount_root = cpu_to_be32(afake->af_root); |
|---|
| 389 | + agf->agf_refcount_level = cpu_to_be32(afake->af_levels); |
|---|
| 390 | + agf->agf_refcount_blocks = cpu_to_be32(afake->af_blocks); |
|---|
| 391 | + xfs_alloc_log_agf(tp, agbp, XFS_AGF_REFCOUNT_BLOCKS | |
|---|
| 392 | + XFS_AGF_REFCOUNT_ROOT | |
|---|
| 393 | + XFS_AGF_REFCOUNT_LEVEL); |
|---|
| 394 | + xfs_btree_commit_afakeroot(cur, tp, agbp, &xfs_refcountbt_ops); |
|---|
| 350 | 395 | } |
|---|
| 351 | 396 | |
|---|
| 352 | 397 | /* |
|---|
| .. | .. |
|---|
| 423 | 468 | if (error) |
|---|
| 424 | 469 | return error; |
|---|
| 425 | 470 | |
|---|
| 426 | | - agf = XFS_BUF_TO_AGF(agbp); |
|---|
| 471 | + agf = agbp->b_addr; |
|---|
| 427 | 472 | agblocks = be32_to_cpu(agf->agf_length); |
|---|
| 428 | 473 | tree_len = be32_to_cpu(agf->agf_refcount_blocks); |
|---|
| 429 | 474 | xfs_trans_brelse(tp, agbp); |
|---|
| 430 | 475 | |
|---|
| 476 | + /* |
|---|
| 477 | + * The log is permanently allocated, so the space it occupies will |
|---|
| 478 | + * never be available for the kinds of things that would require btree |
|---|
| 479 | + * expansion. We therefore can pretend the space isn't there. |
|---|
| 480 | + */ |
|---|
| 481 | + if (mp->m_sb.sb_logstart && |
|---|
| 482 | + XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart) == agno) |
|---|
| 483 | + agblocks -= mp->m_sb.sb_logblocks; |
|---|
| 484 | + |
|---|
| 431 | 485 | *ask += xfs_refcountbt_max_size(mp, agblocks); |
|---|
| 432 | 486 | *used += tree_len; |
|---|
| 433 | 487 | |
|---|