]> www.infradead.org Git - users/hch/xfs.git/commitdiff
xfs: enable realtime reflink realtime-reflink-rebase
authorDarrick J. Wong <djwong@kernel.org>
Mon, 23 Sep 2024 20:42:55 +0000 (13:42 -0700)
committerChristoph Hellwig <hch@lst.de>
Wed, 9 Oct 2024 13:55:51 +0000 (15:55 +0200)
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 86c4361dfd42a3d549a661aed4c9a25027f6b2ea..f352d70f82c8f3fe3afa7e252bfa92139855ae32 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 b47b4479783613b28e21e4acf65e394045b5f379..f7b75a8c5e2209a0bf91bac64c4115a86dcd3bfc 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
@@ -1287,7 +1288,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 461c6a02d0d5ce5105498b53fdbf782cb9a35d04..21300ca4c7bd6dc5aff2a0f0e7d6f9e70ec71e5c 100644 (file)
@@ -1756,14 +1756,23 @@ xfs_fs_fill_super(
 "EXPERIMENTAL metadata directory feature in use. Use at your own risk!");
 
        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;
                }