Commit e6294110 authored by Darrick J. Wong's avatar Darrick J. Wong

xfs: make file range exchange support realtime files

Now that bmap items support the realtime device, we can add the
necessary pieces to the file range exchange code to support exchanging
mappings.  All we really need to do here is adjust the blockcount
upwards to the end of the rt extent and remove the inode checks.
Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
parent 33a9be2b
...@@ -152,12 +152,7 @@ xfs_exchmaps_check_forks( ...@@ -152,12 +152,7 @@ xfs_exchmaps_check_forks(
ifp2->if_format == XFS_DINODE_FMT_LOCAL) ifp2->if_format == XFS_DINODE_FMT_LOCAL)
return -EINVAL; return -EINVAL;
/* We don't support realtime data forks yet. */
if (!XFS_IS_REALTIME_INODE(req->ip1))
return 0; return 0;
if (whichfork == XFS_ATTR_FORK)
return 0;
return -EINVAL;
} }
#ifdef CONFIG_XFS_QUOTA #ifdef CONFIG_XFS_QUOTA
...@@ -198,6 +193,8 @@ xfs_exchmaps_can_skip_mapping( ...@@ -198,6 +193,8 @@ xfs_exchmaps_can_skip_mapping(
struct xfs_exchmaps_intent *xmi, struct xfs_exchmaps_intent *xmi,
struct xfs_bmbt_irec *irec) struct xfs_bmbt_irec *irec)
{ {
struct xfs_mount *mp = xmi->xmi_ip1->i_mount;
/* Do not skip this mapping if the caller did not tell us to. */ /* Do not skip this mapping if the caller did not tell us to. */
if (!(xmi->xmi_flags & XFS_EXCHMAPS_INO1_WRITTEN)) if (!(xmi->xmi_flags & XFS_EXCHMAPS_INO1_WRITTEN))
return false; return false;
...@@ -209,11 +206,64 @@ xfs_exchmaps_can_skip_mapping( ...@@ -209,11 +206,64 @@ xfs_exchmaps_can_skip_mapping(
/* /*
* The mapping is unwritten or a hole. It cannot be a delalloc * The mapping is unwritten or a hole. It cannot be a delalloc
* reservation because we already excluded those. It cannot be an * reservation because we already excluded those. It cannot be an
* unwritten mapping with dirty page cache because we flushed the page * unwritten extent with dirty page cache because we flushed the page
* cache. We don't support realtime files yet, so we needn't (yet) * cache. For files where the allocation unit is 1FSB (files on the
* deal with them. * data dev, rt files if the extent size is 1FSB), we can safely
* skip this mapping.
*/
if (!xfs_inode_has_bigrtalloc(xmi->xmi_ip1))
return true;
/*
* For a realtime file with a multi-fsb allocation unit, the decision
* is trickier because we can only swap full allocation units.
* Unwritten mappings can appear in the middle of an rtx if the rtx is
* partially written, but they can also appear for preallocations.
*
* If the mapping is a hole, skip it entirely. Holes should align with
* rtx boundaries.
*/ */
if (!xfs_bmap_is_real_extent(irec))
return true; return true;
/*
* All mappings below this point are unwritten.
*
* - If the beginning is not aligned to an rtx, trim the end of the
* mapping so that it does not cross an rtx boundary, and swap it.
*
* - If both ends are aligned to an rtx, skip the entire mapping.
*/
if (!isaligned_64(irec->br_startoff, mp->m_sb.sb_rextsize)) {
xfs_fileoff_t new_end;
new_end = roundup_64(irec->br_startoff, mp->m_sb.sb_rextsize);
irec->br_blockcount = min(irec->br_blockcount,
new_end - irec->br_startoff);
return false;
}
if (isaligned_64(irec->br_blockcount, mp->m_sb.sb_rextsize))
return true;
/*
* All mappings below this point are unwritten, start on an rtx
* boundary, and do not end on an rtx boundary.
*
* - If the mapping is longer than one rtx, trim the end of the mapping
* down to an rtx boundary and skip it.
*
* - The mapping is shorter than one rtx. Swap it.
*/
if (irec->br_blockcount > mp->m_sb.sb_rextsize) {
xfs_fileoff_t new_end;
new_end = rounddown_64(irec->br_startoff + irec->br_blockcount,
mp->m_sb.sb_rextsize);
irec->br_blockcount = new_end - irec->br_startoff;
return true;
}
return false;
} }
/* /*
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "xfs_sb.h" #include "xfs_sb.h"
#include "xfs_icache.h" #include "xfs_icache.h"
#include "xfs_log.h" #include "xfs_log.h"
#include "xfs_rtbitmap.h"
#include <linux/fsnotify.h> #include <linux/fsnotify.h>
/* Lock (and optionally join) two inodes for a file range exchange. */ /* Lock (and optionally join) two inodes for a file range exchange. */
...@@ -182,6 +183,14 @@ xfs_exchrange_mappings( ...@@ -182,6 +183,14 @@ xfs_exchrange_mappings(
if (fxr->flags & XFS_EXCHANGE_RANGE_FILE1_WRITTEN) if (fxr->flags & XFS_EXCHANGE_RANGE_FILE1_WRITTEN)
req.flags |= XFS_EXCHMAPS_INO1_WRITTEN; req.flags |= XFS_EXCHMAPS_INO1_WRITTEN;
/*
* Round the request length up to the nearest file allocation unit.
* The prep function already checked that the request offsets and
* length in @fxr are safe to round up.
*/
if (xfs_inode_has_bigrtalloc(ip2))
req.blockcount = xfs_rtb_roundup_rtx(mp, req.blockcount);
error = xfs_exchrange_estimate(&req); error = xfs_exchrange_estimate(&req);
if (error) if (error)
return error; return error;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment