]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - io/pwrite.c
2 * Copyright (c) 2003-2005 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 static cmdinfo_t pwrite_cmd
;
32 " writes a range of bytes (in block size increments) from the given offset\n"
35 " 'pwrite 512 20' - writes 20 bytes at 512 bytes into the open file\n"
37 " Writes into a segment of the currently open file, using either a buffer\n"
38 " filled with a set pattern (0xcdcdcdcd) or data read from an input file.\n"
39 " The writes are performed in sequential blocks starting at offset, with the\n"
40 " blocksize tunable using the -b option (default blocksize is 4096 bytes),\n"
41 " unless a different write pattern is requested.\n"
42 " -S -- use an alternate seed number for filling the write buffer\n"
43 " -i -- input file, source of data to write (used when writing forward)\n"
44 " -d -- open the input file for direct IO\n"
45 " -s -- skip a number of bytes at the start of the input file\n"
46 " -w -- call fdatasync(2) at the end (included in timing results)\n"
47 " -W -- call fsync(2) at the end (included in timing results)\n"
48 " -B -- write backwards through the range from offset (backwards N bytes)\n"
49 " -F -- write forwards through the range of bytes from offset (default)\n"
50 " -O -- perform pwrite call once and return (maybe partial) bytes written\n"
51 " -R -- write at random offsets in the specified range of bytes\n"
52 " -Z N -- zeed the random number generator (used when writing randomly)\n"
53 " (heh, zorry, the -s/-S arguments were already in use in pwrite)\n"
55 " -V N -- use vectored IO with N iovecs of blocksize each (pwritev)\n"
58 " -N -- Perform the pwritev2() with RWF_NOWAIT\n"
76 /* trim the iovec if necessary */
77 if (count
< buffersize
) {
79 while (len
+ iov
[vecs
].iov_len
< count
) {
80 len
+= iov
[vecs
].iov_len
;
83 oldlen
= iov
[vecs
].iov_len
;
84 iov
[vecs
].iov_len
= count
- len
;
91 bytes
= pwritev2(fd
, iov
, vectors
, offset
, pwritev2_flags
);
93 bytes
= pwritev(fd
, iov
, vectors
, offset
);
95 bytes
= pwritev(fd
, iov
, vectors
, offset
);
98 /* restore trimmed iov */
100 iov
[vecs
- 1].iov_len
= oldlen
;
105 #define do_pwritev(fd, offset, count, buffer_size, pwritev2_flags) (0)
117 return pwrite(fd
, buffer
, min(count
, buffer_size
), offset
);
119 return do_pwritev(fd
, offset
, count
, buffer_size
, pwritev2_flags
);
135 if ((bytes
= (offset
% buffersize
)))
137 offset
= max(0, offset
);
138 if ((bytes
= (count
% buffersize
)))
140 count
= max(buffersize
, count
);
141 range
= count
- buffersize
;
146 off
= ((offset
+ (random() % range
)) / buffersize
) *
150 bytes
= do_pwrite(file
->fd
, off
, buffersize
, buffersize
,
160 if (bytes
< buffersize
)
174 off64_t end
, off
= offset
;
175 ssize_t bytes
= 0, bytes_requested
;
176 long long cnt
= *count
;
179 if ((end
= off
- cnt
) < 0) {
180 cnt
+= end
; /* subtraction, end is negative */
186 /* Do initial unaligned write if needed */
187 if ((bytes_requested
= (off
% buffersize
))) {
188 bytes_requested
= min(cnt
, bytes_requested
);
189 off
-= bytes_requested
;
190 bytes
= do_pwrite(file
->fd
, off
, bytes_requested
, buffersize
,
200 if (bytes
< bytes_requested
)
205 /* Iterate backward through the rest of the range */
207 bytes_requested
= min(cnt
, buffersize
);
208 off
-= bytes_requested
;
209 bytes
= do_pwrite(file
->fd
, off
, cnt
, buffersize
,
219 if (bytes
< bytes_requested
)
237 long long bar
= min(bs
, count
);
242 if (fd
> 0) { /* input file given, read buffer first */
243 if (read_buffer(fd
, skip
+ *total
, bs
, &bar
, 0, 1) < 0)
246 bytes
= do_pwrite(file
->fd
, offset
, count
, bar
, pwritev2_flags
);
255 if (bytes
< min(count
, bar
))
273 bytes
= do_pwrite(file
->fd
, offset
, count
, count
, pwritev2_flags
);
287 off64_t offset
, skip
= 0;
288 long long count
, total
, tmp
;
289 unsigned int zeed
= 0, seed
= 0xcdcdcdcd;
290 size_t fsblocksize
, fssectsize
;
291 struct timeval t1
, t2
;
292 char *sp
, *infile
= NULL
;
293 int Cflag
, qflag
, uflag
, dflag
, wflag
, Wflag
;
294 int direction
= IO_FORWARD
;
296 int pwritev2_flags
= 0;
298 Cflag
= qflag
= uflag
= dflag
= wflag
= Wflag
= 0;
299 init_cvtnum(&fsblocksize
, &fssectsize
);
302 while ((c
= getopt(argc
, argv
, "b:BCdf:Fi:NqRs:OS:uV:wWZ:")) != EOF
) {
305 tmp
= cvtnum(fsblocksize
, fssectsize
, optarg
);
307 printf(_("non-numeric bsize -- %s\n"), optarg
);
316 direction
= IO_FORWARD
;
319 direction
= IO_BACKWARD
;
322 direction
= IO_RANDOM
;
336 pwritev2_flags
|= RWF_NOWAIT
;
340 skip
= cvtnum(fsblocksize
, fssectsize
, optarg
);
342 printf(_("non-numeric skip -- %s\n"), optarg
);
347 seed
= strtoul(optarg
, &sp
, 0);
348 if (!sp
|| sp
== optarg
) {
349 printf(_("non-numeric seed -- %s\n"), optarg
);
361 vectors
= strtoul(optarg
, &sp
, 0);
362 if (!sp
|| sp
== optarg
) {
363 printf(_("non-numeric vector count == %s\n"),
376 zeed
= strtoul(optarg
, &sp
, 0);
377 if (!sp
|| sp
== optarg
) {
378 printf(_("non-numeric seed -- %s\n"), optarg
);
383 /* Handle ifdef'd-out options above */
385 printf(_("%s: command -%c not supported\n"), argv
[0], c
);
387 command_usage(&pwrite_cmd
);
391 if (((skip
|| dflag
) && !infile
) || (optind
!= argc
- 2))
392 return command_usage(&pwrite_cmd
);
393 if (infile
&& direction
!= IO_FORWARD
)
394 return command_usage(&pwrite_cmd
);
395 offset
= cvtnum(fsblocksize
, fssectsize
, argv
[optind
]);
397 printf(_("non-numeric offset argument -- %s\n"), argv
[optind
]);
401 count
= cvtnum(fsblocksize
, fssectsize
, argv
[optind
]);
403 printf(_("non-numeric length argument -- %s\n"), argv
[optind
]);
407 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))
414 gettimeofday(&t1
, NULL
);
417 if (!zeed
) /* srandom seed */
419 c
= write_random(offset
, count
, zeed
, &total
, pwritev2_flags
);
422 c
= write_buffer(offset
, count
, bsize
, fd
, skip
, &total
,
426 c
= write_backward(offset
, &count
, &total
, pwritev2_flags
);
429 c
= write_once(offset
, count
, &total
, pwritev2_flags
);
438 if (fsync(file
->fd
) < 0) {
444 if (fdatasync(file
->fd
) < 0) {
451 gettimeofday(&t2
, NULL
);
454 report_io_times("wrote", &t2
, (long long)offset
, count
, total
, c
,
465 pwrite_cmd
.name
= "pwrite";
466 pwrite_cmd
.altname
= "w";
467 pwrite_cmd
.cfunc
= pwrite_f
;
468 pwrite_cmd
.argmin
= 2;
469 pwrite_cmd
.argmax
= -1;
470 pwrite_cmd
.flags
= CMD_NOMAP_OK
| CMD_FOREIGN_OK
;
472 _("[-i infile [-dwNOW] [-s skip]] [-b bs] [-S seed] [-FBR [-Z N]] [-V N] off len");
474 _("writes a number of bytes at a specified offset");
475 pwrite_cmd
.help
= pwrite_help
;
477 add_command(&pwrite_cmd
);