@@ -40,6 +40,7 @@
#include "xfs_refcount.h"
#include "xfs_refcount_btree.h"
#include "xfs_alloc_btree.h"
+#include "xfs_rtalloc.h"
/* getfsmap query state */
struct xfs_getfsmap_info {
@@ -315,6 +316,29 @@ xfs_getfsmap_rtdev_helper(
return xfs_getfsmap_helper(mp, info, rec, rec_daddr);
}
+/* Transform a rtbitmap "record" into a fsmap */
+STATIC int
+xfs_getfsmap_rtdev_rtbitmap_helper(
+ struct xfs_mount *mp,
+ xfs_rtblock_t start,
+ xfs_rtblock_t end,
+ void *priv)
+{
+ struct xfs_getfsmap_info *info = priv;
+ struct xfs_rmap_irec irec;
+ xfs_daddr_t rec_daddr;
+
+ rec_daddr = XFS_FSB_TO_BB(mp, start);
+
+ irec.rm_startblock = start;
+ irec.rm_blockcount = end - start + 1;
+ irec.rm_owner = XFS_RMAP_OWN_NULL; /* "free" */
+ irec.rm_offset = 0;
+ irec.rm_flags = 0;
+
+ return xfs_getfsmap_helper(mp, info, &irec, rec_daddr);
+}
+
/* Transform a bnobt irec into a fsmap */
STATIC int
xfs_getfsmap_datadev_bnobt_helper(
@@ -407,6 +431,103 @@ xfs_getfsmap_logdev(
return xfs_getfsmap_rtdev_helper(&cur, &rmap, info);
}
+/* Execute a getfsmap query against the realtime data device (rtbitmap). */
+STATIC int
+xfs_getfsmap_rtdev_rtbitmap(
+ struct xfs_mount *mp,
+ struct getfsmap *keys,
+ struct xfs_getfsmap_info *info)
+{
+ struct getfsmap *lowkey;
+ struct getfsmap *highkey;
+ xfs_fsblock_t start_fsb;
+ xfs_fsblock_t end_fsb;
+ xfs_rtblock_t rtstart;
+ xfs_rtblock_t rtend;
+ xfs_rtblock_t rem;
+ xfs_daddr_t eofs;
+ int is_free;
+ int error = 0;
+
+ lowkey = keys;
+ highkey = keys + 1;
+ eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks);
+ if (lowkey->fmv_block >= eofs)
+ return 0;
+ if (highkey->fmv_block >= eofs)
+ highkey->fmv_block = eofs - 1;
+ start_fsb = XFS_BB_TO_FSBT(mp, lowkey->fmv_block);
+ end_fsb = XFS_BB_TO_FSB(mp, highkey->fmv_block);
+
+ /* Set up search keys */
+ info->low.rm_startblock = start_fsb;
+ info->low.rm_owner = lowkey->fmv_owner;
+ info->low.rm_offset = XFS_BB_TO_FSBT(mp, lowkey->fmv_offset);
+ info->low.rm_blockcount = 0;
+ xfs_getfsmap_set_irec_flags(&info->low, lowkey);
+
+ info->high.rm_startblock = end_fsb;
+ info->high.rm_owner = highkey->fmv_owner;
+ info->high.rm_offset = XFS_BB_TO_FSBT(mp, highkey->fmv_offset);
+ info->high.rm_blockcount = 0;
+ xfs_getfsmap_set_irec_flags(&info->high, highkey);
+
+ info->missing_owner = FMV_OWN_UNKNOWN;
+
+ trace_xfs_fsmap_low_key(mp, info->dev, info->agno,
+ info->low.rm_startblock,
+ info->low.rm_blockcount,
+ info->low.rm_owner,
+ info->low.rm_offset);
+
+ trace_xfs_fsmap_high_key(mp, info->dev, info->agno,
+ info->high.rm_startblock,
+ info->high.rm_blockcount,
+ info->high.rm_owner,
+ info->high.rm_offset);
+
+ xfs_ilock(mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP);
+
+ /* Iterate the bitmap, looking for discrepancies. */
+ rtstart = 0;
+ rem = mp->m_sb.sb_rblocks;
+ while (rem) {
+ /* Is the first block free? */
+ error = xfs_rtcheck_range(mp, NULL, rtstart, 1, 1, &rtend,
+ &is_free);
+ if (error)
+ goto out_unlock;
+
+ /* How long does the extent go for? */
+ error = xfs_rtfind_forw(mp, NULL, rtstart,
+ mp->m_sb.sb_rblocks - 1, &rtend);
+ if (error)
+ goto out_unlock;
+
+ if (is_free) {
+ error = xfs_getfsmap_rtdev_rtbitmap_helper(mp,
+ rtstart, rtend, info);
+ if (error)
+ goto out_unlock;
+ }
+
+ rem -= rtend - rtstart + 1;
+ rtstart = rtend + 1;
+ }
+
+out_unlock:
+ xfs_iunlock(mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP);
+
+ /* Report any free space at the end of the rtdev */
+ info->last = true;
+ error = xfs_getfsmap_rtdev_rtbitmap_helper(mp, end_fsb, 0, info);
+ if (error)
+ goto err;
+
+err:
+ return error;
+}
+
/* Execute a getfsmap query against the regular data device. */
STATIC int
xfs_getfsmap_datadev(
@@ -699,6 +820,11 @@ xfs_getfsmap(
handlers[1].dev = new_encode_dev(mp->m_logdev_targp->bt_dev);
handlers[1].fn = xfs_getfsmap_logdev;
}
+ if (mp->m_rtdev_targp) {
+ handlers[2].dev = new_encode_dev(mp->m_rtdev_targp->bt_dev);
+ if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
+ handlers[2].fn = xfs_getfsmap_rtdev_rtbitmap;
+ }
xfs_sort(handlers, XFS_GETFSMAP_DEVS, sizeof(struct xfs_getfsmap_dev),
xfs_getfsmap_dev_compare);
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> --- fs/xfs/xfs_fsmap.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+)