]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - io/pwrite.c
Improve the statistics reporting for xfs_io.
[thirdparty/xfsprogs-dev.git] / io / pwrite.c
1 /*
2 * Copyright (c) 2003-2005 Silicon Graphics, Inc. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
22 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31 */
32
33 #include <xfs/libxfs.h>
34 #include "command.h"
35 #include "input.h"
36 #include "init.h"
37 #include "io.h"
38
39 static cmdinfo_t pwrite_cmd;
40
41 static void
42 pwrite_help(void)
43 {
44 printf(_(
45 "\n"
46 " writes a range of bytes (in block size increments) from the given offset\n"
47 "\n"
48 " Example:\n"
49 " 'pwrite 512 20' - writes 20 bytes at 512 bytes into the open file\n"
50 "\n"
51 " Writes into a segment of the currently open file, using either a buffer\n"
52 " filled with a set pattern (0xcdcdcdcd) or data read from an input file.\n"
53 " -S -- use an alternate seed number\n"
54 " -i -- specifies an input file from which to source data to write\n"
55 " -d -- open the input file for direct IO\n"
56 " -s -- skip a number of bytes at the start of the input file\n"
57 " -w -- call fdatasync(2) at the end (included in timing results)\n"
58 " -W -- call fsync(2) at the end (included in timing results)\n"
59 " The writes are performed in sequential blocks starting at offset, with the\n"
60 " blocksize tunable using the -b option (default blocksize is 4096 bytes).\n"
61 "\n"));
62 }
63
64 static int
65 write_buffer(
66 off64_t offset,
67 long long count,
68 ssize_t bs,
69 int fd,
70 off64_t skip,
71 long long *total)
72 {
73 ssize_t bytes, bytes_requested;
74 long long bar = min(bs, count);
75 int ops = 0;
76
77 *total = 0;
78 while (count > 0) {
79 if (fd > 0) { /* input file given, read buffer first */
80 if (read_buffer(fd, skip + *total, bs, &bar, 0, 1) < 0)
81 break;
82 }
83 bytes_requested = min(bar, count);
84 bytes = pwrite64(file->fd, buffer, bytes_requested, offset);
85 if (bytes == 0)
86 break;
87 if (bytes < 0) {
88 perror("pwrite64");
89 return -1;
90 }
91 ops++;
92 *total += bytes;
93 if (bytes < bytes_requested)
94 break;
95 offset += bytes;
96 count -= bytes;
97 }
98 return ops;
99 }
100
101 static int
102 pwrite_f(
103 int argc,
104 char **argv)
105 {
106 off64_t offset, skip = 0;
107 long long count, total;
108 unsigned int seed = 0xcdcdcdcd;
109 int blocksize, sectsize;
110 struct timeval t1, t2;
111 char s1[64], s2[64], ts[64];
112 char *sp, *infile = NULL;
113 int Cflag, uflag, dflag, wflag, Wflag;
114 int c, fd = -1;
115
116 Cflag = uflag = dflag = wflag = Wflag = 0;
117 init_cvtnum(&blocksize, &sectsize);
118 while ((c = getopt(argc, argv, "b:Cdf:i:s:S:uwW")) != EOF) {
119 switch (c) {
120 case 'b':
121 blocksize = cvtnum(blocksize, sectsize, optarg);
122 if (blocksize < 0) {
123 printf(_("non-numeric bsize -- %s\n"), optarg);
124 return 0;
125 }
126 break;
127 case 'C':
128 Cflag = 1;
129 break;
130 case 'd':
131 dflag = 1;
132 break;
133 case 'f':
134 case 'i':
135 infile = optarg;
136 break;
137 case 's':
138 skip = cvtnum(blocksize, sectsize, optarg);
139 if (skip < 0) {
140 printf(_("non-numeric skip -- %s\n"), optarg);
141 return 0;
142 }
143 break;
144 case 'S':
145 seed = strtoul(optarg, &sp, 0);
146 if (!sp || sp == optarg) {
147 printf(_("non-numeric seed -- %s\n"), optarg);
148 return 0;
149 }
150 break;
151 case 'u':
152 uflag = 1;
153 break;
154 case 'w':
155 wflag = 1;
156 break;
157 case 'W':
158 Wflag = 1;
159 break;
160 default:
161 return command_usage(&pwrite_cmd);
162 }
163 }
164 if ( ((skip || dflag) && !infile) || (optind != argc - 2))
165 return command_usage(&pwrite_cmd);
166 offset = cvtnum(blocksize, sectsize, argv[optind]);
167 if (offset < 0) {
168 printf(_("non-numeric offset argument -- %s\n"), argv[optind]);
169 return 0;
170 }
171 optind++;
172 count = cvtnum(blocksize, sectsize, argv[optind]);
173 if (count < 0) {
174 printf(_("non-numeric length argument -- %s\n"), argv[optind]);
175 return 0;
176 }
177
178 if (alloc_buffer(blocksize, uflag, seed) < 0)
179 return 0;
180
181 c = IO_READONLY | (dflag ? IO_DIRECT : 0);
182 if (infile && ((fd = openfile(infile, NULL, c, 0)) < 0))
183 return 0;
184
185 gettimeofday(&t1, NULL);
186 c = write_buffer(offset, count, blocksize, fd, skip, &total);
187 if (c < 0) {
188 close(fd);
189 return 0;
190 }
191 if (Wflag)
192 fsync(file->fd);
193 if (wflag)
194 fdatasync(file->fd);
195 gettimeofday(&t2, NULL);
196 t2 = tsub(t2, t1);
197
198 /* Finally, report back -- -C gives a parsable format */
199 timestr(&t2, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
200 if (!Cflag) {
201 cvtstr((double)total, s1, sizeof(s1));
202 cvtstr(tdiv((double)total, t2), s2, sizeof(s2));
203 printf(_("wrote %lld/%lld bytes at offset %lld\n"),
204 total, count, (long long)offset);
205 printf(_("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n"),
206 s1, c, ts, s2, tdiv((double)c, t2));
207 } else {/* bytes,ops,time,bytes/sec,ops/sec */
208 printf("%lld,%d,%s,%.3f,%.3f\n",
209 total, c, ts,
210 tdiv((double)total, t2), tdiv((double)c, t2));
211 }
212 close(fd);
213 return 0;
214 }
215
216 void
217 pwrite_init(void)
218 {
219 pwrite_cmd.name = _("pwrite");
220 pwrite_cmd.altname = _("w");
221 pwrite_cmd.cfunc = pwrite_f;
222 pwrite_cmd.argmin = 2;
223 pwrite_cmd.argmax = -1;
224 pwrite_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
225 pwrite_cmd.args =
226 _("[-i infile [-d] [-s skip]] [-b bs] [-S seed] [-wW] off len");
227 pwrite_cmd.oneline =
228 _("writes a number of bytes at a specified offset");
229 pwrite_cmd.help = pwrite_help;
230
231 add_command(&pwrite_cmd);
232 }