@@ -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])
@@ -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
@@ -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
@@ -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)
@@ -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;
}
@@ -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 @@ test_xchg_range(void)
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\
@@ -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])
@@ -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)
+ ])
@@ -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
@@ -16,13 +16,13 @@
* 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 XFS_EXCH_RANGE_COMMIT (XFS_EXCH_RANGE_FILE2_FRESH | \
+ XFS_EXCH_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 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 FIEXCHANGE_RANGE _IOWR('X', 129, struct file_xchg_range)
+#define XFS_IOC_EXCHANGE_RANGE _IOWR('X', 129, struct xfs_exch_range)
#endif /* _LINUX_FIEXCHANGE_H */
@@ -171,9 +171,7 @@
#include <sys/mman.h>
#endif
-#ifdef HAVE_FIEXCHANGE
-# include <linux/fiexchange.h>
-#else
+#ifndef HAVE_XFS_IOC_EXCHANGE_RANGE
# include "fiexchange.h"
#endif
@@ -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
@@ -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
@@ -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
@@ -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.