]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
Add a sendfile command to xfs_io for exercising that functionality.
authorNathan Scott <nathans@sgi.com>
Thu, 17 Jun 2004 07:11:29 +0000 (07:11 +0000)
committerNathan Scott <nathans@sgi.com>
Thu, 17 Jun 2004 07:11:29 +0000 (07:11 +0000)
io/sendfile.c [new file with mode: 0644]

diff --git a/io/sendfile.c b/io/sendfile.c
new file mode 100644 (file)
index 0000000..f5d57b1
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2004 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <xfs/libxfs.h>
+#include <sys/sendfile.h>
+#include "command.h"
+#include "input.h"
+#include "init.h"
+#include "io.h"
+
+static cmdinfo_t sendfile_cmd;
+
+static void
+sendfile_help(void)
+{
+       printf(_(
+"\n"
+" transfer a range of bytes from the given offset between files\n"
+"\n"
+" Example:\n"
+" 'send -f 2 512 20' - writes 20 bytes at 512 bytes into the open file\n"
+"\n"
+" Copies data between one file descriptor and another.  Because this copying\n"
+" is done within the kernel, sendfile does not need to transfer data to and\n"
+" from user space.\n"
+" -f -- specifies an input file from which to source data to write\n"
+" -i -- specifies an input file name from which to source data to write.\n"
+" An offset and length in the source file can be optionally specified.\n"
+"\n"));
+}
+
+static int
+send_buffer(
+       off64_t         offset,
+       size_t          count,
+       int             fd,
+       long long       *total)
+{
+       off64_t         off = offset;
+       ssize_t         bytes, bytes_remaining = count;
+       int             ops = 0;
+
+       *total = 0;
+       while (count > 0) {
+               bytes = sendfile64(file->fd, fd, &off, bytes_remaining);
+               if (bytes == 0)
+                       break;
+               if (bytes < 0) {
+                       perror("sendfile64");
+                       return -1;
+               }
+               ops++;
+               *total += bytes;
+               if (bytes >= bytes_remaining)
+                       break;
+               bytes_remaining -= bytes;
+       }
+       return ops;
+}
+
+static int
+sendfile_f(
+       int             argc,
+       char            **argv)
+{
+       off64_t         offset = 0;
+       long long       count, total;
+       unsigned int    blocksize, sectsize;
+       struct timeval  t1, t2;
+       char            s1[64], s2[64], ts[64];
+       char            *infile = NULL;
+       int             c, fd = -1;
+
+       init_cvtnum(&blocksize, &sectsize);
+       while ((c = getopt(argc, argv, "f:i:")) != EOF) {
+               switch (c) {
+               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;
+                       }
+                       break;
+               case 'i':
+                       infile = optarg;
+                       break;
+               default:
+                       return command_usage(&sendfile_cmd);
+               }
+       }
+       if (infile && fd != -1)
+               return command_usage(&sendfile_cmd);
+
+       if (!infile)
+               fd = filetable[fd].fd;
+       else if ((fd = openfile(infile, NULL, IO_READONLY, 0)) < 0)
+               return 0;
+
+       if (optind == argc - 2) {
+               offset = cvtnum(blocksize, sectsize, argv[optind]);
+               if (offset < 0) {
+                       printf(_("non-numeric offset argument -- %s\n"),
+                               argv[optind]);
+                       goto done;
+               }
+               optind++;
+               count = cvtnum(blocksize, sectsize, argv[optind]);
+               if (count < 0) {
+                       printf(_("non-numeric length argument -- %s\n"),
+                               argv[optind]);
+                       goto done;
+               }
+       } else {
+               struct stat64   stat;
+
+               if (fstat64(fd, &stat) < 0) {
+                       perror("fstat64");
+                       goto done;
+               }
+               count = stat.st_size;
+       }
+
+       gettimeofday(&t1, NULL);
+       c = send_buffer(offset, count, fd, &total);
+       if (c < 0)
+               goto done;
+       gettimeofday(&t2, NULL);
+       t2 = tsub(t2, t1);
+
+       printf(_("sent %lld/%lld bytes from offset %lld\n"),
+               total, count, (long long)offset);
+       cvtstr((double)total, s1, sizeof(s1));
+       cvtstr(tdiv((double)total, t2), s2, sizeof(s2));
+       timestr(&t2, ts, sizeof(ts));
+       printf(_("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n"),
+               s1, c, ts, s2, tdiv((double)c, t2));
+done:
+       if (infile)
+               close(fd);
+       return 0;
+}
+
+void
+sendfile_init(void)
+{
+       sendfile_cmd.name = _("sendfile");
+       sendfile_cmd.altname = _("send");
+       sendfile_cmd.cfunc = sendfile_f;
+       sendfile_cmd.argmin = 2;
+       sendfile_cmd.argmax = 4;
+       sendfile_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
+       sendfile_cmd.args =
+               _("-i infile | -f N [off len]");
+       sendfile_cmd.oneline =
+               _("Transfer data directly between file descriptors");
+       sendfile_cmd.help = sendfile_help;
+
+       add_command(&sendfile_cmd);
+}