From c7f1a173a128b6d08e4dc19fd3b4c82cf9d7a2ab Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Thu, 17 Jun 2004 07:11:29 +0000 Subject: [PATCH] Add a sendfile command to xfs_io for exercising that functionality. --- io/sendfile.c | 189 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 io/sendfile.c diff --git a/io/sendfile.c b/io/sendfile.c new file mode 100644 index 000000000..f5d57b1a3 --- /dev/null +++ b/io/sendfile.c @@ -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 +#include +#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, §size); + 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); +} -- 2.47.2