]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
xfs: enable realtime reflink
authorDarrick J. Wong <djwong@kernel.org>
Thu, 21 Nov 2024 00:21:17 +0000 (16:21 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Mon, 23 Dec 2024 21:06:17 +0000 (13:06 -0800)
Enable reflink for realtime devices, as long as the realtime allocation
unit is a single fsblock.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/xfs_reflink.c
fs/xfs/xfs_reflink.h
fs/xfs/xfs_rtalloc.c
fs/xfs/xfs_super.c

index d9b33e22c17669cd179e224744440326d13c573b..59f7fc16eb8093ba74a5b31e61372163d58808fe 100644 (file)
@@ -1822,3 +1822,28 @@ out:
        trace_xfs_reflink_unshare_error(ip, error, _RET_IP_);
        return error;
 }
+
+/*
+ * Can we use reflink with this realtime extent size?  Note that we don't check
+ * for rblocks > 0 here because this can be called as part of attaching a new
+ * rt section.
+ */
+bool
+xfs_reflink_supports_rextsize(
+       struct xfs_mount        *mp,
+       unsigned int            rextsize)
+{
+       /* reflink on the realtime device requires rtgroups */
+       if (!xfs_has_rtgroups(mp))
+              return false;
+
+       /*
+        * Reflink doesn't support rt extent size larger than a single fsblock
+        * because we would have to perform CoW-around for unaligned write
+        * requests to guarantee that we always remap entire rt extents.
+        */
+       if (rextsize != 1)
+               return false;
+
+       return true;
+}
index 3bfd7ab9e1148a8ec472f2e9c3b013371f334ef3..cc4e92278279b6231135512428f4a359689ebb22 100644 (file)
@@ -62,4 +62,6 @@ extern int xfs_reflink_remap_blocks(struct xfs_inode *src, loff_t pos_in,
 extern int xfs_reflink_update_dest(struct xfs_inode *dest, xfs_off_t newlen,
                xfs_extlen_t cowextsize, unsigned int remap_flags);
 
+bool xfs_reflink_supports_rextsize(struct xfs_mount *mp, unsigned int rextsize);
+
 #endif /* __XFS_REFLINK_H */
index 7135a6717a9e114d0c0164841f51b3fad67b8bc8..d8e6d073d64dc931c3761bff68f7a8f5f7aa442d 100644 (file)
@@ -32,6 +32,7 @@
 #include "xfs_error.h"
 #include "xfs_trace.h"
 #include "xfs_rtrefcount_btree.h"
+#include "xfs_reflink.h"
 
 /*
  * Return whether there are any free extents in the size range given
@@ -1292,8 +1293,10 @@ xfs_growfs_rt(
                        goto out_unlock;
                if (xfs_has_quota(mp))
                        goto out_unlock;
-       }
-       if (xfs_has_reflink(mp))
+               if (xfs_has_reflink(mp))
+                       goto out_unlock;
+       } else if (xfs_has_reflink(mp) &&
+                  !xfs_reflink_supports_rextsize(mp, in->extsize))
                goto out_unlock;
 
        error = xfs_sb_validate_fsb_count(&mp->m_sb, in->newblocks);
index ecd5a9f444d86228658f4e57df40da353c672b65..7c3f996cd39e8177938e06ca37e3a3d29b3635c4 100644 (file)
@@ -1754,9 +1754,11 @@ xfs_fs_fill_super(
                xfs_warn_experimental(mp, XFS_EXPERIMENTAL_METADIR);
 
        if (xfs_has_reflink(mp)) {
-               if (mp->m_sb.sb_rblocks) {
+               if (xfs_has_realtime(mp) &&
+                   !xfs_reflink_supports_rextsize(mp, mp->m_sb.sb_rextsize)) {
                        xfs_alert(mp,
-       "reflink not compatible with realtime device!");
+       "reflink not compatible with realtime extent size %u!",
+                                       mp->m_sb.sb_rextsize);
                        error = -EINVAL;
                        goto out_filestream_unmount;
                }