xfs
[Top] [All Lists]

[PATCH] xfs_io: allow zero-length reflink/dedupe commands

To: david@xxxxxxxxxxxxx
Subject: [PATCH] xfs_io: allow zero-length reflink/dedupe commands
From: "Darrick J. Wong" <darrick.wong@xxxxxxxxxx>
Date: Mon, 7 Dec 2015 18:08:33 -0800
Cc: xfs@xxxxxxxxxxx
Delivered-to: xfs@xxxxxxxxxxx
User-agent: Mutt/1.5.21 (2010-09-15)
Since it's convention that calling the reflink/dedupe ioctls with
a zero length means "do this until you hit EOF in the source file",
explicitly permit this as an input.  Fix the ioctl code to handle
this correctly.

Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx>
---
 io/reflink.c |   24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/io/reflink.c b/io/reflink.c
index 5ba1c93..def01be 100644
--- a/io/reflink.c
+++ b/io/reflink.c
@@ -71,7 +71,7 @@ dedupe_ioctl(
        info->fd = file->fd;
        info->logical_offset = doffset;
 
-       while (args->length > 0) {
+       while (args->length > 0 || !*ops) {
                error = ioctl(fd, XFS_IOC_FILE_EXTENT_SAME, args);
                if (error) {
                        perror("XFS_IOC_FILE_EXTENT_SAME");
@@ -85,14 +85,16 @@ dedupe_ioctl(
                        printf(_("Extents did not match.\n"));
                        goto done;
                }
-               if (info->bytes_deduped == 0 ||
-                   info->bytes_deduped > args->length)
+               if (args->length != 0 &&
+                   (info->bytes_deduped == 0 ||
+                    info->bytes_deduped > args->length))
                        break;
 
                (*ops)++;
                args->logical_offset += info->bytes_deduped;
                info->logical_offset += info->bytes_deduped;
-               args->length -= info->bytes_deduped;
+               if (args->length >= info->bytes_deduped)
+                       args->length -= info->bytes_deduped;
                deduped += info->bytes_deduped;
        }
 done:
@@ -145,7 +147,7 @@ dedupe_f(
        }
        optind++;
        count = cvtnum(fsblocksize, fssectsize, argv[optind]);
-       if (count < 1) {
+       if (count < 0) {
                printf(_("non-positive length argument -- %s\n"), argv[optind]);
                return 0;
        }
@@ -202,7 +204,11 @@ reflink_ioctl(
        struct xfs_clone_args   args;
        int                     error;
 
-       if (len) {
+       if (soffset == 0 && doffset == 0 && len == 0) {
+               error = ioctl(file->fd, XFS_IOC_CLONE, fd);
+               if (error)
+                       perror("XFS_IOC_CLONE");
+       } else {
                args.src_fd = fd;
                args.src_offset = soffset;
                args.src_length = len;
@@ -210,10 +216,6 @@ reflink_ioctl(
                error = ioctl(file->fd, XFS_IOC_CLONE_RANGE, &args);
                if (error)
                        perror("XFS_IOC_CLONE_RANGE");
-       } else {
-               error = ioctl(file->fd, XFS_IOC_CLONE, fd);
-               if (error)
-                       perror("XFS_IOC_CLONE");
        }
        if (!error)
                (*ops)++;
@@ -268,7 +270,7 @@ reflink_f(
        }
        optind++;
        count = cvtnum(fsblocksize, fssectsize, argv[optind]);
-       if (count < 1) {
+       if (count < 0) {
                printf(_("non-positive length argument -- %s\n"), argv[optind]);
                return 0;
        }

<Prev in Thread] Current Thread [Next in Thread>
  • [PATCH] xfs_io: allow zero-length reflink/dedupe commands, Darrick J. Wong <=