]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_io: copy_range don't truncate dst_file, and add smart length
authorJianhong Yin <yin-jianhong@163.com>
Thu, 26 Sep 2019 17:41:17 +0000 (13:41 -0400)
committerEric Sandeen <sandeen@redhat.com>
Thu, 26 Sep 2019 17:41:17 +0000 (13:41 -0400)
1. copy_range should be a simple wrapper for copy_file_range(2)
and nothing else. and there's already -t option for truncate.
so here we remove the truncate action in copy_range.
see: https://patchwork.kernel.org/comment/22863587/#1

2. improve the default length value generation:
if -l option is omitted use the length that from src_offset to end
(src_file's size - src_offset) instead.
if src_offset is greater than file size, length is 0.

3. update manpage

4. rename var name from 'src, dst' to 'src_off, dst_off'

and have confirmed that this change will not affect xfstests.

Signed-off-by: Jianhong Yin <yin-jianhong@163.com>
[sandeen: fix long line]
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
io/copy_file_range.c
man/man8/xfs_io.8

index b7b9fd88e77bdc3c154d63d813c31ff0bf0cdd10..800b98da7f0230037df3f46af5cbcace531359ee 100644 (file)
@@ -36,13 +36,13 @@ copy_range_help(void)
  * glibc buffered copy fallback.
  */
 static loff_t
-copy_file_range_cmd(int fd, long long *src, long long *dst, size_t len)
+copy_file_range_cmd(int fd, long long *src_off, long long *dst_off, size_t len)
 {
        loff_t ret;
 
        do {
-               ret = syscall(__NR_copy_file_range, fd, src, file->fd, dst,
-                               len, 0);
+               ret = syscall(__NR_copy_file_range, fd, src_off,
+                               file->fd, dst_off, len, 0);
                if (ret == -1) {
                        perror("copy_range");
                        return errno;
@@ -66,21 +66,13 @@ copy_src_filesize(int fd)
        return st.st_size;
 }
 
-static int
-copy_dst_truncate(void)
-{
-       int ret = ftruncate(file->fd, 0);
-       if (ret < 0)
-               perror("ftruncate");
-       return ret;
-}
-
 static int
 copy_range_f(int argc, char **argv)
 {
-       long long src = 0;
-       long long dst = 0;
+       long long src_off = 0;
+       long long dst_off = 0;
        size_t len = 0;
+       bool len_specified = false;
        int opt;
        int ret;
        int fd;
@@ -93,15 +85,15 @@ copy_range_f(int argc, char **argv)
        while ((opt = getopt(argc, argv, "s:d:l:f:")) != -1) {
                switch (opt) {
                case 's':
-                       src = cvtnum(fsblocksize, fssectsize, optarg);
-                       if (src < 0) {
+                       src_off = cvtnum(fsblocksize, fssectsize, optarg);
+                       if (src_off < 0) {
                                printf(_("invalid source offset -- %s\n"), optarg);
                                return 0;
                        }
                        break;
                case 'd':
-                       dst = cvtnum(fsblocksize, fssectsize, optarg);
-                       if (dst < 0) {
+                       dst_off = cvtnum(fsblocksize, fssectsize, optarg);
+                       if (dst_off < 0) {
                                printf(_("invalid destination offset -- %s\n"), optarg);
                                return 0;
                        }
@@ -112,6 +104,7 @@ copy_range_f(int argc, char **argv)
                                printf(_("invalid length -- %s\n"), optarg);
                                return 0;
                        }
+                       len_specified = true;
                        break;
                case 'f':
                        src_file_nr = atoi(argv[1]);
@@ -137,7 +130,7 @@ copy_range_f(int argc, char **argv)
                fd = filetable[src_file_nr].fd;
        }
 
-       if (src == 0 && dst == 0 && len == 0) {
+       if (!len_specified) {
                off64_t sz;
 
                sz = copy_src_filesize(fd);
@@ -145,16 +138,11 @@ copy_range_f(int argc, char **argv)
                        ret = 1;
                        goto out;
                }
-               len = sz;
-
-               ret = copy_dst_truncate();
-               if (ret < 0) {
-                       ret = 1;
-                       goto out;
-               }
+               if (sz > src_off)
+                       len = sz - src_off;
        }
 
-       ret = copy_file_range_cmd(fd, &src, &dst, len);
+       ret = copy_file_range_cmd(fd, &src_off, &dst_off, len);
 out:
        close(fd);
        return ret;
index 6e064bddef2314ed38a714247b47820103c86951..61c35c8e903596dd1b69503a08c1c320dd4b38ab 100644 (file)
@@ -669,13 +669,13 @@ The source must be specified either by path
 or as another open file
 .RB ( \-f ).
 If
-.I src_file
-.IR src_offset ,
-.IR dst_offset ,
-and
 .I length
-are omitted the contents of src_file will be copied to the beginning of the
-open file, overwriting any data already there.
+is not specified, this command copies data from
+.I src_offset
+to the end of
+.BI src_file
+into the dst_file at
+.IR dst_offset .
 .RS 1.0i
 .PD 0
 .TP 0.4i