]> www.infradead.org Git - users/hch/xfs.git/commitdiff
xfs: enable sharing of realtime file blocks
authorDarrick J. Wong <djwong@kernel.org>
Mon, 23 Sep 2024 20:42:36 +0000 (13:42 -0700)
committerChristoph Hellwig <hch@lst.de>
Wed, 9 Oct 2024 13:55:49 +0000 (15:55 +0200)
Update the remapping routines to be able to handle realtime files.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
fs/xfs/xfs_reflink.c

index 0b3a78877ad9a6d74970ecf25acdbd114d585c05..cdef7f70df6977b09be8f3f2716642d753fa62e9 100644 (file)
@@ -33,6 +33,7 @@
 #include "xfs_rtrefcount_btree.h"
 #include "xfs_rtalloc.h"
 #include "xfs_rtgroup.h"
+#include "xfs_metafile.h"
 
 /*
  * Copy on Write of Shared Blocks
@@ -1186,14 +1187,29 @@ out_error:
 static int
 xfs_reflink_ag_has_free_space(
        struct xfs_mount        *mp,
-       xfs_agnumber_t          agno)
+       struct xfs_inode        *ip,
+       xfs_fsblock_t           fsb)
 {
        struct xfs_perag        *pag;
+       xfs_agnumber_t          agno;
        int                     error = 0;
 
        if (!xfs_has_rmapbt(mp))
                return 0;
+       if (XFS_IS_REALTIME_INODE(ip)) {
+               struct xfs_rtgroup      *rtg;
+               xfs_rgnumber_t          rgno;
+
+               rgno = xfs_rtb_to_rgno(mp, fsb);
+               rtg = xfs_rtgroup_get(mp, rgno);
+               if (xfs_metafile_resv_critical(rtg->rtg_inodes[XFS_RTGI_RMAP]) ||
+                   xfs_metafile_resv_critical(rtg->rtg_inodes[XFS_RTGI_REFCOUNT]))
+                       error = -ENOSPC;
+               xfs_rtgroup_put(rtg);
+               return error;
+       }
 
+       agno = XFS_FSB_TO_AGNO(mp, fsb);
        pag = xfs_perag_get(mp, agno);
        if (xfs_ag_resv_critical(pag, XFS_AG_RESV_RMAPBT) ||
            xfs_ag_resv_critical(pag, XFS_AG_RESV_METADATA))
@@ -1307,8 +1323,8 @@ xfs_reflink_remap_extent(
 
        /* No reflinking if the AG of the dest mapping is low on space. */
        if (dmap_written) {
-               error = xfs_reflink_ag_has_free_space(mp,
-                               XFS_FSB_TO_AGNO(mp, dmap->br_startblock));
+               error = xfs_reflink_ag_has_free_space(mp, ip,
+                               dmap->br_startblock);
                if (error)
                        goto out_cancel;
        }
@@ -1567,8 +1583,8 @@ xfs_reflink_remap_prep(
 
        /* Check file eligibility and prepare for block sharing. */
        ret = -EINVAL;
-       /* Don't reflink realtime inodes */
-       if (XFS_IS_REALTIME_INODE(src) || XFS_IS_REALTIME_INODE(dest))
+       /* Can't reflink between data and rt volumes */
+       if (XFS_IS_REALTIME_INODE(src) != XFS_IS_REALTIME_INODE(dest))
                goto out_unlock;
 
        /* Don't share DAX file data with non-DAX file. */