]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - io/pwrite.c
2 * Copyright (c) 2003-2005 Silicon Graphics, Inc. All Rights Reserved.
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.
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.
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.
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.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
33 #include <xfs/libxfs.h>
34 #include <xfs/command.h>
35 #include <xfs/input.h>
39 static cmdinfo_t pwrite_cmd
;
46 " writes a range of bytes (in block size increments) from the given offset\n"
49 " 'pwrite 512 20' - writes 20 bytes at 512 bytes into the open file\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 " The writes are performed in sequential blocks starting at offset, with the\n"
54 " blocksize tunable using the -b option (default blocksize is 4096 bytes),\n"
55 " unless a different write pattern is requested.\n"
56 " -S -- use an alternate seed number for filling the write buffer\n"
57 " -i -- input file, source of data to write (used when writing forward)\n"
58 " -d -- open the input file for direct IO\n"
59 " -s -- skip a number of bytes at the start of the input file\n"
60 " -w -- call fdatasync(2) at the end (included in timing results)\n"
61 " -W -- call fsync(2) at the end (included in timing results)\n"
62 " -B -- write backwards through the range from offset (backwards N bytes)\n"
63 " -F -- write forwards through the range of bytes from offset (default)\n"
64 " -R -- write at random offsets in the specified range of bytes\n"
65 " -Z N -- zeed the random number generator (used when writing randomly)\n"
66 " (heh, zorry, the -s/-S arguments were already in use in pwrite)\n"
82 if ((bytes
= (offset
% buffersize
)))
84 offset
= max(0, offset
);
85 if ((bytes
= (count
% buffersize
)))
87 count
= max(buffersize
, count
);
88 range
= count
- buffersize
;
92 off
= ((random() % range
) / buffersize
) * buffersize
;
93 bytes
= pwrite64(file
->fd
, buffer
, buffersize
, off
);
102 if (bytes
< buffersize
)
115 off64_t end
, off
= offset
;
116 ssize_t bytes
= 0, bytes_requested
;
117 long long cnt
= *count
;
120 if ((end
= off
- cnt
) < 0) {
121 cnt
+= end
; /* subtraction, end is negative */
127 /* Do initial unaligned write if needed */
128 if ((bytes_requested
= (off
% buffersize
))) {
129 bytes_requested
= min(cnt
, bytes_requested
);
130 off
-= bytes_requested
;
131 bytes
= pwrite(file
->fd
, buffer
, bytes_requested
, off
);
140 if (bytes
< bytes_requested
)
145 /* Iterate backward through the rest of the range */
147 bytes_requested
= min(cnt
, buffersize
);
148 off
-= bytes_requested
;
149 bytes
= pwrite64(file
->fd
, buffer
, bytes_requested
, off
);
158 if (bytes
< bytes_requested
)
174 size_t bytes_requested
;
176 long long bar
= min(bs
, count
);
181 if (fd
> 0) { /* input file given, read buffer first */
182 if (read_buffer(fd
, skip
+ *total
, bs
, &bar
, 0, 1) < 0)
185 bytes_requested
= min(bar
, count
);
186 bytes
= pwrite64(file
->fd
, buffer
, bytes_requested
, offset
);
195 if (bytes
< bytes_requested
)
209 off64_t offset
, skip
= 0;
210 long long count
, total
, tmp
;
211 unsigned int zeed
= 0, seed
= 0xcdcdcdcd;
212 unsigned int fsblocksize
, fssectsize
;
213 struct timeval t1
, t2
;
214 char s1
[64], s2
[64], ts
[64];
215 char *sp
, *infile
= NULL
;
216 int Cflag
, uflag
, dflag
, wflag
, Wflag
;
217 int direction
= IO_FORWARD
;
220 Cflag
= uflag
= dflag
= wflag
= Wflag
= 0;
221 init_cvtnum(&fsblocksize
, &fssectsize
);
224 while ((c
= getopt(argc
, argv
, "b:Cdf:i:s:S:uwWZ:")) != EOF
) {
227 tmp
= cvtnum(fsblocksize
, fssectsize
, optarg
);
229 printf(_("non-numeric bsize -- %s\n"), optarg
);
238 direction
= IO_FORWARD
;
241 direction
= IO_BACKWARD
;
244 direction
= IO_RANDOM
;
254 skip
= cvtnum(fsblocksize
, fssectsize
, optarg
);
256 printf(_("non-numeric skip -- %s\n"), optarg
);
261 seed
= strtoul(optarg
, &sp
, 0);
262 if (!sp
|| sp
== optarg
) {
263 printf(_("non-numeric seed -- %s\n"), optarg
);
277 zeed
= strtoul(optarg
, &sp
, 0);
278 if (!sp
|| sp
== optarg
) {
279 printf(_("non-numeric seed -- %s\n"), optarg
);
284 return command_usage(&pwrite_cmd
);
287 if (((skip
|| dflag
) && !infile
) || (optind
!= argc
- 2))
288 return command_usage(&pwrite_cmd
);
289 if (infile
&& direction
!= IO_FORWARD
)
290 return command_usage(&pwrite_cmd
);
291 offset
= cvtnum(fsblocksize
, fssectsize
, argv
[optind
]);
293 printf(_("non-numeric offset argument -- %s\n"), argv
[optind
]);
297 count
= cvtnum(fsblocksize
, fssectsize
, argv
[optind
]);
299 printf(_("non-numeric length argument -- %s\n"), argv
[optind
]);
303 if (alloc_buffer(bsize
, uflag
, seed
) < 0)
306 c
= IO_READONLY
| (dflag
? IO_DIRECT
: 0);
307 if (infile
&& ((fd
= openfile(infile
, NULL
, c
, 0)) < 0))
310 gettimeofday(&t1
, NULL
);
313 if (!zeed
) /* srandom seed */
315 c
= write_random(offset
, count
, zeed
, &total
);
318 c
= write_buffer(offset
, count
, bsize
, fd
, skip
, &total
);
321 c
= write_backward(offset
, &count
, &total
);
334 gettimeofday(&t2
, NULL
);
337 /* Finally, report back -- -C gives a parsable format */
338 timestr(&t2
, ts
, sizeof(ts
), Cflag
? VERBOSE_FIXED_TIME
: 0);
340 cvtstr((double)total
, s1
, sizeof(s1
));
341 cvtstr(tdiv((double)total
, t2
), s2
, sizeof(s2
));
342 printf(_("wrote %lld/%lld bytes at offset %lld\n"),
343 total
, count
, (long long)offset
);
344 printf(_("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n"),
345 s1
, c
, ts
, s2
, tdiv((double)c
, t2
));
346 } else {/* bytes,ops,time,bytes/sec,ops/sec */
347 printf("%lld,%d,%s,%.3f,%.3f\n",
349 tdiv((double)total
, t2
), tdiv((double)c
, t2
));
358 pwrite_cmd
.name
= _("pwrite");
359 pwrite_cmd
.altname
= _("w");
360 pwrite_cmd
.cfunc
= pwrite_f
;
361 pwrite_cmd
.argmin
= 2;
362 pwrite_cmd
.argmax
= -1;
363 pwrite_cmd
.flags
= CMD_NOMAP_OK
| CMD_FOREIGN_OK
;
365 _("[-i infile [-d] [-s skip]] [-b bs] [-S seed] [-wW] off len");
367 _("writes a number of bytes at a specified offset");
368 pwrite_cmd
.help
= pwrite_help
;
370 add_command(&pwrite_cmd
);