~cr3/+junk/dt

« back to all changes in this revision

Viewing changes to NonMsFiles/dtaio.c

  • Committer: Marc Tardif
  • Date: 2010-04-14 19:09:45 UTC
  • Revision ID: marc.tardif@canonical.com-20100414190945-op293hsog8niroma
Initial release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
 *                                                                          *
 
3
 *                        COPYRIGHT (c) 1990 - 2004                         *
 
4
 *                         This Software Provided                           *
 
5
 *                                   By                                     *
 
6
 *                        Robin's Nest Software Inc.                        *
 
7
 *                                                                          *
 
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.                              *
 
15
 *                                                                          *
 
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   *
 
22
 * THIS SOFTWARE.                                                           *
 
23
 *                                                                          *
 
24
 ****************************************************************************/
 
25
/*
 
26
 * Module:      dtaio.c
 
27
 * Author:      Robin T. Miller
 
28
 * Date:        August 26, 1993 
 
29
 *
 
30
 * Description:
 
31
 *      Functions to handle POSIX Asynchronous I/O requests for 'dt' program.
 
32
 */
 
33
 
 
34
#if defined(AIO)
 
35
 
 
36
#include "dt.h"
 
37
#include <aio.h>
 
38
#include <limits.h>
 
39
#include <sys/stat.h>
 
40
 
 
41
#if !defined(AIO_PRIO_DFL)
 
42
#  define AIO_PRIO_DFL  0               /* Default scheduling priority. */
 
43
#endif /* !defined(AIO_PRIO_DFL) */
 
44
 
 
45
/*
 
46
 * Modification History:
 
47
 *
 
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.
 
51
 *
 
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).
 
55
 *
 
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.
 
60
 *
 
61
 * January 17th, 2003 by Robin Miller.
 
62
 *      On HP-UX, accept ENXIO for I/O's pass EOF.
 
63
 *
 
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;
 
67
 *
 
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.
 
71
 *
 
72
 * January 26th, 2001 by Robin Miller.
 
73
 *      Added support for reverse reading and writing.
 
74
 *
 
75
 * January 24th, 2001 by Robin Miller.
 
76
 *      Add support for variable I/O requests sizes.
 
77
 *
 
78
 * January 14th, 2001 by Robin Miller.
 
79
 *      Added support for multiple volumes option.
 
80
 *      Fixed multi-volume write w/lbdata option problem.
 
81
 *
 
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.
 
85
 *
 
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!
 
89
 *
 
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.
 
94
 *
 
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.
 
98
 *
 
99
 * January 6th, 2000 by Robin Miller.
 
100
 *      Added support for multi-volume media.
 
101
 *      Added a couple missing aio_return() calls.
 
102
 *
 
103
 * December 30th, 1999 by Robin Miller.
 
104
 *      Modify call to do_random() to pass the transfer size.
 
105
 *
 
106
 * November 10th, 1999 by Robin Miller.
 
107
 *      If aio_return() fails, report device information.
 
108
 *
 
109
 * August 7th, 1999 by Robin Miller.
 
110
 *      Minor mods to support AIO on SCO UnixWare 7.1.
 
111
 *
 
112
 * July 29, 1999 by Robin Miller.
 
113
 *      Merge in changes made to compile on FreeBSD.
 
114
 *
 
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.
 
119
 * 
 
120
 * July 5th, 1999 by Robin Miller.
 
121
 *      Cleanup of compilation warnings on Linux.
 
122
 *
 
123
 * May 27, 1999 by Robin Miller.
 
124
 *      Added support for micro-second delays.
 
125
 *
 
126
 * March 1, 1999 by Robin Miller.
 
127
 *      For tapes when Debug is enabled, report the file number.
 
128
 *
 
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.
 
132
 *
 
133
 * December 21, 1998 by Robin Miller.
 
134
 *      Updates necessary to match tape API changes.
 
135
 *
 
136
 * November 16, 1998 by Robin Miller.
 
137
 *      Added pointer to current AIO control block for error reporting.
 
138
 *
 
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.
 
148
 *
 
149
 * March 20, 1998 by Robin Miller.
 
150
 *      Update counts in dtaio_waitall() for accurate statistics.
 
151
 *
 
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).
 
157
 *
 
158
 * January 9, 1998 by Robin Miller.
 
159
 *      Don't initialize data buffer being written for "disable=compare"
 
160
 * which yields better performance.
 
161
 *
 
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.
 
166
 *
 
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. ]
 
171
 *
 
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.:
 
176
 *
 
177
 *      % dt of=/dev/rmt0h min=10k max=64k incr=1 pattern=incr
 
178
 *
 
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. ]
 
183
 *
 
184
 * July 15, 1995 by Robin Miller.
 
185
 *      Fix end of media error handling (ENOSPC), and cleanup code.
 
186
 *
 
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. ]
 
190
 *
 
191
 * April 15, 1994 by Wayne Casagrande.
 
192
 *      Update aiosuspend() interface, which now takes different arguments
 
193
 * due to POSIX standard changing.
 
194
 *
 
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.
 
199
 *
 
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.
 
205
 */
 
206
 
 
207
/*
 
208
 * Forward References:
 
209
 */
 
210
#if 0
 
211
static void dtaio_checkdevice(struct dinfo *dip);
 
212
#endif
 
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);
 
219
 
 
220
#define AIO_BUFS        8               /* Default number of AIO buffers. */
 
221
#define AIO_NotQed      -1              /* AIO request not queued flag. */
 
222
 
 
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.   */
 
230
 
 
231
/*
 
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.
 
235
 */
 
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.  */
 
239
 
 
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. */
 
243
 
 
244
/*
 
245
 * Declare the POSIX Asynchronous I/O test functions.
 
246
 */
 
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,                              */
 
251
        init_file,              nofunc,
 
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
 
260
};
 
261
 
 
262
/************************************************************************
 
263
 *                                                                      *
 
264
 * dtaio_close_file() - Close an open file descriptor.                  *
 
265
 *                                                                      *
 
266
 * Description:                                                         *
 
267
 *      This function does the AIO file descriptor close processing.    *
 
268
 *                                                                      *
 
269
 * Inputs:      dip = The device information pointer.                   *
 
270
 *                                                                      *
 
271
 * Return Value:                                                        *
 
272
 *              Returns 0 / -1 = SUCCESS / FAILURE.                     *
 
273
 *                                                                      *
 
274
 ************************************************************************/
 
275
int
 
276
dtaio_close_file (struct dinfo *dip)
 
277
{
 
278
    int status = SUCCESS;
 
279
 
 
280
    if (dip->di_closing || (dip->di_fd == NoFd)) {
 
281
        return (status);                /* Closing or not open. */
 
282
    }
 
283
    /*
 
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.
 
286
     */
 
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));
 
292
}
 
293
 
 
294
/*
 
295
 * Allocate and initialize AIO data structures.
 
296
 */
 
297
int
 
298
dtaio_initialize (struct dinfo *dip)
 
299
{
 
300
    struct aiocb *acbp;
 
301
    size_t size = (sizeof(struct aiocb) * aio_bufs);
 
302
    int index;
 
303
    int status = SUCCESS;
 
304
 
 
305
#if 0
 
306
    /*
 
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
 
310
     */
 
311
    dtaio_checkdevice (dip);
 
312
#endif
 
313
 
 
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");
 
316
        aio_bufs = 1;
 
317
        size = (sizeof(struct aiocb) * aio_bufs);
 
318
    }
 
319
 
 
320
    aio_index = 0;
 
321
    aio_offset = (off_t) 0;
 
322
    if (acbs == NULL) {
 
323
        acbs = (struct aiocb *) Malloc (size);
 
324
        bzero ((char *) acbs, size);
 
325
        if (rotate_flag) {
 
326
            size_t psize = (aio_bufs * sizeof(u_char *));
 
327
            aiobufs = (u_char **) Malloc (psize);
 
328
            bzero ((char *) aiobufs, psize);
 
329
        }
 
330
    }
 
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);
 
334
            if (rotate_flag) {
 
335
                aiobufs[index] = (u_char *) acbp->aio_buf;
 
336
            }
 
337
        }
 
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)
 
343
        /*
 
344
         * Note: The AIO manual recommends setting AIO_RAW, but when
 
345
         *       this is set, EINVAL is returned by aio_read/aio_write!
 
346
         */
 
347
#  if defined(SCO)
 
348
        acbp->aio_flags = 0;                    /* Must be zero to work! */
 
349
#  endif /* defined(SCO) */
 
350
        acbp->aio_sigevent.sigev_notify = SIGEV_NONE;
 
351
#if 0
 
352
        acbp->aio_flags = 0; /*AIO_RAW;*/       /* Required on SVR4.2(?) */
 
353
        /*
 
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!
 
357
         */
 
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;
 
362
#endif
 
363
#endif /* defined(SCO) || defined(HP_UX) */
 
364
        /*
 
365
         * Use first buffer allocated for initial skip reads, etc.
 
366
         */
 
367
        if (index == 0) data_buffer = (u_char *) acbp->aio_buf;
 
368
    }
 
369
    return (status);
 
370
}
 
371
 
 
372
#if 0
 
373
static void
 
374
dtaio_checkdevice (struct dinfo *dip)
 
375
{
 
376
    struct stat sb;
 
377
 
 
378
    /*
 
379
     * Asynchronous I/O is for character devices *only*.
 
380
     *    [ Is this true for all operating systems? ]
 
381
     */
 
382
    if (fstat (dip->di_fd, &sb) == FAILURE) {
 
383
        report_error("fstat", FALSE);
 
384
        exit (FATAL_ERROR);
 
385
    }
 
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",
 
389
                                                                dip->di_dname);
 
390
        exit (FATAL_ERROR);
 
391
    }
 
392
    return;
 
393
}
 
394
#endif /* 0 */
 
395
 
 
396
/*
 
397
 * Cancel outstanding I/O on the specified file descriptor.
 
398
 */
 
399
int
 
400
dtaio_cancel (struct dinfo *dip)
 
401
{
 
402
    int status;
 
403
 
 
404
    /*
 
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.
 
408
     */
 
409
    if ((status = aio_cancel (dip->di_fd, NULL)) == FAILURE) {
 
410
        /*
 
411
         * aio_cancel() returns EBADF if we never issued any AIO!
 
412
         */
 
413
        if (errno != EBADF) {
 
414
            report_error ("aio_cancel", TRUE);
 
415
        }
 
416
        return (status);
 
417
    }
 
418
    if (debug_flag) {
 
419
 
 
420
        switch (status) {
 
421
 
 
422
            case AIO_ALLDONE:
 
423
                Printf ("All requests completed before cancel...\n");
 
424
                break;
 
425
 
 
426
            case AIO_CANCELED:
 
427
                Printf ("Outstanding requests were canceled...\n");
 
428
                break;
 
429
 
 
430
            case AIO_NOTCANCELED:
 
431
                Fprintf ("Outstanding (active?) request NOT canceled...\n");
 
432
                break;
 
433
 
 
434
            default:
 
435
                Fprintf ("Unexpected status of %d from aio_cancel()...\n", status);
 
436
                break;
 
437
        }
 
438
    }
 
439
    return (status);
 
440
}
 
441
 
 
442
int
 
443
dtaio_cancel_reads (struct dinfo *dip)
 
444
{
 
445
    int status;
 
446
    struct dtype *dtp = dip->di_dtype;
 
447
 
 
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;
 
453
        /*
 
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!!!).
 
457
         */
 
458
        if (end_of_file) count++;
 
459
        status = DoBackwardSpaceFile (dip, count);
 
460
        if (status == SUCCESS) {
 
461
            status = DoForwardSpaceFile (dip, (daddr_t) 1);
 
462
        }
 
463
    } else if (aio_record_adjust && (dtp->dt_dtype == DT_TAPE) ) {
 
464
        /*
 
465
         * If we've read partially into the next file, backup.
 
466
         */
 
467
        status = DoBackwardSpaceFile (dip, (daddr_t) 1);
 
468
        if (status == SUCCESS) {
 
469
            status = DoForwardSpaceFile (dip, (daddr_t) 1);
 
470
        }
 
471
    }
 
472
    return (status);
 
473
}
 
474
 
 
475
#if defined(EEI)
 
476
 
 
477
static int
 
478
dtaio_restart(struct dinfo *dip, struct aiocb *first_acbp)
 
479
{
 
480
    struct aiocb *acbp = first_acbp;
 
481
    size_t bsize;
 
482
    ssize_t count, adjust;
 
483
    int index, error, status = SUCCESS;
 
484
 
 
485
    /*
 
486
     * Find starting index of this AIO request.
 
487
     */
 
488
    for (index = 0; index < aio_bufs; index++) {
 
489
        if (first_acbp == &acbs[index]) break;
 
490
    }
 
491
    if (index == aio_bufs) abort(); /* Should NEVER happen! */
 
492
 
 
493
    /*
 
494
     * Now, wait for and restart all previously active I/O's.
 
495
     */
 
496
    do {
 
497
        /*
 
498
         * Assumes the first request was already waited for!
 
499
         */
 
500
        if (Debug_flag) {
 
501
            Printf ("Restarting request for acbp at %#lx...\n", acbp);
 
502
        }
 
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);
 
507
                return (error);
 
508
            }
 
509
        } else {
 
510
            if ( (error = aio_write (acbp)) == FAILURE) {
 
511
                acbp->aio_fildes = AIO_NotQed;
 
512
                report_error ("aio_write", TRUE);
 
513
                return (error);
 
514
            }
 
515
        }
 
516
        if (++index == aio_bufs) index = 0;
 
517
        if (index == aio_index) break;
 
518
 
 
519
        acbp = &acbs[index];
 
520
        if (acbp->aio_fildes == AIO_NotQed) abort();
 
521
 
 
522
        error = dtaio_wait (dip, acbp);
 
523
        (void) aio_return (acbp);
 
524
 
 
525
    } while (TRUE);
 
526
 
 
527
    return (status);
 
528
}
 
529
 
 
530
#endif /* defined(EEI) */
 
531
 
 
532
static int
 
533
dtaio_wait (struct dinfo *dip, struct aiocb *acbp)
 
534
{
 
535
    int error, status;
 
536
 
 
537
    if (Debug_flag) {
 
538
        Printf ("Waiting for acbp at %#lx to complete...\n", acbp);
 
539
    }
 
540
    /*
 
541
     * Loop waiting for an I/O request to complete.
 
542
     */
 
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);
 
551
                return (status);
 
552
            }
 
553
        }
 
554
    }
 
555
    if ( (error == FAILURE) && !terminating_flag) {
 
556
        report_error ("aio_error", TRUE);
 
557
    }
 
558
    return (error);
 
559
}
 
560
 
 
561
static int
 
562
dtaio_waitall(struct dinfo *dip, bool canceling)
 
563
{
 
564
    struct aiocb *acbp;
 
565
    register size_t bsize;
 
566
    register ssize_t count;
 
567
    ssize_t adjust;
 
568
    int index, error, status = SUCCESS;
 
569
 
 
570
    /*
 
571
     * During EEI reset handling, don't touch the active requests,
 
572
     * since dtaio_restart() needs this state to restart reqeusts.
 
573
     */
 
574
    if (dip->di_proc_eei) return (status);
 
575
    /*
 
576
     * Loop waiting for all I/O requests to complete.
 
577
     */
 
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))) {
 
583
            status = error;
 
584
            if (status == FAILURE) {
 
585
                acbp->aio_fildes = AIO_NotQed;
 
586
                continue;       /* aio_error() failed! */
 
587
            }
 
588
        }
 
589
        count = aio_return (acbp);
 
590
        acbp->aio_fildes = AIO_NotQed;
 
591
        errno = error;
 
592
        if ( (count == FAILURE) && !dip->di_closing && !terminating_flag) {
 
593
            /*
 
594
             * End of media is handled below.
 
595
             */
 
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) */
 
601
                current_acb = acbp;
 
602
                report_error ("aio_return", TRUE);
 
603
                ReportDeviceInfo (dip, acbp->aio_nbytes, 0, (errno == EIO));
 
604
                status = FAILURE;
 
605
                /* adjust counts below */
 
606
            }
 
607
        } else if (error) {
 
608
            count = FAILURE;
 
609
        }
 
610
 
 
611
        bsize = acbp->aio_nbytes;
 
612
 
 
613
        /*
 
614
         * Adjust for short records or no data transferred.
 
615
         */
 
616
        if (count == FAILURE) {
 
617
            aio_data_bytes -= bsize;
 
618
            aio_file_bytes -= bsize;
 
619
        } else if (adjust = (bsize - count)) {
 
620
            if (debug_flag) {
 
621
                Printf("Adjusting byte counts by %d bytes...\n", adjust);
 
622
            }
 
623
            aio_data_bytes -= adjust;
 
624
            aio_file_bytes -= adjust;
 
625
        }
 
626
 
 
627
        /*
 
628
         * Count files or records to adjust after I/O's complete.
 
629
         */
 
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) {
 
633
            aio_record_adjust++;
 
634
            /*
 
635
             * Adjust counts for total statistics.
 
636
             */
 
637
            if (!canceling) {
 
638
                if (dip->di_mode == READ_MODE) {
 
639
                    dip->di_dbytes_read += count;
 
640
                    dip->di_fbytes_read += count;
 
641
                } else {
 
642
                    dip->di_dbytes_written += count;
 
643
                    dip->di_fbytes_written += count;
 
644
                }
 
645
                aio_data_adjust += count;
 
646
                if (count == bsize) {
 
647
                    records_processed++;
 
648
                } else {
 
649
                    partial_records++;
 
650
                }
 
651
            }
 
652
        }
 
653
    }
 
654
    return (status);
 
655
}
 
656
 
 
657
/*
 
658
 * Function to wait for and process read requests.
 
659
 */
 
660
static int
 
661
dtaio_wait_reads (struct dinfo *dip)
 
662
{
 
663
    struct aiocb *acbp;
 
664
    int index, error, status = SUCCESS;
 
665
 
 
666
    /*
 
667
     * Loop waiting for all I/O requests to complete.
 
668
     */
 
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;
 
673
        
 
674
        if ( (error = dtaio_process_read (dip, acbp)) == FAILURE) {
 
675
            status = error;
 
676
        }
 
677
        if ( end_of_file ||
 
678
             (dip->di_records_read >= record_limit) || (dip->di_fbytes_read >= data_limit) ) {
 
679
            break;
 
680
        }
 
681
    }
 
682
    return (status);
 
683
}
 
684
 
 
685
/*
 
686
 * Function to wait for and process write requests.
 
687
 */
 
688
static int
 
689
dtaio_wait_writes (struct dinfo *dip)
 
690
{
 
691
    struct aiocb *acbp;
 
692
    int index, error, status = SUCCESS;
 
693
 
 
694
    /*
 
695
     * Loop waiting for all I/O requests to complete.
 
696
     */
 
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;
 
701
        
 
702
        if ( (error = dtaio_process_write (dip, acbp)) == FAILURE) {
 
703
            status = error;
 
704
            if (error_count >= error_limit) break;
 
705
        }
 
706
    }
 
707
    return (status);
 
708
}
 
709
 
 
710
/************************************************************************
 
711
 *                                                                      *
 
712
 * dtaio_read_data() - Read and optionally verify data read.            *
 
713
 *                                                                      *
 
714
 * Inputs:      dip = The device information pointer.                   *
 
715
 *                                                                      *
 
716
 * Outputs:     Returns SUCCESS/FAILURE = Ok/Error.                     *
 
717
 *                                                                      *
 
718
 ************************************************************************/
 
719
int
 
720
dtaio_read_data (struct dinfo *dip)
 
721
{
 
722
    register struct aiocb *acbp;
 
723
    int error, status = SUCCESS;
 
724
    register size_t bsize, dsize;
 
725
 
 
726
    if (dip->di_random_access) {
 
727
        if (io_dir == REVERSE) {
 
728
            (void)set_position(dip, (off_t)rdata_limit);
 
729
        }
 
730
        aio_lba = get_lba(dip);
 
731
        aio_offset = get_position(dip);
 
732
    } else {
 
733
        aio_offset = dip->di_offset;
 
734
        aio_lba = make_lbdata (dip, aio_offset);
 
735
    }
 
736
    aio_data_bytes = aio_file_bytes = aio_record_count = 0;
 
737
 
 
738
    /*
 
739
     * For variable length records, initialize to minimum record size.
 
740
     */
 
741
    if (min_size) {
 
742
        if (variable_flag) {
 
743
            dsize = get_variable (dip);
 
744
        } else {
 
745
            dsize = min_size;
 
746
        }
 
747
    } else {
 
748
        dsize = block_size;
 
749
    }
 
750
 
 
751
    /*
 
752
     * Now read and optionally verify the input records.
 
753
     */
 
754
    while ( (error_count < error_limit) &&
 
755
            (dip->di_fbytes_read < data_limit) &&
 
756
            (dip->di_records_read < record_limit) ) {
 
757
 
 
758
        if (volumes_flag && (multi_volume >= volume_limit) &&
 
759
                  (dip->di_volume_records >= volume_records)) {
 
760
            dip->di_volume_records = volume_records;
 
761
            break;
 
762
        }
 
763
 
 
764
        /*
 
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.
 
769
         */
 
770
        while ( (error_count < error_limit) &&
 
771
                (aio_record_count < record_limit) &&
 
772
                (aio_file_bytes < data_limit) ) {
 
773
 
 
774
            if (volumes_flag && (multi_volume >= volume_limit) &&
 
775
                      (dip->di_volume_records >= volume_records)) {
 
776
                break;
 
777
            }
 
778
 
 
779
            if (rdelay_count) {                 /* Optional read delay. */
 
780
                mySleep (rdelay_count);
 
781
            }
 
782
 
 
783
            /*
 
784
             * If data limit was specified, ensure we don't exceed it.
 
785
             */
 
786
            if ( (aio_file_bytes + dsize) > data_limit) {
 
787
                bsize = (data_limit - aio_file_bytes);
 
788
            } else {
 
789
                bsize = dsize;
 
790
            }
 
791
 
 
792
            acbp = &acbs[aio_index];
 
793
            /*
 
794
             * If requested, rotate the data buffer through ROTATE_SIZE bytes
 
795
             * to force various unaligned buffer accesses.
 
796
             */
 
797
            if (rotate_flag) {
 
798
                data_buffer = aiobufs[aio_index];
 
799
                data_buffer += (rotate_offset++ % ROTATE_SIZE);
 
800
                acbp->aio_buf = data_buffer;
 
801
            } else {
 
802
                data_buffer = (u_char *) acbp->aio_buf;
 
803
            }
 
804
 
 
805
            acbp->aio_fildes = dip->di_fd;
 
806
 
 
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);
 
811
            }
 
812
 
 
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);
 
816
            }
 
817
 
 
818
            acbp->aio_nbytes = bsize;
 
819
 
 
820
            if (io_type == RANDOM_IO) {
 
821
                acbp->aio_offset = do_random (dip, FALSE, bsize);
 
822
            } else {
 
823
                acbp->aio_offset = aio_offset;
 
824
            }
 
825
 
 
826
            /*
 
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).
 
830
             */
 
831
            if ((io_mode == TEST_MODE) && compare_flag) {
 
832
                init_buffer (data_buffer, bsize, ~pattern);
 
833
                init_padbytes (data_buffer, bsize, ~pattern);
 
834
            }
 
835
 
 
836
            if (Debug_flag) {
 
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);
 
842
                }
 
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);
 
845
            }
 
846
            if ( (error = aio_read (acbp)) == FAILURE) {
 
847
                acbp->aio_fildes = AIO_NotQed;
 
848
                report_error ("aio_read", TRUE);
 
849
                return (error);
 
850
            }
 
851
 
 
852
            /*
 
853
             * Must adjust record/data counts here to avoid writing
 
854
             * too much data, even though the writes are incomplete.
 
855
             */
 
856
            aio_data_bytes += bsize;
 
857
            aio_file_bytes += bsize;
 
858
            aio_record_count++;
 
859
 
 
860
            if (io_dir == FORWARD) {
 
861
                aio_offset += bsize;
 
862
            }
 
863
 
 
864
            if (step_offset) {
 
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;
 
869
                }
 
870
            }
 
871
 
 
872
            /*
 
873
             * For variable length records, adjust the next record size.
 
874
             */
 
875
            if (min_size) {
 
876
                if (variable_flag) {
 
877
                    dsize = get_variable (dip);
 
878
                } else {
 
879
                    dsize += incr_count;
 
880
                    if (dsize > max_size) dsize = min_size;
 
881
                }
 
882
            }
 
883
 
 
884
            /*
 
885
             * Always ensure the next control block has completed.
 
886
             */
 
887
            if (++aio_index == aio_bufs) aio_index = 0;
 
888
            if ( (io_dir == REVERSE) && (aio_offset == (off_t) file_position) ) {
 
889
                break;
 
890
            }
 
891
            acbp = &acbs[aio_index];
 
892
            if (acbp->aio_fildes == AIO_NotQed) continue; /* Never Q'ed. */
 
893
 
 
894
            if ( (status = dtaio_process_read (dip, acbp)) == FAILURE) {
 
895
                return (status);
 
896
            }
 
897
            if ( end_of_file ) return (status);
 
898
        }
 
899
        /*
 
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.
 
905
         */
 
906
        status = dtaio_wait_reads(dip);
 
907
        if ( end_of_file ) break;       /* Stop reading at end of file. */
 
908
    }
 
909
    return (status);
 
910
}
 
911
 
 
912
/************************************************************************
 
913
 *                                                                      *
 
914
 * dtaio_process_read() - Process AIO reads & optionally verify data.   *
 
915
 *                                                                      *
 
916
 * Description:                                                         *
 
917
 *      This function does waits for the requested AIO read request,    *
 
918
 * checks the completion status, and optionally verifies the data read. *
 
919
 *                                                                      *
 
920
 * Inputs:      dip = The device information pointer.                   *
 
921
 *              acbp = The AIO control block.                           *
 
922
 *                                                                      *
 
923
 * Outputs:     Returns SUCCESS/FAILURE/WARNING = Ok/Error/Warning.     *
 
924
 *                                                                      *
 
925
 ************************************************************************/
 
926
static int
 
927
dtaio_process_read (struct dinfo *dip, struct aiocb *acbp)
 
928
{
 
929
    struct dtfuncs *dtf = dip->di_funcs;
 
930
    register size_t bsize, dsize;
 
931
    register ssize_t count;
 
932
    ssize_t adjust;
 
933
    int error, status = SUCCESS;
 
934
 
 
935
#if defined(EEI)
 
936
retry:
 
937
#endif
 
938
    current_acb = acbp;
 
939
    error = dtaio_wait (dip, acbp);
 
940
    count = aio_return (acbp);
 
941
 
 
942
#if defined(EEI)
 
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);
 
948
                goto retry;
 
949
            }
 
950
        } else if (eei_flag) {
 
951
            (void) get_eei_status(dip->di_fd, dip->di_mt);
 
952
        }
 
953
    }
 
954
#endif /* defined(EEI) */
 
955
 
 
956
    acbp->aio_fildes = AIO_NotQed;
 
957
    errno = error;
 
958
 
 
959
    if (volumes_flag && (multi_volume >= volume_limit) &&
 
960
              (dip->di_volume_records == volume_records)) {
 
961
        return (SUCCESS);
 
962
    }
 
963
 
 
964
    if (count == FAILURE) {
 
965
        /*
 
966
         * End of media is handled below.
 
967
         */
 
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));
 
975
            return (FAILURE);
 
976
        }
 
977
    } else if (error) {
 
978
        count = FAILURE;
 
979
    }
 
980
 
 
981
    bsize = acbp->aio_nbytes;
 
982
    data_buffer = (u_char *)acbp->aio_buf;
 
983
 
 
984
    if (min_size) {
 
985
        dsize = bsize;
 
986
    } else {
 
987
        dsize = block_size;
 
988
    }
 
989
 
 
990
    /*
 
991
     * Adjust for short records or no data transferred.
 
992
     */
 
993
    if (count == FAILURE) {
 
994
        aio_data_bytes -= bsize;
 
995
        aio_file_bytes -= bsize;
 
996
    } else if (adjust = (bsize - count)) {
 
997
        if (debug_flag) {
 
998
            Printf("Adjusting byte counts by %d bytes...\n", adjust);
 
999
        }
 
1000
        aio_data_bytes -= adjust;
 
1001
        aio_file_bytes -= adjust;
 
1002
    }
 
1003
 
 
1004
    /*
 
1005
     * Process end of file/media conditions and handle multi-volume.
 
1006
     */
 
1007
    if ( is_Eof (dip, count, &status) ) {
 
1008
        if (multi_flag) {
 
1009
            if ( (dip->di_dtype->dt_dtype == DT_TAPE) &&
 
1010
                 !dip->di_end_of_logical ) {
 
1011
                return (status);        /* Expect two file marks @ EOM. */
 
1012
            }
 
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;
 
1017
        }
 
1018
        return (status);
 
1019
    } else {
 
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++;
 
1027
            } else {
 
1028
                partial_records++;
 
1029
            }
 
1030
            dip->di_offset = (acbp->aio_offset + count);
 
1031
        }
 
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);
 
1040
        }
 
1041
    }
 
1042
 
 
1043
    /*
 
1044
     * Verify the data (unless disabled).
 
1045
     */
 
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));
 
1050
            if (iot_pattern) {
 
1051
                aio_lba = init_iotdata (vsize, aio_lba, lbdata_size);
 
1052
            }
 
1053
        }
 
1054
        status = (*dtf->tf_verify_data)(dip, data_buffer, vsize, pattern, &aio_lba);
 
1055
        /*
 
1056
         * Verify the pad bytes (if enabled).
 
1057
         */
 
1058
        if ( (status == SUCCESS) && pad_check) {
 
1059
            (void) verify_padbytes (dip, data_buffer, vsize, ~pattern, bsize);
 
1060
        }
 
1061
    }
 
1062
    dip->di_records_read++;
 
1063
    dip->di_volume_records++;
 
1064
 
 
1065
    if ( ((io_dir == REVERSE) && (acbp->aio_offset == (off_t) file_position)) ||
 
1066
         (step_offset && ((acbp->aio_offset - step_offset) <= (off_t) file_position)) ) {
 
1067
        set_Eof(dip);
 
1068
    }
 
1069
    return (status);
 
1070
}
 
1071
 
 
1072
/************************************************************************
 
1073
 *                                                                      *
 
1074
 * dtaio_write_data() - Write specified data to the output file.        *
 
1075
 *                                                                      *
 
1076
 * Inputs:      dip = The device information pointer.                   *
 
1077
 *                                                                      *
 
1078
 * Outputs:     Returns SUCCESS/FAILURE = Ok/Error.                     *
 
1079
 *                                                                      *
 
1080
 ************************************************************************/
 
1081
int
 
1082
dtaio_write_data (struct dinfo *dip)
 
1083
{
 
1084
    register struct aiocb *acbp;
 
1085
    int error, status = SUCCESS;
 
1086
    register size_t bsize, dsize;
 
1087
    u_int32 lba = lbdata_addr;
 
1088
 
 
1089
    if (dip->di_random_access) {
 
1090
        if (io_dir == REVERSE) {
 
1091
            (void)set_position(dip, (off_t)rdata_limit);
 
1092
        }
 
1093
        aio_lba = lba = get_lba(dip);
 
1094
        aio_offset = get_position(dip);
 
1095
    } else {
 
1096
        aio_offset = dip->di_offset;
 
1097
        aio_lba = lba = make_lbdata (dip, aio_offset);
 
1098
    }
 
1099
    aio_data_bytes = aio_file_bytes = aio_record_count = 0;
 
1100
 
 
1101
    /*
 
1102
     * For variable length records, initialize to minimum record size.
 
1103
     */
 
1104
    if (min_size) {
 
1105
        if (variable_flag) {
 
1106
            dsize = get_variable (dip);
 
1107
        } else {
 
1108
            dsize = min_size;
 
1109
        }
 
1110
    } else {
 
1111
        dsize = block_size;
 
1112
    }
 
1113
 
 
1114
    /*
 
1115
     * Now write the specifed number of records.
 
1116
     */
 
1117
    while ( (error_count < error_limit) &&
 
1118
            (dip->di_fbytes_written < data_limit) &&
 
1119
            (dip->di_records_written < record_limit) ) {
 
1120
 
 
1121
        if (volumes_flag && (multi_volume >= volume_limit) &&
 
1122
                  (dip->di_volume_records >= volume_records)) {
 
1123
            dip->di_volume_records = volume_records;
 
1124
            break;
 
1125
        }
 
1126
 
 
1127
        /*
 
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.
 
1132
         */
 
1133
        while ( (error_count < error_limit) &&
 
1134
                (aio_record_count < record_limit) &&
 
1135
                (aio_file_bytes < data_limit) ) {
 
1136
 
 
1137
            if (volumes_flag && (multi_volume >= volume_limit) &&
 
1138
                      (dip->di_volume_records >= volume_records)) {
 
1139
                break;
 
1140
            }
 
1141
 
 
1142
            if (wdelay_count) {                 /* Optional write delay */
 
1143
                mySleep (wdelay_count);
 
1144
            }
 
1145
 
 
1146
            /*
 
1147
             * If data limit was specified, ensure we don't exceed it.
 
1148
             */
 
1149
            if ( (aio_file_bytes + dsize) > data_limit) {
 
1150
                bsize = (data_limit - aio_file_bytes);
 
1151
            } else {
 
1152
                bsize = dsize;
 
1153
            }
 
1154
 
 
1155
            acbp = &acbs[aio_index];
 
1156
            /*
 
1157
             * If requested, rotate the data buffer through ROTATE_SIZE bytes
 
1158
             * to force various unaligned buffer accesses.
 
1159
             */
 
1160
            if (rotate_flag) {
 
1161
                data_buffer = aiobufs[aio_index];
 
1162
                data_buffer += (rotate_offset++ % ROTATE_SIZE);
 
1163
                acbp->aio_buf = data_buffer;
 
1164
            } else {
 
1165
                data_buffer = (u_char *) acbp->aio_buf;
 
1166
            }
 
1167
 
 
1168
            acbp->aio_fildes = dip->di_fd;
 
1169
 
 
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);
 
1174
            }
 
1175
 
 
1176
            acbp->aio_nbytes = bsize;
 
1177
 
 
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);
 
1181
            }
 
1182
 
 
1183
            if (io_type == RANDOM_IO) {
 
1184
                acbp->aio_offset = do_random (dip, FALSE, bsize);
 
1185
            } else {
 
1186
                acbp->aio_offset = aio_offset;
 
1187
            }
 
1188
 
 
1189
            if (iot_pattern || lbdata_flag) {
 
1190
                lba = make_lbdata (dip, (dip->di_volume_bytes + acbp->aio_offset));
 
1191
            }
 
1192
 
 
1193
            /*
 
1194
             * Initialize the data buffer with a pattern.
 
1195
             */
 
1196
            if ((io_mode == TEST_MODE) && compare_flag) {
 
1197
                if (iot_pattern) {
 
1198
                    lba = init_iotdata(bsize, lba, lbdata_size);
 
1199
                }
 
1200
                fill_buffer (data_buffer, bsize, pattern);
 
1201
            }
 
1202
 
 
1203
            /*
 
1204
             * Initialize the logical block data (if enabled).
 
1205
             */
 
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);
 
1209
            }
 
1210
 
 
1211
            if (Debug_flag) {
 
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);
 
1217
                }
 
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);
 
1220
            }
 
1221
 
 
1222
            if ( (error = aio_write (acbp)) == FAILURE) {
 
1223
                acbp->aio_fildes = AIO_NotQed;
 
1224
                report_error ("aio_write", TRUE);
 
1225
                return (error);
 
1226
            }
 
1227
 
 
1228
            /*
 
1229
             * Must adjust record/data counts here to avoid writing
 
1230
             * too much data, even though the writes are incomplete.
 
1231
             */
 
1232
            aio_data_bytes += bsize;
 
1233
            aio_file_bytes += bsize;
 
1234
            aio_record_count++;
 
1235
 
 
1236
            if (io_dir == FORWARD) {
 
1237
                aio_offset += bsize;
 
1238
            } 
 
1239
 
 
1240
            if (step_offset) {
 
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;
 
1245
                }
 
1246
            }
 
1247
 
 
1248
            /*
 
1249
             * For variable length records, adjust the next record size.
 
1250
             */
 
1251
            if (min_size) {
 
1252
                if (variable_flag) {
 
1253
                    dsize = get_variable (dip);
 
1254
                } else {
 
1255
                    dsize += incr_count;
 
1256
                    if (dsize > max_size) dsize = min_size;
 
1257
                }
 
1258
            }
 
1259
 
 
1260
            /*
 
1261
             * Always ensure the next control block has completed.
 
1262
             */
 
1263
            if (++aio_index == aio_bufs) aio_index = 0;
 
1264
            if ( (io_dir == REVERSE) && (aio_offset == (off_t) file_position) ) {
 
1265
                break;
 
1266
            }
 
1267
            acbp = &acbs[aio_index];
 
1268
            if (acbp->aio_fildes == AIO_NotQed) continue; /* Never Q'ed. */
 
1269
 
 
1270
            if ( (status = dtaio_process_write (dip, acbp)) == FAILURE) {
 
1271
                return (status);
 
1272
            }
 
1273
            if (end_of_file) break;
 
1274
        }
 
1275
        /*
 
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.
 
1281
         */
 
1282
        status = dtaio_wait_writes(dip);
 
1283
        if (end_of_file) break;
 
1284
    }
 
1285
    return (status);
 
1286
}
 
1287
 
 
1288
/************************************************************************
 
1289
 *                                                                      *
 
1290
 * dtaio_process_write() - Process AIO write requests.                  *
 
1291
 *                                                                      *
 
1292
 * Description:                                                         *
 
1293
 *      This function does waits for the requested AIO write request    *
 
1294
 * and checks the completion status.                                    *
 
1295
 *                                                                      *
 
1296
 * Inputs:      dip = The device info pointer.                          *
 
1297
 *              acbp = The AIO control block.                           *
 
1298
 *                                                                      *
 
1299
 * Outputs:     Returns SUCCESS/FAILURE/WARNING = Ok/Error/Partial.     *
 
1300
 *                                                                      *
 
1301
 ************************************************************************/
 
1302
static int
 
1303
dtaio_process_write (struct dinfo *dip, struct aiocb *acbp)
 
1304
{
 
1305
    register size_t bsize, dsize;
 
1306
    register ssize_t count;
 
1307
    ssize_t adjust;
 
1308
    int error, status = SUCCESS;
 
1309
 
 
1310
#if defined(EEI)
 
1311
retry:
 
1312
#endif
 
1313
    current_acb = acbp;
 
1314
    error = dtaio_wait (dip, acbp);
 
1315
    count = aio_return (acbp);
 
1316
 
 
1317
#if defined(EEI)
 
1318
    if (dip->di_dtype->dt_dtype == DT_TAPE) {
 
1319
        if ( (errno == EIO) && eei_resets) {
 
1320
            if ( HandleTapeResets(dip) ) {
 
1321
                dtaio_restart(dip, acbp);
 
1322
                goto retry;
 
1323
            }
 
1324
        } else if (eei_flag) {
 
1325
            (void) get_eei_status(dip->di_fd, dip->di_mt);
 
1326
        }
 
1327
    }
 
1328
#endif /* defined(EEI) */
 
1329
 
 
1330
    acbp->aio_fildes = AIO_NotQed;
 
1331
    errno = error;
 
1332
 
 
1333
    if (volumes_flag && (multi_volume >= volume_limit) &&
 
1334
              (dip->di_volume_records == volume_records)) {
 
1335
        return (SUCCESS);
 
1336
    }
 
1337
 
 
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));
 
1346
            return (FAILURE);
 
1347
        }
 
1348
    } else if (error) {
 
1349
        count = FAILURE;
 
1350
    }
 
1351
 
 
1352
    bsize = acbp->aio_nbytes;
 
1353
 
 
1354
    if (min_size) {
 
1355
        dsize = bsize;  /* Can lead to wrong partial record count :-) */
 
1356
    } else {
 
1357
        dsize = block_size;
 
1358
    }
 
1359
 
 
1360
    /*
 
1361
     * Adjust for short records or no data transferred.
 
1362
     */
 
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;
 
1369
    }
 
1370
 
 
1371
    if (count > (ssize_t) 0) {
 
1372
        dip->di_dbytes_written += count;
 
1373
        dip->di_fbytes_written += count;
 
1374
        dip->di_vbytes_written += count;
 
1375
    }
 
1376
 
 
1377
    /*
 
1378
     * Process end of file/media conditions and handle multi-volume.
 
1379
     */
 
1380
    if ( is_Eof (dip, count, &status) ) {
 
1381
        if (multi_flag) {
 
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;
 
1386
        }
 
1387
        return (status);
 
1388
    }
 
1389
 
 
1390
    if (count > (ssize_t) 0) {
 
1391
        if (count == dsize) {
 
1392
            records_processed++;
 
1393
        } else {
 
1394
            partial_records++;
 
1395
        }
 
1396
        dip->di_offset = (acbp->aio_offset + count);
 
1397
    }
 
1398
    if ((status = check_write (dip, count, bsize)) == FAILURE) {
 
1399
        if (error_count >= error_limit) return (status);
 
1400
    }
 
1401
 
 
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) ) {
 
1405
            return (status);
 
1406
        }
 
1407
    }
 
1408
    dip->di_records_written++;
 
1409
    dip->di_volume_records++;
 
1410
 
 
1411
    if ( ((io_dir == REVERSE) && (acbp->aio_offset == (off_t) file_position)) ||
 
1412
         (step_offset && ((acbp->aio_offset - step_offset) <= (off_t) file_position)) ) {
 
1413
        set_Eof(dip);
 
1414
    }
 
1415
    return (status);
 
1416
}
 
1417
 
 
1418
#endif /* defined(AIO) */