]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_io: allow passing an open file to copy_range
authorAmir Goldstein <amir73il@gmail.com>
Wed, 10 Jul 2019 15:36:25 +0000 (11:36 -0400)
committerEric Sandeen <sandeen@redhat.com>
Wed, 10 Jul 2019 15:36:25 +0000 (11:36 -0400)
Commit 1a05efba ("io: open pipes in non-blocking mode")
addressed a specific copy_range issue with pipes by always opening
pipes in non-blocking mode.

This change takes a different approach and allows passing any
open file as the source file to copy_range.  Besides providing
more flexibility to the copy_range command, this allows xfstests
to check if xfs_io supports passing an open file to copy_range.

The intended usage is:
$ mkfifo fifo
$ xfs_io -f -n -r -c "open -f dst" -C "copy_range -f 0" fifo

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
io/copy_file_range.c
man/man8/xfs_io.8

index d069e5bb905a994e0441083c9214e99dc329edb5..4a0e7a7759c0373409336483c5193dc351a71459 100644 (file)
@@ -26,6 +26,8 @@ copy_range_help(void)
                                               file at offset 200\n\
  'copy_range some_file' - copies all bytes from some_file into the open file\n\
                           at position 0\n\
+ 'copy_range -f 2' - copies all bytes from open file 2 into the current open file\n\
+                          at position 0\n\
 "));
 }
 
@@ -82,11 +84,12 @@ copy_range_f(int argc, char **argv)
        int opt;
        int ret;
        int fd;
+       int src_file_arg = 1;
        size_t fsblocksize, fssectsize;
 
        init_cvtnum(&fsblocksize, &fssectsize);
 
-       while ((opt = getopt(argc, argv, "s:d:l:")) != -1) {
+       while ((opt = getopt(argc, argv, "s:d:l:f:")) != -1) {
                switch (opt) {
                case 's':
                        src = cvtnum(fsblocksize, fssectsize, optarg);
@@ -109,15 +112,28 @@ copy_range_f(int argc, char **argv)
                                return 0;
                        }
                        break;
+               case 'f':
+                       fd = atoi(argv[1]);
+                       if (fd < 0 || fd >= filecount) {
+                               printf(_("value %d is out of range (0-%d)\n"),
+                                       fd, filecount-1);
+                               return 0;
+                       }
+                       fd = filetable[fd].fd;
+                       /* Expect no src_file arg */
+                       src_file_arg = 0;
+                       break;
                }
        }
 
-       if (optind != argc - 1)
+       if (optind != argc - src_file_arg)
                return command_usage(&copy_range_cmd);
 
-       fd = openfile(argv[optind], NULL, IO_READONLY, 0, NULL);
-       if (fd < 0)
-               return 0;
+       if (src_file_arg) {
+               fd = openfile(argv[optind], NULL, IO_READONLY, 0, NULL);
+               if (fd < 0)
+                       return 0;
+       }
 
        if (src == 0 && dst == 0 && len == 0) {
                off64_t sz;
@@ -150,7 +166,7 @@ copy_range_init(void)
        copy_range_cmd.argmin = 1;
        copy_range_cmd.argmax = 7;
        copy_range_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
-       copy_range_cmd.args = _("[-s src_off] [-d dst_off] [-l len] src_file");
+       copy_range_cmd.args = _("[-s src_off] [-d dst_off] [-l len] src_file | -f N");
        copy_range_cmd.oneline = _("Copy a range of data between two files");
        copy_range_cmd.help = copy_range_help;
 
index 980dcfd35ea45f2f57afbceab4bf6a2c53b67b1f..6e064bddef2314ed38a714247b47820103c86951 100644 (file)
@@ -660,12 +660,16 @@ Do not print timing statistics at all.
 .RE
 .PD
 .TP
-.BI "copy_range [ -s " src_offset " ] [ -d " dst_offset " ] [ -l " length " ] src_file"
+.BI "copy_range [ -s " src_offset " ] [ -d " dst_offset " ] [ -l " length " ] src_file | \-f " N
 On filesystems that support the
 .BR copy_file_range (2)
-system call, copies data from the
+system call, copies data from the source file into the current open file.
+The source must be specified either by path
+.RB ( src_file )
+or as another open file
+.RB ( \-f ).
+If
 .I src_file
-into the open file.  If
 .IR src_offset ,
 .IR dst_offset ,
 and