2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
36 * This file contains several functions to doing reads and writes.
37 * It was written so that a single function could be called in a test
38 * program and only a io type field value would have to change to
39 * do different types of io. There is even a couple of functions that
40 * will allow you to parse a string to determine the iotype.
42 * This file contains functions for writing/reading to/from open files
45 * Functions declared in this module - see individual function code for
48 * int stride_bounds(int offset, int stride, int nstrides,
49 * int bytes_per_stride, int *min, int *max);
51 * int lio_write_buffer(int fd, int method, char *buffer, int size,
52 * char **errmsg, long wrd);
53 * int lio_read_buffer(int fd, int method, char *buffer, int size,
54 * char **errmsg, long wrd);
57 * int lio_wait4asyncio(int method, int fd, struct iosw **statptr)
58 * int lio_check_asyncio(char *io_type, int size, struct iosw *status)
61 * int lio_wait4asyncio(int method, int fd, aiocb_t *aiocbp)
62 * int lio_check_asyncio(char *io_type, int size, aiocb_t *aiocbp, int method)
65 * int lio_parse_io_arg1(char *string)
66 * void lio_help1(char *prefix);
68 * int lio_parse_io_arg2(char *string, char **badtoken)
69 * void lio_help2(char *prefix);
71 * int lio_set_debug(int level);
74 * struct lio_info_type Lio_info1[];
75 * struct lio_info_type Lio_info2[];
77 * Author : Richard Logan
83 #define _LARGEFILE64_SOURCE
89 #include <sys/types.h>
92 #include <sys/param.h>
94 #include <sys/types.h>
99 #include <sys/secparm.h>
100 #include <sys/iosw.h>
101 #include <sys/listio.h>
103 /* for linux or sgi */
104 #include <sys/uio.h> /* readv(2)/writev(2) */
105 #include <string.h> /* bzero */
107 #if defined(__linux__) || defined(__sun) || defined(__hpux) || defined(_AIX)
108 #if !defined(UCLINUX) && !defined(__UCLIBC__)
112 #include <stdlib.h> /* atoi, abs */
114 #include "tlibio.h" /* defines LIO* marcos */
117 #define PATH_MAX MAXPATHLEN
120 #if 0 /* disabled until it's needed -- roehrich 6/11/97 */
121 #define BUG1_workaround 1 /* Work around a condition where aio_return gives
122 * a value of zero but there is no errno followup
123 * and the read/write operation actually did its
129 static void lio_async_signal_handler();
131 static void lio_async_callback_handler();
135 * Define the structure as used in lio_parse_arg1 and lio_help1
137 struct lio_info_type Lio_info1
[] = {
138 { "s", LIO_IO_SYNC
, "sync i/o" },
139 { "p", LIO_IO_ASYNC
|LIO_WAIT_SIGACTIVE
, "async i/o using a loop to wait for a signal" },
140 { "b", LIO_IO_ASYNC
|LIO_WAIT_SIGPAUSE
, "async i/o using pause" },
141 { "a", LIO_IO_ASYNC
|LIO_WAIT_RECALL
, "async i/o using recall/aio_suspend" },
142 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
144 LIO_RANDOM
|LIO_IO_TYPES
|LIO_WAIT_TYPES
, "random sync i/o types and wait methods" },
146 LIO_RANDOM
|LIO_IO_ATYPES
|LIO_WAIT_ATYPES
, "random i/o types and wait methods" },
149 LIO_RANDOM
|LIO_IO_TYPES
|LIO_WAIT_TYPES
, "random i/o types and wait methods" },
151 LIO_RANDOM
|LIO_IO_TYPES
|LIO_WAIT_TYPES
, "random i/o types and wait methods" },
153 { "l", LIO_IO_SLISTIO
|LIO_WAIT_RECALL
, "single stride sync listio" },
154 { "L", LIO_IO_ALISTIO
|LIO_WAIT_RECALL
, "single stride async listio using recall" },
155 { "X", LIO_IO_ALISTIO
|LIO_WAIT_SIGPAUSE
, "single stride async listio using pause" },
156 { "v", LIO_IO_SYNCV
, "single buffer sync readv/writev" },
157 { "P", LIO_IO_SYNCP
, "sync pread/pwrite" },
161 * Define the structure used by lio_parse_arg2 and lio_help2
163 struct lio_info_type Lio_info2
[] = {
164 { "sync", LIO_IO_SYNC
, "sync i/o (read/write)"},
165 { "async", LIO_IO_ASYNC
, "async i/o (reada/writea/aio_read/aio_write)" },
166 { "slistio", LIO_IO_SLISTIO
, "single stride sync listio" },
167 { "alistio", LIO_IO_ALISTIO
, "single stride async listio" },
168 { "syncv", LIO_IO_SYNCV
, "single buffer sync readv/writev"},
169 { "syncp", LIO_IO_SYNCP
, "pread/pwrite"},
170 { "active", LIO_WAIT_ACTIVE
, "spin on status/control values" },
171 { "recall", LIO_WAIT_RECALL
, "use recall(2)/aio_suspend(3) to wait for i/o to complete" },
172 { "sigactive", LIO_WAIT_SIGACTIVE
, "spin waiting for signal" },
173 { "sigpause", LIO_WAIT_SIGPAUSE
, "call pause(2) to wait for signal" },
174 /* nowait is a touchy thing, it's an accident that this implementation worked at all. 6/27/97 roehrich */
175 /* { "nowait", LIO_WAIT_NONE, "do not wait for async io to complete" },*/
176 { "random", LIO_RANDOM
, "set random bit" },
178 LIO_RANDOM
|LIO_IO_TYPES
|LIO_WAIT_TYPES
,
179 "all random i/o types and wait methods (except nowait)" },
182 char Lio_SysCall
[PATH_MAX
]; /* string containing last i/o system call */
184 static volatile int Received_signal
= 0; /* number of signals received */
185 static volatile int Rec_signal
;
186 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
187 static volatile int Received_callback
= 0; /* number of callbacks received */
188 static volatile int Rec_callback
;
190 static char Errormsg
[500];
191 static int Debug_level
= 0;
195 /***********************************************************************
198 * Determine the bounds of a strided request, normalized to offset. Returns
199 * the number of bytes needed to satisfy the request, and optionally sets
200 * *min and *max to the mininum and maximum bytes referenced, normalized
203 * Returns -1 on error - the only possible error conditions are illegal values
204 * for nstrides and/or bytes_per_stride - both parameters must be >= 0.
207 ***********************************************************************/
210 stride_bounds(offset
, stride
, nstrides
, bytes_per_stride
, min
, max
)
214 int bytes_per_stride
;
218 int nbytes
, min_byte
, max_byte
;
224 if (nstrides
< 0 || bytes_per_stride
< 0) {
229 stride
= bytes_per_stride
;
233 * Determine the # of bytes needed to satisfy the request. This
234 * value, along with the offset argument, determines the min and max
239 nbytes
= abs(stride
) * (nstrides
-1) + bytes_per_stride
;
242 max_byte
= offset
+ bytes_per_stride
- 1;
243 min_byte
= max_byte
- nbytes
+ 1;
246 max_byte
= min_byte
+ nbytes
- 1;
260 /***********************************************************************
261 * This function will allow someone to set the debug level.
262 ***********************************************************************/
273 /***********************************************************************
274 * This function will parse a string and return desired io-method.
275 * Only the first character of the string is used.
277 * This function does not provide for meaningful option arguments,
278 * but it supports current growfiles/btlk interface.
281 ***********************************************************************/
283 lio_parse_io_arg1(char *string
)
290 * Determine if token is a valid string.
292 for(ind
=0; ind
<sizeof(Lio_info1
)/sizeof(struct lio_info_type
); ind
++) {
293 if ( strcmp(string
, Lio_info1
[ind
].token
) == 0 ) {
294 mask
|= Lio_info1
[ind
].bits
;
308 /***********************************************************************
309 * This function will print a help message describing the characters
310 * that can be parsed by lio_parse_io_arg1().
311 * They will be printed one per line.
313 ***********************************************************************/
315 lio_help1(char *prefix
)
319 for(ind
=0; ind
<sizeof(Lio_info1
)/sizeof(struct lio_info_type
); ind
++) {
320 printf("%s %s : %s\n", prefix
,
321 Lio_info1
[ind
].token
, Lio_info1
[ind
].desc
);
327 /***********************************************************************
328 * This function will parse a string and return the desired io-method.
329 * This function will take a comma separated list of io type and wait
330 * method tokens as defined in Lio_info2[]. If a token does not match
331 * any of the tokens in Lio_info2[], it will be coverted to a number.
332 * If it was a number, those bits are also set.
335 ***********************************************************************/
337 lio_parse_io_arg2(char *string
, char **badtoken
)
339 char *token
= string
;
353 for (; ((*cc
!= ',') && (*cc
!= '\0')); cc
++);
360 * Determine if token is a valid string or number and if
361 * so, add the bits to the mask.
363 for(ind
=0; ind
<sizeof(Lio_info2
)/sizeof(struct lio_info_type
); ind
++) {
364 if ( strcmp(token
, Lio_info2
[ind
].token
) == 0 ) {
365 mask
|= Lio_info2
[ind
].bits
;
372 * If token does not match one of the defined tokens, determine
373 * if it is a number, if so, add the bits.
376 if (sscanf(token
, "%i%c", &tmp
, &chr
) == 1 ) {
384 if (!found
) { /* token is not valid */
385 if ( badtoken
!= NULL
)
399 /***********************************************************************
400 * This function will print a help message describing the tokens
401 * that can be parsed by lio_parse_io_arg2().
402 * It will print them one per line.
405 ***********************************************************************/
407 lio_help2(char *prefix
)
411 for(ind
=0; ind
<sizeof(Lio_info2
)/sizeof(struct lio_info_type
); ind
++) {
412 printf("%s %s : %s\n", prefix
,
413 Lio_info2
[ind
].token
, Lio_info2
[ind
].desc
);
418 /***********************************************************************
419 * This is an internal signal handler.
420 * If the handler is called, it will increment the Received_signal
422 ***********************************************************************/
424 lio_async_signal_handler(int sig
)
427 printf("DEBUG %s/%d: received signal %d, a signal caught %d times\n",
428 __FILE__
, __LINE__
, sig
, Received_signal
+1);
435 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
436 /***********************************************************************
437 * This is an internal callback handler.
438 * If the handler is called, it will increment the Received_callback
440 ***********************************************************************/
442 lio_async_callback_handler(sigval_t sigval
)
445 printf("DEBUG %s/%d: received callback, nbytes=%ld, a callback called %d times\n",
446 __FILE__
, __LINE__
, (long)sigval
.sival_int
, Received_callback
+1);
454 /***********************************************************************
456 * This function will randomly choose an io type and wait method
457 * from set of io types and wait methods. Since this information
458 * is stored in a bitmask, it randomly chooses an io type from
459 * the io type bits specified and does the same for wait methods.
462 * This function will return a value with all non choosen io type
463 * and wait method bits cleared. The LIO_RANDOM bit is also
464 * cleared. All other bits are left unchanged.
467 ***********************************************************************/
469 lio_random_methods(long curr_mask
)
474 /* remove random select, io type, and wait method bits from curr_mask */
475 mask
= curr_mask
& (~(LIO_IO_TYPES
| LIO_WAIT_TYPES
| LIO_RANDOM
));
477 /* randomly select io type from specified io types */
478 mask
= mask
| random_bit(curr_mask
& LIO_IO_TYPES
);
480 /* randomly select wait methods from specified wait methods */
481 mask
= mask
| random_bit(curr_mask
& LIO_WAIT_TYPES
);
486 static void wait4sync_io(int fd
, int read
)
492 select(fd
+1, read
? &s
: NULL
, read
? NULL
: &s
, NULL
, NULL
);
495 /***********************************************************************
496 * Generic write function
497 * This function can be used to do a write using write(2), writea(2),
498 * aio_write(3), writev(2), pwrite(2),
499 * or single stride listio(2)/lio_listio(3).
500 * By setting the desired bits in the method
501 * bitmask, the caller can control the type of write and the wait method
502 * that will be used. If no io type bits are set, write will be used.
504 * If async io was attempted and no wait method bits are set then the
505 * wait method is: recall(2) for writea(2) and listio(2); aio_suspend(3) for
506 * aio_write(3) and lio_listio(3).
508 * If multiple wait methods are specified,
509 * only one wait method will be used. The order is predetermined.
511 * If the call specifies a signal and one of the two signal wait methods,
512 * a signal handler for the signal is set. This will reset an already
513 * set handler for this signal.
515 * If the LIO_RANDOM method bit is set, this function will randomly
516 * choose a io type and wait method from bits in the method argument.
518 * If an error is encountered, an error message will be generated
519 * in a internal static buffer. If errmsg is not NULL, it will
520 * be updated to point to the static buffer, allowing the caller
521 * to print the error message.
524 * If a system call fails, -errno is returned.
525 * If LIO_WAIT_NONE bit is set, the return value is the return value
526 * of the system call.
527 * If the io did not fail, the amount of data written is returned.
528 * If the size the system call say was written is different
529 * then what was asked to be written, errmsg is updated for
530 * this error condition. The return value is still the amount
531 * the system call says was written.
534 ***********************************************************************/
536 lio_write_buffer(fd
, method
, buffer
, size
, sig
, errmsg
, wrd
)
537 int fd
; /* open file descriptor */
538 int method
; /* contains io type and wait method bitmask */
539 char *buffer
; /* pointer to buffer */
540 int size
; /* the size of the io */
541 int sig
; /* signal to use if async io */
542 char **errmsg
; /* char pointer that will be updated to point to err message */
543 long wrd
; /* to allow future features, use zero for now */
545 int ret
= 0; /* syscall return or used to get random method */
546 char *io_type
; /* Holds string of type of io */
547 int omethod
= method
;
548 int listio_cmd
; /* Holds the listio/lio_listio cmd */
550 struct listreq request
; /* Used when a listio is wanted */
551 struct iosw status
, *statptr
[1];
553 /* for linux or sgi */
554 struct iovec iov
; /* iovec for writev(2) */
557 aiocb_t aiocbp
; /* POSIX aio control block */
558 aiocb_t
*aiolist
[1]; /* list of aio control blocks for lio_listio */
559 off64_t poffset
; /* pwrite(2) offset */
561 #if defined(__linux__) && !defined(__UCLIBC__)
562 struct aiocb aiocbp
; /* POSIX aio control block */
563 struct aiocb
*aiolist
[1]; /* list of aio control blocks for lio_listio */
564 off64_t poffset
; /* pwrite(2) offset */
567 * If LIO_RANDOM bit specified, get new method randomly.
569 if ( method
& LIO_RANDOM
) {
570 if( Debug_level
> 3 )
571 printf("DEBUG %s/%d: method mask to choose from: %#o\n", __FILE__
, __LINE__
, method
);
572 method
= lio_random_methods(method
);
573 if ( Debug_level
> 2 )
574 printf("DEBUG %s/%d: random chosen method %#o\n", __FILE__
, __LINE__
, method
);
577 if ( errmsg
!= NULL
)
580 Rec_signal
=Received_signal
; /* get the current number of signals received */
581 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
582 Rec_callback
=Received_callback
; /* get the current number of callbacks received */
586 memset(&status
, 0x00, sizeof(struct iosw
));
587 memset(&request
, 0x00, sizeof(struct listreq
));
588 statptr
[0] = &status
;
590 /* for linux or sgi */
591 memset(&iov
, 0x00, sizeof(struct iovec
));
592 iov
.iov_base
= buffer
;
595 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
597 memset(&aiocbp
, 0x00, sizeof(aiocb_t
));
599 memset(&aiocbp
, 0x00, sizeof(struct aiocb
));
601 aiocbp
.aio_fildes
= fd
;
602 aiocbp
.aio_nbytes
= size
;
603 aiocbp
.aio_buf
= buffer
;
604 /* aiocbp.aio_offset = lseek( fd, 0, SEEK_CUR ); -- set below */
605 aiocbp
.aio_sigevent
.sigev_notify
= SIGEV_NONE
;
606 aiocbp
.aio_sigevent
.sigev_signo
= 0;
608 aiocbp
.aio_sigevent
.sigev_func
= NULL
;
609 aiocbp
.aio_sigevent
.sigev_value
.sival_int
= 0;
610 #elif defined(__linux__) && !defined(__UCLIBC__)
611 aiocbp
.aio_sigevent
.sigev_notify_function
= NULL
;
612 aiocbp
.aio_sigevent
.sigev_notify_attributes
= 0;
614 aiolist
[0] = &aiocbp
;
616 if( (ret
= lseek( fd
, 0, SEEK_CUR
)) == -1 ){
618 /* If there is an error and it is not ESPIPE then kick out the error.
619 * If the fd is a fifo then we have to make sure that
620 * lio_random_methods() didn't select pwrite/pread; if it did then
621 * switch to write/read.
623 if( errno
== ESPIPE
){
624 if( method
& LIO_IO_SYNCP
){
625 if( omethod
& LIO_RANDOM
){
626 method
&= ~LIO_IO_SYNCP
;
627 method
|= LIO_IO_SYNC
;
628 if( Debug_level
> 2 )
629 printf("DEBUG %s/%d: random chosen method switched to %#o for fifo\n", __FILE__
, __LINE__
, method
);
631 else if( Debug_level
){
632 printf("DEBUG %s/%d: pwrite will fail when it writes to a fifo\n",
633 __FILE__
, __LINE__
);
636 /* else: let it ride */
639 sprintf(Errormsg
, "%s/%d lseek(fd=%d,0,SEEK_CUR) failed, errno=%d %s",
640 __FILE__
, __LINE__
, fd
, errno
, strerror(errno
));
644 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
645 poffset
= (off64_t
)ret
;
647 aiocbp
.aio_offset
= ret
;
652 * If the LIO_USE_SIGNAL bit is not set, only use the signal
653 * if the LIO_WAIT_SIGPAUSE or the LIO_WAIT_SIGACTIVE bits are bit.
654 * Otherwise there is not necessary a signal handler to trap
657 if ( sig
&& !(method
& LIO_USE_SIGNAL
) &&
658 ! (method
& LIO_WAIT_SIGTYPES
) ){
660 sig
=0; /* ignore signal parameter */
663 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
664 if ( sig
&& (method
& LIO_WAIT_CBTYPES
) )
665 sig
=0; /* ignore signal parameter */
669 * only setup signal hander if sig was specified and
670 * a sig wait method was specified.
671 * Doing this will change the handler for this signal. The
672 * old signal handler will not be restored.
673 *** restoring the signal handler could be added ***
676 if ( sig
&& (method
& LIO_WAIT_SIGTYPES
) ){
678 sigctl(SCTL_REG
, sig
, lio_async_signal_handler
);
680 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
681 aiocbp
.aio_sigevent
.sigev_notify
= SIGEV_SIGNAL
;
682 aiocbp
.aio_sigevent
.sigev_signo
= sig
;
683 sigset(sig
, lio_async_signal_handler
);
687 else if( method
& LIO_WAIT_CBTYPES
){
688 /* sival_int just has to be something that I can use
689 * to identify the callback, and "size" happens to be handy...
691 aiocbp
.aio_sigevent
.sigev_notify
= SIGEV_CALLBACK
;
692 aiocbp
.aio_sigevent
.sigev_func
= lio_async_callback_handler
;
693 aiocbp
.aio_sigevent
.sigev_value
.sival_int
= size
;
696 #if defined(__linux__) && !defined(__UCLIBC__)
697 else if( method
& LIO_WAIT_CBTYPES
){
698 /* sival_int just has to be something that I can use
699 * to identify the callback, and "size" happens to be handy...
701 aiocbp
.aio_sigevent
.sigev_notify
= SIGEV_THREAD
;
702 aiocbp
.aio_sigevent
.sigev_notify_function
= lio_async_callback_handler
;
703 aiocbp
.aio_sigevent
.sigev_notify_attributes
= (void*)(uintptr_t)size
;
707 * Determine the system call that will be called and produce
708 * the string of the system call and place it in Lio_SysCall.
709 * Also update the io_type char pointer to give brief description
710 * of system call. Execute the system call and check for
711 * system call failure. If sync i/o, return the number of
712 * bytes written/read.
715 if ( (method
& LIO_IO_SYNC
) || (method
& (LIO_IO_TYPES
| LIO_IO_ATYPES
)) == 0 ){
717 * write(2) is used if LIO_IO_SYNC bit is set or not none
718 * of the LIO_IO_TYPES bits are set (default).
722 "write(%d, buf, %d)", fd
, size
);
726 printf("DEBUG %s/%d: %s\n", __FILE__
, __LINE__
, Lio_SysCall
);
729 if (((ret
= write(fd
, buffer
, size
)) == -1) && errno
!=EAGAIN
&& errno
!=EINTR
) {
730 sprintf(Errormsg
, "%s/%d write(%d, buf, %d) ret:-1, errno=%d %s",
732 fd
, size
, errno
, strerror(errno
));
739 "%s/%d write(%d, buf, %d) returned=%d",
746 if ( Debug_level
> 1 )
747 printf("DEBUG %s/%d: write completed without error (ret %d)\n",
748 __FILE__
, __LINE__
, ret
);
758 else if ( method
& LIO_IO_ASYNC
) {
761 "writea(%d, buf, %d, &status, %d)", fd
, size
, sig
);
765 printf("DEBUG %s/%d: %s\n", __FILE__
, __LINE__
, Lio_SysCall
);
769 if ((ret
= writea(fd
, buffer
, size
, &status
, sig
)) == -1) {
771 "%s/%d writea(%d, buf, %d, &stat, %d) ret:-1, errno=%d %s",
773 fd
, size
, sig
, errno
, strerror(errno
));
778 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
780 "aio_write(fildes=%d, buf, nbytes=%d, signo=%d)", fd
, size
, sig
);
784 printf("DEBUG %s/%d: %s\n", __FILE__
, __LINE__
, Lio_SysCall
);
789 if ((ret
= aio_write(&aiocbp
)) == -1) {
791 "%s/%d aio_write(fildes=%d, buf, nbytes=%d, signo=%d) ret:-1, errno=%d %s",
793 fd
, size
, sig
, errno
, strerror(errno
));
801 else if ( method
& LIO_IO_SLISTIO
) {
803 request
.li_opcode
= LO_WRITE
;
804 request
.li_fildes
= fd
;
805 request
.li_buf
= buffer
;
806 request
.li_nbyte
= size
;
807 request
.li_status
= &status
;
808 request
.li_signo
= sig
;
809 request
.li_nstride
= 0;
810 request
.li_filstride
= 0;
811 request
.li_memstride
= 0;
814 io_type
="listio(2) sync write";
817 "listio(LC_WAIT, &req, 1) LO_WRITE, fd:%d, nbyte:%d",
821 printf("DEBUG %s/%d: %s\n", __FILE__
, __LINE__
, Lio_SysCall
);
825 if ( listio(listio_cmd
, &request
, 1) == -1 ) {
826 sprintf(Errormsg
, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
828 Lio_SysCall
, fd
, size
, errno
, strerror(errno
));
833 if ( Debug_level
> 1 )
834 printf("DEBUG %s/%d: %s did not return -1\n",
835 __FILE__
, __LINE__
, Lio_SysCall
);
837 ret
=lio_check_asyncio(io_type
, size
, &status
);
841 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
843 aiocbp
.aio_lio_opcode
= LIO_WRITE
;
845 io_type
="lio_listio(3) sync write";
848 "lio_listio(LIO_WAIT, aiolist, 1, NULL) LIO_WRITE, fd:%d, nbyte:%d, sig:%d",
852 printf("DEBUG %s/%d: %s\n", __FILE__
, __LINE__
, Lio_SysCall
);
857 if ( lio_listio(listio_cmd
, aiolist
, 1, NULL
) == -1 ) {
858 sprintf(Errormsg
, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
860 Lio_SysCall
, fd
, size
, errno
, strerror(errno
));
866 if ( Debug_level
> 1 )
867 printf("DEBUG %s/%d: %s did not return -1\n",
868 __FILE__
, __LINE__
, Lio_SysCall
);
870 ret
=lio_check_asyncio(io_type
, size
, &aiocbp
, method
);
873 } /* LIO_IO_SLISTIO */
875 else if ( method
& LIO_IO_ALISTIO
) {
877 request
.li_opcode
= LO_WRITE
;
878 request
.li_fildes
= fd
;
879 request
.li_buf
= buffer
;
880 request
.li_nbyte
= size
;
881 request
.li_status
= &status
;
882 request
.li_signo
= sig
;
883 request
.li_nstride
= 0;
884 request
.li_filstride
= 0;
885 request
.li_memstride
= 0;
888 io_type
="listio(2) async write";
891 "listio(LC_START, &req, 1) LO_WRITE, fd:%d, nbyte:%d",
895 printf("DEBUG %s/%d: %s\n", __FILE__
, __LINE__
, Lio_SysCall
);
899 if ( listio(listio_cmd
, &request
, 1) == -1 ) {
900 sprintf(Errormsg
, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
902 Lio_SysCall
, fd
, size
, errno
, strerror(errno
));
907 #if defined (sgi) || (defined(__linux__) && !defined(__UCLIBC__))
908 aiocbp
.aio_lio_opcode
= LIO_WRITE
;
909 listio_cmd
=LIO_NOWAIT
;
910 io_type
="lio_listio(3) async write";
913 "lio_listio(LIO_NOWAIT, aiolist, 1, NULL) LIO_WRITE, fd:%d, nbyte:%d",
917 printf("DEBUG %s/%d: %s\n", __FILE__
, __LINE__
, Lio_SysCall
);
922 if ( lio_listio(listio_cmd
, aiolist
, 1, NULL
) == -1 ) {
923 sprintf(Errormsg
, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
925 Lio_SysCall
, fd
, size
, errno
, strerror(errno
));
931 }/* LIO_IO_ALISTIO */
934 else if ( method
& LIO_IO_SYNCV
) {
938 "writev(%d, &iov, 1) nbyte:%d", fd
, size
);
941 printf("DEBUG %s/%d: %s\n", __FILE__
, __LINE__
, Lio_SysCall
);
943 if ((ret
= writev(fd
, &iov
, 1)) == -1) {
944 sprintf(Errormsg
, "%s/%d writev(%d, iov, 1) nbyte:%d ret:-1, errno=%d %s",
946 fd
, size
, errno
, strerror(errno
));
952 "%s/%d writev(%d, iov, 1) nbyte:%d returned=%d",
956 else if ( Debug_level
> 1 )
957 printf("DEBUG %s/%d: writev completed without error (ret %d)\n",
958 __FILE__
, __LINE__
, ret
);
964 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
965 else if ( method
& LIO_IO_SYNCP
) {
969 "pwrite(%d, buf, %d, %lld)", fd
, size
, (long long)poffset
);
972 printf("DEBUG %s/%d: %s\n", __FILE__
, __LINE__
, Lio_SysCall
);
974 if ((ret
= pwrite(fd
, buffer
, size
, poffset
)) == -1) {
975 sprintf(Errormsg
, "%s/%d pwrite(%d, buf, %d, %lld) ret:-1, errno=%d %s",
977 fd
, size
, (long long)poffset
, errno
, strerror(errno
));
983 "%s/%d pwrite(%d, buf, %d, %lld) returned=%d",
985 fd
, size
, (long long)poffset
, ret
);
987 else if ( Debug_level
> 1 )
988 printf("DEBUG %s/%d: pwrite completed without error (ret %d)\n",
989 __FILE__
, __LINE__
, ret
);
996 printf("DEBUG %s/%d: No I/O method chosen\n", __FILE__
, __LINE__
);
1001 * wait for async io to complete.
1004 ret
=lio_wait4asyncio(method
, fd
, statptr
);
1006 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1007 ret
=lio_wait4asyncio(method
, fd
, &aiocbp
);
1011 * If there was an error waiting for async i/o to complete,
1012 * return the error value (errno) to the caller.
1013 * Note: Errormsg should already have been updated.
1020 * If i/o was not waited for (may not have been completed at this time),
1021 * return the size that was requested.
1027 * check that async io was successful.
1028 * Note: if the there was an system call failure, -errno
1029 * was returned and Errormsg should already have been updated.
1030 * If amount i/o was different than size, Errormsg should already
1031 * have been updated but the actual i/o size if returned.
1035 ret
=lio_check_asyncio(io_type
, size
, &status
);
1037 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1038 ret
=lio_check_asyncio(io_type
, size
, &aiocbp
, method
);
1042 } /* end of lio_write_buffer */
1044 /***********************************************************************
1045 * Generic read function
1046 * This function can be used to do a read using read(2), reada(2),
1047 * aio_read(3), readv(2), pread(2),
1048 * or single stride listio(2)/lio_listio(3).
1049 * By setting the desired bits in the method
1050 * bitmask, the caller can control the type of read and the wait method
1051 * that will be used. If no io type bits are set, read will be used.
1053 * If async io was attempted and no wait method bits are set then the
1054 * wait method is: recall(2) for reada(2) and listio(2); aio_suspend(3) for
1055 * aio_read(3) and lio_listio(3).
1057 * If multiple wait methods are specified,
1058 * only one wait method will be used. The order is predetermined.
1060 * If the call specifies a signal and one of the two signal wait methods,
1061 * a signal handler for the signal is set. This will reset an already
1062 * set handler for this signal.
1064 * If the LIO_RANDOM method bit is set, this function will randomly
1065 * choose a io type and wait method from bits in the method argument.
1067 * If an error is encountered, an error message will be generated
1068 * in a internal static buffer. If errmsg is not NULL, it will
1069 * be updated to point to the static buffer, allowing the caller
1070 * to print the error message.
1073 * If a system call fails, -errno is returned.
1074 * If LIO_WAIT_NONE bit is set, the return value is the return value
1075 * of the system call.
1076 * If the io did not fail, the amount of data written is returned.
1077 * If the size the system call say was written is different
1078 * then what was asked to be written, errmsg is updated for
1079 * this error condition. The return value is still the amount
1080 * the system call says was written.
1083 ***********************************************************************/
1085 lio_read_buffer(fd
, method
, buffer
, size
, sig
, errmsg
, wrd
)
1086 int fd
; /* open file descriptor */
1087 int method
; /* contains io type and wait method bitmask */
1088 char *buffer
; /* pointer to buffer */
1089 int size
; /* the size of the io */
1090 int sig
; /* signal to use if async io */
1091 char **errmsg
; /* char pointer that will be updated to point to err message */
1092 long wrd
; /* to allow future features, use zero for now */
1094 int ret
= 0; /* syscall return or used to get random method */
1095 char *io_type
; /* Holds string of type of io */
1096 int listio_cmd
; /* Holds the listio/lio_listio cmd */
1097 int omethod
= method
;
1099 struct listreq request
; /* Used when a listio is wanted */
1100 struct iosw status
, *statptr
[1];
1102 /* for linux or sgi */
1103 struct iovec iov
; /* iovec for readv(2) */
1106 aiocb_t aiocbp
; /* POSIX aio control block */
1107 aiocb_t
*aiolist
[1]; /* list of aio control blocks for lio_listio */
1108 off64_t poffset
; /* pread(2) offset */
1110 #if defined (__linux__) && !defined(__UCLIBC__)
1111 struct aiocb aiocbp
; /* POSIX aio control block */
1112 struct aiocb
*aiolist
[1]; /* list of aio control blocks for lio_listio */
1113 off64_t poffset
; /* pread(2) offset */
1117 * If LIO_RANDOM bit specified, get new method randomly.
1119 if ( method
& LIO_RANDOM
) {
1120 if( Debug_level
> 3 )
1121 printf("DEBUG %s/%d: method mask to choose from: %#o\n", __FILE__
, __LINE__
, method
);
1122 method
= lio_random_methods(method
);
1123 if ( Debug_level
> 2 )
1124 printf("DEBUG %s/%d: random chosen method %#o\n", __FILE__
, __LINE__
, method
);
1127 if ( errmsg
!= NULL
)
1130 Rec_signal
=Received_signal
; /* get the current number of signals received */
1131 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1132 Rec_callback
=Received_callback
; /* get the current number of callbacks received */
1136 memset(&status
, 0x00, sizeof(struct iosw
));
1137 memset(&request
, 0x00, sizeof(struct listreq
));
1138 statptr
[0] = &status
;
1140 /* for linux or sgi */
1141 memset(&iov
, 0x00, sizeof(struct iovec
));
1142 iov
.iov_base
= buffer
;
1145 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1147 memset(&aiocbp
, 0x00, sizeof(aiocb_t
));
1149 memset(&aiocbp
, 0x00, sizeof(struct aiocb
));
1151 aiocbp
.aio_fildes
= fd
;
1152 aiocbp
.aio_nbytes
= size
;
1153 aiocbp
.aio_buf
= buffer
;
1154 /* aiocbp.aio_offset = lseek( fd, 0, SEEK_CUR ); -- set below */
1155 aiocbp
.aio_sigevent
.sigev_notify
= SIGEV_NONE
;
1156 aiocbp
.aio_sigevent
.sigev_signo
= 0;
1158 aiocbp
.aio_sigevent
.sigev_func
= NULL
;
1159 aiocbp
.aio_sigevent
.sigev_value
.sival_int
= 0;
1160 #elif defined(__linux__) && !defined(__UCLIBC__)
1161 aiocbp
.aio_sigevent
.sigev_notify_function
= NULL
;
1162 aiocbp
.aio_sigevent
.sigev_notify_attributes
= 0;
1164 aiolist
[0] = &aiocbp
;
1166 if( (ret
= lseek( fd
, 0, SEEK_CUR
)) == -1 ){
1168 /* If there is an error and it is not ESPIPE then kick out the error.
1169 * If the fd is a fifo then we have to make sure that
1170 * lio_random_methods() didn't select pwrite/pread; if it did then
1171 * switch to write/read.
1173 if( errno
== ESPIPE
){
1174 if( method
& LIO_IO_SYNCP
){
1175 if( omethod
& LIO_RANDOM
){
1176 method
&= ~LIO_IO_SYNCP
;
1177 method
|= LIO_IO_SYNC
;
1178 if( Debug_level
> 2 )
1179 printf("DEBUG %s/%d: random chosen method switched to %#o for fifo\n", __FILE__
, __LINE__
, method
);
1181 else if( Debug_level
){
1182 printf("DEBUG %s/%d: pread will fail when it reads from a fifo\n",
1183 __FILE__
, __LINE__
);
1186 /* else: let it ride */
1189 sprintf(Errormsg
, "%s/%d lseek(fd=%d,0,SEEK_CUR) failed, errno=%d %s",
1190 __FILE__
, __LINE__
, fd
, errno
, strerror(errno
));
1194 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1195 poffset
= (off64_t
)ret
;
1197 aiocbp
.aio_offset
= ret
;
1202 * If the LIO_USE_SIGNAL bit is not set, only use the signal
1203 * if the LIO_WAIT_SIGPAUSE or the LIO_WAIT_SIGACTIVE bits are set.
1204 * Otherwise there is not necessarily a signal handler to trap
1207 if ( sig
&& !(method
& LIO_USE_SIGNAL
) &&
1208 ! (method
& LIO_WAIT_SIGTYPES
) ){
1210 sig
=0; /* ignore signal parameter */
1213 #if defined(sgi) || (defined(__linux__)&& !defined(__UCLIBC__))
1214 if ( sig
&& (method
& LIO_WAIT_CBTYPES
) )
1215 sig
=0; /* ignore signal parameter */
1219 * only setup signal hander if sig was specified and
1220 * a sig wait method was specified.
1221 * Doing this will change the handler for this signal. The
1222 * old signal handler will not be restored.
1223 *** restoring the signal handler could be added ***
1226 if ( sig
&& (method
& LIO_WAIT_SIGTYPES
) ){
1228 sigctl(SCTL_REG
, sig
, lio_async_signal_handler
);
1230 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1231 aiocbp
.aio_sigevent
.sigev_notify
= SIGEV_SIGNAL
;
1232 aiocbp
.aio_sigevent
.sigev_signo
= sig
;
1233 sigset(sig
, lio_async_signal_handler
);
1237 else if( method
& LIO_WAIT_CBTYPES
){
1238 aiocbp
.aio_sigevent
.sigev_notify
= SIGEV_CALLBACK
;
1239 aiocbp
.aio_sigevent
.sigev_func
= lio_async_callback_handler
;
1240 /* sival_int just has to be something that I can use
1241 * to identify the callback, and "size" happens to be handy...
1243 aiocbp
.aio_sigevent
.sigev_value
.sival_int
= size
;
1246 #if defined(__linux__) && !defined(__UCLIBC__)
1247 else if( method
& LIO_WAIT_CBTYPES
){
1248 aiocbp
.aio_sigevent
.sigev_notify
= SIGEV_THREAD
;
1249 aiocbp
.aio_sigevent
.sigev_notify_function
= lio_async_callback_handler
;
1250 /* sival_int just has to be something that I can use
1251 * to identify the callback, and "size" happens to be handy...
1253 aiocbp
.aio_sigevent
.sigev_notify_attributes
= (void*)(uintptr_t)size
;
1258 * Determine the system call that will be called and produce
1259 * the string of the system call and place it in Lio_SysCall.
1260 * Also update the io_type char pointer to give brief description
1261 * of system call. Execute the system call and check for
1262 * system call failure. If sync i/o, return the number of
1263 * bytes written/read.
1266 if ( (method
& LIO_IO_SYNC
) || (method
& (LIO_IO_TYPES
| LIO_IO_ATYPES
)) == 0 ){
1268 * read(2) is used if LIO_IO_SYNC bit is set or not none
1269 * of the LIO_IO_TYPES bits are set (default).
1272 sprintf(Lio_SysCall
,
1273 "read(%d, buf, %d)", fd
, size
);
1276 if ( Debug_level
) {
1277 printf("DEBUG %s/%d: %s\n", __FILE__
, __LINE__
, Lio_SysCall
);
1281 if (((ret
= read(fd
, buffer
, size
)) == -1) && errno
!=EINTR
&& errno
!=EAGAIN
) {
1282 sprintf(Errormsg
, "%s/%d read(%d, buf, %d) ret:-1, errno=%d %s",
1284 fd
, size
, errno
, strerror(errno
));
1288 if(ret
==0) return 0;
1290 if ( ret
!= size
) {
1292 "%s/%d read(%d, buf, %d) returned=%d",
1299 if ( Debug_level
> 1 )
1300 printf("DEBUG %s/%d: read completed without error (ret %d)\n",
1301 __FILE__
, __LINE__
, ret
);
1306 wait4sync_io(fd
, 1);
1311 else if ( method
& LIO_IO_ASYNC
) {
1313 sprintf(Lio_SysCall
,
1314 "reada(%d, buf, %d, &status, %d)", fd
, size
, sig
);
1317 if ( Debug_level
) {
1318 printf("DEBUG %s/%d: %s\n", __FILE__
, __LINE__
, Lio_SysCall
);
1322 if ((ret
= reada(fd
, buffer
, size
, &status
, sig
)) == -1) {
1324 "%s/%d reada(%d, buf, %d, &stat, %d) ret:-1, errno=%d %s",
1326 fd
, size
, sig
, errno
, strerror(errno
));
1331 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1332 sprintf(Lio_SysCall
,
1333 "aio_read(fildes=%d, buf, nbytes=%d, signo=%d)", fd
, size
, sig
);
1336 if ( Debug_level
) {
1337 printf("DEBUG %s/%d: %s\n", __FILE__
, __LINE__
, Lio_SysCall
);
1342 if ((ret
= aio_read(&aiocbp
)) == -1) {
1344 "%s/%d aio_read(fildes=%d, buf, nbytes=%d, signo=%d) ret:-1, errno=%d %s",
1346 fd
, size
, sig
, errno
, strerror(errno
));
1352 } /* LIO_IO_ASYNC */
1354 else if ( method
& LIO_IO_SLISTIO
) {
1356 request
.li_opcode
= LO_READ
;
1357 request
.li_fildes
= fd
;
1358 request
.li_buf
= buffer
;
1359 request
.li_nbyte
= size
;
1360 request
.li_status
= &status
;
1361 request
.li_signo
= sig
;
1362 request
.li_nstride
= 0;
1363 request
.li_filstride
= 0;
1364 request
.li_memstride
= 0;
1367 io_type
="listio(2) sync read";
1369 sprintf(Lio_SysCall
,
1370 "listio(LC_WAIT, &req, 1) LO_READ, fd:%d, nbyte:%d",
1373 if ( Debug_level
) {
1374 printf("DEBUG %s/%d: %s\n", __FILE__
, __LINE__
, Lio_SysCall
);
1378 if ( listio(listio_cmd
, &request
, 1) == -1 ) {
1379 sprintf(Errormsg
, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1381 Lio_SysCall
, fd
, size
, errno
, strerror(errno
));
1386 if ( Debug_level
> 1 )
1387 printf("DEBUG %s/%d: %s did not return -1\n",
1388 __FILE__
, __LINE__
, Lio_SysCall
);
1390 ret
=lio_check_asyncio(io_type
, size
, &status
);
1393 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1394 aiocbp
.aio_lio_opcode
= LIO_READ
;
1395 listio_cmd
=LIO_WAIT
;
1396 io_type
="lio_listio(3) sync read";
1398 sprintf(Lio_SysCall
,
1399 "lio_listio(LIO_WAIT, aiolist, 1, NULL) LIO_READ, fd:%d, nbyte:%d",
1402 if ( Debug_level
) {
1403 printf("DEBUG %s/%d: %s\n", __FILE__
, __LINE__
, Lio_SysCall
);
1408 if ( lio_listio(listio_cmd
, aiolist
, 1, NULL
) == -1 ) {
1409 sprintf(Errormsg
, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1411 Lio_SysCall
, fd
, size
, errno
, strerror(errno
));
1417 if ( Debug_level
> 1 )
1418 printf("DEBUG %s/%d: %s did not return -1\n",
1419 __FILE__
, __LINE__
, Lio_SysCall
);
1421 ret
=lio_check_asyncio(io_type
, size
, &aiocbp
, method
);
1424 }/* LIO_IO_SLISTIO */
1426 else if ( method
& LIO_IO_ALISTIO
) {
1428 request
.li_opcode
= LO_READ
;
1429 request
.li_fildes
= fd
;
1430 request
.li_buf
= buffer
;
1431 request
.li_nbyte
= size
;
1432 request
.li_status
= &status
;
1433 request
.li_signo
= sig
;
1434 request
.li_nstride
= 0;
1435 request
.li_filstride
= 0;
1436 request
.li_memstride
= 0;
1438 listio_cmd
=LC_START
;
1439 io_type
="listio(2) async read";
1441 sprintf(Lio_SysCall
,
1442 "listio(LC_START, &req, 1) LO_READ, fd:%d, nbyte:%d",
1445 if ( Debug_level
) {
1446 printf("DEBUG %s/%d: %s\n", __FILE__
, __LINE__
, Lio_SysCall
);
1450 if ( listio(listio_cmd
, &request
, 1) == -1 ) {
1451 sprintf(Errormsg
, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1453 Lio_SysCall
, fd
, size
, errno
, strerror(errno
));
1458 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1459 aiocbp
.aio_lio_opcode
= LIO_READ
;
1460 listio_cmd
=LIO_NOWAIT
;
1461 io_type
="lio_listio(3) async read";
1463 sprintf(Lio_SysCall
,
1464 "lio_listio(LIO_NOWAIT, aiolist, 1, NULL) LIO_READ, fd:%d, nbyte:%d",
1467 if ( Debug_level
) {
1468 printf("DEBUG %s/%d: %s\n", __FILE__
, __LINE__
, Lio_SysCall
);
1473 if ( lio_listio(listio_cmd
, aiolist
, 1, NULL
) == -1 ) {
1474 sprintf(Errormsg
, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1476 Lio_SysCall
, fd
, size
, errno
, strerror(errno
));
1482 } /* LIO_IO_ALISTIO */
1485 else if ( method
& LIO_IO_SYNCV
) {
1488 sprintf(Lio_SysCall
,
1489 "readv(%d, &iov, 1) nbyte:%d", fd
, size
);
1491 if ( Debug_level
) {
1492 printf("DEBUG %s/%d: %s\n", __FILE__
, __LINE__
, Lio_SysCall
);
1494 if ((ret
= readv(fd
, &iov
, 1)) == -1) {
1495 sprintf(Errormsg
, "%s/%d readv(%d, iov, 1) nbyte:%d ret:-1, errno=%d %s",
1497 fd
, size
, errno
, strerror(errno
));
1501 if ( ret
!= size
) {
1503 "%s/%d readv(%d, iov, 1) nbyte:%d returned=%d",
1507 else if ( Debug_level
> 1 )
1508 printf("DEBUG %s/%d: readv completed without error (ret %d)\n",
1509 __FILE__
, __LINE__
, ret
);
1512 } /* LIO_IO_SYNCV */
1515 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1516 else if ( method
& LIO_IO_SYNCP
) {
1519 sprintf(Lio_SysCall
,
1520 "pread(%d, buf, %d, %lld)", fd
, size
, (long long)poffset
);
1522 if ( Debug_level
) {
1523 printf("DEBUG %s/%d: %s\n", __FILE__
, __LINE__
, Lio_SysCall
);
1525 if ((ret
= pread(fd
, buffer
, size
, poffset
)) == -1) {
1526 sprintf(Errormsg
, "%s/%d pread(%d, buf, %d, %lld) ret:-1, errno=%d %s",
1528 fd
, size
, (long long)poffset
, errno
, strerror(errno
));
1532 if ( ret
!= size
) {
1534 "%s/%d pread(%d, buf, %d, %lld) returned=%d",
1536 fd
, size
, (long long)poffset
, ret
);
1538 else if ( Debug_level
> 1 )
1539 printf("DEBUG %s/%d: pread completed without error (ret %d)\n",
1540 __FILE__
, __LINE__
, ret
);
1543 } /* LIO_IO_SYNCP */
1547 printf("DEBUG %s/%d: No I/O method chosen\n", __FILE__
, __LINE__
);
1552 * wait for async io to complete.
1553 * Note: Sync io should have returned prior to getting here.
1556 ret
=lio_wait4asyncio(method
, fd
, statptr
);
1558 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1559 ret
=lio_wait4asyncio(method
, fd
, &aiocbp
);
1563 * If there was an error waiting for async i/o to complete,
1564 * return the error value (errno) to the caller.
1565 * Note: Errormsg should already have been updated.
1572 * If i/o was not waited for (may not have been completed at this time),
1573 * return the size that was requested.
1579 * check that async io was successful.
1580 * Note: if the there was an system call failure, -errno
1581 * was returned and Errormsg should already have been updated.
1582 * If amount i/o was different than size, Errormsg should already
1583 * have been updated but the actual i/o size if returned.
1587 ret
=lio_check_asyncio(io_type
, size
, &status
);
1589 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1590 ret
=lio_check_asyncio(io_type
, size
, &aiocbp
, method
);
1594 } /* end of lio_read_buffer */
1597 #if !defined(__sun) && !defined(__hpux) && !defined(_AIX)
1598 /***********************************************************************
1599 * This function will check that async io was successful.
1600 * It can also be used to check sync listio since it uses the
1604 * If status.sw_error is set, -status.sw_error is returned.
1605 * Otherwise sw_count's field value is returned.
1608 ***********************************************************************/
1610 int lio_check_asyncio(char *io_type
, int size
, struct iosw
*status
)
1612 int lio_check_asyncio(char *io_type
, int size
, aiocb_t
*aiocbp
, int method
)
1613 #elif defined(__linux__) && !defined(__UCLIBC__)
1614 int lio_check_asyncio(char *io_type
, int size
, struct aiocb
*aiocbp
, int method
)
1619 if ( status
->sw_error
) {
1621 "%s/%d %s, sw_error set = %d %s, sw_count = %d",
1622 __FILE__
, __LINE__
, io_type
,
1623 status
->sw_error
, strerror(status
->sw_error
), status
->sw_count
);
1624 return -status
->sw_error
;
1626 else if ( status
->sw_count
!= size
) {
1628 "%s/%d %s, sw_count not as expected(%d), but actual:%d",
1629 __FILE__
, __LINE__
, io_type
,
1630 size
, status
->sw_count
);
1632 else if ( Debug_level
> 1 ) {
1633 printf("DEBUG %s/%d: %s completed without error (sw_error == 0, sw_count == %d)\n",
1634 __FILE__
, __LINE__
, io_type
, status
->sw_count
);
1637 return status
->sw_count
;
1643 /* The I/O may have been synchronous with signal completion. It doesn't
1644 * make sense, but the combination could be generated. Release the
1645 * completion signal here otherwise it'll hang around and bite us
1648 if( aiocbp
->aio_sigevent
.sigev_notify
== SIGEV_SIGNAL
)
1649 sigrelse( aiocbp
->aio_sigevent
.sigev_signo
);
1651 ret
= aio_error( aiocbp
);
1653 while( ret
== EINPROGRESS
){
1654 ret
= aio_error( aiocbp
);
1659 "%s/%d %s, aio_error had to loop on EINPROGRESS, cnt=%d; random method %#o; sigev_notify=%s",
1660 __FILE__
, __LINE__
, io_type
, cnt
, method
,
1661 (aiocbp
->aio_sigevent
.sigev_notify
== SIGEV_SIGNAL
? "signal" :
1662 aiocbp
->aio_sigevent
.sigev_notify
== SIGEV_NONE
? "none" :
1663 #ifdef SIGEV_CALLBACK
1664 aiocbp
->aio_sigevent
.sigev_notify
== SIGEV_CALLBACK
? "callback" :
1666 aiocbp
->aio_sigevent
.sigev_notify
== SIGEV_THREAD
? "thread" :
1673 "%s/%d %s, aio_error = %d %s; random method %#o",
1674 __FILE__
, __LINE__
, io_type
,
1679 ret
= aio_return( aiocbp
);
1682 "%s/%d %s, aio_return not as expected(%d), but actual:%d",
1683 __FILE__
, __LINE__
, io_type
,
1686 #ifdef BUG1_workaround
1689 if( Debug_level
> 1 ){
1690 printf("WARN %s/%d: %s completed with bug1_workaround (aio_error == 0, aio_return now == %d)\n",
1691 __FILE__
, __LINE__
, io_type
, ret
);
1694 #endif /* BUG1_workaround */
1697 else if( Debug_level
> 1 ){
1698 printf("DEBUG %s/%d: %s completed without error (aio_error == 0, aio_return == %d)\n",
1699 __FILE__
, __LINE__
, io_type
, ret
);
1705 } /* end of lio_check_asyncio */
1708 /***********************************************************************
1710 * This function will wait for async io to complete.
1711 * If multiple wait methods are specified, the order is predetermined
1712 * to LIO_WAIT_RECALL,
1713 * LIO_WAIT_ACTIVE, LIO_WAIT_SIGPAUSE, LIO_WAIT_SIGACTIVE,
1714 * then LIO_WAIT_NONE.
1716 * If no wait method was specified the default wait method is: recall(2)
1717 * or aio_suspend(3), as appropriate.
1720 * <0: errno of failed recall
1721 * 0 : async io was completed
1722 * 1 : async was not waited for, io may not have completed.
1725 ***********************************************************************/
1727 int lio_wait4asyncio(int method
, int fd
, struct iosw
**statptr
)
1729 int lio_wait4asyncio(int method
, int fd
, aiocb_t
*aiocbp
)
1730 #elif defined(__linux__) && !defined(__UCLIBC__)
1731 int lio_wait4asyncio(int method
, int fd
, struct aiocb
*aiocbp
)
1736 const aiocb_t
*aioary
[1];
1738 #if defined(__linux__)&& !defined(__UCLIBC__)
1740 const struct aiocb
*aioary
[1];
1743 if ( (method
& LIO_WAIT_RECALL
)
1744 #if defined(sgi) || (defined(__linux__)&& !defined(__UCLIBC__))
1745 || (method
& LIO_WAIT_CBSUSPEND
)
1746 || (method
& LIO_WAIT_SIGSUSPEND
)
1748 || ((method
& LIO_WAIT_TYPES
) == 0) ){
1750 * If method has LIO_WAIT_RECALL bit set or method does
1751 * not have any wait method bits set (default), use recall/aio_suspend.
1754 if ( Debug_level
> 2 )
1755 printf("DEBUG %s/%d: wait method : recall\n", __FILE__
, __LINE__
);
1757 if ( recall(fd
, 1, statptr
) ) {
1758 sprintf(Errormsg
, "%s/%d recall(%d, 1, stat) failed, errno:%d %s",
1760 fd
, errno
, strerror(errno
));
1764 if ( Debug_level
> 2 )
1765 printf("DEBUG %s/%d: wait method : aio_suspend, sigev_notify=%s\n", __FILE__
, __LINE__
,
1766 (aiocbp
->aio_sigevent
.sigev_notify
== SIGEV_SIGNAL
? "signal" :
1767 aiocbp
->aio_sigevent
.sigev_notify
== SIGEV_NONE
? "none" :
1768 #ifdef SIGEV_CALLBACK
1769 aiocbp
->aio_sigevent
.sigev_notify
== SIGEV_CALLBACK
? "callback" :
1771 aiocbp
->aio_sigevent
.sigev_notify
== SIGEV_THREAD
? "thread" :
1775 ret
= aio_suspend( aioary
, 1, NULL
);
1776 if( (ret
== -1) && (errno
== EINTR
) ){
1777 if( aiocbp
->aio_sigevent
.sigev_notify
== SIGEV_SIGNAL
){
1778 if( Debug_level
> 2 ){
1779 printf("DEBUG %s/%d: aio_suspend received EINTR, sigev_notify=SIGEV_SIGNAL -- ok\n",
1780 __FILE__
, __LINE__
);
1784 sprintf(Errormsg
, "%s/%d aio_suspend received EINTR, sigev_notify=%s, not ok\n",
1786 (aiocbp
->aio_sigevent
.sigev_notify
== SIGEV_SIGNAL
? "signal" :
1787 aiocbp
->aio_sigevent
.sigev_notify
== SIGEV_NONE
? "none" :
1788 #ifdef SIGEV_CALLBACK
1789 aiocbp
->aio_sigevent
.sigev_notify
== SIGEV_CALLBACK
? "callback" :
1791 aiocbp
->aio_sigevent
.sigev_notify
== SIGEV_THREAD
? "thread" :
1797 sprintf(Errormsg
, "%s/%d aio_suspend(fildes=%d, aioary, 1, NULL) failed, errno:%d %s",
1799 fd
, errno
, strerror(errno
));
1804 } else if ( method
& LIO_WAIT_ACTIVE
) {
1805 if ( Debug_level
> 2 )
1806 printf("DEBUG %s/%d: wait method : active\n", __FILE__
, __LINE__
);
1810 * loop until sw_flag, sw_count or sw_error field elements
1811 * change to non-zero.
1814 while ( (*statptr
)->sw_flag
== 0 &&
1815 (*statptr
)->sw_count
== 0 &&
1816 (*statptr
)->sw_error
== 0 ) {
1820 /* loop while aio_error() returns EINPROGRESS */
1823 ret
= aio_error( aiocbp
);
1824 if( (ret
== 0) || (ret
!= EINPROGRESS
) ){
1831 if ( Debug_level
> 5 && cnt
&& (cnt
% 50) == 0 )
1832 printf("DEBUG %s/%d: wait active cnt = %d\n",
1833 __FILE__
, __LINE__
, cnt
);
1835 } else if ( method
& LIO_WAIT_SIGPAUSE
) {
1836 if ( Debug_level
> 2 )
1837 printf("DEBUG %s/%d: wait method : sigpause\n", __FILE__
, __LINE__
);
1839 /* note: don't do the sigon() for CRAY in this case. why? -- roehrich 6/11/97 */
1840 if( aiocbp
->aio_sigevent
.sigev_notify
== SIGEV_SIGNAL
)
1841 sigrelse( aiocbp
->aio_sigevent
.sigev_signo
);
1843 printf("DEBUG %s/%d: sigev_notify != SIGEV_SIGNAL\n", __FILE__
, __LINE__
);
1849 } else if ( method
& LIO_WAIT_SIGACTIVE
) {
1850 if ( Debug_level
> 2 )
1851 printf("DEBUG %s/%d: wait method : sigactive\n", __FILE__
, __LINE__
);
1855 if( aiocbp
->aio_sigevent
.sigev_notify
== SIGEV_SIGNAL
)
1856 sigrelse( aiocbp
->aio_sigevent
.sigev_signo
);
1858 printf("DEBUG %s/%d: sigev_notify != SIGEV_SIGNAL\n", __FILE__
, __LINE__
);
1862 /* loop waiting for signal */
1863 while ( Received_signal
== Rec_signal
){
1867 sigrelse( aiocbp
->aio_sigevent
.sigev_signo
);
1871 } else if ( method
& LIO_WAIT_NONE
) {
1872 if ( Debug_level
> 2 )
1873 printf("DEBUG %s/%d: wait method : none\n", __FILE__
, __LINE__
);
1874 /* It's broken because the aiocb/iosw is an automatic variable in
1875 * lio_{read,write}_buffer, so when the function returns and the
1876 * I/O completes there will be nowhere to write the I/O status.
1877 * It doesn't cause a problem on unicos--probably because of some
1878 * compiler quirk, or an accident. It causes POSIX async I/O
1879 * to core dump some threads. spr/pv 705909. 6/27/97 roehrich
1881 sprintf(Errormsg
, "%s/%d LIO_WAIT_NONE was selected (this is broken)\n",
1882 __FILE__
, __LINE__
);
1890 if( Debug_level
> 2 )
1891 printf("DEBUG %s/%d: no wait method was chosen\n", __FILE__
, __LINE__
);
1897 } /* end of lio_wait4asyncio */
1899 #endif /* ifndef linux */
1903 /***********************************************************************
1904 * The following code is provided as unit test.
1905 * Just define add "-DUNIT_TEST=1" to the cc line.
1908 ***********************************************************************/
1909 struct unit_info_t
{
1914 { LIO_IO_SYNC
, 0, "sync io" },
1915 { LIO_IO_SYNCV
, 0, "sync readv/writev" },
1916 { LIO_IO_SYNCP
, 0, "sync pread/pwrite" },
1917 { LIO_IO_ASYNC
, 0, "async io, def wait" },
1918 { LIO_IO_SLISTIO
, 0, "sync listio" },
1919 { LIO_IO_ALISTIO
, 0, "async listio, def wait" },
1920 { LIO_IO_ASYNC
|LIO_WAIT_ACTIVE
, 0, "async active" },
1921 { LIO_IO_ASYNC
|LIO_WAIT_RECALL
, 0, "async recall/suspend" },
1922 { LIO_IO_ASYNC
|LIO_WAIT_SIGPAUSE
, SIGUSR1
, "async sigpause" },
1923 { LIO_IO_ASYNC
|LIO_WAIT_SIGACTIVE
, SIGUSR1
, "async sigactive" },
1924 { LIO_IO_ALISTIO
|LIO_WAIT_ACTIVE
, 0, "async listio active" },
1925 { LIO_IO_ALISTIO
|LIO_WAIT_RECALL
, 0, "async listio recall" },
1926 { LIO_IO_ALISTIO
|LIO_WAIT_SIGACTIVE
, SIGUSR1
, "async listio sigactive" },
1927 { LIO_IO_ALISTIO
|LIO_WAIT_SIGPAUSE
, SIGUSR1
, "async listio sigpause" },
1928 { LIO_IO_ASYNC
, SIGUSR2
, "async io, def wait, sigusr2" },
1929 { LIO_IO_ALISTIO
, SIGUSR2
, "async listio, def wait, sigusr2" },
1937 extern char *optarg
;
1948 int exit_status
= 0;
1951 char *symbols
= NULL
;
1954 while( (c
= getopt(argc
,argv
,"s:di:")) != -1 ){
1956 case 's': symbols
= optarg
; break;
1957 case 'd': ++die_on_err
; break;
1958 case 'i': iter
= atoi(optarg
); break;
1962 if ((fd
=open("unit_test_file", O_CREAT
|O_RDWR
|O_TRUNC
, 0777)) == -1 ) {
1963 perror("open(unit_test_file, O_CREAT|O_RDWR|O_TRUNC, 0777) failed");
1969 if ( symbols
!= NULL
) {
1970 if ( (method
=lio_parse_io_arg2(symbols
, &err
)) == -1 ){
1971 printf("lio_parse_io_arg2(%s, &err) failed, bad token starting at %s\n",
1977 printf("lio_parse_io_arg2(%s, &err) returned %#o\n", symbols
, method
);
1980 for(ind
=0; ind
< iter
; ind
++ ) {
1981 memset( buffer
, 'A', 4096 );
1982 if( lseek(fd
, 0, 0) == -1 ){
1983 printf("lseek(fd,0,0), %d, failed, errno %d\n",
1987 if ((ret
=lio_write_buffer(fd
, method
, buffer
,
1988 size
, SIGUSR1
, &err
, 0)) != size
) {
1989 printf("lio_write_buffer returned -1, err = %s\n", err
);
1991 printf("lio_write_buffer returned %d\n", ret
);
1993 memset( buffer
, 'B', 4096 );
1994 if( lseek(fd
, 0, 0) == -1 ){
1995 printf("lseek(fd,0,0), %d, failed, errno %d\n",
1999 if ((ret
=lio_read_buffer(fd
, method
, buffer
,
2000 size
, SIGUSR2
, &err
, 0)) != size
) {
2001 printf("lio_read_buffer returned -1, err = %s\n", err
);
2003 printf("lio_read_buffer returned %d\n", ret
);
2005 for( i
= 0; i
< 4096; ++i
){
2006 if( buffer
[i
] != 'A' ){
2007 printf(" buffer[%d] = %d\n", i
, buffer
[i
] );
2018 unlink("unit_test_file");
2022 for(ind
=0; ind
< sizeof(Unit_info
)/sizeof(struct unit_info_t
); ind
++ ) {
2024 printf("\n********* write %s ***************\n", Unit_info
[ind
].str
);
2025 if( lseek(fd
, 0, 0) == -1 ){
2026 printf("lseek(fd,0,0), %d, failed, errno %d\n",
2031 memset( buffer
, 'A', 4096 );
2032 if ((ret
=lio_write_buffer(fd
, Unit_info
[ind
].method
, buffer
,
2033 size
, Unit_info
[ind
].sig
, &err
, 0)) != size
) {
2034 printf(">>>>> lio_write_buffer(fd,0%x,buffer,%d,%d,err,0) returned -1,\n err = %s\n",
2035 Unit_info
[ind
].method
, size
, Unit_info
[ind
].sig
, err
);
2040 printf("lio_write_buffer returned %d\n", ret
);
2043 printf("\n********* read %s ***************\n", Unit_info
[ind
].str
);
2044 if( lseek(fd
, 0, 0) == -1 ){
2045 printf("lseek(fd,0,0), %d, failed, errno %d\n",
2049 memset( buffer
, 'B', 4096 );
2050 if ((ret
=lio_read_buffer(fd
, Unit_info
[ind
].method
, buffer
,
2051 size
, Unit_info
[ind
].sig
, &err
, 0)) != size
) {
2052 printf(">>>>> lio_read_buffer(fd,0%x,buffer,%d,%d,err,0) returned -1,\n err = %s\n",
2053 Unit_info
[ind
].method
, size
, Unit_info
[ind
].sig
, err
);
2058 printf("lio_read_buffer returned %d\n", ret
);
2061 for( i
= 0; i
< 4096; ++i
){
2062 if( buffer
[i
] != 'A' ){
2063 printf(" buffer[%d] = %d\n", i
, buffer
[i
] );
2077 unlink("unit_test_file");