]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - io/pread.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
26 static cmdinfo_t pread_cmd
;
33 " reads a range of bytes in a specified block size from the given offset\n"
36 " 'pread -v 512 20' - dumps 20 bytes read from 512 bytes into the file\n"
38 " Reads a segment of the currently open file, optionally dumping it to the\n"
39 " standard output stream (with -v option) for subsequent inspection.\n"
40 " The reads are performed in sequential blocks starting at offset, with the\n"
41 " blocksize tunable using the -b option (default blocksize is 4096 bytes),\n"
42 " unless a different pattern is requested.\n"
43 " -B -- read backwards through the range from offset (backwards N bytes)\n"
44 " -F -- read forwards through the range of bytes from offset (default)\n"
45 " -v -- be verbose, dump out buffers (used when reading forwards)\n"
46 " -R -- read at random offsets in the range of bytes\n"
47 " -Z N -- zeed the random number generator (used when reading randomly)\n"
48 " (heh, zorry, the -s/-S arguments were already in use in pwrite)\n"
50 " -V N -- use vectored IO with N iovecs of blocksize each (preadv)\n"
53 " When in \"random\" mode, the number of read operations will equal the\n"
54 " number required to do a complete forward/backward scan of the range.\n"
55 " Note that the offset within the range is chosen at random each time\n"
56 " (an offset may be read more than once when operating in this mode).\n"
74 iov
= calloc(vectors
, sizeof(struct iovec
));
79 for (i
= 0; i
< vectors
; i
++) {
80 iov
[i
].iov_base
= memalign(pagesize
, bsize
);
81 if (!iov
[i
].iov_base
) {
85 iov
[i
].iov_len
= bsize
;
87 memset(iov
[i
].iov_base
, seed
, bsize
);
89 buffersize
= bsize
* vectors
;
93 free(iov
[i
].iov_base
);
106 return alloc_iovec(bsize
, uflag
, seed
);
108 if (bsize
> highwater
) {
111 buffer
= memalign(pagesize
, bsize
);
114 highwater
= buffersize
= 0;
121 memset(buffer
, seed
, buffersize
);
134 for (i
= 0, p
= (char *)buf
; i
< len
; i
+= 16) {
137 printf("%08llx: ", (unsigned long long)offset
+ i
);
138 for (j
= 0; j
< 16 && i
+ j
< len
; j
++, p
++)
141 for (j
= 0; j
< 16 && i
+ j
< len
; j
++, s
++) {
142 if (isalnum((int)*s
))
159 __dump_buffer(buffer
, offset
, len
);
163 for (i
= 0; len
> 0 && i
< vectors
; i
++) {
164 l
= min(len
, iov
[i
].iov_len
);
166 __dump_buffer(iov
[i
].iov_base
, offset
, l
);
184 /* trim the iovec if necessary */
185 if (count
< buffersize
) {
187 while (len
+ iov
[vecs
].iov_len
< count
) {
188 len
+= iov
[vecs
].iov_len
;
191 oldlen
= iov
[vecs
].iov_len
;
192 iov
[vecs
].iov_len
= count
- len
;
197 bytes
= preadv(fd
, iov
, vectors
, offset
);
199 /* restore trimmed iov */
201 iov
[vecs
- 1].iov_len
= oldlen
;
206 #define do_preadv(fd, offset, count, buffer_size) (0)
217 return pread(fd
, buffer
, min(count
, buffer_size
), offset
);
219 return do_preadv(fd
, offset
, count
, buffer_size
);
231 off64_t end
, off
, range
;
236 end
= lseek(fd
, 0, SEEK_END
);
237 offset
= (eof
|| offset
> end
) ? end
: offset
;
238 if ((bytes
= (offset
% buffersize
)))
240 offset
= max(0, offset
);
241 if ((bytes
= (count
% buffersize
)))
243 count
= max(buffersize
, count
);
244 range
= count
- buffersize
;
249 off
= ((offset
+ (random() % range
)) / buffersize
) *
253 bytes
= do_pread(fd
, off
, buffersize
, buffersize
);
262 if (bytes
< buffersize
)
277 off64_t end
, off
= *offset
;
278 ssize_t bytes
= 0, bytes_requested
;
279 long long cnt
= *count
;
282 end
= lseek(fd
, 0, SEEK_END
);
283 off
= eof
? end
: min(end
, lseek(fd
, off
, SEEK_SET
));
284 if ((end
= off
- cnt
) < 0) {
285 cnt
+= end
; /* subtraction, end is negative */
292 /* Do initial unaligned read if needed */
293 if ((bytes_requested
= (off
% buffersize
))) {
294 off
-= bytes_requested
;
295 bytes
= do_pread(fd
, off
, bytes_requested
, buffersize
);
304 if (bytes
< bytes_requested
)
309 /* Iterate backward through the rest of the range */
311 bytes_requested
= min(cnt
, buffersize
);
312 off
-= bytes_requested
;
313 bytes
= do_pread(fd
, off
, cnt
, buffersize
);
322 if (bytes
< bytes_requested
)
343 while (count
> 0 || eof
) {
344 bytes
= do_pread(fd
, offset
, count
, buffersize
);
353 dump_buffer(offset
, bytes
);
355 if (onlyone
|| bytes
< min(count
, buffersize
))
372 return read_forward(fd
, offset
, count
, total
, verbose
, onlyone
, 0);
382 unsigned int zeed
= 0;
383 long long count
, total
, tmp
;
384 size_t fsblocksize
, fssectsize
;
385 struct timeval t1
, t2
;
387 int Cflag
, qflag
, uflag
, vflag
;
388 int eof
= 0, direction
= IO_FORWARD
;
391 Cflag
= qflag
= uflag
= vflag
= 0;
392 init_cvtnum(&fsblocksize
, &fssectsize
);
395 while ((c
= getopt(argc
, argv
, "b:BCFRquvV:Z:")) != EOF
) {
398 tmp
= cvtnum(fsblocksize
, fssectsize
, optarg
);
400 printf(_("non-numeric bsize -- %s\n"), optarg
);
409 direction
= IO_FORWARD
;
412 direction
= IO_BACKWARD
;
415 direction
= IO_RANDOM
;
428 vectors
= strtoul(optarg
, &sp
, 0);
429 if (!sp
|| sp
== optarg
) {
430 printf(_("non-numeric vector count == %s\n"),
437 zeed
= strtoul(optarg
, &sp
, 0);
438 if (!sp
|| sp
== optarg
) {
439 printf(_("non-numeric seed -- %s\n"), optarg
);
444 return command_usage(&pread_cmd
);
447 if (optind
!= argc
- 2)
448 return command_usage(&pread_cmd
);
450 offset
= cvtnum(fsblocksize
, fssectsize
, argv
[optind
]);
451 if (offset
< 0 && (direction
& (IO_RANDOM
|IO_BACKWARD
))) {
452 eof
= -1; /* read from EOF */
453 } else if (offset
< 0) {
454 printf(_("non-numeric length argument -- %s\n"), argv
[optind
]);
458 count
= cvtnum(fsblocksize
, fssectsize
, argv
[optind
]);
459 if (count
< 0 && (direction
& (IO_RANDOM
|IO_FORWARD
))) {
460 eof
= -1; /* read to EOF */
461 } else if (count
< 0) {
462 printf(_("non-numeric length argument -- %s\n"), argv
[optind
]);
466 if (alloc_buffer(bsize
, uflag
, 0xabababab) < 0)
469 gettimeofday(&t1
, NULL
);
472 if (!zeed
) /* srandom seed */
474 c
= read_random(file
->fd
, offset
, count
, &total
, zeed
, eof
);
477 c
= read_forward(file
->fd
, offset
, count
, &total
, vflag
, 0, eof
);
482 c
= read_backward(file
->fd
, &offset
, &count
, &total
, eof
);
491 gettimeofday(&t2
, NULL
);
494 report_io_times("read", &t2
, (long long)offset
, count
, total
, c
, Cflag
);
501 pread_cmd
.name
= "pread";
502 pread_cmd
.altname
= "r";
503 pread_cmd
.cfunc
= pread_f
;
504 pread_cmd
.argmin
= 2;
505 pread_cmd
.argmax
= -1;
506 pread_cmd
.flags
= CMD_NOMAP_OK
| CMD_FOREIGN_OK
;
507 pread_cmd
.args
= _("[-b bs] [-v] [-i N] [-FBR [-Z N]] off len");
508 pread_cmd
.oneline
= _("reads a number of bytes at a specified offset");
509 pread_cmd
.help
= pread_help
;
511 add_command(&pread_cmd
);