@@ -13,6 +13,7 @@
#include "libfrog/paths.h"
#include "libfrog/fsgeom.h"
#include "libfrog/bulkstat.h"
+#include "libfrog/file_exchange.h"
#include <fcntl.h>
#include <errno.h>
@@ -122,12 +123,6 @@ open_handle(
return 0;
}
-static int
-xfs_swapext(int fd, xfs_swapext_t *sx)
-{
- return ioctl(fd, XFS_IOC_SWAPEXT, sx);
-}
-
static int
xfs_fscounts(int fd, xfs_fsop_counts_t *counts)
{
@@ -1150,14 +1145,13 @@ packfile(
struct xfs_bulkstat *statp,
struct fsxattr *fsxp)
{
+ struct xfs_exch_range fxr;
int tfd = -1;
- int srval;
int retval = -1; /* Failure is the default */
int nextents, extent, cur_nextents, new_nextents;
unsigned blksz_dio;
unsigned dio_min;
struct dioattr dio;
- static xfs_swapext_t sx;
struct xfs_flock64 space;
off64_t cnt, pos;
void *fbuf = NULL;
@@ -1194,6 +1188,20 @@ packfile(
}
unlink(tname);
+ /*
+ * Set up everything in the swap request except for the destination
+ * freshness check, which we'll do separately since we already have
+ * a bulkstat.
+ */
+ error = xfrog_file_exchange_prep(file_fd,
+ XFS_EXCH_RANGE_NONATOMIC | XFS_EXCH_RANGE_FULL_FILES,
+ 0, tfd, 0, statp->bs_size, &fxr);
+ if (error) {
+ fsrprintf(_("error %d setting up swapext request\n"), error);
+ goto out;
+ }
+ xfrog_file_exchange_require_file2_fresh(&fxr, statp);
+
/* Setup extended attributes */
if (fsr_setup_attr_fork(file_fd->fd, tfd, statp) != 0) {
fsrprintf(_("failed to set ATTR fork on tmp: %s:\n"), tname);
@@ -1404,19 +1412,6 @@ packfile(
goto out;
}
- error = -xfrog_bulkstat_v5_to_v1(file_fd, &sx.sx_stat, statp);
- if (error) {
- fsrprintf(_("bstat conversion error on %s: %s\n"),
- fname, strerror(error));
- goto out;
- }
-
- sx.sx_version = XFS_SX_VERSION;
- sx.sx_fdtarget = file_fd->fd;
- sx.sx_fdtmp = tfd;
- sx.sx_offset = 0;
- sx.sx_length = statp->bs_size;
-
/* switch to the owner's id, to keep quota in line */
if (fchown(tfd, statp->bs_uid, statp->bs_gid) < 0) {
if (vflag)
@@ -1426,25 +1421,29 @@ packfile(
}
/* Swap the extents */
- srval = xfs_swapext(file_fd->fd, &sx);
- if (srval < 0) {
- if (errno == ENOTSUP) {
- if (vflag || dflag)
- fsrprintf(_("%s: file type not supported\n"), fname);
- } else if (errno == EFAULT) {
- /* The file has changed since we started the copy */
- if (vflag || dflag)
- fsrprintf(_("%s: file modified defrag aborted\n"),
- fname);
- } else if (errno == EBUSY) {
- /* Timestamp has changed or mmap'ed file */
- if (vflag || dflag)
- fsrprintf(_("%s: file busy\n"), fname);
- } else {
- fsrprintf(_("XFS_IOC_SWAPEXT failed: %s: %s\n"),
- fname, strerror(errno));
- }
- goto out;
+ error = xfrog_file_exchange(file_fd, &fxr);
+ switch (error) {
+ case 0:
+ break;
+ case ENOTSUP:
+ if (vflag || dflag)
+ fsrprintf(_("%s: file type not supported\n"), fname);
+ break;
+ case EFAULT:
+ case EDOM:
+ /* The file has changed since we started the copy */
+ if (vflag || dflag)
+ fsrprintf(_("%s: file modified defrag aborted\n"),
+ fname);
+ break;
+ case EBUSY:
+ /* Timestamp has changed or mmap'ed file */
+ if (vflag || dflag)
+ fsrprintf(_("%s: file busy\n"), fname);
+ break;
+ default:
+ fsrprintf(_("XFS_IOC_SWAPEXT failed: %s: %s\n"),
+ fname, strerror(error));
}
/* Report progress */
@@ -54,6 +54,23 @@ xfrog_file_exchange_prep_freshness(
return 0;
}
+/*
+ * Enable checking that the target (or destination) file has not been modified
+ * since a particular point in time.
+ */
+void
+xfrog_file_exchange_require_file2_fresh(
+ struct xfs_exch_range *req,
+ struct xfs_bulkstat *bulkstat)
+{
+ req->flags |= XFS_EXCH_RANGE_FILE2_FRESH;
+ req->file2_ino = bulkstat->bs_ino;
+ req->file2_mtime = bulkstat->bs_mtime;
+ req->file2_ctime = bulkstat->bs_ctime;
+ req->file2_mtime_nsec = bulkstat->bs_mtime_nsec;
+ req->file2_ctime_nsec = bulkstat->bs_ctime_nsec;
+}
+
/* Prepare an extent swap request. */
int
xfrog_file_exchange_prep(
@@ -6,6 +6,8 @@
#ifndef __LIBFROG_FILE_EXCHANGE_H__
#define __LIBFROG_FILE_EXCHANGE_H__
+void xfrog_file_exchange_require_file2_fresh(struct xfs_exch_range *req,
+ struct xfs_bulkstat *bulkstat);
int xfrog_file_exchange_prep(struct xfs_fd *file2, uint64_t flags,
int64_t file2_offset, int file1_fd, int64_t file1_offset,
int64_t length, struct xfs_exch_range *req);