mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
xfs: enable fsmap reporting for internal RT devices
File system with internal RT devices are a bit odd in that we need to report AGs and RGs. To make this happen use separate synthetic fmr_device values for the different sections instead of the dev_t mapping used by other XFS configurations. The data device is reported as file system metadata before the start of the RGs for the synthetic RT fmr_device. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
This commit is contained in:
parent
14d355dcec
commit
e50ec7fac8
2 changed files with 72 additions and 17 deletions
|
@ -1082,6 +1082,15 @@ struct xfs_rtgroup_geometry {
|
|||
#define XFS_IOC_COMMIT_RANGE _IOW ('X', 131, struct xfs_commit_range)
|
||||
/* XFS_IOC_GETFSUUID ---------- deprecated 140 */
|
||||
|
||||
/*
|
||||
* Devices supported by a single XFS file system. Reported in fsmaps fmr_device
|
||||
* when using internal RT devices.
|
||||
*/
|
||||
enum xfs_device {
|
||||
XFS_DEV_DATA = 1,
|
||||
XFS_DEV_LOG = 2,
|
||||
XFS_DEV_RT = 3,
|
||||
};
|
||||
|
||||
#ifndef HAVE_BBMACROS
|
||||
/*
|
||||
|
|
|
@ -879,17 +879,39 @@ xfs_getfsmap_rtdev_rmapbt(
|
|||
struct xfs_mount *mp = tp->t_mountp;
|
||||
struct xfs_rtgroup *rtg = NULL;
|
||||
struct xfs_btree_cur *bt_cur = NULL;
|
||||
xfs_daddr_t rtstart_daddr;
|
||||
xfs_rtblock_t start_rtb;
|
||||
xfs_rtblock_t end_rtb;
|
||||
xfs_rgnumber_t start_rg, end_rg;
|
||||
uint64_t eofs;
|
||||
int error = 0;
|
||||
|
||||
eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks);
|
||||
eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_rtstart + mp->m_sb.sb_rblocks);
|
||||
if (keys[0].fmr_physical >= eofs)
|
||||
return 0;
|
||||
start_rtb = xfs_daddr_to_rtb(mp, keys[0].fmr_physical);
|
||||
end_rtb = xfs_daddr_to_rtb(mp, min(eofs - 1, keys[1].fmr_physical));
|
||||
|
||||
rtstart_daddr = XFS_FSB_TO_BB(mp, mp->m_sb.sb_rtstart);
|
||||
if (keys[0].fmr_physical < rtstart_daddr) {
|
||||
struct xfs_fsmap_irec frec = {
|
||||
.owner = XFS_RMAP_OWN_FS,
|
||||
.len_daddr = rtstart_daddr,
|
||||
};
|
||||
|
||||
/* Adjust the low key if we are continuing from where we left off. */
|
||||
if (keys[0].fmr_length > 0) {
|
||||
info->low_daddr = keys[0].fmr_physical + keys[0].fmr_length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fabricate an rmap entry for space occupied by the data dev */
|
||||
error = xfs_getfsmap_helper(tp, info, &frec);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
start_rtb = xfs_daddr_to_rtb(mp, rtstart_daddr + keys[0].fmr_physical);
|
||||
end_rtb = xfs_daddr_to_rtb(mp, rtstart_daddr +
|
||||
min(eofs - 1, keys[1].fmr_physical));
|
||||
|
||||
info->missing_owner = XFS_FMR_OWN_FREE;
|
||||
|
||||
|
@ -1004,22 +1026,40 @@ xfs_getfsmap_rtdev_rmapbt(
|
|||
}
|
||||
#endif /* CONFIG_XFS_RT */
|
||||
|
||||
static uint32_t
|
||||
xfs_getfsmap_device(
|
||||
struct xfs_mount *mp,
|
||||
enum xfs_device dev)
|
||||
{
|
||||
if (mp->m_sb.sb_rtstart)
|
||||
return dev;
|
||||
|
||||
switch (dev) {
|
||||
case XFS_DEV_DATA:
|
||||
return new_encode_dev(mp->m_ddev_targp->bt_dev);
|
||||
case XFS_DEV_LOG:
|
||||
return new_encode_dev(mp->m_logdev_targp->bt_dev);
|
||||
case XFS_DEV_RT:
|
||||
if (!mp->m_rtdev_targp)
|
||||
break;
|
||||
return new_encode_dev(mp->m_rtdev_targp->bt_dev);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Do we recognize the device? */
|
||||
STATIC bool
|
||||
xfs_getfsmap_is_valid_device(
|
||||
struct xfs_mount *mp,
|
||||
struct xfs_fsmap *fm)
|
||||
{
|
||||
if (fm->fmr_device == 0 || fm->fmr_device == UINT_MAX ||
|
||||
fm->fmr_device == new_encode_dev(mp->m_ddev_targp->bt_dev))
|
||||
return true;
|
||||
if (mp->m_logdev_targp &&
|
||||
fm->fmr_device == new_encode_dev(mp->m_logdev_targp->bt_dev))
|
||||
return true;
|
||||
if (mp->m_rtdev_targp &&
|
||||
fm->fmr_device == new_encode_dev(mp->m_rtdev_targp->bt_dev))
|
||||
return true;
|
||||
return false;
|
||||
return fm->fmr_device == 0 ||
|
||||
fm->fmr_device == UINT_MAX ||
|
||||
fm->fmr_device == xfs_getfsmap_device(mp, XFS_DEV_DATA) ||
|
||||
fm->fmr_device == xfs_getfsmap_device(mp, XFS_DEV_LOG) ||
|
||||
(mp->m_rtdev_targp &&
|
||||
fm->fmr_device == xfs_getfsmap_device(mp, XFS_DEV_RT));
|
||||
}
|
||||
|
||||
/* Ensure that the low key is less than the high key. */
|
||||
|
@ -1126,7 +1166,7 @@ xfs_getfsmap(
|
|||
/* Set up our device handlers. */
|
||||
memset(handlers, 0, sizeof(handlers));
|
||||
handlers[0].nr_sectors = XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
|
||||
handlers[0].dev = new_encode_dev(mp->m_ddev_targp->bt_dev);
|
||||
handlers[0].dev = xfs_getfsmap_device(mp, XFS_DEV_DATA);
|
||||
if (use_rmap)
|
||||
handlers[0].fn = xfs_getfsmap_datadev_rmapbt;
|
||||
else
|
||||
|
@ -1134,7 +1174,7 @@ xfs_getfsmap(
|
|||
if (mp->m_logdev_targp != mp->m_ddev_targp) {
|
||||
handlers[1].nr_sectors = XFS_FSB_TO_BB(mp,
|
||||
mp->m_sb.sb_logblocks);
|
||||
handlers[1].dev = new_encode_dev(mp->m_logdev_targp->bt_dev);
|
||||
handlers[1].dev = xfs_getfsmap_device(mp, XFS_DEV_LOG);
|
||||
handlers[1].fn = xfs_getfsmap_logdev;
|
||||
}
|
||||
#ifdef CONFIG_XFS_RT
|
||||
|
@ -1144,7 +1184,7 @@ xfs_getfsmap(
|
|||
*/
|
||||
if (mp->m_rtdev_targp && (use_rmap || !xfs_has_zoned(mp))) {
|
||||
handlers[2].nr_sectors = XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks);
|
||||
handlers[2].dev = new_encode_dev(mp->m_rtdev_targp->bt_dev);
|
||||
handlers[2].dev = xfs_getfsmap_device(mp, XFS_DEV_RT);
|
||||
if (use_rmap)
|
||||
handlers[2].fn = xfs_getfsmap_rtdev_rmapbt;
|
||||
else
|
||||
|
@ -1234,7 +1274,13 @@ xfs_getfsmap(
|
|||
|
||||
if (tp)
|
||||
xfs_trans_cancel(tp);
|
||||
head->fmh_oflags = FMH_OF_DEV_T;
|
||||
|
||||
/*
|
||||
* For internal RT device we need to report different synthetic devices
|
||||
* for a single physical device, and thus can't report the actual dev_t.
|
||||
*/
|
||||
if (!mp->m_sb.sb_rtstart)
|
||||
head->fmh_oflags = FMH_OF_DEV_T;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue