xfs: always honor OWN_UNKNOWN rmap removal requests

Calling xfs_rmap_free with an unknown owner is supposed to remove any
rmaps covering that range regardless of owner. This is used by the EFI
recovery code to say "we're freeing this, it mustn't be owned by
anything anymore", but for whatever reason xfs_free_ag_extent filters
them out.

Therefore, remove the filter and make xfs_rmap_unmap actually treat it
as a wildcard owner -- free anything that's already there, and if
there's no owner at all then that's fine too.

There are two existing callers of bmap_add_free that take care the rmap
deferred ops themselves and use OWN_UNKNOWN to skip the EFI-based rmap
cleanup; convert these to use OWN_NULL (via helpers), and now we really
require that an RUI (if any) gets added to the defer ops before any EFI.

Lastly, now that xfs_free_extent filters out OWN_NULL rmap free requests,
growfs will have to consult directly with the rmap to ensure that there
aren't any rmaps in the grown region.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>

+48 -4
+2 -2
fs/xfs/libxfs/xfs_alloc.c
··· 702 702 ASSERT(args->agbno % args->alignment == 0); 703 703 704 704 /* if not file data, insert new block into the reverse map btree */ 705 - if (args->oinfo.oi_owner != XFS_RMAP_OWN_UNKNOWN) { 705 + if (!xfs_rmap_should_skip_owner_update(&args->oinfo)) { 706 706 error = xfs_rmap_alloc(args->tp, args->agbp, args->agno, 707 707 args->agbno, args->len, &args->oinfo); 708 708 if (error) ··· 1682 1682 bno_cur = cnt_cur = NULL; 1683 1683 mp = tp->t_mountp; 1684 1684 1685 - if (oinfo->oi_owner != XFS_RMAP_OWN_UNKNOWN) { 1685 + if (!xfs_rmap_should_skip_owner_update(oinfo)) { 1686 1686 error = xfs_rmap_free(tp, agbp, agno, bno, len, oinfo); 1687 1687 if (error) 1688 1688 goto error0;
+25
fs/xfs/libxfs/xfs_rmap.c
··· 444 444 goto out_done; 445 445 } 446 446 447 + /* 448 + * If we're doing an unknown-owner removal for EFI recovery, we expect 449 + * to find the full range in the rmapbt or nothing at all. If we 450 + * don't find any rmaps overlapping either end of the range, we're 451 + * done. Hopefully this means that the EFI creator already queued 452 + * (and finished) a RUI to remove the rmap. 453 + */ 454 + if (owner == XFS_RMAP_OWN_UNKNOWN && 455 + ltrec.rm_startblock + ltrec.rm_blockcount <= bno) { 456 + struct xfs_rmap_irec rtrec; 457 + 458 + error = xfs_btree_increment(cur, 0, &i); 459 + if (error) 460 + goto out_error; 461 + if (i == 0) 462 + goto out_done; 463 + error = xfs_rmap_get_rec(cur, &rtrec, &i); 464 + if (error) 465 + goto out_error; 466 + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); 467 + if (rtrec.rm_startblock >= bno + len) 468 + goto out_done; 469 + } 470 + 447 471 /* Make sure the unwritten flag matches. */ 448 472 XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) == 449 473 (ltrec.rm_flags & XFS_RMAP_UNWRITTEN), out_error); ··· 688 664 flags |= XFS_RMAP_UNWRITTEN; 689 665 trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len, 690 666 unwritten, oinfo); 667 + ASSERT(!xfs_rmap_should_skip_owner_update(oinfo)); 691 668 692 669 /* 693 670 * For the initial lookup, look for an exact match or the left-adjacent
+15 -1
fs/xfs/libxfs/xfs_rmap.h
··· 61 61 xfs_rmap_skip_owner_update( 62 62 struct xfs_owner_info *oi) 63 63 { 64 - oi->oi_owner = XFS_RMAP_OWN_UNKNOWN; 64 + xfs_rmap_ag_owner(oi, XFS_RMAP_OWN_NULL); 65 + } 66 + 67 + static inline bool 68 + xfs_rmap_should_skip_owner_update( 69 + struct xfs_owner_info *oi) 70 + { 71 + return oi->oi_owner == XFS_RMAP_OWN_NULL; 72 + } 73 + 74 + static inline void 75 + xfs_rmap_any_owner_update( 76 + struct xfs_owner_info *oi) 77 + { 78 + xfs_rmap_ag_owner(oi, XFS_RMAP_OWN_UNKNOWN); 65 79 } 66 80 67 81 /* Reverse mapping functions. */
+1 -1
fs/xfs/xfs_extfree_item.c
··· 538 538 return error; 539 539 efdp = xfs_trans_get_efd(tp, efip, efip->efi_format.efi_nextents); 540 540 541 - xfs_rmap_skip_owner_update(&oinfo); 541 + xfs_rmap_any_owner_update(&oinfo); 542 542 for (i = 0; i < efip->efi_format.efi_nextents; i++) { 543 543 extp = &efip->efi_format.efi_extents[i]; 544 544 error = xfs_trans_free_extent(tp, efdp, extp->ext_start,
+5
fs/xfs/xfs_fsops.c
··· 571 571 * this doesn't actually exist in the rmap btree. 572 572 */ 573 573 xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_NULL); 574 + error = xfs_rmap_free(tp, bp, agno, 575 + be32_to_cpu(agf->agf_length) - new, 576 + new, &oinfo); 577 + if (error) 578 + goto error0; 574 579 error = xfs_free_extent(tp, 575 580 XFS_AGB_TO_FSB(mp, agno, 576 581 be32_to_cpu(agf->agf_length) - new),