]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - io/pwrite.c
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2003-2005 Silicon Graphics, Inc.
13 static cmdinfo_t pwrite_cmd
;
20 " writes a range of bytes (in block size increments) from the given offset\n"
23 " 'pwrite 512 20' - writes 20 bytes at 512 bytes into the open file\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"
27 " The writes are performed in sequential blocks starting at offset, with the\n"
28 " blocksize tunable using the -b option (default blocksize is 4096 bytes),\n"
29 " unless a different write pattern is requested.\n"
30 " -q -- quiet mode, do not write anything to standard output.\n"
31 " -S -- use an alternate seed number for filling the write buffer\n"
32 " -i -- input file, source of data to write (used when writing forward)\n"
33 " -d -- open the input file for direct IO\n"
34 " -s -- skip a number of bytes at the start of the input file\n"
35 " -w -- call fdatasync(2) at the end (included in timing results)\n"
36 " -W -- call fsync(2) at the end (included in timing results)\n"
37 " -B -- write backwards through the range from offset (backwards N bytes)\n"
38 " -F -- write forwards through the range of bytes from offset (default)\n"
39 " -O -- perform pwrite call once and return (maybe partial) bytes written\n"
40 " -R -- write at random offsets in the specified range of bytes\n"
41 " -Z N -- zeed the random number generator (used when writing randomly)\n"
42 " (heh, zorry, the -s/-S arguments were already in use in pwrite)\n"
43 " -V N -- use vectored IO with N iovecs of blocksize each (pwritev)\n"
45 " -N -- Perform the pwritev2() with RWF_NOWAIT\n"
46 " -D -- Perform the pwritev2() with RWF_DSYNC\n"
62 /* trim the iovec if necessary */
63 if (count
< io_buffersize
) {
65 while (len
+ iov
[vecs
].iov_len
< count
) {
66 len
+= iov
[vecs
].iov_len
;
69 oldlen
= iov
[vecs
].iov_len
;
70 iov
[vecs
].iov_len
= count
- len
;
77 bytes
= pwritev2(fd
, iov
, vectors
, offset
, pwritev2_flags
);
79 bytes
= pwritev(fd
, iov
, vectors
, offset
);
81 bytes
= pwritev(fd
, iov
, vectors
, offset
);
84 /* restore trimmed iov */
86 iov
[vecs
- 1].iov_len
= oldlen
;
100 return pwrite(fd
, io_buffer
, min(count
, buffer_size
), offset
);
102 return do_pwritev(fd
, offset
, count
, pwritev2_flags
);
118 if ((bytes
= (offset
% io_buffersize
)))
120 offset
= max(0, offset
);
121 if ((bytes
= (count
% io_buffersize
)))
123 count
= max(io_buffersize
, count
);
124 range
= count
- io_buffersize
;
129 off
= ((offset
+ (random() % range
)) / io_buffersize
) *
133 bytes
= do_pwrite(file
->fd
, off
, io_buffersize
, io_buffersize
,
143 if (bytes
< io_buffersize
)
157 off_t end
, off
= offset
;
158 ssize_t bytes
= 0, bytes_requested
;
159 long long cnt
= *count
;
162 if ((end
= off
- cnt
) < 0) {
163 cnt
+= end
; /* subtraction, end is negative */
169 /* Do initial unaligned write if needed */
170 if ((bytes_requested
= (off
% io_buffersize
))) {
171 bytes_requested
= min(cnt
, bytes_requested
);
172 off
-= bytes_requested
;
173 bytes
= do_pwrite(file
->fd
, off
, bytes_requested
, io_buffersize
,
183 if (bytes
< bytes_requested
)
188 /* Iterate backward through the rest of the range */
190 bytes_requested
= min(cnt
, io_buffersize
);
191 off
-= bytes_requested
;
192 bytes
= do_pwrite(file
->fd
, off
, cnt
, io_buffersize
,
202 if (bytes
< bytes_requested
)
220 long long bar
= min(bs
, count
);
225 if (fd
> 0) { /* input file given, read buffer first */
226 if (read_buffer(fd
, skip
+ *total
, bs
, &bar
, 0, 1) < 0)
229 bytes
= do_pwrite(file
->fd
, offset
, count
, bar
, pwritev2_flags
);
238 if (bytes
< min(count
, bar
))
256 bytes
= do_pwrite(file
->fd
, offset
, count
, count
, pwritev2_flags
);
272 off_t offset
, skip
= 0;
273 long long count
, total
, tmp
;
274 unsigned int zeed
= 0, seed
= 0xcdcdcdcd;
275 size_t fsblocksize
, fssectsize
;
276 struct timeval t1
, t2
;
277 char *sp
, *infile
= NULL
;
278 int Cflag
, qflag
, uflag
, dflag
, wflag
, Wflag
;
279 int direction
= IO_FORWARD
;
281 int pwritev2_flags
= 0;
283 Cflag
= qflag
= uflag
= dflag
= wflag
= Wflag
= 0;
284 init_cvtnum(&fsblocksize
, &fssectsize
);
287 while ((c
= getopt(argc
, argv
, "b:BCdDf:Fi:NqRs:OS:uV:wWZ:")) != EOF
) {
290 tmp
= cvtnum(fsblocksize
, fssectsize
, optarg
);
292 printf(_("non-numeric bsize -- %s\n"), optarg
);
302 direction
= IO_FORWARD
;
305 direction
= IO_BACKWARD
;
308 direction
= IO_RANDOM
;
322 pwritev2_flags
|= RWF_NOWAIT
;
325 pwritev2_flags
|= RWF_DSYNC
;
329 skip
= cvtnum(fsblocksize
, fssectsize
, optarg
);
331 printf(_("non-numeric skip -- %s\n"), optarg
);
337 seed
= strtoul(optarg
, &sp
, 0);
338 if (!sp
|| sp
== optarg
) {
339 printf(_("non-numeric seed -- %s\n"), optarg
);
351 vectors
= strtoul(optarg
, &sp
, 0);
352 if (!sp
|| sp
== optarg
) {
353 printf(_("non-numeric vector count == %s\n"),
366 zeed
= strtoul(optarg
, &sp
, 0);
367 if (!sp
|| sp
== optarg
) {
368 printf(_("non-numeric seed -- %s\n"), optarg
);
374 /* Handle ifdef'd-out options above */
377 printf(_("%s: command -%c not supported\n"), argv
[0], c
);
379 command_usage(&pwrite_cmd
);
383 if (((skip
|| dflag
) && !infile
) || (optind
!= argc
- 2)) {
385 return command_usage(&pwrite_cmd
);
387 if (infile
&& direction
!= IO_FORWARD
) {
389 return command_usage(&pwrite_cmd
);
391 offset
= cvtnum(fsblocksize
, fssectsize
, argv
[optind
]);
393 printf(_("non-numeric offset argument -- %s\n"), argv
[optind
]);
398 count
= cvtnum(fsblocksize
, fssectsize
, argv
[optind
]);
400 printf(_("non-numeric length argument -- %s\n"), argv
[optind
]);
405 if (alloc_buffer(bsize
, uflag
, seed
) < 0) {
410 c
= IO_READONLY
| (dflag
? IO_DIRECT
: 0);
411 if (infile
&& ((fd
= openfile(infile
, NULL
, c
, 0, NULL
)) < 0)) {
416 gettimeofday(&t1
, NULL
);
419 if (!zeed
) /* srandom seed */
421 c
= write_random(offset
, count
, zeed
, &total
, pwritev2_flags
);
424 c
= write_buffer(offset
, count
, bsize
, fd
, skip
, &total
,
428 c
= write_backward(offset
, &count
, &total
, pwritev2_flags
);
431 c
= write_once(offset
, count
, &total
, pwritev2_flags
);
442 if (fsync(file
->fd
) < 0) {
449 if (fdatasync(file
->fd
) < 0) {
458 gettimeofday(&t2
, NULL
);
461 report_io_times("wrote", &t2
, (long long)offset
, count
, total
, c
,
472 pwrite_cmd
.name
= "pwrite";
473 pwrite_cmd
.altname
= "w";
474 pwrite_cmd
.cfunc
= pwrite_f
;
475 pwrite_cmd
.argmin
= 2;
476 pwrite_cmd
.argmax
= -1;
477 pwrite_cmd
.flags
= CMD_NOMAP_OK
| CMD_FOREIGN_OK
;
479 _("[-i infile [-qdDwNOW] [-s skip]] [-b bs] [-S seed] [-FBR [-Z N]] [-V N] off len");
481 _("writes a number of bytes at a specified offset");
482 pwrite_cmd
.help
= pwrite_help
;
484 add_command(&pwrite_cmd
);