]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - io/pwrite.c
xfs_io: remove useless do_preadv and do_pwritev arguments
[thirdparty/xfsprogs-dev.git] / io / pwrite.c
CommitLineData
959ef981 1// SPDX-License-Identifier: GPL-2.0
e246ba5f 2/*
da23017d
NS
3 * Copyright (c) 2003-2005 Silicon Graphics, Inc.
4 * All Rights Reserved.
e246ba5f
NS
5 */
6
64a93371 7#include <sys/uio.h>
6b803e5a
CH
8#include "command.h"
9#include "input.h"
e246ba5f 10#include "init.h"
48c46ee3 11#include "io.h"
e246ba5f
NS
12
13static cmdinfo_t pwrite_cmd;
14
15static void
16pwrite_help(void)
17{
18 printf(_(
19"\n"
20" writes a range of bytes (in block size increments) from the given offset\n"
21"\n"
22" Example:\n"
48c46ee3 23" 'pwrite 512 20' - writes 20 bytes at 512 bytes into the open file\n"
e246ba5f
NS
24"\n"
25" Writes into a segment of the currently open file, using either a buffer\n"
26" filled with a set pattern (0xcdcdcdcd) or data read from an input file.\n"
e246ba5f 27" The writes are performed in sequential blocks starting at offset, with the\n"
8fb2237e
NS
28" blocksize tunable using the -b option (default blocksize is 4096 bytes),\n"
29" unless a different write pattern is requested.\n"
30" -S -- use an alternate seed number for filling the write buffer\n"
31" -i -- input file, source of data to write (used when writing forward)\n"
32" -d -- open the input file for direct IO\n"
33" -s -- skip a number of bytes at the start of the input file\n"
34" -w -- call fdatasync(2) at the end (included in timing results)\n"
35" -W -- call fsync(2) at the end (included in timing results)\n"
36" -B -- write backwards through the range from offset (backwards N bytes)\n"
37" -F -- write forwards through the range of bytes from offset (default)\n"
43ba1d61 38" -O -- perform pwrite call once and return (maybe partial) bytes written\n"
8fb2237e
NS
39" -R -- write at random offsets in the specified range of bytes\n"
40" -Z N -- zeed the random number generator (used when writing randomly)\n"
41" (heh, zorry, the -s/-S arguments were already in use in pwrite)\n"
197d5828 42#ifdef HAVE_PWRITEV
10899f17 43" -V N -- use vectored IO with N iovecs of blocksize each (pwritev)\n"
197d5828 44#endif
0799d5cf
GR
45#ifdef HAVE_PWRITEV2
46" -N -- Perform the pwritev2() with RWF_NOWAIT\n"
d9763825 47" -D -- Perform the pwritev2() with RWF_DSYNC\n"
0799d5cf 48#endif
e246ba5f
NS
49"\n"));
50}
51
197d5828 52#ifdef HAVE_PWRITEV
421c9220 53static ssize_t
197d5828 54do_pwritev(
10899f17
DC
55 int fd,
56 off64_t offset,
421c9220 57 size_t count,
c5deeac9 58 int pwritev2_flags)
10899f17 59{
197d5828
ES
60 int vecs = 0;
61 ssize_t oldlen = 0;
62 ssize_t bytes = 0;
10899f17
DC
63
64 /* trim the iovec if necessary */
65 if (count < buffersize) {
66 size_t len = 0;
67 while (len + iov[vecs].iov_len < count) {
68 len += iov[vecs].iov_len;
69 vecs++;
70 }
71 oldlen = iov[vecs].iov_len;
72 iov[vecs].iov_len = count - len;
73 vecs++;
74 } else {
75 vecs = vectors;
76 }
c5deeac9
GR
77#ifdef HAVE_PWRITEV2
78 if (pwritev2_flags)
79 bytes = pwritev2(fd, iov, vectors, offset, pwritev2_flags);
80 else
81 bytes = pwritev(fd, iov, vectors, offset);
82#else
10899f17 83 bytes = pwritev(fd, iov, vectors, offset);
c5deeac9 84#endif
10899f17
DC
85
86 /* restore trimmed iov */
87 if (oldlen)
88 iov[vecs - 1].iov_len = oldlen;
89
90 return bytes;
91}
197d5828 92#else
248b6f9a 93#define do_pwritev(fd, offset, count, pwritev2_flags) (0)
197d5828
ES
94#endif
95
421c9220 96static ssize_t
197d5828
ES
97do_pwrite(
98 int fd,
99 off64_t offset,
421c9220
ZL
100 size_t count,
101 size_t buffer_size,
c5deeac9 102 int pwritev2_flags)
197d5828
ES
103{
104 if (!vectors)
2f9a125c 105 return pwrite(fd, buffer, min(count, buffer_size), offset);
197d5828 106
248b6f9a 107 return do_pwritev(fd, offset, count, pwritev2_flags);
197d5828
ES
108}
109
8fb2237e
NS
110static int
111write_random(
112 off64_t offset,
113 long long count,
114 unsigned int seed,
c5deeac9
GR
115 long long *total,
116 int pwritev2_flags)
8fb2237e
NS
117{
118 off64_t off, range;
119 ssize_t bytes;
120 int ops = 0;
121
122 srandom(seed);
123 if ((bytes = (offset % buffersize)))
124 offset -= bytes;
125 offset = max(0, offset);
126 if ((bytes = (count % buffersize)))
127 count += bytes;
128 count = max(buffersize, count);
129 range = count - buffersize;
130
131 *total = 0;
132 while (count > 0) {
2ab8ecbe
DM
133 if (range)
134 off = ((offset + (random() % range)) / buffersize) *
135 buffersize;
136 else
137 off = offset;
c5deeac9
GR
138 bytes = do_pwrite(file->fd, off, buffersize, buffersize,
139 pwritev2_flags);
8fb2237e
NS
140 if (bytes == 0)
141 break;
142 if (bytes < 0) {
2f9a125c 143 perror("pwrite");
8fb2237e
NS
144 return -1;
145 }
146 ops++;
147 *total += bytes;
148 if (bytes < buffersize)
149 break;
150 count -= bytes;
151 }
152 return ops;
153}
154
155static int
156write_backward(
157 off64_t offset,
158 long long *count,
c5deeac9
GR
159 long long *total,
160 int pwritev2_flags)
8fb2237e
NS
161{
162 off64_t end, off = offset;
163 ssize_t bytes = 0, bytes_requested;
164 long long cnt = *count;
165 int ops = 0;
166
167 if ((end = off - cnt) < 0) {
168 cnt += end; /* subtraction, end is negative */
169 end = 0;
170 }
171 *total = 0;
172 *count = cnt;
173
174 /* Do initial unaligned write if needed */
175 if ((bytes_requested = (off % buffersize))) {
176 bytes_requested = min(cnt, bytes_requested);
177 off -= bytes_requested;
c5deeac9
GR
178 bytes = do_pwrite(file->fd, off, bytes_requested, buffersize,
179 pwritev2_flags);
8fb2237e
NS
180 if (bytes == 0)
181 return ops;
182 if (bytes < 0) {
2f9a125c 183 perror("pwrite");
8fb2237e
NS
184 return -1;
185 }
186 ops++;
187 *total += bytes;
188 if (bytes < bytes_requested)
189 return ops;
190 cnt -= bytes;
191 }
192
193 /* Iterate backward through the rest of the range */
194 while (cnt > end) {
195 bytes_requested = min(cnt, buffersize);
196 off -= bytes_requested;
c5deeac9
GR
197 bytes = do_pwrite(file->fd, off, cnt, buffersize,
198 pwritev2_flags);
8fb2237e
NS
199 if (bytes == 0)
200 break;
201 if (bytes < 0) {
2f9a125c 202 perror("pwrite");
8fb2237e
NS
203 return -1;
204 }
205 ops++;
206 *total += bytes;
207 if (bytes < bytes_requested)
208 break;
209 cnt -= bytes;
210 }
211 return ops;
212}
213
e246ba5f
NS
214static int
215write_buffer(
216 off64_t offset,
92d9b902 217 long long count,
2c2f6d79 218 size_t bs,
e246ba5f
NS
219 int fd,
220 off64_t skip,
c5deeac9
GR
221 long long *total,
222 int pwritev2_flags)
e246ba5f 223{
2c2f6d79 224 ssize_t bytes;
92d9b902
NS
225 long long bar = min(bs, count);
226 int ops = 0;
e246ba5f
NS
227
228 *total = 0;
8e2153bf 229 while (count >= 0) {
e246ba5f 230 if (fd > 0) { /* input file given, read buffer first */
92d9b902 231 if (read_buffer(fd, skip + *total, bs, &bar, 0, 1) < 0)
e246ba5f
NS
232 break;
233 }
c5deeac9 234 bytes = do_pwrite(file->fd, offset, count, bar, pwritev2_flags);
e246ba5f
NS
235 if (bytes == 0)
236 break;
237 if (bytes < 0) {
2f9a125c 238 perror("pwrite");
92d9b902 239 return -1;
e246ba5f 240 }
92d9b902 241 ops++;
e246ba5f 242 *total += bytes;
10899f17 243 if (bytes < min(count, bar))
e246ba5f
NS
244 break;
245 offset += bytes;
246 count -= bytes;
8e2153bf
ES
247 if (count == 0)
248 break;
e246ba5f 249 }
92d9b902 250 return ops;
e246ba5f
NS
251}
252
43ba1d61
GR
253static int
254write_once(
255 off64_t offset,
256 long long count,
257 long long *total,
258 int pwritev2_flags)
259{
421c9220 260 ssize_t bytes;
43ba1d61 261 bytes = do_pwrite(file->fd, offset, count, count, pwritev2_flags);
99d6e84f
GR
262 if (bytes < 0) {
263 perror("pwrite");
43ba1d61 264 return -1;
99d6e84f 265 }
43ba1d61
GR
266 *total = bytes;
267 return 1;
268}
269
270
e246ba5f
NS
271static int
272pwrite_f(
273 int argc,
274 char **argv)
275{
8fb2237e 276 size_t bsize;
e246ba5f 277 off64_t offset, skip = 0;
2c2f6d79 278 long long count, total, tmp;
8fb2237e 279 unsigned int zeed = 0, seed = 0xcdcdcdcd;
d026b19e 280 size_t fsblocksize, fssectsize;
92d9b902 281 struct timeval t1, t2;
e246ba5f 282 char *sp, *infile = NULL;
d347f827 283 int Cflag, qflag, uflag, dflag, wflag, Wflag;
8fb2237e 284 int direction = IO_FORWARD;
5c7bef67 285 int c, fd = -1;
c5deeac9 286 int pwritev2_flags = 0;
e246ba5f 287
d347f827 288 Cflag = qflag = uflag = dflag = wflag = Wflag = 0;
8fb2237e
NS
289 init_cvtnum(&fsblocksize, &fssectsize);
290 bsize = fsblocksize;
291
d9763825 292 while ((c = getopt(argc, argv, "b:BCdDf:Fi:NqRs:OS:uV:wWZ:")) != EOF) {
e246ba5f
NS
293 switch (c) {
294 case 'b':
8fb2237e 295 tmp = cvtnum(fsblocksize, fssectsize, optarg);
2c2f6d79 296 if (tmp < 0) {
e246ba5f
NS
297 printf(_("non-numeric bsize -- %s\n"), optarg);
298 return 0;
299 }
8fb2237e 300 bsize = tmp;
e246ba5f 301 break;
5c7bef67
NS
302 case 'C':
303 Cflag = 1;
304 break;
8fb2237e
NS
305 case 'F':
306 direction = IO_FORWARD;
307 break;
308 case 'B':
309 direction = IO_BACKWARD;
310 break;
311 case 'R':
312 direction = IO_RANDOM;
313 break;
43ba1d61
GR
314 case 'O':
315 direction = IO_ONCE;
316 break;
e246ba5f
NS
317 case 'd':
318 dflag = 1;
319 break;
320 case 'f':
321 case 'i':
322 infile = optarg;
323 break;
0799d5cf
GR
324#ifdef HAVE_PWRITEV2
325 case 'N':
326 pwritev2_flags |= RWF_NOWAIT;
327 break;
d9763825
DC
328 case 'D':
329 pwritev2_flags |= RWF_DSYNC;
330 break;
0799d5cf 331#endif
e246ba5f 332 case 's':
8fb2237e 333 skip = cvtnum(fsblocksize, fssectsize, optarg);
638473d8 334 if (skip < 0) {
e246ba5f
NS
335 printf(_("non-numeric skip -- %s\n"), optarg);
336 return 0;
337 }
338 break;
339 case 'S':
340 seed = strtoul(optarg, &sp, 0);
341 if (!sp || sp == optarg) {
342 printf(_("non-numeric seed -- %s\n"), optarg);
343 return 0;
344 }
345 break;
d347f827
NS
346 case 'q':
347 qflag = 1;
348 break;
48c46ee3
NS
349 case 'u':
350 uflag = 1;
351 break;
68c269ca 352#ifdef HAVE_PWRITEV
10899f17
DC
353 case 'V':
354 vectors = strtoul(optarg, &sp, 0);
355 if (!sp || sp == optarg) {
197d5828 356 printf(_("non-numeric vector count == %s\n"),
10899f17
DC
357 optarg);
358 return 0;
359 }
360 break;
68c269ca 361#endif
5ecb3de2
NS
362 case 'w':
363 wflag = 1;
364 break;
365 case 'W':
366 Wflag = 1;
367 break;
8fb2237e
NS
368 case 'Z':
369 zeed = strtoul(optarg, &sp, 0);
370 if (!sp || sp == optarg) {
371 printf(_("non-numeric seed -- %s\n"), optarg);
372 return 0;
373 }
374 break;
e246ba5f 375 default:
68c269ca
GR
376 /* Handle ifdef'd-out options above */
377 if (c != '?')
378 printf(_("%s: command -%c not supported\n"), argv[0], c);
379 else
380 command_usage(&pwrite_cmd);
381 return 0;
e246ba5f
NS
382 }
383 }
8fb2237e 384 if (((skip || dflag) && !infile) || (optind != argc - 2))
48c46ee3 385 return command_usage(&pwrite_cmd);
8fb2237e
NS
386 if (infile && direction != IO_FORWARD)
387 return command_usage(&pwrite_cmd);
388 offset = cvtnum(fsblocksize, fssectsize, argv[optind]);
638473d8 389 if (offset < 0) {
e246ba5f
NS
390 printf(_("non-numeric offset argument -- %s\n"), argv[optind]);
391 return 0;
392 }
393 optind++;
8fb2237e 394 count = cvtnum(fsblocksize, fssectsize, argv[optind]);
638473d8 395 if (count < 0) {
e246ba5f
NS
396 printf(_("non-numeric length argument -- %s\n"), argv[optind]);
397 return 0;
398 }
399
8fb2237e 400 if (alloc_buffer(bsize, uflag, seed) < 0)
e246ba5f
NS
401 return 0;
402
24cd0fec 403 c = IO_READONLY | (dflag ? IO_DIRECT : 0);
3fcab549 404 if (infile && ((fd = openfile(infile, NULL, c, 0, NULL)) < 0))
e246ba5f
NS
405 return 0;
406
92d9b902 407 gettimeofday(&t1, NULL);
8fb2237e
NS
408 switch (direction) {
409 case IO_RANDOM:
410 if (!zeed) /* srandom seed */
411 zeed = time(NULL);
c5deeac9 412 c = write_random(offset, count, zeed, &total, pwritev2_flags);
8fb2237e
NS
413 break;
414 case IO_FORWARD:
c5deeac9
GR
415 c = write_buffer(offset, count, bsize, fd, skip, &total,
416 pwritev2_flags);
8fb2237e
NS
417 break;
418 case IO_BACKWARD:
c5deeac9 419 c = write_backward(offset, &count, &total, pwritev2_flags);
8fb2237e 420 break;
43ba1d61
GR
421 case IO_ONCE:
422 c = write_once(offset, count, &total, pwritev2_flags);
423 break;
8fb2237e 424 default:
9234d416 425 total = 0;
8fb2237e
NS
426 ASSERT(0);
427 }
d347f827
NS
428 if (c < 0)
429 goto done;
74919c4e
LB
430 if (Wflag) {
431 if (fsync(file->fd) < 0) {
432 perror("fsync");
433 goto done;
434 }
435 }
436 if (wflag) {
437 if (fdatasync(file->fd) < 0) {
438 perror("fdatasync");
439 goto done;
440 }
441 }
d347f827
NS
442 if (qflag)
443 goto done;
92d9b902
NS
444 gettimeofday(&t2, NULL);
445 t2 = tsub(t2, t1);
446
a9b61ce9
DW
447 report_io_times("wrote", &t2, (long long)offset, count, total, c,
448 Cflag);
d347f827 449done:
886578b4
LM
450 if (infile)
451 close(fd);
e246ba5f
NS
452 return 0;
453}
454
455void
456pwrite_init(void)
457{
ad765595
AM
458 pwrite_cmd.name = "pwrite";
459 pwrite_cmd.altname = "w";
e246ba5f
NS
460 pwrite_cmd.cfunc = pwrite_f;
461 pwrite_cmd.argmin = 2;
462 pwrite_cmd.argmax = -1;
48c46ee3 463 pwrite_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
e246ba5f 464 pwrite_cmd.args =
d9763825 465_("[-i infile [-dDwNOW] [-s skip]] [-b bs] [-S seed] [-FBR [-Z N]] [-V N] off len");
e246ba5f
NS
466 pwrite_cmd.oneline =
467 _("writes a number of bytes at a specified offset");
468 pwrite_cmd.help = pwrite_help;
469
470 add_command(&pwrite_cmd);
471}