]> git.apps.os.sepia.ceph.com Git - xfstests-dev.git/commitdiff
misc: privatize the FIEXCHANGE ioctl for now
authorDarrick J. Wong <djwong@kernel.org>
Thu, 16 Nov 2023 17:30:37 +0000 (09:30 -0800)
committerZorro Lang <zlang@kernel.org>
Thu, 16 Nov 2023 19:01:37 +0000 (03:01 +0800)
I'm abandoning (for now) efforts to bring atomic file content exchanges
to the VFS.  The goal here is to reduce friction in getting online fsck
merged, so Dave and I want to take this back to being a private XFS
ioctl so we can explore with it for a while before committing it to the
stable KABI.

Shift all the existing FIEXCHANGE usage to XFS_IOC_EXCHANGE_RANGE, and
try to pick it up from xfs_fs_staging.h if the system xfslibs-dev
package has such an animal.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Zorro Lang <zlang@kernel.org>
15 files changed:
configure.ac
doc/group-names.txt
include/builddefs.in
ltp/Makefile
ltp/fsstress.c
ltp/fsx.c
m4/package_libcdev.m4
m4/package_xfslibs.m4
src/Makefile
src/fiexchange.h
src/global.h
src/vfs/Makefile
tests/generic/724
tests/xfs/122.out
tests/xfs/791

index 733304533027c11c52943c5bd71822197acb58bb..b22fc52bffeffa568aa8a4fa63a77d7cde8aadde 100644 (file)
@@ -70,7 +70,7 @@ AC_HAVE_SEEK_DATA
 AC_HAVE_BMV_OF_SHARED
 AC_HAVE_NFTW
 AC_HAVE_RLIMIT_NOFILE
-AC_HAVE_FIEXCHANGE
+AC_HAVE_XFS_IOC_EXCHANGE_RANGE
 AC_HAVE_FICLONE
 
 AC_CHECK_FUNCS([renameat2])
index c3dcca37553772065ec8497a0e605b7b847e5926..fec6bf71abcb2c22862589ae7d79a190eadf88fe 100644 (file)
@@ -52,7 +52,7 @@ enospc                        ENOSPC error reporting
 exportfs               file handles
 fiemap                 fiemap ioctl
 filestreams            XFS filestreams allocator
-fiexchange             FIEXCHANGE_RANGE ioctl
+fiexchange             XFS_IOC_EXCHANGE_RANGE ioctl
 freeze                 filesystem freeze tests
 fsck                   general fsck tests
 fsmap                  FS_IOC_GETFSMAP ioctl
index 446350d5fc5fd15d862cd950799554cdfa35ac16..ce95fe7d4b2e14672f724e0392367141b4bdf3b4 100644 (file)
@@ -72,7 +72,7 @@ HAVE_SEEK_DATA = @have_seek_data@
 HAVE_NFTW = @have_nftw@
 HAVE_BMV_OF_SHARED = @have_bmv_of_shared@
 HAVE_RLIMIT_NOFILE = @have_rlimit_nofile@
-HAVE_FIEXCHANGE = @have_fiexchange@
+HAVE_XFS_IOC_EXCHANGE_RANGE = @have_xfs_ioc_exchange_range@
 HAVE_FICLONE = @have_ficlone@
 
 GCCFLAGS = -funsigned-char -fno-strict-aliasing -Wall
index c2b70d896e66f037d5a90e28253cfcb68fd280b7..c0b28240764b1f6dbf02bc7325797f7021d6db5e 100644 (file)
@@ -36,8 +36,8 @@ ifeq ($(HAVE_COPY_FILE_RANGE),yes)
 LCFLAGS += -DHAVE_COPY_FILE_RANGE
 endif
 
-ifeq ($(HAVE_FIEXCHANGE),yes)
-LCFLAGS += -DHAVE_FIEXCHANGE
+ifeq ($(HAVE_XFS_IOC_EXCHANGE_RANGE),yes)
+LCFLAGS += -DHAVE_XFS_IOC_EXCHANGE_RANGE
 endif
 
 default: depend $(TARGETS)
index abe2874253b61ebb798416e8fda8bf9e5d390f14..2681ed2b087331a76af4b5c097b0203759172e37 100644 (file)
@@ -2592,8 +2592,8 @@ xchgrange_f(
        opnum_t                 opno,
        long                    r)
 {
-#ifdef FIEXCHANGE_RANGE
-       struct file_xchg_range  fxr = { 0 };
+#ifdef XFS_IOC_EXCHANGE_RANGE
+       struct xfs_exch_range   fxr = { 0 };
        static __u64            swap_flags = 0;
        struct pathname         fpath1;
        struct pathname         fpath2;
@@ -2721,10 +2721,10 @@ xchgrange_f(
        fxr.flags = swap_flags;
 
 retry:
-       ret = ioctl(fd2, FIEXCHANGE_RANGE, &fxr);
+       ret = ioctl(fd2, XFS_IOC_EXCHANGE_RANGE, &fxr);
        e = ret < 0 ? errno : 0;
-       if (e == EOPNOTSUPP && !(swap_flags & FILE_XCHG_RANGE_NONATOMIC)) {
-               swap_flags = FILE_XCHG_RANGE_NONATOMIC;
+       if (e == EOPNOTSUPP && !(swap_flags & XFS_EXCH_RANGE_NONATOMIC)) {
+               swap_flags = XFS_EXCH_RANGE_NONATOMIC;
                fxr.flags |= swap_flags;
                goto retry;
        }
index a30e2a8dbcb43de9b902910c8dc93e48f2f848ef..777ba0de5d3ec9aef828acf5d80a5988b41c818b 100644 (file)
--- a/ltp/fsx.c
+++ b/ltp/fsx.c
@@ -1389,27 +1389,27 @@ do_insert_range(unsigned offset, unsigned length)
 }
 #endif
 
-#ifdef FIEXCHANGE_RANGE
+#ifdef XFS_IOC_EXCHANGE_RANGE
 static __u64 swap_flags = 0;
 
 int
 test_xchg_range(void)
 {
-       struct file_xchg_range  fsr = {
+       struct xfs_exch_range   fsr = {
                .file1_fd = fd,
-               .flags = FILE_XCHG_RANGE_DRY_RUN | swap_flags,
+               .flags = XFS_EXCH_RANGE_DRY_RUN | swap_flags,
        };
        int ret, e;
 
 retry:
-       ret = ioctl(fd, FIEXCHANGE_RANGE, &fsr);
+       ret = ioctl(fd, XFS_IOC_EXCHANGE_RANGE, &fsr);
        e = ret < 0 ? errno : 0;
-       if (e == EOPNOTSUPP && !(swap_flags & FILE_XCHG_RANGE_NONATOMIC)) {
+       if (e == EOPNOTSUPP && !(swap_flags & XFS_EXCH_RANGE_NONATOMIC)) {
                /*
                 * If the call fails with atomic mode, try again with non
                 * atomic mode.
                 */
-               swap_flags = FILE_XCHG_RANGE_NONATOMIC;
+               swap_flags = XFS_EXCH_RANGE_NONATOMIC;
                fsr.flags |= swap_flags;
                goto retry;
        }
@@ -1427,7 +1427,7 @@ retry:
 void
 do_xchg_range(unsigned offset, unsigned length, unsigned dest)
 {
-       struct file_xchg_range  fsr = {
+       struct xfs_exch_range   fsr = {
                .file1_fd = fd,
                .file1_offset = offset,
                .file2_offset = dest,
@@ -1470,10 +1470,10 @@ do_xchg_range(unsigned offset, unsigned length, unsigned dest)
                        testcalls, offset, offset+length, length, dest);
        }
 
-       if (ioctl(fd, FIEXCHANGE_RANGE, &fsr) == -1) {
+       if (ioctl(fd, XFS_IOC_EXCHANGE_RANGE, &fsr) == -1) {
                prt("exchange range: 0x%x to 0x%x at 0x%x\n", offset,
                                offset + length, dest);
-               prterr("do_xchg_range: FIEXCHANGE_RANGE");
+               prterr("do_xchg_range: XFS_IOC_EXCHANGE_RANGE");
                report_failure(161);
                goto out_free;
        }
@@ -2452,7 +2452,7 @@ usage(void)
 #ifdef HAVE_COPY_FILE_RANGE
 "      -E: Do not use copy range calls\n"
 #endif
-#ifdef FIEXCHANGE_RANGE
+#ifdef XFS_IOC_EXCHANGE_RANGE
 "      -0: Do not use exchange range calls\n"
 #endif
 "      -K: Do not use keep size\n\
index 0f4b8063f31477a0686a6fb0b3a3b75c016335b5..d5d88b8e44626fd89c49248e6b6ec40fd0493757 100644 (file)
@@ -155,26 +155,6 @@ AC_DEFUN([AC_HAVE_RLIMIT_NOFILE],
     AC_SUBST(have_rlimit_nofile)
   ])
 
-#
-# Check if we have a FIEXCHANGE_RANGE ioctl (Linux)
-#
-AC_DEFUN([AC_HAVE_FIEXCHANGE],
-  [ AC_MSG_CHECKING([for FIEXCHANGE_RANGE])
-    AC_LINK_IFELSE([AC_LANG_PROGRAM([[
-#define _GNU_SOURCE
-#include <sys/syscall.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-#include <linux/fs.h>
-#include <linux/fiexchange.h>
-    ]], [[
-         struct file_xchg_range fxr;
-         ioctl(-1, FIEXCHANGE_RANGE, &fxr);
-    ]])],[have_fiexchange=yes
-       AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no)])
-    AC_SUBST(have_fiexchange)
-  ])
-
 # Check if we have FICLONE
 AC_DEFUN([AC_HAVE_FICLONE],
   [ AC_MSG_CHECKING([for FICLONE])
index 8ef58cc06444d5f4d5f68984dbcf0ac07cb52b2b..1549360df60f0465c3896fbbf61b7a56f8bf3dac 100644 (file)
@@ -119,3 +119,17 @@ AC_DEFUN([AC_HAVE_BMV_OF_SHARED],
        AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no)])
     AC_SUBST(have_bmv_of_shared)
   ])
+
+# Check if we have XFS_IOC_EXCHANGE_RANGE
+AC_DEFUN([AC_HAVE_XFS_IOC_EXCHANGE_RANGE],
+  [ AC_MSG_CHECKING([for XFS_IOC_EXCHANGE_RANGE])
+    AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+#define _GNU_SOURCE
+#include <xfs/xfs.h>
+    ]], [[
+         struct xfs_exch_range obj;
+         ioctl(-1, XFS_IOC_EXCHANGE_RANGE, &obj);
+    ]])],[have_xfs_ioc_exchange_range=yes
+       AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no)])
+    AC_SUBST(have_xfs_ioc_exchange_range)
+  ])
index 49dd2f6c1e16009e75076c59976b6e01ec715b20..8160a0e8ecec769e00e9eabe86a4b77aa909851e 100644 (file)
@@ -98,6 +98,10 @@ ifeq ($(HAVE_FICLONE),yes)
      TARGETS += t_reflink_read_race
 endif
 
+ifeq ($(HAVE_XFS_IOC_EXCHANGE_RANGE),yes)
+LCFLAGS += -DHAVE_XFS_IOC_EXCHANGE_RANGE
+endif
+
 CFILES = $(TARGETS:=.c)
 LDIRT = $(TARGETS) fssum
 
index 29b3ac0ff59973c499fdacfb7df4a7b034c33d52..6a3ae8964d11426ba8a4000bb0993715f004daac 100644 (file)
  * called against (which we'll call file2).  Filesystems must be able to
  * restart and complete the operation even after the system goes down.
  */
-struct file_xchg_range {
+struct xfs_exch_range {
        __s64           file1_fd;
        __s64           file1_offset;   /* file1 offset, bytes */
        __s64           file2_offset;   /* file2 offset, bytes */
        __s64           length;         /* bytes to exchange */
 
-       __u64           flags;          /* see FILE_XCHG_RANGE_* below */
+       __u64           flags;          /* see XFS_EXCH_RANGE_* below */
 
        /* file2 metadata for optional freshness checks */
        __s64           file2_ino;      /* inode number */
@@ -38,39 +38,39 @@ struct file_xchg_range {
  * Atomic exchange operations are not required.  This relaxes the requirement
  * that the filesystem must be able to complete the operation after a crash.
  */
-#define FILE_XCHG_RANGE_NONATOMIC      (1 << 0)
+#define XFS_EXCH_RANGE_NONATOMIC       (1 << 0)
 
 /*
  * Check that file2's inode number, mtime, and ctime against the values
  * provided, and return -EBUSY if there isn't an exact match.
  */
-#define FILE_XCHG_RANGE_FILE2_FRESH    (1 << 1)
+#define XFS_EXCH_RANGE_FILE2_FRESH     (1 << 1)
 
 /*
  * Check that the file1's length is equal to file1_offset + length, and that
  * file2's length is equal to file2_offset + length.  Returns -EDOM if there
  * isn't an exact match.
  */
-#define FILE_XCHG_RANGE_FULL_FILES     (1 << 2)
+#define XFS_EXCH_RANGE_FULL_FILES      (1 << 2)
 
 /*
  * Exchange file data all the way to the ends of both files, and then exchange
  * the file sizes.  This flag can be used to replace a file's contents with a
  * different amount of data.  length will be ignored.
  */
-#define FILE_XCHG_RANGE_TO_EOF         (1 << 3)
+#define XFS_EXCH_RANGE_TO_EOF          (1 << 3)
 
 /* Flush all changes in file data and file metadata to disk before returning. */
-#define FILE_XCHG_RANGE_FSYNC          (1 << 4)
+#define XFS_EXCH_RANGE_FSYNC           (1 << 4)
 
 /* Dry run; do all the parameter verification but do not change anything. */
-#define FILE_XCHG_RANGE_DRY_RUN                (1 << 5)
+#define XFS_EXCH_RANGE_DRY_RUN         (1 << 5)
 
 /*
- * Do not exchange any part of the range where file1's mapping is a hole.  This
- * can be used to emulate scatter-gather atomic writes with a temp file.
+ * Only exchange ranges where file1's range maps to a written extent.  This can
+ * be used to emulate scatter-gather atomic writes with a temp file.
  */
-#define FILE_XCHG_RANGE_SKIP_FILE1_HOLES (1 << 6)
+#define XFS_EXCH_RANGE_FILE1_WRITTEN   (1 << 6)
 
 /*
  * Commit the contents of file1 into file2 if file2 has the same inode number,
@@ -83,19 +83,19 @@ struct file_xchg_range {
  * commit is complete.
  *
  * This flag should not be combined with NONATOMIC.  It can be combined with
- * SKIP_FILE1_HOLES.
+ * FILE1_WRITTEN.
  */
-#define FILE_XCHG_RANGE_COMMIT         (FILE_XCHG_RANGE_FILE2_FRESH | \
-                                        FILE_XCHG_RANGE_FSYNC)
-
-#define FILE_XCHG_RANGE_ALL_FLAGS      (FILE_XCHG_RANGE_NONATOMIC | \
-                                        FILE_XCHG_RANGE_FILE2_FRESH | \
-                                        FILE_XCHG_RANGE_FULL_FILES | \
-                                        FILE_XCHG_RANGE_TO_EOF | \
-                                        FILE_XCHG_RANGE_FSYNC | \
-                                        FILE_XCHG_RANGE_DRY_RUN | \
-                                        FILE_XCHG_RANGE_SKIP_FILE1_HOLES)
-
-#define FIEXCHANGE_RANGE       _IOWR('X', 129, struct file_xchg_range)
+#define XFS_EXCH_RANGE_COMMIT          (XFS_EXCH_RANGE_FILE2_FRESH | \
+                                        XFS_EXCH_RANGE_FSYNC)
+
+#define XFS_EXCH_RANGE_ALL_FLAGS       (XFS_EXCH_RANGE_NONATOMIC | \
+                                        XFS_EXCH_RANGE_FILE2_FRESH | \
+                                        XFS_EXCH_RANGE_FULL_FILES | \
+                                        XFS_EXCH_RANGE_TO_EOF | \
+                                        XFS_EXCH_RANGE_FSYNC | \
+                                        XFS_EXCH_RANGE_DRY_RUN | \
+                                        XFS_EXCH_RANGE_FILE1_WRITTEN)
+
+#define XFS_IOC_EXCHANGE_RANGE _IOWR('X', 129, struct xfs_exch_range)
 
 #endif /* _LINUX_FIEXCHANGE_H */
index 49570ef11733c782a5eff1e4ca8a6817ba706ef0..4f92308d6c22068bc1cc909fedeff072c7d8af60 100644 (file)
 #include <sys/mman.h>
 #endif
 
-#ifdef HAVE_FIEXCHANGE
-# include <linux/fiexchange.h>
-#else
+#ifndef HAVE_XFS_IOC_EXCHANGE_RANGE
 # include "fiexchange.h"
 #endif
 
index 4841da1286bfec5a382d4cb5db6ec31967821b6a..868540f5787e9377f089fb1186c5c2a0bfeb7b92 100644 (file)
@@ -19,6 +19,10 @@ ifeq ($(HAVE_URING), true)
 LLDLIBS += -luring
 endif
 
+ifeq ($(HAVE_XFS_IOC_EXCHANGE_RANGE),yes)
+LCFLAGS += -DHAVE_XFS_IOC_EXCHANGE_RANGE
+endif
+
 default: depend $(TARGETS)
 
 depend: .dep
index 8d7dc4e12ad0eb2b3498efc5224aad288618dabb..67e0dba446ba8c3b91bf4f844b54a3e141bcd8bc 100755 (executable)
@@ -5,7 +5,7 @@
 # FS QA Test No. 724
 #
 # Test scatter-gather atomic file writes.  We create a temporary file, write
-# sparsely to it, then use FILE_SWAP_RANGE_SKIP_FILE1_HOLES flag to swap
+# sparsely to it, then use XFS_EXCH_RANGE_FILE1_WRITTEN flag to swap
 # atomicallly only the ranges that we wrote.
 
 . ./common/preamble
index 21549db7fd86e45d827582bd68e54a51c4c228f2..89f7b735b0e00b40b867e92faa914460061f19da 100644 (file)
@@ -90,6 +90,7 @@ sizeof(struct xfs_disk_dquot) = 104
 sizeof(struct xfs_dqblk) = 136
 sizeof(struct xfs_dsb) = 264
 sizeof(struct xfs_dsymlink_hdr) = 56
+sizeof(struct xfs_exch_range) = 120
 sizeof(struct xfs_extent_data) = 24
 sizeof(struct xfs_extent_data_info) = 32
 sizeof(struct xfs_fs_eofblocks) = 128
index d82314ee082051fbb85d0d3aba341a731605f79e..4944c1517c09937143dd08862ac7a606e8e62697 100755 (executable)
@@ -5,7 +5,7 @@
 # FS QA Test No. 791
 #
 # Test scatter-gather atomic file writes.  We create a temporary file, write
-# sparsely to it, then use FILE_SWAP_RANGE_SKIP_FILE1_HOLES flag to swap
+# sparsely to it, then use XFS_EXCH_RANGE_FILE1_WRITTEN flag to swap
 # atomicallly only the ranges that we wrote.  Inject an error so that we can
 # test that log recovery finishes the swap.