/* Decide if this mapping is shared. */ STATIC int xfs_getfsmap_is_shared( struct xfs_trans *tp, struct xfs_getfsmap_info *info, struct xfs_rmap_irec *rec, bool *stat) { struct xfs_mount *mp = tp->t_mountp; struct xfs_btree_cur *cur; xfs_agblock_t fbno; xfs_extlen_t flen; int error; *stat = false; if (!xfs_sb_version_hasreflink(&mp->m_sb)) return 0; /* rt files will have agno set to NULLAGNUMBER */ if (info->agno == NULLAGNUMBER) return 0; /* Are there any shared blocks here? */ flen = 0; cur = xfs_refcountbt_init_cursor(mp, tp, info->agf_bp, info->agno, NULL); error = xfs_refcount_find_shared(cur, rec->rm_startblock, rec->rm_blockcount, &fbno, &flen, false); xfs_btree_del_cursor(cur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); if (error) return error; *stat = flen > 0; return 0; }
/* * Given an AG extent, find the lowest-numbered run of shared blocks * within that range and return the range in fbno/flen. If * find_end_of_shared is true, return the longest contiguous extent of * shared blocks. If there are no shared extents, fbno and flen will * be set to NULLAGBLOCK and 0, respectively. */ int xfs_reflink_find_shared( struct xfs_mount *mp, struct xfs_trans *tp, xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t aglen, xfs_agblock_t *fbno, xfs_extlen_t *flen, bool find_end_of_shared) { struct xfs_buf *agbp; struct xfs_btree_cur *cur; int error; error = xfs_alloc_read_agf(mp, tp, agno, 0, &agbp); if (error) return error; if (!agbp) return -ENOMEM; cur = xfs_refcountbt_init_cursor(mp, tp, agbp, agno, NULL); error = xfs_refcount_find_shared(cur, agbno, aglen, fbno, flen, find_end_of_shared); xfs_btree_del_cursor(cur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); xfs_trans_brelse(tp, agbp); return error; }
static struct xfs_btree_cur * xfs_refcountbt_dup_cursor( struct xfs_btree_cur *cur) { return xfs_refcountbt_init_cursor(cur->bc_mp, cur->bc_tp, cur->bc_private.a.agbp, cur->bc_private.a.agno, cur->bc_private.a.dfops); }