.. | .. |
---|
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 | |
---|