@@ -2609,8 +2609,7 @@ exchangerange_f(
long r)
{
#ifdef XFS_IOC_EXCHANGE_RANGE
- struct xfs_exch_range fxr = { 0 };
- static __u64 swap_flags = 0;
+ struct xfs_exchange_range fxr = { 0 };
struct pathname fpath1;
struct pathname fpath2;
struct stat64 stat1;
@@ -2734,16 +2733,9 @@ exchangerange_f(
fxr.file1_offset = off1;
fxr.length = len;
fxr.file2_offset = off2;
- fxr.flags = swap_flags;
-retry:
ret = ioctl(fd2, XFS_IOC_EXCHANGE_RANGE, &fxr);
e = ret < 0 ? errno : 0;
- if (e == EOPNOTSUPP && !(swap_flags & XFS_EXCH_RANGE_NONATOMIC)) {
- swap_flags = XFS_EXCH_RANGE_NONATOMIC;
- fxr.flags |= swap_flags;
- goto retry;
- }
if (v1 || v2) {
printf("%d/%lld: exchangerange %s%s [%lld,%lld] -> %s%s [%lld,%lld]",
procid, opno,
@@ -1390,29 +1390,17 @@ do_insert_range(unsigned offset, unsigned length)
#endif
#ifdef XFS_IOC_EXCHANGE_RANGE
-static __u64 swap_flags = 0;
-
int
test_exchange_range(void)
{
- struct xfs_exch_range fsr = {
+ struct xfs_exchange_range fsr = {
.file1_fd = fd,
- .flags = XFS_EXCH_RANGE_DRY_RUN | swap_flags,
+ .flags = XFS_EXCHANGE_RANGE_DRY_RUN,
};
int ret, e;
-retry:
ret = ioctl(fd, XFS_IOC_EXCHANGE_RANGE, &fsr);
e = ret < 0 ? errno : 0;
- if (e == EOPNOTSUPP && !(swap_flags & XFS_EXCH_RANGE_NONATOMIC)) {
- /*
- * If the call fails with atomic mode, try again with non
- * atomic mode.
- */
- swap_flags = XFS_EXCH_RANGE_NONATOMIC;
- fsr.flags |= swap_flags;
- goto retry;
- }
if (e == EOPNOTSUPP || errno == ENOTTY) {
if (!quiet)
fprintf(stderr,
@@ -1427,12 +1415,11 @@ test_exchange_range(void)
void
do_exchange_range(unsigned offset, unsigned length, unsigned dest)
{
- struct xfs_exch_range fsr = {
+ struct xfs_exchange_range fsr = {
.file1_fd = fd,
.file1_offset = offset,
.file2_offset = dest,
.length = length,
- .flags = swap_flags,
};
void *p;
@@ -99,7 +99,7 @@ AC_DEFUN([AC_NEED_INTERNAL_XFS_IOC_EXCHANGE_RANGE],
#define _GNU_SOURCE
#include <xfs/xfs.h>
]], [[
- struct xfs_exch_range obj;
+ struct xfs_exchange_range obj;
ioctl(-1, XFS_IOC_EXCHANGE_RANGE, &obj);
]])],[AC_MSG_RESULT(yes)],
[need_internal_xfs_ioc_exchange_range=yes
@@ -16,86 +16,42 @@
* called against (which we'll call file2). Filesystems must be able to
* restart and complete the operation even after the system goes down.
*/
-struct xfs_exch_range {
- __s64 file1_fd;
- __s64 file1_offset; /* file1 offset, bytes */
- __s64 file2_offset; /* file2 offset, bytes */
- __s64 length; /* bytes to exchange */
+struct xfs_exchange_range {
+ __s32 file1_fd;
+ __u32 pad; /* must be zeroes */
+ __u64 file1_offset; /* file1 offset, bytes */
+ __u64 file2_offset; /* file2 offset, bytes */
+ __u64 length; /* bytes to exchange */
- __u64 flags; /* see XFS_EXCH_RANGE_* below */
-
- /* file2 metadata for optional freshness checks */
- __s64 file2_ino; /* inode number */
- __s64 file2_mtime; /* modification time */
- __s64 file2_ctime; /* change time */
- __s32 file2_mtime_nsec; /* mod time, nsec */
- __s32 file2_ctime_nsec; /* change time, nsec */
-
- __u64 pad[6]; /* must be zeroes */
+ __u64 flags; /* see XFS_EXCHANGE_RANGE_* below */
};
-/*
- * Atomic exchange operations are not required. This relaxes the requirement
- * that the filesystem must be able to complete the operation after a crash.
- */
-#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 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 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 XFS_EXCH_RANGE_TO_EOF (1 << 3)
+#define XFS_EXCHANGE_RANGE_TO_EOF (1ULL << 0)
/* Flush all changes in file data and file metadata to disk before returning. */
-#define XFS_EXCH_RANGE_FSYNC (1 << 4)
+#define XFS_EXCHANGE_RANGE_DSYNC (1ULL << 1)
/* Dry run; do all the parameter verification but do not change anything. */
-#define XFS_EXCH_RANGE_DRY_RUN (1 << 5)
+#define XFS_EXCHANGE_RANGE_DRY_RUN (1ULL << 2)
/*
- * 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.
+ * Exchange only the parts of the two files where the file allocation units
+ * mapped to file1's range have been written to. This can accelerate
+ * scatter-gather atomic writes with a temp file if all writes are aligned to
+ * the file allocation unit.
*/
-#define XFS_EXCH_RANGE_FILE1_WRITTEN (1 << 6)
+#define XFS_EXCHANGE_RANGE_FILE1_WRITTEN (1ULL << 3)
-/*
- * Commit the contents of file1 into file2 if file2 has the same inode number,
- * mtime, and ctime as the arguments provided to the call. The old contents of
- * file2 will be moved to file1.
- *
- * With this flag, all committed information can be retrieved even if the
- * system crashes or is rebooted. This includes writing through or flushing a
- * disk cache if present. The call blocks until the device reports that the
- * commit is complete.
- *
- * This flag should not be combined with NONATOMIC. It can be combined with
- * FILE1_WRITTEN.
- */
-#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_EXCHANGE_RANGE_ALL_FLAGS (XFS_EXCHANGE_RANGE_TO_EOF | \
+ XFS_EXCHANGE_RANGE_DSYNC | \
+ XFS_EXCHANGE_RANGE_DRY_RUN | \
+ XFS_EXCHANGE_RANGE_FILE1_WRITTEN)
-#define XFS_IOC_EXCHANGE_RANGE _IOWR('X', 129, struct xfs_exch_range)
+#define XFS_IOC_EXCHANGE_RANGE _IOWR('X', 129, struct xfs_exchange_range)
#endif /* _LINUX_FIEXCHANGE_H */
@@ -9,10 +9,20 @@
#include <config.h>
+#ifdef NEED_INTERNAL_XFS_IOC_EXCHANGE_RANGE
+/* Override struct xfs_exchange_range in xfslibs */
+# define xfs_exchange_range sys_xfs_exchange_range
+#endif
+
#ifdef HAVE_XFS_XFS_H
#include <xfs/xfs.h>
#endif
+#ifdef NEED_INTERNAL_XFS_IOC_EXCHANGE_RANGE
+# undef xfs_exchange_range
+# undef XFS_IOC_EXCHANGE_RANGE
+#endif
+
#ifdef HAVE_XFS_LIBXFS_H
#include <xfs/libxfs.h>
#endif
@@ -10,7 +10,6 @@
#include <unistd.h>
#include <ftw.h>
#include <linux/fs.h>
-#include <xfs/xfs.h>
#include "global.h"
@@ -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 XFS_EXCHRANGE_FILE1_WRITTEN flag to swap
+# sparsely to it, then use XFS_EXCHANGE_RANGE_FILE1_WRITTEN flag to swap
# atomicallly only the ranges that we wrote.
. ./common/preamble
@@ -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 XFS_EXCHRANGE_FILE1_WRITTEN flag to swap
+# sparsely to it, then use XFS_EXCHANGE_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.