]> www.infradead.org Git - users/hch/xfs.git/commitdiff
xfs: enable realtime reflink
authorDarrick J. Wong <djwong@kernel.org>
Tue, 15 Oct 2024 19:40:44 +0000 (12:40 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 5 Nov 2024 21:36:35 +0000 (13:36 -0800)
Enable reflink for realtime devices, sort of.

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

index 3ad8d197028d71b4eb514eef19ec33de55bae2be..952cb01b8584e15e7b382284fef515af1bc1f78a 100644 (file)
@@ -1823,3 +1823,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 66f61776c0d18c43dcdd7c34d890400d1e2519c9..6651c0cf24c66972e00bc8d26b8dd53d2bbeb322 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
@@ -1289,7 +1290,8 @@ xfs_growfs_rt(
        error = -EOPNOTSUPP;
        if ((xfs_has_rmapbt(mp) || xfs_has_quota(mp)) && !xfs_has_rtgroups(mp))
                goto out_unlock;
-       if (xfs_has_reflink(mp))
+       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 ba927591f3577e588f377b9ea0c8a1ab0c12a805..0a123ffcf17995db0e2601bf528cbf054a361809 100644 (file)
@@ -1754,14 +1754,23 @@ 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;
                }
 
-               if (xfs_globals.always_cow) {
+               /*
+                * always-cow mode is not supported on filesystems with rt
+                * extent sizes larger than a single block because we'd have
+                * to perform write-around for unaligned writes because remap
+                * requests must be aligned to an rt extent.
+                */
+               if (xfs_globals.always_cow &&
+                   (!xfs_has_realtime(mp) || mp->m_sb.sb_rextsize == 1)) {
                        xfs_info(mp, "using DEBUG-only always_cow mode.");
                        mp->m_always_cow = true;
                }