1
/****************************************************************************
3
* COPYRIGHT (c) 1990 - 2004 *
4
* This Software Provided *
6
* Robin's Nest Software Inc. *
8
* Permission to use, copy, modify, distribute and sell this software and *
9
* its documentation for any purpose and without fee is hereby granted, *
10
* provided that the above copyright notice appear in all copies and that *
11
* both that copyright notice and this permission notice appear in the *
12
* supporting documentation, and that the name of the author not be used *
13
* in advertising or publicity pertaining to distribution of the software *
14
* without specific, written prior permission. *
16
* THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, *
17
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN *
18
* NO EVENT SHALL HE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL *
19
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR *
20
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS *
21
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF *
24
****************************************************************************/
27
* Author: Robin T. Miller
28
* Date: August 26, 1993
31
* Functions to handle POSIX Asynchronous I/O requests for 'dt' program.
41
#if !defined(AIO_PRIO_DFL)
42
# define AIO_PRIO_DFL 0 /* Default scheduling priority. */
43
#endif /* !defined(AIO_PRIO_DFL) */
46
* Modification History:
48
* October 21st, 2004 by Robin Miller.
49
* For variable record lengths, ensure we prime the first size
50
* to ensure it meets device size alignment requirements.
52
* February 13th, 2004 by Robin Miller.
53
* Factor in the file position when doing reverse I/O, to avoid
54
* writing/reading into that area (which is now deemed protected).
56
* November 17th, 2003 by Robin Miller.
57
* Breakup output to stdout or stderr, rather than writing
58
* all output to stderr. If output file is stdout ('-') or a log
59
* file is specified, then all output reverts to stderr.
61
* January 17th, 2003 by Robin Miller.
62
* On HP-UX, accept ENXIO for I/O's pass EOF.
64
* November 14th, 2002 by Robin Miller.
65
* On HP-UX, initialize aiocb->aio_sigevent field, or else
66
* EINVAL is returned. aio_sigevent.sigev_notify = SIGEV_NONE;
68
* June 25th, 2001 by Robin Miller.
69
* Restructured code associated with Tru64 Unix EEI, so we obtain
70
* the EEI status for all tape errors, not just EIO errors.
72
* January 26th, 2001 by Robin Miller.
73
* Added support for reverse reading and writing.
75
* January 24th, 2001 by Robin Miller.
76
* Add support for variable I/O requests sizes.
78
* January 14th, 2001 by Robin Miller.
79
* Added support for multiple volumes option.
80
* Fixed multi-volume write w/lbdata option problem.
82
* October 4th, 2000 by Robin Miller.
83
* Update is_Eof() to accept ENXIO for AIO reads @ EOM on
84
* SCO UnixWare systems. All other systems return ENOSPC or zero.
86
* May 9th, 2000 by Robin Miller.
87
* Ensure the closing flag gets reset in dtaio_close_file() before
88
* calling close_file(), or the file descriptor won't get closed!
90
* May 8th, 2000 by Robin Miller.
91
* Honor the di_closing flag, to avoid a race condition with the
92
* close function being called again while still closing, from the
93
* terminate() routine called by the runtime= alarm, or signals.
95
* February 17th, 2000 by Robin Miller.
96
* Adding better support for multi-volume tape testing. Mainly,
97
* make it work with writing multiple tape files, rather than one file.
99
* January 6th, 2000 by Robin Miller.
100
* Added support for multi-volume media.
101
* Added a couple missing aio_return() calls.
103
* December 30th, 1999 by Robin Miller.
104
* Modify call to do_random() to pass the transfer size.
106
* November 10th, 1999 by Robin Miller.
107
* If aio_return() fails, report device information.
109
* August 7th, 1999 by Robin Miller.
110
* Minor mods to support AIO on SCO UnixWare 7.1.
112
* July 29, 1999 by Robin Miller.
113
* Merge in changes made to compile on FreeBSD.
115
* July 22nd, 1999 by Robin Miller.
116
* o Added support for IOT (DJ's) test pattern.
117
* o Fixed problem writing wrong starting lba, when lbdata
118
* and random I/O options were enabled.
120
* July 5th, 1999 by Robin Miller.
121
* Cleanup of compilation warnings on Linux.
123
* May 27, 1999 by Robin Miller.
124
* Added support for micro-second delays.
126
* March 1, 1999 by Robin Miller.
127
* For tapes when Debug is enabled, report the file number.
129
* January 13, 1998 by Robin Miller.
130
* Add support for restarting I/O's after EEI reset recovery.
131
* Modified dtaio_waitall() to optionally adjust data/file counts.
133
* December 21, 1998 by Robin Miller.
134
* Updates necessary to match tape API changes.
136
* November 16, 1998 by Robin Miller.
137
* Added pointer to current AIO control block for error reporting.
139
* October 26, 1998 by Robin Miller.
140
* o Fix incorrect record number displayed when Debug is enabled.
141
* o Don't exit read/write loops when processing partial records.
142
* o Fix problem in write function, where short write processing,
143
* caused us not to write sufficent data bytes (actually, the
144
* file loop in write_file() caused dtaio_write_data() to be
145
* called again, and we'd actually end up writing too much!
146
* o When random I/O and lbdata options are both enabled, use the
147
* file offset seeked to as the starting lbdata address.
149
* March 20, 1998 by Robin Miller.
150
* Update counts in dtaio_waitall() for accurate statistics.
152
* January 28, 1998 by Robin Miller.
153
* Add dtaio_close() function, to wait for queued I/O's when we're
154
* aborting, to avoid kernel I/O rundown problem, which panic's
155
* the system if we close the CAM disk driver device descriptor,
156
* prior to AIO's completing (fixed in steelos by Anton Verhulst).
158
* January 9, 1998 by Robin Miller.
159
* Don't initialize data buffer being written for "disable=compare"
160
* which yields better performance.
162
* April 3, 1997 by Robin Miller.
163
* Removed use of undocumented AIO_SEEK_CUR in aio_offset.
164
* Also fixed bug where random I/O offset was clobbered, thus
165
* resulting in sequential I/O.
167
* February 28, 1996 by Robin Miller.
168
* Added support for copying and verifying device/files.
169
* Modified logic so read errors honor users' error limit.
170
* [ NOTE: Copy and verify operations are done sequentially. ]
172
* November 11, 1995 by Robin Miller.
173
* Fix bug with init'ing and performing pad byte verification.
174
* This caused variable length reads with small increment values
175
* to report an (invalid) pad byte data compare error. e.g.:
177
* % dt of=/dev/rmt0h min=10k max=64k incr=1 pattern=incr
179
* July 17, 1995 by Robin Miller.
180
* Conditionalize aio_suspend() via "#if defined(POSIX_4D11)" for
181
* earlier POSIX drafts so only one copy of this file is necessary.
182
* [ NOTE: This is accomplished via -DPOSIX_4D11 in our Makefile. ]
184
* July 15, 1995 by Robin Miller.
185
* Fix end of media error handling (ENOSPC), and cleanup code.
187
* July 14, 1995 by Robin Miller.
188
* Add logic to allow rotating through 1st ROTATE_SIZE byes of buffers.
189
* [ This option was being silently ignored before, and nobody knew. ]
191
* April 15, 1994 by Wayne Casagrande.
192
* Update aiosuspend() interface, which now takes different arguments
193
* due to POSIX standard changing.
195
* January 20, 1994 by Robin Miller.
196
* When initializing the data buffer, don't do the entire buffer since
197
* init'ing large buffer (e.g. 100m) using min, max, and incr options cause
198
* excessive paging and VERY poor performance.
200
* October 15, 1993 by Robin Miller.
201
* Sorry folks, major screw up on my part. I forgot to redefine the
202
* test function (tf_write_data) field to point a the dtaio_write_data()
203
* function, so... synchronous writes were still being done (damn!!!).
204
* Also fixed bug when writing to stop looping when end of file reached.
208
* Forward References:
211
static void dtaio_checkdevice(struct dinfo *dip);
213
static int dtaio_wait(struct dinfo *dip, struct aiocb *acbp);
214
static int dtaio_waitall(struct dinfo *dip, bool canceling);
215
static int dtaio_wait_reads(struct dinfo *dip);
216
static int dtaio_wait_writes(struct dinfo *dip);
217
static int dtaio_process_read(struct dinfo *dip, struct aiocb *acbp);
218
static int dtaio_process_write(struct dinfo *dip, struct aiocb *acbp);
220
#define AIO_BUFS 8 /* Default number of AIO buffers. */
221
#define AIO_NotQed -1 /* AIO request not queued flag. */
223
int aio_bufs = AIO_BUFS; /* The number of AIO buffers. */
224
int aio_index; /* Index to AIO control block. */
225
volatile off_t aio_offset; /* AIO offset (we maintain). */
226
v_large aio_data_bytes; /* Total data bytes per pass. */
227
v_large aio_file_bytes; /* # of tape bytes processed. */
228
vu_long aio_record_count; /* # of records to processed. */
229
u_int32 aio_lba; /* AIO logical block address. */
232
* The following variables are meant to be used with tape devices to
233
* backup unprocessed files and/or records due to read-ahead, to be
234
* repositioned prior to the next test or before closing the tape.
236
u_long aio_data_adjust; /* # of data bytes to adjust. */
237
u_long aio_file_adjust; /* # of tape files to adjust. */
238
u_long aio_record_adjust; /* # of tape record to adjust. */
240
struct aiocb *acbs; /* Pointer to AIO control blocks. */
241
u_char **aiobufs; /* Pointer to base buffer addrs. */
242
struct aiocb *current_acb; /* Current acb for error reports. */
245
* Declare the POSIX Asynchronous I/O test functions.
247
struct dtfuncs aio_funcs = {
248
/* tf_open, tf_close, tf_initialize, */
249
open_file, dtaio_close_file, dtaio_initialize,
250
/* tf_start_test, tf_end_test, */
252
/* tf_read_file, tf_read_data, tf_cancel_reads, */
253
read_file, dtaio_read_data, dtaio_cancel_reads,
254
/* tf_write_file, tf_write_data, tf_cancel_writes, */
255
write_file, dtaio_write_data, nofunc,
256
/* tf_flush_data, tf_verify_data, tf_reopen_file, */
257
flush_file, verify_data, reopen_file,
258
/* tf_startup, tf_cleanup, tf_validate_opts */
259
nofunc, nofunc, validate_opts
262
/************************************************************************
264
* dtaio_close_file() - Close an open file descriptor. *
267
* This function does the AIO file descriptor close processing. *
269
* Inputs: dip = The device information pointer. *
272
* Returns 0 / -1 = SUCCESS / FAILURE. *
274
************************************************************************/
276
dtaio_close_file (struct dinfo *dip)
278
int status = SUCCESS;
280
if (dip->di_closing || (dip->di_fd == NoFd)) {
281
return (status); /* Closing or not open. */
284
* Avoid cancel'ing I/O more than once using the closing flag.
285
* We can get called again by alarm expiring or signal handler.
287
dip->di_closing = TRUE;
288
(void) dtaio_cancel (dip);
289
status = dtaio_waitall (dip, FALSE);
290
dip->di_closing = FALSE;
291
return (close_file (dip));
295
* Allocate and initialize AIO data structures.
298
dtaio_initialize (struct dinfo *dip)
301
size_t size = (sizeof(struct aiocb) * aio_bufs);
303
int status = SUCCESS;
307
* This check isn't being done, since when linked with libaio.a,
308
* AIO is mimiced via multiple threads to any device, not just
309
* character devices as with libaioraw.a
311
dtaio_checkdevice (dip);
314
if ( (dip->di_dtype->dt_dtype == DT_TAPE) && raw_flag && (aio_bufs > 1) ) {
315
Printf("Sorry, tapes are limited to 1 AIO with raw option!\n");
317
size = (sizeof(struct aiocb) * aio_bufs);
321
aio_offset = (off_t) 0;
323
acbs = (struct aiocb *) Malloc (size);
324
bzero ((char *) acbs, size);
326
size_t psize = (aio_bufs * sizeof(u_char *));
327
aiobufs = (u_char **) Malloc (psize);
328
bzero ((char *) aiobufs, psize);
331
for (index = 0, acbp = acbs; index < aio_bufs; index++, acbp++) {
332
if (acbp->aio_buf == NULL) {
333
acbp->aio_buf = myalloc (data_size, align_offset);
335
aiobufs[index] = (u_char *) acbp->aio_buf;
338
acbp->aio_fildes = AIO_NotQed;
339
acbp->aio_offset = (off_t) 0;
340
acbp->aio_nbytes = block_size;
341
acbp->aio_reqprio = AIO_PRIO_DFL; /* Set default priority. */
342
#if defined(SCO) || defined(HP_UX)
344
* Note: The AIO manual recommends setting AIO_RAW, but when
345
* this is set, EINVAL is returned by aio_read/aio_write!
348
acbp->aio_flags = 0; /* Must be zero to work! */
349
# endif /* defined(SCO) */
350
acbp->aio_sigevent.sigev_notify = SIGEV_NONE;
352
acbp->aio_flags = 0; /*AIO_RAW;*/ /* Required on SVR4.2(?) */
354
* This signaling method did not exist with the first release
355
* of POSIX AIO. Perhaps I'll add this completion method in
356
* a future release. Note: Tru64 Unix now supports this too!
358
acbp->aio_sigevent.sigev_signo = /* use with SIGEV_SIGNAL */;
359
acbp->aio_sigevent.sigev_notify = SIGEV_CALLBACK;
360
acbp->aio_sigevent.sigev_func = my_aio_completion_function;
361
acbp->aio_sigevent.sigev_value = acbp;
363
#endif /* defined(SCO) || defined(HP_UX) */
365
* Use first buffer allocated for initial skip reads, etc.
367
if (index == 0) data_buffer = (u_char *) acbp->aio_buf;
374
dtaio_checkdevice (struct dinfo *dip)
379
* Asynchronous I/O is for character devices *only*.
380
* [ Is this true for all operating systems? ]
382
if (fstat (dip->di_fd, &sb) == FAILURE) {
383
report_error("fstat", FALSE);
386
if (!S_ISCHR(sb.st_mode) ) {
387
LogMsg (efp, logLevelCrit, 0,
388
"'%s' is NOT a character device, cannot use asynchronous I/O.\n",
397
* Cancel outstanding I/O on the specified file descriptor.
400
dtaio_cancel (struct dinfo *dip)
405
* This is not a very useful operation on DEC OSF/1 at this time,
406
* since the drivers do *not* contain a cancel entry point.
407
* So... you cannot actually cancel outstanding I/O requests.
409
if ((status = aio_cancel (dip->di_fd, NULL)) == FAILURE) {
411
* aio_cancel() returns EBADF if we never issued any AIO!
413
if (errno != EBADF) {
414
report_error ("aio_cancel", TRUE);
423
Printf ("All requests completed before cancel...\n");
427
Printf ("Outstanding requests were canceled...\n");
430
case AIO_NOTCANCELED:
431
Fprintf ("Outstanding (active?) request NOT canceled...\n");
435
Fprintf ("Unexpected status of %d from aio_cancel()...\n", status);
443
dtaio_cancel_reads (struct dinfo *dip)
446
struct dtype *dtp = dip->di_dtype;
448
aio_data_adjust = aio_file_adjust = aio_record_adjust = 0L;
449
(void) dtaio_cancel (dip);
450
status = dtaio_waitall (dip, TRUE);
451
if (aio_file_adjust && (dtp->dt_dtype == DT_TAPE) ) {
452
daddr_t count = (daddr_t)aio_file_adjust;
454
* Tapes are tricky... we must backup prior to the
455
* last file(s) we processed, then forward space over
456
* its' file mark to be properly positioned (yuck!!!).
458
if (end_of_file) count++;
459
status = DoBackwardSpaceFile (dip, count);
460
if (status == SUCCESS) {
461
status = DoForwardSpaceFile (dip, (daddr_t) 1);
463
} else if (aio_record_adjust && (dtp->dt_dtype == DT_TAPE) ) {
465
* If we've read partially into the next file, backup.
467
status = DoBackwardSpaceFile (dip, (daddr_t) 1);
468
if (status == SUCCESS) {
469
status = DoForwardSpaceFile (dip, (daddr_t) 1);
478
dtaio_restart(struct dinfo *dip, struct aiocb *first_acbp)
480
struct aiocb *acbp = first_acbp;
482
ssize_t count, adjust;
483
int index, error, status = SUCCESS;
486
* Find starting index of this AIO request.
488
for (index = 0; index < aio_bufs; index++) {
489
if (first_acbp == &acbs[index]) break;
491
if (index == aio_bufs) abort(); /* Should NEVER happen! */
494
* Now, wait for and restart all previously active I/O's.
498
* Assumes the first request was already waited for!
501
Printf ("Restarting request for acbp at %#lx...\n", acbp);
503
if (dip->di_mode == READ_MODE) {
504
if ( (error = aio_read (acbp)) == FAILURE) {
505
acbp->aio_fildes = AIO_NotQed;
506
report_error ("aio_read", TRUE);
510
if ( (error = aio_write (acbp)) == FAILURE) {
511
acbp->aio_fildes = AIO_NotQed;
512
report_error ("aio_write", TRUE);
516
if (++index == aio_bufs) index = 0;
517
if (index == aio_index) break;
520
if (acbp->aio_fildes == AIO_NotQed) abort();
522
error = dtaio_wait (dip, acbp);
523
(void) aio_return (acbp);
530
#endif /* defined(EEI) */
533
dtaio_wait (struct dinfo *dip, struct aiocb *acbp)
538
Printf ("Waiting for acbp at %#lx to complete...\n", acbp);
541
* Loop waiting for an I/O request to complete.
543
while ((error = aio_error (acbp)) == EINPROGRESS) {
544
#if defined(POSIX_4D11)
545
if ((status = aio_suspend (1, (const struct aiocb **)&acbp)) == FAILURE) {
546
#else /* Beyond draft 11... */
547
if ((status = aio_suspend ((const struct aiocb **)&acbp,1,NULL)) == FAILURE) {
548
#endif /* defined(POSIX_4D11) */
549
if (errno != EINTR) {
550
report_error ("aio_suspend", TRUE);
555
if ( (error == FAILURE) && !terminating_flag) {
556
report_error ("aio_error", TRUE);
562
dtaio_waitall(struct dinfo *dip, bool canceling)
565
register size_t bsize;
566
register ssize_t count;
568
int index, error, status = SUCCESS;
571
* During EEI reset handling, don't touch the active requests,
572
* since dtaio_restart() needs this state to restart reqeusts.
574
if (dip->di_proc_eei) return (status);
576
* Loop waiting for all I/O requests to complete.
578
for (index = 0; index < aio_bufs; index++) {
579
acbp = &acbs[aio_index];
580
if (++aio_index == aio_bufs) aio_index = 0;
581
if (acbp->aio_fildes == AIO_NotQed) continue;
582
if ( (error = dtaio_wait (dip, acbp))) {
584
if (status == FAILURE) {
585
acbp->aio_fildes = AIO_NotQed;
586
continue; /* aio_error() failed! */
589
count = aio_return (acbp);
590
acbp->aio_fildes = AIO_NotQed;
592
if ( (count == FAILURE) && !dip->di_closing && !terminating_flag) {
594
* End of media is handled below.
596
#if defined(SCO) || defined(HP_UX)
597
if ( (error != ENOSPC) && (error != ENXIO) ) {
598
#else /* !defined(SCO) && !defined(HP_UX) */
599
if (error != ENOSPC) {
600
#endif /* defined(SCO) || defined(HP_UX) */
602
report_error ("aio_return", TRUE);
603
ReportDeviceInfo (dip, acbp->aio_nbytes, 0, (errno == EIO));
605
/* adjust counts below */
611
bsize = acbp->aio_nbytes;
614
* Adjust for short records or no data transferred.
616
if (count == FAILURE) {
617
aio_data_bytes -= bsize;
618
aio_file_bytes -= bsize;
619
} else if (adjust = (bsize - count)) {
621
Printf("Adjusting byte counts by %d bytes...\n", adjust);
623
aio_data_bytes -= adjust;
624
aio_file_bytes -= adjust;
628
* Count files or records to adjust after I/O's complete.
630
if ( is_Eof (dip, count, (int *) 0) ) {
631
if (!dip->di_end_of_media) aio_file_adjust++;
632
} else if (count > (ssize_t) 0) {
635
* Adjust counts for total statistics.
638
if (dip->di_mode == READ_MODE) {
639
dip->di_dbytes_read += count;
640
dip->di_fbytes_read += count;
642
dip->di_dbytes_written += count;
643
dip->di_fbytes_written += count;
645
aio_data_adjust += count;
646
if (count == bsize) {
658
* Function to wait for and process read requests.
661
dtaio_wait_reads (struct dinfo *dip)
664
int index, error, status = SUCCESS;
667
* Loop waiting for all I/O requests to complete.
669
for (index = 0; index < aio_bufs; index++) {
670
acbp = &acbs[aio_index];
671
if (++aio_index == aio_bufs) aio_index = 0;
672
if (acbp->aio_fildes == AIO_NotQed) continue;
674
if ( (error = dtaio_process_read (dip, acbp)) == FAILURE) {
678
(dip->di_records_read >= record_limit) || (dip->di_fbytes_read >= data_limit) ) {
686
* Function to wait for and process write requests.
689
dtaio_wait_writes (struct dinfo *dip)
692
int index, error, status = SUCCESS;
695
* Loop waiting for all I/O requests to complete.
697
for (index = 0; index < aio_bufs; index++) {
698
acbp = &acbs[aio_index];
699
if (++aio_index == aio_bufs) aio_index = 0;
700
if (acbp->aio_fildes == AIO_NotQed) continue;
702
if ( (error = dtaio_process_write (dip, acbp)) == FAILURE) {
704
if (error_count >= error_limit) break;
710
/************************************************************************
712
* dtaio_read_data() - Read and optionally verify data read. *
714
* Inputs: dip = The device information pointer. *
716
* Outputs: Returns SUCCESS/FAILURE = Ok/Error. *
718
************************************************************************/
720
dtaio_read_data (struct dinfo *dip)
722
register struct aiocb *acbp;
723
int error, status = SUCCESS;
724
register size_t bsize, dsize;
726
if (dip->di_random_access) {
727
if (io_dir == REVERSE) {
728
(void)set_position(dip, (off_t)rdata_limit);
730
aio_lba = get_lba(dip);
731
aio_offset = get_position(dip);
733
aio_offset = dip->di_offset;
734
aio_lba = make_lbdata (dip, aio_offset);
736
aio_data_bytes = aio_file_bytes = aio_record_count = 0;
739
* For variable length records, initialize to minimum record size.
743
dsize = get_variable (dip);
752
* Now read and optionally verify the input records.
754
while ( (error_count < error_limit) &&
755
(dip->di_fbytes_read < data_limit) &&
756
(dip->di_records_read < record_limit) ) {
758
if (volumes_flag && (multi_volume >= volume_limit) &&
759
(dip->di_volume_records >= volume_records)) {
760
dip->di_volume_records = volume_records;
765
* Two loops are used with AIO. The inner loop queues requests up
766
* to the requested amount, and the outer loop checks the actual
767
* data processed. This is done mainly for tapes to handle short
768
* reads & to efficiently handle multiple tape files.
770
while ( (error_count < error_limit) &&
771
(aio_record_count < record_limit) &&
772
(aio_file_bytes < data_limit) ) {
774
if (volumes_flag && (multi_volume >= volume_limit) &&
775
(dip->di_volume_records >= volume_records)) {
779
if (rdelay_count) { /* Optional read delay. */
780
mySleep (rdelay_count);
784
* If data limit was specified, ensure we don't exceed it.
786
if ( (aio_file_bytes + dsize) > data_limit) {
787
bsize = (data_limit - aio_file_bytes);
792
acbp = &acbs[aio_index];
794
* If requested, rotate the data buffer through ROTATE_SIZE bytes
795
* to force various unaligned buffer accesses.
798
data_buffer = aiobufs[aio_index];
799
data_buffer += (rotate_offset++ % ROTATE_SIZE);
800
acbp->aio_buf = data_buffer;
802
data_buffer = (u_char *) acbp->aio_buf;
805
acbp->aio_fildes = dip->di_fd;
807
if (io_dir == REVERSE) {
808
/*debug*/ if (!aio_offset) abort(); /*debug*/
809
bsize = MIN((aio_offset-file_position), bsize);
810
aio_offset = (off_t)(aio_offset - bsize);
813
if (debug_flag && (bsize != dsize) && !variable_flag) {
814
Printf ("Record #%lu, Reading a partial record of %lu bytes...\n",
815
(aio_record_count + 1), bsize);
818
acbp->aio_nbytes = bsize;
820
if (io_type == RANDOM_IO) {
821
acbp->aio_offset = do_random (dip, FALSE, bsize);
823
acbp->aio_offset = aio_offset;
827
* If we'll be doing a data compare after the read, then
828
* fill the data buffer with the inverted pattern to ensure
829
* the buffer actually gets written into (driver debug mostly).
831
if ((io_mode == TEST_MODE) && compare_flag) {
832
init_buffer (data_buffer, bsize, ~pattern);
833
init_padbytes (data_buffer, bsize, ~pattern);
837
u_int32 iolba = NO_LBA;
838
off_t iopos = (off_t) 0;
839
if (dip->di_random_access || lbdata_flag || iot_pattern) {
840
iopos = (dip->di_volume_bytes + acbp->aio_offset);
841
iolba = make_lbdata(dip, iopos);
843
report_record(dip, (dip->di_files_read + 1), (aio_record_count + 1),
844
iolba, iopos, READ_MODE, (void *)acbp->aio_buf, acbp->aio_nbytes);
846
if ( (error = aio_read (acbp)) == FAILURE) {
847
acbp->aio_fildes = AIO_NotQed;
848
report_error ("aio_read", TRUE);
853
* Must adjust record/data counts here to avoid writing
854
* too much data, even though the writes are incomplete.
856
aio_data_bytes += bsize;
857
aio_file_bytes += bsize;
860
if (io_dir == FORWARD) {
865
if (io_dir == FORWARD) {
866
aio_offset += step_offset;
867
} else if ((aio_offset -= step_offset) <= (off_t) file_position) {
868
aio_offset = (off_t) file_position;
873
* For variable length records, adjust the next record size.
877
dsize = get_variable (dip);
880
if (dsize > max_size) dsize = min_size;
885
* Always ensure the next control block has completed.
887
if (++aio_index == aio_bufs) aio_index = 0;
888
if ( (io_dir == REVERSE) && (aio_offset == (off_t) file_position) ) {
891
acbp = &acbs[aio_index];
892
if (acbp->aio_fildes == AIO_NotQed) continue; /* Never Q'ed. */
894
if ( (status = dtaio_process_read (dip, acbp)) == FAILURE) {
897
if ( end_of_file ) return (status);
900
* We get to this point after we've Q'ed enough requests to
901
* fulfill the requested record and/or data limit. We now
902
* wait for these Q'ed requests to complete, adjusting the
903
* global transfer statistics appropriately which reflects
904
* the actual data processed.
906
status = dtaio_wait_reads(dip);
907
if ( end_of_file ) break; /* Stop reading at end of file. */
912
/************************************************************************
914
* dtaio_process_read() - Process AIO reads & optionally verify data. *
917
* This function does waits for the requested AIO read request, *
918
* checks the completion status, and optionally verifies the data read. *
920
* Inputs: dip = The device information pointer. *
921
* acbp = The AIO control block. *
923
* Outputs: Returns SUCCESS/FAILURE/WARNING = Ok/Error/Warning. *
925
************************************************************************/
927
dtaio_process_read (struct dinfo *dip, struct aiocb *acbp)
929
struct dtfuncs *dtf = dip->di_funcs;
930
register size_t bsize, dsize;
931
register ssize_t count;
933
int error, status = SUCCESS;
939
error = dtaio_wait (dip, acbp);
940
count = aio_return (acbp);
943
if (dip->di_dtype->dt_dtype == DT_TAPE) {
944
if ( (errno == EIO) && eei_resets) {
945
if ( HandleTapeResets(dip) ) {
946
int error = dtaio_restart(dip, acbp);
947
if (error) return (error);
950
} else if (eei_flag) {
951
(void) get_eei_status(dip->di_fd, dip->di_mt);
954
#endif /* defined(EEI) */
956
acbp->aio_fildes = AIO_NotQed;
959
if (volumes_flag && (multi_volume >= volume_limit) &&
960
(dip->di_volume_records == volume_records)) {
964
if (count == FAILURE) {
966
* End of media is handled below.
968
#if defined(SCO) || defined(HP_UX)
969
if ( (error != ENOSPC) && (error != ENXIO) ) {
970
#else /* !defined(SCO) && !defined(HP_UX) */
971
if (error != ENOSPC) {
972
#endif /* defined(SCO) || defined(HP_UX) */
973
report_error ("aio_return", TRUE);
974
ReportDeviceInfo (dip, acbp->aio_nbytes, 0, (errno == EIO));
981
bsize = acbp->aio_nbytes;
982
data_buffer = (u_char *)acbp->aio_buf;
991
* Adjust for short records or no data transferred.
993
if (count == FAILURE) {
994
aio_data_bytes -= bsize;
995
aio_file_bytes -= bsize;
996
} else if (adjust = (bsize - count)) {
998
Printf("Adjusting byte counts by %d bytes...\n", adjust);
1000
aio_data_bytes -= adjust;
1001
aio_file_bytes -= adjust;
1005
* Process end of file/media conditions and handle multi-volume.
1007
if ( is_Eof (dip, count, &status) ) {
1009
if ( (dip->di_dtype->dt_dtype == DT_TAPE) &&
1010
!dip->di_end_of_logical ) {
1011
return (status); /* Expect two file marks @ EOM. */
1013
status = HandleMultiVolume (dip);
1014
aio_record_count = dip->di_records_read;
1015
/*aio_file_bytes = dip->di_dbytes_read;*/
1016
aio_offset = (off_t) 0;
1020
dip->di_end_of_file = FALSE; /* Reset saved end of file state. */
1021
if (count > (ssize_t) 0) {
1022
dip->di_dbytes_read += count;
1023
dip->di_fbytes_read += count;
1024
dip->di_vbytes_read += count;
1025
if (count == dsize) {
1026
records_processed++;
1030
dip->di_offset = (acbp->aio_offset + count);
1032
if ((status = check_read (dip, count, bsize)) == FAILURE) {
1033
if (error_count >= error_limit) return (status);
1034
} else if (io_mode == COPY_MODE) {
1035
status = copy_record (output_dinfo, data_buffer, count);
1036
if ( (error_count >= error_limit) || end_of_file) return (status);
1037
} else if (io_mode == VERIFY_MODE) {
1038
status = verify_record (output_dinfo, data_buffer, count);
1039
if ( (error_count >= error_limit) || end_of_file) return (status);
1044
* Verify the data (unless disabled).
1046
if ( (status != FAILURE) && compare_flag && (io_mode == TEST_MODE)) {
1047
ssize_t vsize = count;
1048
if (lbdata_flag || iot_pattern) {
1049
aio_lba = make_lbdata(dip, (dip->di_volume_bytes + acbp->aio_offset));
1051
aio_lba = init_iotdata (vsize, aio_lba, lbdata_size);
1054
status = (*dtf->tf_verify_data)(dip, data_buffer, vsize, pattern, &aio_lba);
1056
* Verify the pad bytes (if enabled).
1058
if ( (status == SUCCESS) && pad_check) {
1059
(void) verify_padbytes (dip, data_buffer, vsize, ~pattern, bsize);
1062
dip->di_records_read++;
1063
dip->di_volume_records++;
1065
if ( ((io_dir == REVERSE) && (acbp->aio_offset == (off_t) file_position)) ||
1066
(step_offset && ((acbp->aio_offset - step_offset) <= (off_t) file_position)) ) {
1072
/************************************************************************
1074
* dtaio_write_data() - Write specified data to the output file. *
1076
* Inputs: dip = The device information pointer. *
1078
* Outputs: Returns SUCCESS/FAILURE = Ok/Error. *
1080
************************************************************************/
1082
dtaio_write_data (struct dinfo *dip)
1084
register struct aiocb *acbp;
1085
int error, status = SUCCESS;
1086
register size_t bsize, dsize;
1087
u_int32 lba = lbdata_addr;
1089
if (dip->di_random_access) {
1090
if (io_dir == REVERSE) {
1091
(void)set_position(dip, (off_t)rdata_limit);
1093
aio_lba = lba = get_lba(dip);
1094
aio_offset = get_position(dip);
1096
aio_offset = dip->di_offset;
1097
aio_lba = lba = make_lbdata (dip, aio_offset);
1099
aio_data_bytes = aio_file_bytes = aio_record_count = 0;
1102
* For variable length records, initialize to minimum record size.
1105
if (variable_flag) {
1106
dsize = get_variable (dip);
1115
* Now write the specifed number of records.
1117
while ( (error_count < error_limit) &&
1118
(dip->di_fbytes_written < data_limit) &&
1119
(dip->di_records_written < record_limit) ) {
1121
if (volumes_flag && (multi_volume >= volume_limit) &&
1122
(dip->di_volume_records >= volume_records)) {
1123
dip->di_volume_records = volume_records;
1128
* Two loops are used with AIO. The inner loop queues requests up
1129
* tto the requested amount, and the outer loop checks the actual
1130
* data processed. This is done to handle short reads, which can
1131
* happen frequently with random I/O and large block sizes.
1133
while ( (error_count < error_limit) &&
1134
(aio_record_count < record_limit) &&
1135
(aio_file_bytes < data_limit) ) {
1137
if (volumes_flag && (multi_volume >= volume_limit) &&
1138
(dip->di_volume_records >= volume_records)) {
1142
if (wdelay_count) { /* Optional write delay */
1143
mySleep (wdelay_count);
1147
* If data limit was specified, ensure we don't exceed it.
1149
if ( (aio_file_bytes + dsize) > data_limit) {
1150
bsize = (data_limit - aio_file_bytes);
1155
acbp = &acbs[aio_index];
1157
* If requested, rotate the data buffer through ROTATE_SIZE bytes
1158
* to force various unaligned buffer accesses.
1161
data_buffer = aiobufs[aio_index];
1162
data_buffer += (rotate_offset++ % ROTATE_SIZE);
1163
acbp->aio_buf = data_buffer;
1165
data_buffer = (u_char *) acbp->aio_buf;
1168
acbp->aio_fildes = dip->di_fd;
1170
if (io_dir == REVERSE) {
1171
/*debug*/ if (!aio_offset) abort(); /*debug*/
1172
bsize = MIN((aio_offset-file_position), bsize);
1173
aio_offset = (off_t)(aio_offset - bsize);
1176
acbp->aio_nbytes = bsize;
1178
if (debug_flag && (bsize != dsize) && !variable_flag) {
1179
Printf ("Record #%lu, Writing a partial record of %d bytes...\n",
1180
(aio_record_count + 1), bsize);
1183
if (io_type == RANDOM_IO) {
1184
acbp->aio_offset = do_random (dip, FALSE, bsize);
1186
acbp->aio_offset = aio_offset;
1189
if (iot_pattern || lbdata_flag) {
1190
lba = make_lbdata (dip, (dip->di_volume_bytes + acbp->aio_offset));
1194
* Initialize the data buffer with a pattern.
1196
if ((io_mode == TEST_MODE) && compare_flag) {
1198
lba = init_iotdata(bsize, lba, lbdata_size);
1200
fill_buffer (data_buffer, bsize, pattern);
1204
* Initialize the logical block data (if enabled).
1206
if (lbdata_flag && lbdata_size && !iot_pattern) {
1207
lba = winit_lbdata (dip, (dip->di_volume_bytes + acbp->aio_offset),
1208
data_buffer, bsize, lba, lbdata_size);
1212
u_int32 iolba = NO_LBA;
1213
off_t iopos = (off_t) 0;
1214
if (dip->di_random_access || lbdata_flag || iot_pattern) {
1215
iopos = (dip->di_volume_bytes + acbp->aio_offset);
1216
iolba = make_lbdata(dip, iopos);
1218
report_record(dip, (dip->di_files_written + 1), (aio_record_count + 1),
1219
iolba, iopos, WRITE_MODE, (void *)acbp->aio_buf, acbp->aio_nbytes);
1222
if ( (error = aio_write (acbp)) == FAILURE) {
1223
acbp->aio_fildes = AIO_NotQed;
1224
report_error ("aio_write", TRUE);
1229
* Must adjust record/data counts here to avoid writing
1230
* too much data, even though the writes are incomplete.
1232
aio_data_bytes += bsize;
1233
aio_file_bytes += bsize;
1236
if (io_dir == FORWARD) {
1237
aio_offset += bsize;
1241
if (io_dir == FORWARD) {
1242
aio_offset += step_offset;
1243
} else if ((aio_offset -= step_offset) <= (off_t) file_position) {
1244
aio_offset = (off_t) file_position;
1249
* For variable length records, adjust the next record size.
1252
if (variable_flag) {
1253
dsize = get_variable (dip);
1255
dsize += incr_count;
1256
if (dsize > max_size) dsize = min_size;
1261
* Always ensure the next control block has completed.
1263
if (++aio_index == aio_bufs) aio_index = 0;
1264
if ( (io_dir == REVERSE) && (aio_offset == (off_t) file_position) ) {
1267
acbp = &acbs[aio_index];
1268
if (acbp->aio_fildes == AIO_NotQed) continue; /* Never Q'ed. */
1270
if ( (status = dtaio_process_write (dip, acbp)) == FAILURE) {
1273
if (end_of_file) break;
1276
* We get to this point after we've Q'ed enough requests to
1277
* fulfill the requested record and/or data limit. We now
1278
* wait for these Q'ed requests to complete, adjusting the
1279
* global transfer statistics appropriately which reflects
1280
* the actual data processed.
1282
status = dtaio_wait_writes(dip);
1283
if (end_of_file) break;
1288
/************************************************************************
1290
* dtaio_process_write() - Process AIO write requests. *
1293
* This function does waits for the requested AIO write request *
1294
* and checks the completion status. *
1296
* Inputs: dip = The device info pointer. *
1297
* acbp = The AIO control block. *
1299
* Outputs: Returns SUCCESS/FAILURE/WARNING = Ok/Error/Partial. *
1301
************************************************************************/
1303
dtaio_process_write (struct dinfo *dip, struct aiocb *acbp)
1305
register size_t bsize, dsize;
1306
register ssize_t count;
1308
int error, status = SUCCESS;
1314
error = dtaio_wait (dip, acbp);
1315
count = aio_return (acbp);
1318
if (dip->di_dtype->dt_dtype == DT_TAPE) {
1319
if ( (errno == EIO) && eei_resets) {
1320
if ( HandleTapeResets(dip) ) {
1321
dtaio_restart(dip, acbp);
1324
} else if (eei_flag) {
1325
(void) get_eei_status(dip->di_fd, dip->di_mt);
1328
#endif /* defined(EEI) */
1330
acbp->aio_fildes = AIO_NotQed;
1333
if (volumes_flag && (multi_volume >= volume_limit) &&
1334
(dip->di_volume_records == volume_records)) {
1338
if (count == FAILURE) {
1339
#if defined(SCO) || defined(HP_UX)
1340
if ( (error != ENOSPC) && (error != ENXIO) ) {
1341
#else /* !defined(SCO) && !defined(HP_UX) */
1342
if (error != ENOSPC) {
1343
#endif /* defined(SCO) || defined(HP_UX) */
1344
report_error ("aio_return", TRUE);
1345
ReportDeviceInfo (dip, acbp->aio_nbytes, 0, (errno == EIO));
1352
bsize = acbp->aio_nbytes;
1355
dsize = bsize; /* Can lead to wrong partial record count :-) */
1361
* Adjust for short records or no data transferred.
1363
if (count == FAILURE) {
1364
aio_data_bytes -= bsize;
1365
aio_file_bytes -= bsize;
1366
} else if (adjust = (bsize - count)) {
1367
aio_data_bytes -= adjust;
1368
aio_file_bytes -= adjust;
1371
if (count > (ssize_t) 0) {
1372
dip->di_dbytes_written += count;
1373
dip->di_fbytes_written += count;
1374
dip->di_vbytes_written += count;
1378
* Process end of file/media conditions and handle multi-volume.
1380
if ( is_Eof (dip, count, &status) ) {
1382
status = HandleMultiVolume (dip);
1383
aio_record_count = dip->di_records_written;
1384
/*aio_file_bytes = dip->di_dbytes_written;*/
1385
aio_offset = (off_t) 0;
1390
if (count > (ssize_t) 0) {
1391
if (count == dsize) {
1392
records_processed++;
1396
dip->di_offset = (acbp->aio_offset + count);
1398
if ((status = check_write (dip, count, bsize)) == FAILURE) {
1399
if (error_count >= error_limit) return (status);
1402
if ( (status != FAILURE) && raw_flag) {
1403
status = write_verify(dip, (u_char *)acbp->aio_buf, count, dsize, acbp->aio_offset);
1404
if ( (status == FAILURE) && (error_count >= error_limit) ) {
1408
dip->di_records_written++;
1409
dip->di_volume_records++;
1411
if ( ((io_dir == REVERSE) && (acbp->aio_offset == (off_t) file_position)) ||
1412
(step_offset && ((acbp->aio_offset - step_offset) <= (off_t) file_position)) ) {
1418
#endif /* defined(AIO) */