]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - io/pread.c
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2003-2005 Silicon Graphics, Inc.
8 #define _DEFAULT_SOURCE
16 static cmdinfo_t pread_cmd
;
23 " reads a range of bytes in a specified block size from the given offset\n"
26 " 'pread -v 512 20' - dumps 20 bytes read from 512 bytes into the file\n"
28 " Reads a segment of the currently open file, optionally dumping it to the\n"
29 " standard output stream (with -v option) for subsequent inspection.\n"
30 " The reads are performed in sequential blocks starting at offset, with the\n"
31 " blocksize tunable using the -b option (default blocksize is 4096 bytes),\n"
32 " unless a different pattern is requested.\n"
33 " -q -- quiet mode, do not write anything to standard output.\n"
34 " -B -- read backwards through the range from offset (backwards N bytes)\n"
35 " -F -- read forwards through the range of bytes from offset (default)\n"
36 " -v -- be verbose, dump out buffers (used when reading forwards)\n"
37 " -R -- read at random offsets in the range of bytes\n"
38 " -Z N -- zeed the random number generator (used when reading randomly)\n"
39 " (heh, zorry, the -s/-S arguments were already in use in pwrite)\n"
40 " -V N -- use vectored IO with N iovecs of blocksize each (preadv)\n"
42 " When in \"random\" mode, the number of read operations will equal the\n"
43 " number required to do a complete forward/backward scan of the range.\n"
44 " Note that the offset within the range is chosen at random each time\n"
45 " (an offset may be read more than once when operating in this mode).\n"
63 iov
= calloc(vectors
, sizeof(struct iovec
));
68 for (i
= 0; i
< vectors
; i
++) {
69 iov
[i
].iov_base
= memalign(pagesize
, bsize
);
70 if (!iov
[i
].iov_base
) {
74 iov
[i
].iov_len
= bsize
;
76 memset(iov
[i
].iov_base
, seed
, bsize
);
78 io_buffersize
= bsize
* vectors
;
82 free(iov
[i
].iov_base
);
95 return alloc_iovec(bsize
, uflag
, seed
);
97 if (bsize
> highwater
) {
100 io_buffer
= memalign(pagesize
, bsize
);
103 highwater
= io_buffersize
= 0;
108 io_buffersize
= bsize
;
110 memset(io_buffer
, seed
, io_buffersize
);
123 for (i
= 0, p
= (char *)buf
; i
< len
; i
+= 16) {
126 printf("%08llx: ", (unsigned long long)offset
+ i
);
127 for (j
= 0; j
< 16 && i
+ j
< len
; j
++, p
++)
130 for (j
= 0; j
< 16 && i
+ j
< len
; j
++, s
++) {
131 if (isalnum((int)*s
))
148 __dump_buffer(io_buffer
, offset
, len
);
152 for (i
= 0; len
> 0 && i
< vectors
; i
++) {
153 l
= min(len
, iov
[i
].iov_len
);
155 __dump_buffer(iov
[i
].iov_base
, offset
, l
);
171 /* trim the iovec if necessary */
172 if (count
< io_buffersize
) {
174 while (len
+ iov
[vecs
].iov_len
< count
) {
175 len
+= iov
[vecs
].iov_len
;
178 oldlen
= iov
[vecs
].iov_len
;
179 iov
[vecs
].iov_len
= count
- len
;
184 bytes
= preadv(fd
, iov
, vectors
, offset
);
186 /* restore trimmed iov */
188 iov
[vecs
- 1].iov_len
= oldlen
;
201 return pread(fd
, io_buffer
, min(count
, buffer_size
), offset
);
203 return do_preadv(fd
, offset
, count
);
215 off_t end
, off
, range
;
220 end
= lseek(fd
, 0, SEEK_END
);
221 offset
= (eof
|| offset
> end
) ? end
: offset
;
222 if ((bytes
= (offset
% io_buffersize
)))
224 offset
= max(0, offset
);
225 if ((bytes
= (count
% io_buffersize
)))
227 count
= max(io_buffersize
, count
);
228 range
= count
- io_buffersize
;
233 off
= ((offset
+ (random() % range
)) / io_buffersize
) *
237 bytes
= do_pread(fd
, off
, io_buffersize
, io_buffersize
);
246 if (bytes
< io_buffersize
)
261 off_t end
, off
= *offset
;
262 ssize_t bytes
= 0, bytes_requested
;
263 long long cnt
= *count
;
266 end
= lseek(fd
, 0, SEEK_END
);
267 off
= eof
? end
: min(end
, lseek(fd
, off
, SEEK_SET
));
268 if ((end
= off
- cnt
) < 0) {
269 cnt
+= end
; /* subtraction, end is negative */
276 /* Do initial unaligned read if needed */
277 if ((bytes_requested
= (off
% io_buffersize
))) {
278 off
-= bytes_requested
;
279 bytes
= do_pread(fd
, off
, bytes_requested
, io_buffersize
);
288 if (bytes
< bytes_requested
)
293 /* Iterate backward through the rest of the range */
295 bytes_requested
= min(cnt
, io_buffersize
);
296 off
-= bytes_requested
;
297 bytes
= do_pread(fd
, off
, cnt
, io_buffersize
);
306 if (bytes
< bytes_requested
)
327 while (count
> 0 || eof
) {
328 bytes
= do_pread(fd
, offset
, count
, io_buffersize
);
337 dump_buffer(offset
, bytes
);
339 if (onlyone
|| bytes
< min(count
, io_buffersize
))
356 return read_forward(fd
, offset
, count
, total
, verbose
, onlyone
, 0);
366 unsigned int zeed
= 0;
367 long long count
, total
, tmp
;
368 size_t fsblocksize
, fssectsize
;
369 struct timeval t1
, t2
;
371 int Cflag
, qflag
, uflag
, vflag
;
372 int eof
= 0, direction
= IO_FORWARD
;
375 Cflag
= qflag
= uflag
= vflag
= 0;
376 init_cvtnum(&fsblocksize
, &fssectsize
);
379 while ((c
= getopt(argc
, argv
, "b:BCFRquvV:Z:")) != EOF
) {
382 tmp
= cvtnum(fsblocksize
, fssectsize
, optarg
);
384 printf(_("non-numeric bsize -- %s\n"), optarg
);
394 direction
= IO_FORWARD
;
397 direction
= IO_BACKWARD
;
400 direction
= IO_RANDOM
;
412 vectors
= strtoul(optarg
, &sp
, 0);
413 if (!sp
|| sp
== optarg
) {
414 printf(_("non-numeric vector count == %s\n"),
421 zeed
= strtoul(optarg
, &sp
, 0);
422 if (!sp
|| sp
== optarg
) {
423 printf(_("non-numeric seed -- %s\n"), optarg
);
430 return command_usage(&pread_cmd
);
433 if (optind
!= argc
- 2) {
435 return command_usage(&pread_cmd
);
438 offset
= cvtnum(fsblocksize
, fssectsize
, argv
[optind
]);
439 if (offset
< 0 && (direction
& (IO_RANDOM
|IO_BACKWARD
))) {
440 eof
= -1; /* read from EOF */
441 } else if (offset
< 0) {
442 printf(_("non-numeric length argument -- %s\n"), argv
[optind
]);
447 count
= cvtnum(fsblocksize
, fssectsize
, argv
[optind
]);
448 if (count
< 0 && (direction
& (IO_RANDOM
|IO_FORWARD
))) {
449 eof
= -1; /* read to EOF */
450 } else if (count
< 0) {
451 printf(_("non-numeric length argument -- %s\n"), argv
[optind
]);
456 if (alloc_buffer(bsize
, uflag
, 0xabababab) < 0) {
461 gettimeofday(&t1
, NULL
);
464 if (!zeed
) /* srandom seed */
466 c
= read_random(file
->fd
, offset
, count
, &total
, zeed
, eof
);
469 c
= read_forward(file
->fd
, offset
, count
, &total
, vflag
, 0, eof
);
474 c
= read_backward(file
->fd
, &offset
, &count
, &total
, eof
);
486 gettimeofday(&t2
, NULL
);
489 report_io_times("read", &t2
, (long long)offset
, count
, total
, c
, Cflag
);
496 pread_cmd
.name
= "pread";
497 pread_cmd
.altname
= "r";
498 pread_cmd
.cfunc
= pread_f
;
499 pread_cmd
.argmin
= 2;
500 pread_cmd
.argmax
= -1;
501 pread_cmd
.flags
= CMD_NOMAP_OK
| CMD_FOREIGN_OK
;
502 pread_cmd
.args
= _("[-b bs] [-qv] [-i N] [-FBR [-Z N]] off len");
503 pread_cmd
.oneline
= _("reads a number of bytes at a specified offset");
504 pread_cmd
.help
= pread_help
;
506 add_command(&pread_cmd
);