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
85 #include <sys/types.h>
88 #include <sys/param.h>
90 #include <sys/types.h>
94 #include <sys/secparm.h>
96 #include <sys/listio.h>
98 /* for linux or sgi */
99 #include <sys/uio.h> /* readv(2)/writev(2) */
100 #include <string.h> /* bzero */
105 #include <stdlib.h> /* atoi, abs */
107 #include "tlibio.h" /* defines LIO* marcos */
110 #define PATH_MAX MAXPATHLEN
113 #if 0 /* disabled until it's needed -- roehrich 6/11/97 */
114 #define BUG1_workaround 1 /* Work around a condition where aio_return gives
115 * a value of zero but there is no errno followup
116 * and the read/write operation actually did its
123 static void lio_async_signal_handler();
126 static void lio_async_callback_handler();
130 * Define the structure as used in lio_parse_arg1 and lio_help1
132 struct lio_info_type Lio_info1[] = {
133 { "s", LIO_IO_SYNC, "sync i/o" },
134 { "p", LIO_IO_ASYNC|LIO_WAIT_SIGACTIVE, "async i/o using a loop to wait for a signal" },
135 { "b", LIO_IO_ASYNC|LIO_WAIT_SIGPAUSE, "async i/o using pause" },
136 { "a", LIO_IO_ASYNC|LIO_WAIT_RECALL, "async i/o using recall/aio_suspend" },
139 LIO_RANDOM|LIO_IO_TYPES|LIO_WAIT_TYPES, "random sync i/o types and wait methods" },
141 LIO_RANDOM|LIO_IO_ATYPES|LIO_WAIT_ATYPES, "random i/o types and wait methods" },
144 LIO_RANDOM|LIO_IO_TYPES|LIO_WAIT_TYPES, "random i/o types and wait methods" },
146 LIO_RANDOM|LIO_IO_TYPES|LIO_WAIT_TYPES, "random i/o types and wait methods" },
148 { "l", LIO_IO_SLISTIO|LIO_WAIT_RECALL, "single stride sync listio" },
149 { "L", LIO_IO_ALISTIO|LIO_WAIT_RECALL, "single stride async listio using recall" },
150 { "X", LIO_IO_ALISTIO|LIO_WAIT_SIGPAUSE, "single stride async listio using pause" },
151 { "v", LIO_IO_SYNCV, "single buffer sync readv/writev" },
152 { "P", LIO_IO_SYNCP, "sync pread/pwrite" },
156 * Define the structure used by lio_parse_arg2 and lio_help2
158 struct lio_info_type Lio_info2[] = {
159 { "sync", LIO_IO_SYNC, "sync i/o (read/write)"},
160 { "async", LIO_IO_ASYNC, "async i/o (reada/writea/aio_read/aio_write)" },
161 { "slistio", LIO_IO_SLISTIO, "single stride sync listio" },
162 { "alistio", LIO_IO_ALISTIO, "single stride async listio" },
163 { "syncv", LIO_IO_SYNCV, "single buffer sync readv/writev"},
164 { "syncp", LIO_IO_SYNCP, "pread/pwrite"},
165 { "active", LIO_WAIT_ACTIVE, "spin on status/control values" },
166 { "recall", LIO_WAIT_RECALL, "use recall(2)/aio_suspend(3) to wait for i/o to complete" },
167 { "sigactive", LIO_WAIT_SIGACTIVE, "spin waiting for signal" },
168 { "sigpause", LIO_WAIT_SIGPAUSE, "call pause(2) to wait for signal" },
169 /* nowait is a touchy thing, it's an accident that this implementation worked at all. 6/27/97 roehrich */
170 /* { "nowait", LIO_WAIT_NONE, "do not wait for async io to complete" },*/
171 { "random", LIO_RANDOM, "set random bit" },
173 LIO_RANDOM|LIO_IO_TYPES|LIO_WAIT_TYPES,
174 "all random i/o types and wait methods (except nowait)" },
177 char Lio_SysCall[PATH_MAX]; /* string containing last i/o system call */
179 static volatile int Received_signal = 0; /* number of signals received */
180 static volatile int Rec_signal;
182 static volatile int Received_callback = 0; /* number of callbacks received */
183 static volatile int Rec_callback;
185 static char Errormsg[500];
186 static int Debug_level = 0;
190 /***********************************************************************
193 * Determine the bounds of a strided request, normalized to offset. Returns
194 * the number of bytes needed to satisfy the request, and optionally sets
195 * *min and *max to the mininum and maximum bytes referenced, normalized
198 * Returns -1 on error - the only possible error conditions are illegal values
199 * for nstrides and/or bytes_per_stride - both parameters must be >= 0.
202 ***********************************************************************/
205 stride_bounds(offset, stride, nstrides, bytes_per_stride, min, max)
209 int bytes_per_stride;
213 int nbytes, min_byte, max_byte;
219 if (nstrides < 0 || bytes_per_stride < 0) {
224 stride = bytes_per_stride;
228 * Determine the # of bytes needed to satisfy the request. This
229 * value, along with the offset argument, determines the min and max
234 nbytes = abs(stride) * (nstrides-1) + bytes_per_stride;
237 max_byte = offset + bytes_per_stride - 1;
238 min_byte = max_byte - nbytes + 1;
241 max_byte = min_byte + nbytes - 1;
255 /***********************************************************************
256 * This function will allow someone to set the debug level.
257 ***********************************************************************/
268 /***********************************************************************
269 * This function will parse a string and return desired io-method.
270 * Only the first character of the string is used.
272 * This function does not provide for meaningful option arguments,
273 * but it supports current growfiles/btlk interface.
276 ***********************************************************************/
278 lio_parse_io_arg1(char *string)
285 * Determine if token is a valid string.
287 for(ind=0; ind<sizeof(Lio_info1)/sizeof(struct lio_info_type); ind++) {
288 if ( strcmp(string, Lio_info1[ind].token) == 0 ) {
289 mask |= Lio_info1[ind].bits;
303 /***********************************************************************
304 * This function will print a help message describing the characters
305 * that can be parsed by lio_parse_io_arg1().
306 * They will be printed one per line.
308 ***********************************************************************/
310 lio_help1(char *prefix)
314 for(ind=0; ind<sizeof(Lio_info1)/sizeof(struct lio_info_type); ind++) {
315 printf("%s %s : %s\n", prefix,
316 Lio_info1[ind].token, Lio_info1[ind].desc);
322 /***********************************************************************
323 * This function will parse a string and return the desired io-method.
324 * This function will take a comma separated list of io type and wait
325 * method tokens as defined in Lio_info2[]. If a token does not match
326 * any of the tokens in Lio_info2[], it will be coverted to a number.
327 * If it was a number, those bits are also set.
330 ***********************************************************************/
332 lio_parse_io_arg2(char *string, char **badtoken)
334 char *token = string;
348 for (; ((*cc != ',') && (*cc != '\0')); cc++);
355 * Determine if token is a valid string or number and if
356 * so, add the bits to the mask.
358 for(ind=0; ind<sizeof(Lio_info2)/sizeof(struct lio_info_type); ind++) {
359 if ( strcmp(token, Lio_info2[ind].token) == 0 ) {
360 mask |= Lio_info2[ind].bits;
367 * If token does not match one of the defined tokens, determine
368 * if it is a number, if so, add the bits.
371 if (sscanf(token, "%i%c", &tmp, &chr) == 1 ) {
379 if (!found) { /* token is not valid */
380 if ( badtoken != NULL)
394 /***********************************************************************
395 * This function will print a help message describing the tokens
396 * that can be parsed by lio_parse_io_arg2().
397 * It will print them one per line.
400 ***********************************************************************/
402 lio_help2(char *prefix)
406 for(ind=0; ind<sizeof(Lio_info2)/sizeof(struct lio_info_type); ind++) {
407 printf("%s %s : %s\n", prefix,
408 Lio_info2[ind].token, Lio_info2[ind].desc);
414 /***********************************************************************
415 * This is an internal signal handler.
416 * If the handler is called, it will increment the Received_signal
418 ***********************************************************************/
420 lio_async_signal_handler(int sig)
423 printf("DEBUG %s/%d: received signal %d, a signal caught %d times\n",
424 __FILE__, __LINE__, sig, Received_signal+1);
433 /***********************************************************************
434 * This is an internal callback handler.
435 * If the handler is called, it will increment the Received_callback
437 ***********************************************************************/
439 lio_async_callback_handler(sigval_t sigval)
442 printf("DEBUG %s/%d: received callback, nbytes=%ld, a callback called %d times\n",
443 __FILE__, __LINE__, sigval.sival_int, Received_callback+1);
451 /***********************************************************************
453 * This function will randomly choose an io type and wait method
454 * from set of io types and wait methods. Since this information
455 * is stored in a bitmask, it randomly chooses an io type from
456 * the io type bits specified and does the same for wait methods.
459 * This function will return a value with all non choosen io type
460 * and wait method bits cleared. The LIO_RANDOM bit is also
461 * cleared. All other bits are left unchanged.
464 ***********************************************************************/
466 lio_random_methods(long curr_mask)
471 /* remove random select, io type, and wait method bits from curr_mask */
472 mask = curr_mask & (~(LIO_IO_TYPES | LIO_WAIT_TYPES | LIO_RANDOM));
474 /* randomly select io type from specified io types */
475 mask = mask | random_bit(curr_mask & LIO_IO_TYPES);
477 /* randomly select wait methods from specified wait methods */
478 mask = mask | random_bit(curr_mask & LIO_WAIT_TYPES);
483 /***********************************************************************
484 * Generic write function
485 * This function can be used to do a write using write(2), writea(2),
486 * aio_write(3), writev(2), pwrite(2),
487 * or single stride listio(2)/lio_listio(3).
488 * By setting the desired bits in the method
489 * bitmask, the caller can control the type of write and the wait method
490 * that will be used. If no io type bits are set, write will be used.
492 * If async io was attempted and no wait method bits are set then the
493 * wait method is: recall(2) for writea(2) and listio(2); aio_suspend(3) for
494 * aio_write(3) and lio_listio(3).
496 * If multiple wait methods are specified,
497 * only one wait method will be used. The order is predetermined.
499 * If the call specifies a signal and one of the two signal wait methods,
500 * a signal handler for the signal is set. This will reset an already
501 * set handler for this signal.
503 * If the LIO_RANDOM method bit is set, this function will randomly
504 * choose a io type and wait method from bits in the method argument.
506 * If an error is encountered, an error message will be generated
507 * in a internal static buffer. If errmsg is not NULL, it will
508 * be updated to point to the static buffer, allowing the caller
509 * to print the error message.
512 * If a system call fails, -errno is returned.
513 * If LIO_WAIT_NONE bit is set, the return value is the return value
514 * of the system call.
515 * If the io did not fail, the amount of data written is returned.
516 * If the size the system call say was written is different
517 * then what was asked to be written, errmsg is updated for
518 * this error condition. The return value is still the amount
519 * the system call says was written.
522 ***********************************************************************/
524 lio_write_buffer(fd, method, buffer, size, sig, errmsg, wrd)
525 int fd; /* open file descriptor */
526 int method; /* contains io type and wait method bitmask */
527 char *buffer; /* pointer to buffer */
528 int size; /* the size of the io */
529 int sig; /* signal to use if async io */
530 char **errmsg; /* char pointer that will be updated to point to err message */
531 long wrd; /* to allow future features, use zero for now */
533 int ret = 0; /* syscall return or used to get random method */
534 char *io_type; /* Holds string of type of io */
536 int omethod = method;
537 int listio_cmd; /* Holds the listio/lio_listio cmd */
540 struct listreq request; /* Used when a listio is wanted */
541 struct iosw status, *statptr[1];
543 /* for linux or sgi */
544 struct iovec iov; /* iovec for writev(2) */
547 aiocb_t aiocbp; /* POSIX aio control block */
548 aiocb_t *aiolist[1]; /* list of aio control blocks for lio_listio */
549 off64_t poffset; /* pwrite(2) offset */
553 * If LIO_RANDOM bit specified, get new method randomly.
555 if ( method & LIO_RANDOM ) {
556 if( Debug_level > 3 )
557 printf("DEBUG %s/%d: method mask to choose from: %#o\n", __FILE__, __LINE__, method );
558 method = lio_random_methods(method);
559 if ( Debug_level > 2 )
560 printf("DEBUG %s/%d: random chosen method %#o\n", __FILE__, __LINE__, method);
563 if ( errmsg != NULL )
566 Rec_signal=Received_signal; /* get the current number of signals received */
568 Rec_callback=Received_callback; /* get the current number of callbacks received */
572 bzero(&status, sizeof(struct iosw));
573 bzero(&request, sizeof(struct listreq));
574 statptr[0] = &status;
576 /* for linux or sgi */
577 bzero(&iov, sizeof(struct iovec));
578 iov.iov_base = buffer;
582 bzero(&aiocbp, sizeof(aiocb_t));
583 aiocbp.aio_fildes = fd;
584 aiocbp.aio_nbytes = size;
585 aiocbp.aio_buf = buffer;
586 /* aiocbp.aio_offset = lseek( fd, 0, SEEK_CUR ); -- set below */
587 aiocbp.aio_sigevent.sigev_notify = SIGEV_NONE;
588 aiocbp.aio_sigevent.sigev_signo = 0;
589 aiocbp.aio_sigevent.sigev_func = NULL;
590 aiocbp.aio_sigevent.sigev_value.sival_int = 0;
591 aiolist[0] = &aiocbp;
593 if( (ret = lseek( fd, 0, SEEK_CUR )) == -1 ){
595 /* If there is an error and it is not ESPIPE then kick out the error.
596 * If the fd is a fifo then we have to make sure that
597 * lio_random_methods() didn't select pwrite/pread; if it did then
598 * switch to write/read.
600 if( errno == ESPIPE ){
601 if( method & LIO_IO_SYNCP ){
602 if( omethod & LIO_RANDOM ){
603 method &= ~LIO_IO_SYNCP;
604 method |= LIO_IO_SYNC;
605 if( Debug_level > 2 )
606 printf("DEBUG %s/%d: random chosen method switched to %#o for fifo\n", __FILE__, __LINE__, method );
608 else if( Debug_level ){
609 printf("DEBUG %s/%d: pwrite will fail when it writes to a fifo\n",
610 __FILE__, __LINE__ );
613 /* else: let it ride */
616 sprintf(Errormsg, "%s/%d lseek(fd=%d,0,SEEK_CUR) failed, errno=%d %s",
617 __FILE__, __LINE__, fd, errno, strerror(errno));
621 poffset = (off64_t)ret;
622 aiocbp.aio_offset = ret;
627 * If the LIO_USE_SIGNAL bit is not set, only use the signal
628 * if the LIO_WAIT_SIGPAUSE or the LIO_WAIT_SIGACTIVE bits are bit.
629 * Otherwise there is not necessary a signal handler to trap
632 if ( sig && !(method & LIO_USE_SIGNAL) &&
633 ! (method & LIO_WAIT_SIGTYPES) ){
635 sig=0; /* ignore signal parameter */
639 if ( sig && (method & LIO_WAIT_CBTYPES) )
640 sig=0; /* ignore signal parameter */
644 * only setup signal hander if sig was specified and
645 * a sig wait method was specified.
646 * Doing this will change the handler for this signal. The
647 * old signal handler will not be restored.
648 *** restoring the signal handler could be added ***
651 if ( sig && (method & LIO_WAIT_SIGTYPES) ){
653 sigctl(SCTL_REG, sig, lio_async_signal_handler);
656 aiocbp.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
657 aiocbp.aio_sigevent.sigev_signo = sig;
658 sigset(sig, lio_async_signal_handler);
662 else if( method & LIO_WAIT_CBTYPES ){
663 /* sival_int just has to be something that I can use
664 * to identify the callback, and "size" happens to be handy...
666 aiocbp.aio_sigevent.sigev_notify = SIGEV_CALLBACK;
667 aiocbp.aio_sigevent.sigev_func = lio_async_callback_handler;
668 aiocbp.aio_sigevent.sigev_value.sival_int = size;
673 * Determine the system call that will be called and produce
674 * the string of the system call and place it in Lio_SysCall.
675 * Also update the io_type char pointer to give brief description
676 * of system call. Execute the system call and check for
677 * system call failure. If sync i/o, return the number of
678 * bytes written/read.
681 if ( (method & LIO_IO_SYNC) || (method & LIO_IO_TYPES) == 0 ){
683 * write(2) is used if LIO_IO_SYNC bit is set or not none
684 * of the LIO_IO_TYPES bits are set (default).
688 "write(%d, buf, %d)", fd, size);
692 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
695 if ((ret = write(fd, buffer, size)) == -1) {
696 sprintf(Errormsg, "%s/%d write(%d, buf, %d) ret:-1, errno=%d %s",
698 fd, size, errno, strerror(errno));
704 "%s/%d write(%d, buf, %d) returned=%d",
708 else if ( Debug_level > 1 )
709 printf("DEBUG %s/%d: write completed without error (ret %d)\n",
710 __FILE__, __LINE__, ret);
716 else if ( method & LIO_IO_ASYNC ) {
719 "writea(%d, buf, %d, &status, %d)", fd, size, sig);
723 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
727 if ((ret = writea(fd, buffer, size, &status, sig)) == -1) {
729 "%s/%d writea(%d, buf, %d, &stat, %d) ret:-1, errno=%d %s",
731 fd, size, sig, errno, strerror(errno));
738 "aio_write(fildes=%d, buf, nbytes=%d, signo=%d)", fd, size, sig);
742 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
747 if ((ret = aio_write(&aiocbp)) == -1) {
749 "%s/%d aio_write(fildes=%d, buf, nbytes=%d, signo=%d) ret:-1, errno=%d %s",
751 fd, size, sig, errno, strerror(errno));
759 else if ( method & LIO_IO_SLISTIO ) {
761 request.li_opcode = LO_WRITE;
762 request.li_fildes = fd;
763 request.li_buf = buffer;
764 request.li_nbyte = size;
765 request.li_status = &status;
766 request.li_signo = sig;
767 request.li_nstride = 0;
768 request.li_filstride = 0;
769 request.li_memstride = 0;
772 io_type="listio(2) sync write";
775 "listio(LC_WAIT, &req, 1) LO_WRITE, fd:%d, nbyte:%d",
779 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
783 if ( listio(listio_cmd, &request, 1) == -1 ) {
784 sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
786 Lio_SysCall, fd, size, errno, strerror(errno));
791 if ( Debug_level > 1 )
792 printf("DEBUG %s/%d: %s did not return -1\n",
793 __FILE__, __LINE__, Lio_SysCall);
795 ret=lio_check_asyncio(io_type, size, &status);
801 aiocbp.aio_lio_opcode = LIO_WRITE;
803 io_type="lio_listio(3) sync write";
806 "lio_listio(LIO_WAIT, aiolist, 1, NULL) LIO_WRITE, fd:%d, nbyte:%d, sig:%d",
810 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
815 if ( lio_listio(listio_cmd, aiolist, 1, NULL) == -1 ) {
816 sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
818 Lio_SysCall, fd, size, errno, strerror(errno));
824 if ( Debug_level > 1 )
825 printf("DEBUG %s/%d: %s did not return -1\n",
826 __FILE__, __LINE__, Lio_SysCall);
828 ret=lio_check_asyncio(io_type, size, &aiocbp, method);
831 } /* LIO_IO_SLISTIO */
833 else if ( method & LIO_IO_ALISTIO ) {
835 request.li_opcode = LO_WRITE;
836 request.li_fildes = fd;
837 request.li_buf = buffer;
838 request.li_nbyte = size;
839 request.li_status = &status;
840 request.li_signo = sig;
841 request.li_nstride = 0;
842 request.li_filstride = 0;
843 request.li_memstride = 0;
846 io_type="listio(2) async write";
849 "listio(LC_START, &req, 1) LO_WRITE, fd:%d, nbyte:%d",
853 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
857 if ( listio(listio_cmd, &request, 1) == -1 ) {
858 sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
860 Lio_SysCall, fd, size, errno, strerror(errno));
866 aiocbp.aio_lio_opcode = LIO_WRITE;
867 listio_cmd=LIO_NOWAIT;
868 io_type="lio_listio(3) async write";
871 "lio_listio(LIO_NOWAIT, aiolist, 1, NULL) LIO_WRITE, fd:%d, nbyte:%d",
875 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
880 if ( lio_listio(listio_cmd, aiolist, 1, NULL) == -1 ) {
881 sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
883 Lio_SysCall, fd, size, errno, strerror(errno));
889 }/* LIO_IO_ALISTIO */
892 else if ( method & LIO_IO_SYNCV ) {
896 "writev(%d, &iov, 1) nbyte:%d", fd, size);
899 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
901 if ((ret = writev(fd, &iov, 1)) == -1) {
902 sprintf(Errormsg, "%s/%d writev(%d, iov, 1) nbyte:%d ret:-1, errno=%d %s",
904 fd, size, errno, strerror(errno));
910 "%s/%d writev(%d, iov, 1) nbyte:%d returned=%d",
914 else if ( Debug_level > 1 )
915 printf("DEBUG %s/%d: writev completed without error (ret %d)\n",
916 __FILE__, __LINE__, ret);
923 else if ( method & LIO_IO_SYNCP ) {
927 "pwrite(%d, buf, %d, %lld)", fd, size, poffset);
930 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
932 if ((ret = pwrite(fd, buffer, size, poffset)) == -1) {
933 sprintf(Errormsg, "%s/%d pwrite(%d, buf, %d, %lld) ret:-1, errno=%d %s",
935 fd, size, poffset, errno, strerror(errno));
941 "%s/%d pwrite(%d, buf, %d, %lld) returned=%d",
943 fd, size, poffset, ret);
945 else if ( Debug_level > 1 )
946 printf("DEBUG %s/%d: pwrite completed without error (ret %d)\n",
947 __FILE__, __LINE__, ret);
954 printf("DEBUG %s/%d: No I/O method chosen\n", __FILE__, __LINE__ );
959 * wait for async io to complete.
962 ret=lio_wait4asyncio(method, fd, statptr);
965 ret=lio_wait4asyncio(method, fd, &aiocbp);
969 * If there was an error waiting for async i/o to complete,
970 * return the error value (errno) to the caller.
971 * Note: Errormsg should already have been updated.
978 * If i/o was not waited for (may not have been completed at this time),
979 * return the size that was requested.
985 * check that async io was successful.
986 * Note: if the there was an system call failure, -errno
987 * was returned and Errormsg should already have been updated.
988 * If amount i/o was different than size, Errormsg should already
989 * have been updated but the actual i/o size if returned.
993 ret=lio_check_asyncio(io_type, size, &status);
996 ret=lio_check_asyncio(io_type, size, &aiocbp, method);
1000 } /* end of lio_write_buffer */
1002 /***********************************************************************
1003 * Generic read function
1004 * This function can be used to do a read using read(2), reada(2),
1005 * aio_read(3), readv(2), pread(2),
1006 * or single stride listio(2)/lio_listio(3).
1007 * By setting the desired bits in the method
1008 * bitmask, the caller can control the type of read and the wait method
1009 * that will be used. If no io type bits are set, read will be used.
1011 * If async io was attempted and no wait method bits are set then the
1012 * wait method is: recall(2) for reada(2) and listio(2); aio_suspend(3) for
1013 * aio_read(3) and lio_listio(3).
1015 * If multiple wait methods are specified,
1016 * only one wait method will be used. The order is predetermined.
1018 * If the call specifies a signal and one of the two signal wait methods,
1019 * a signal handler for the signal is set. This will reset an already
1020 * set handler for this signal.
1022 * If the LIO_RANDOM method bit is set, this function will randomly
1023 * choose a io type and wait method from bits in the method argument.
1025 * If an error is encountered, an error message will be generated
1026 * in a internal static buffer. If errmsg is not NULL, it will
1027 * be updated to point to the static buffer, allowing the caller
1028 * to print the error message.
1031 * If a system call fails, -errno is returned.
1032 * If LIO_WAIT_NONE bit is set, the return value is the return value
1033 * of the system call.
1034 * If the io did not fail, the amount of data written is returned.
1035 * If the size the system call say was written is different
1036 * then what was asked to be written, errmsg is updated for
1037 * this error condition. The return value is still the amount
1038 * the system call says was written.
1041 ***********************************************************************/
1043 lio_read_buffer(fd, method, buffer, size, sig, errmsg, wrd)
1044 int fd; /* open file descriptor */
1045 int method; /* contains io type and wait method bitmask */
1046 char *buffer; /* pointer to buffer */
1047 int size; /* the size of the io */
1048 int sig; /* signal to use if async io */
1049 char **errmsg; /* char pointer that will be updated to point to err message */
1050 long wrd; /* to allow future features, use zero for now */
1052 int ret = 0; /* syscall return or used to get random method */
1053 char *io_type; /* Holds string of type of io */
1055 int listio_cmd; /* Holds the listio/lio_listio cmd */
1056 int omethod = method;
1059 struct listreq request; /* Used when a listio is wanted */
1060 struct iosw status, *statptr[1];
1062 /* for linux or sgi */
1063 struct iovec iov; /* iovec for readv(2) */
1066 aiocb_t aiocbp; /* POSIX aio control block */
1067 aiocb_t *aiolist[1]; /* list of aio control blocks for lio_listio */
1068 off64_t poffset; /* pread(2) offset */
1072 * If LIO_RANDOM bit specified, get new method randomly.
1074 if ( method & LIO_RANDOM ) {
1075 if( Debug_level > 3 )
1076 printf("DEBUG %s/%d: method mask to choose from: %#o\n", __FILE__, __LINE__, method );
1077 method = lio_random_methods(method);
1078 if ( Debug_level > 2 )
1079 printf("DEBUG %s/%d: random chosen method %#o\n", __FILE__, __LINE__, method);
1082 if ( errmsg != NULL )
1085 Rec_signal=Received_signal; /* get the current number of signals received */
1087 Rec_callback=Received_callback; /* get the current number of callbacks received */
1091 bzero(&status, sizeof(struct iosw));
1092 bzero(&request, sizeof(struct listreq));
1093 statptr[0] = &status;
1095 /* for linux or sgi */
1096 bzero(&iov, sizeof(struct iovec));
1097 iov.iov_base = buffer;
1101 bzero(&aiocbp, sizeof(aiocb_t));
1102 aiocbp.aio_fildes = fd;
1103 aiocbp.aio_nbytes = size;
1104 aiocbp.aio_buf = buffer;
1105 /* aiocbp.aio_offset = lseek( fd, 0, SEEK_CUR ); -- set below */
1106 aiocbp.aio_sigevent.sigev_notify = SIGEV_NONE;
1107 aiocbp.aio_sigevent.sigev_signo = 0;
1108 aiocbp.aio_sigevent.sigev_func = NULL;
1109 aiocbp.aio_sigevent.sigev_value.sival_int = 0;
1110 aiolist[0] = &aiocbp;
1112 if( (ret = lseek( fd, 0, SEEK_CUR )) == -1 ){
1114 /* If there is an error and it is not ESPIPE then kick out the error.
1115 * If the fd is a fifo then we have to make sure that
1116 * lio_random_methods() didn't select pwrite/pread; if it did then
1117 * switch to write/read.
1119 if( errno == ESPIPE ){
1120 if( method & LIO_IO_SYNCP ){
1121 if( omethod & LIO_RANDOM ){
1122 method &= ~LIO_IO_SYNCP;
1123 method |= LIO_IO_SYNC;
1124 if( Debug_level > 2 )
1125 printf("DEBUG %s/%d: random chosen method switched to %#o for fifo\n", __FILE__, __LINE__, method );
1127 else if( Debug_level ){
1128 printf("DEBUG %s/%d: pread will fail when it reads from a fifo\n",
1129 __FILE__, __LINE__ );
1132 /* else: let it ride */
1135 sprintf(Errormsg, "%s/%d lseek(fd=%d,0,SEEK_CUR) failed, errno=%d %s",
1136 __FILE__, __LINE__, fd, errno, strerror(errno));
1140 poffset = (off64_t)ret;
1141 aiocbp.aio_offset = ret;
1146 * If the LIO_USE_SIGNAL bit is not set, only use the signal
1147 * if the LIO_WAIT_SIGPAUSE or the LIO_WAIT_SIGACTIVE bits are set.
1148 * Otherwise there is not necessarily a signal handler to trap
1151 if ( sig && !(method & LIO_USE_SIGNAL) &&
1152 ! (method & LIO_WAIT_SIGTYPES) ){
1154 sig=0; /* ignore signal parameter */
1158 if ( sig && (method & LIO_WAIT_CBTYPES) )
1159 sig=0; /* ignore signal parameter */
1163 * only setup signal hander if sig was specified and
1164 * a sig wait method was specified.
1165 * Doing this will change the handler for this signal. The
1166 * old signal handler will not be restored.
1167 *** restoring the signal handler could be added ***
1170 if ( sig && (method & LIO_WAIT_SIGTYPES) ){
1172 sigctl(SCTL_REG, sig, lio_async_signal_handler);
1175 aiocbp.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
1176 aiocbp.aio_sigevent.sigev_signo = sig;
1177 sigset(sig, lio_async_signal_handler);
1181 else if( method & LIO_WAIT_CBTYPES ){
1182 aiocbp.aio_sigevent.sigev_notify = SIGEV_CALLBACK;
1183 aiocbp.aio_sigevent.sigev_func = lio_async_callback_handler;
1184 /* sival_int just has to be something that I can use
1185 * to identify the callback, and "size" happens to be handy...
1187 aiocbp.aio_sigevent.sigev_value.sival_int = size;
1192 * Determine the system call that will be called and produce
1193 * the string of the system call and place it in Lio_SysCall.
1194 * Also update the io_type char pointer to give brief description
1195 * of system call. Execute the system call and check for
1196 * system call failure. If sync i/o, return the number of
1197 * bytes written/read.
1200 if ( (method & LIO_IO_SYNC) || (method & LIO_IO_TYPES) == 0 ){
1202 * read(2) is used if LIO_IO_SYNC bit is set or not none
1203 * of the LIO_IO_TYPES bits are set (default).
1206 sprintf(Lio_SysCall,
1207 "read(%d, buf, %d)", fd, size);
1210 if ( Debug_level ) {
1211 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
1214 if ((ret = read(fd, buffer, size)) == -1) {
1215 sprintf(Errormsg, "%s/%d read(%d, buf, %d) ret:-1, errno=%d %s",
1217 fd, size, errno, strerror(errno));
1221 if ( ret != size ) {
1223 "%s/%d read(%d, buf, %d) returned=%d",
1227 else if ( Debug_level > 1 )
1228 printf("DEBUG %s/%d: read completed without error (ret %d)\n",
1229 __FILE__, __LINE__, ret);
1235 else if ( method & LIO_IO_ASYNC ) {
1237 sprintf(Lio_SysCall,
1238 "reada(%d, buf, %d, &status, %d)", fd, size, sig);
1241 if ( Debug_level ) {
1242 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
1246 if ((ret = reada(fd, buffer, size, &status, sig)) == -1) {
1248 "%s/%d reada(%d, buf, %d, &stat, %d) ret:-1, errno=%d %s",
1250 fd, size, sig, errno, strerror(errno));
1256 sprintf(Lio_SysCall,
1257 "aio_read(fildes=%d, buf, nbytes=%d, signo=%d)", fd, size, sig);
1260 if ( Debug_level ) {
1261 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
1266 if ((ret = aio_read(&aiocbp)) == -1) {
1268 "%s/%d aio_read(fildes=%d, buf, nbytes=%d, signo=%d) ret:-1, errno=%d %s",
1270 fd, size, sig, errno, strerror(errno));
1276 } /* LIO_IO_ASYNC */
1278 else if ( method & LIO_IO_SLISTIO ) {
1280 request.li_opcode = LO_READ;
1281 request.li_fildes = fd;
1282 request.li_buf = buffer;
1283 request.li_nbyte = size;
1284 request.li_status = &status;
1285 request.li_signo = sig;
1286 request.li_nstride = 0;
1287 request.li_filstride = 0;
1288 request.li_memstride = 0;
1291 io_type="listio(2) sync read";
1293 sprintf(Lio_SysCall,
1294 "listio(LC_WAIT, &req, 1) LO_READ, fd:%d, nbyte:%d",
1297 if ( Debug_level ) {
1298 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
1302 if ( listio(listio_cmd, &request, 1) == -1 ) {
1303 sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1305 Lio_SysCall, fd, size, errno, strerror(errno));
1310 if ( Debug_level > 1 )
1311 printf("DEBUG %s/%d: %s did not return -1\n",
1312 __FILE__, __LINE__, Lio_SysCall);
1314 ret=lio_check_asyncio(io_type, size, &status);
1318 aiocbp.aio_lio_opcode = LIO_READ;
1319 listio_cmd=LIO_WAIT;
1320 io_type="lio_listio(3) sync read";
1322 sprintf(Lio_SysCall,
1323 "lio_listio(LIO_WAIT, aiolist, 1, NULL) LIO_READ, fd:%d, nbyte:%d",
1326 if ( Debug_level ) {
1327 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
1332 if ( lio_listio(listio_cmd, aiolist, 1, NULL) == -1 ) {
1333 sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1335 Lio_SysCall, fd, size, errno, strerror(errno));
1341 if ( Debug_level > 1 )
1342 printf("DEBUG %s/%d: %s did not return -1\n",
1343 __FILE__, __LINE__, Lio_SysCall);
1345 ret=lio_check_asyncio(io_type, size, &aiocbp, method);
1348 }/* LIO_IO_SLISTIO */
1350 else if ( method & LIO_IO_ALISTIO ) {
1352 request.li_opcode = LO_READ;
1353 request.li_fildes = fd;
1354 request.li_buf = buffer;
1355 request.li_nbyte = size;
1356 request.li_status = &status;
1357 request.li_signo = sig;
1358 request.li_nstride = 0;
1359 request.li_filstride = 0;
1360 request.li_memstride = 0;
1362 listio_cmd=LC_START;
1363 io_type="listio(2) async read";
1365 sprintf(Lio_SysCall,
1366 "listio(LC_START, &req, 1) LO_READ, fd:%d, nbyte:%d",
1369 if ( Debug_level ) {
1370 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
1374 if ( listio(listio_cmd, &request, 1) == -1 ) {
1375 sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1377 Lio_SysCall, fd, size, errno, strerror(errno));
1383 aiocbp.aio_lio_opcode = LIO_READ;
1384 listio_cmd=LIO_NOWAIT;
1385 io_type="lio_listio(3) async read";
1387 sprintf(Lio_SysCall,
1388 "lio_listio(LIO_NOWAIT, aiolist, 1, NULL) LIO_READ, fd:%d, nbyte:%d",
1391 if ( Debug_level ) {
1392 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
1397 if ( lio_listio(listio_cmd, aiolist, 1, NULL) == -1 ) {
1398 sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1400 Lio_SysCall, fd, size, errno, strerror(errno));
1406 } /* LIO_IO_ALISTIO */
1409 else if ( method & LIO_IO_SYNCV ) {
1412 sprintf(Lio_SysCall,
1413 "readv(%d, &iov, 1) nbyte:%d", fd, size);
1415 if ( Debug_level ) {
1416 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
1418 if ((ret = readv(fd, &iov, 1)) == -1) {
1419 sprintf(Errormsg, "%s/%d readv(%d, iov, 1) nbyte:%d ret:-1, errno=%d %s",
1421 fd, size, errno, strerror(errno));
1425 if ( ret != size ) {
1427 "%s/%d readv(%d, iov, 1) nbyte:%d returned=%d",
1431 else if ( Debug_level > 1 )
1432 printf("DEBUG %s/%d: readv completed without error (ret %d)\n",
1433 __FILE__, __LINE__, ret);
1436 } /* LIO_IO_SYNCV */
1440 else if ( method & LIO_IO_SYNCP ) {
1443 sprintf(Lio_SysCall,
1444 "pread(%d, buf, %d, %lld)", fd, size, poffset);
1446 if ( Debug_level ) {
1447 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
1449 if ((ret = pread(fd, buffer, size, poffset)) == -1) {
1450 sprintf(Errormsg, "%s/%d pread(%d, buf, %d, %lld) ret:-1, errno=%d %s",
1452 fd, size, poffset, errno, strerror(errno));
1456 if ( ret != size ) {
1458 "%s/%d pread(%d, buf, %d, %lld) returned=%d",
1460 fd, size, poffset, ret);
1462 else if ( Debug_level > 1 )
1463 printf("DEBUG %s/%d: pread completed without error (ret %d)\n",
1464 __FILE__, __LINE__, ret);
1467 } /* LIO_IO_SYNCP */
1471 printf("DEBUG %s/%d: No I/O method chosen\n", __FILE__, __LINE__ );
1476 * wait for async io to complete.
1477 * Note: Sync io should have returned prior to getting here.
1480 ret=lio_wait4asyncio(method, fd, statptr);
1483 ret=lio_wait4asyncio(method, fd, &aiocbp);
1487 * If there was an error waiting for async i/o to complete,
1488 * return the error value (errno) to the caller.
1489 * Note: Errormsg should already have been updated.
1496 * If i/o was not waited for (may not have been completed at this time),
1497 * return the size that was requested.
1503 * check that async io was successful.
1504 * Note: if the there was an system call failure, -errno
1505 * was returned and Errormsg should already have been updated.
1506 * If amount i/o was different than size, Errormsg should already
1507 * have been updated but the actual i/o size if returned.
1511 ret=lio_check_asyncio(io_type, size, &status);
1514 ret=lio_check_asyncio(io_type, size, &aiocbp, method);
1518 } /* end of lio_read_buffer */
1522 /***********************************************************************
1523 * This function will check that async io was successful.
1524 * It can also be used to check sync listio since it uses the
1528 * If status.sw_error is set, -status.sw_error is returned.
1529 * Otherwise sw_count's field value is returned.
1532 ***********************************************************************/
1535 lio_check_asyncio(char *io_type, int size, struct iosw *status)
1537 lio_check_asyncio(char *io_type, int size, aiocb_t *aiocbp, int method)
1543 if ( status->sw_error ) {
1545 "%s/%d %s, sw_error set = %d %s, sw_count = %d",
1546 __FILE__, __LINE__, io_type,
1547 status->sw_error, strerror(status->sw_error), status->sw_count);
1548 return -status->sw_error;
1550 else if ( status->sw_count != size ) {
1552 "%s/%d %s, sw_count not as expected(%d), but actual:%d",
1553 __FILE__, __LINE__, io_type,
1554 size, status->sw_count);
1556 else if ( Debug_level > 1 ) {
1557 printf("DEBUG %s/%d: %s completed without error (sw_error == 0, sw_count == %d)\n",
1558 __FILE__, __LINE__, io_type, status->sw_count);
1561 return status->sw_count;
1567 /* The I/O may have been synchronous with signal completion. It doesn't
1568 * make sense, but the combination could be generated. Release the
1569 * completion signal here otherwise it'll hang around and bite us
1572 if( aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL )
1573 sigrelse( aiocbp->aio_sigevent.sigev_signo );
1575 ret = aio_error( aiocbp );
1577 while( ret == EINPROGRESS ){
1578 ret = aio_error( aiocbp );
1583 "%s/%d %s, aio_error had to loop on EINPROGRESS, cnt=%d; random method %#o; sigev_notify=%s",
1584 __FILE__, __LINE__, io_type, cnt, method,
1585 (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL ? "signal" :
1586 aiocbp->aio_sigevent.sigev_notify == SIGEV_NONE ? "none" :
1587 aiocbp->aio_sigevent.sigev_notify == SIGEV_CALLBACK ? "callback" :
1594 "%s/%d %s, aio_error = %d %s; random method %#o",
1595 __FILE__, __LINE__, io_type,
1600 ret = aio_return( aiocbp );
1603 "%s/%d %s, aio_return not as expected(%d), but actual:%d",
1604 __FILE__, __LINE__, io_type,
1607 #ifdef BUG1_workaround
1610 if( Debug_level > 1 ){
1611 printf("WARN %s/%d: %s completed with bug1_workaround (aio_error == 0, aio_return now == %d)\n",
1612 __FILE__, __LINE__, io_type, ret);
1615 #endif /* BUG1_workaround */
1618 else if( Debug_level > 1 ){
1619 printf("DEBUG %s/%d: %s completed without error (aio_error == 0, aio_return == %d)\n",
1620 __FILE__, __LINE__, io_type, ret);
1627 } /* end of lio_check_asyncio */
1630 /***********************************************************************
1632 * This function will wait for async io to complete.
1633 * If multiple wait methods are specified, the order is predetermined
1634 * to LIO_WAIT_RECALL,
1635 * LIO_WAIT_ACTIVE, LIO_WAIT_SIGPAUSE, LIO_WAIT_SIGACTIVE,
1636 * then LIO_WAIT_NONE.
1638 * If no wait method was specified the default wait method is: recall(2)
1639 * or aio_suspend(3), as appropriate.
1642 * <0: errno of failed recall
1643 * 0 : async io was completed
1644 * 1 : async was not waited for, io may not have completed.
1647 ***********************************************************************/
1650 lio_wait4asyncio(int method, int fd, struct iosw **statptr)
1652 lio_wait4asyncio(int method, int fd, aiocb_t *aiocbp)
1658 const aiocb_t *aioary[1];
1661 if ( (method & LIO_WAIT_RECALL)
1663 || (method & LIO_WAIT_CBSUSPEND)
1664 || (method & LIO_WAIT_SIGSUSPEND)
1666 || ((method & LIO_WAIT_TYPES) == 0) ){
1668 * If method has LIO_WAIT_RECALL bit set or method does
1669 * not have any wait method bits set (default), use recall/aio_suspend.
1672 if ( Debug_level > 2 )
1673 printf("DEBUG %s/%d: wait method : recall\n", __FILE__, __LINE__);
1675 if ( recall(fd, 1, statptr) ) {
1676 sprintf(Errormsg, "%s/%d recall(%d, 1, stat) failed, errno:%d %s",
1678 fd, errno, strerror(errno));
1682 if ( Debug_level > 2 )
1683 printf("DEBUG %s/%d: wait method : aio_suspend, sigev_notify=%s\n", __FILE__, __LINE__,
1684 (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL ? "signal" :
1685 aiocbp->aio_sigevent.sigev_notify == SIGEV_NONE ? "none" :
1686 aiocbp->aio_sigevent.sigev_notify == SIGEV_CALLBACK ? "callback" :
1690 ret = aio_suspend( aioary, 1, NULL );
1691 if( (ret == -1) && (errno == EINTR) ){
1692 if( aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL ){
1693 if( Debug_level > 2 ){
1694 printf("DEBUG %s/%d: aio_suspend received EINTR, sigev_notify=SIGEV_SIGNAL -- ok\n",
1695 __FILE__, __LINE__ );
1699 sprintf(Errormsg, "%s/%d aio_suspend received EINTR, sigev_notify=%s, not ok\n",
1701 (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL ? "signal" :
1702 aiocbp->aio_sigevent.sigev_notify == SIGEV_NONE ? "none" :
1703 aiocbp->aio_sigevent.sigev_notify == SIGEV_CALLBACK ? "callback" :
1709 sprintf(Errormsg, "%s/%d aio_suspend(fildes=%d, aioary, 1, NULL) failed, errno:%d %s",
1711 fd, errno, strerror(errno));
1716 } else if ( method & LIO_WAIT_ACTIVE ) {
1717 if ( Debug_level > 2 )
1718 printf("DEBUG %s/%d: wait method : active\n", __FILE__, __LINE__);
1722 * loop until sw_flag, sw_count or sw_error field elements
1723 * change to non-zero.
1726 while ( (*statptr)->sw_flag == 0 &&
1727 (*statptr)->sw_count == 0 &&
1728 (*statptr)->sw_error == 0 ) {
1732 /* loop while aio_error() returns EINPROGRESS */
1735 ret = aio_error( aiocbp );
1736 if( (ret == 0) || (ret != EINPROGRESS) ){
1743 if ( Debug_level > 5 && cnt && (cnt % 50) == 0 )
1744 printf("DEBUG %s/%d: wait active cnt = %d\n",
1745 __FILE__, __LINE__, cnt);
1747 } else if ( method & LIO_WAIT_SIGPAUSE ) {
1748 if ( Debug_level > 2 )
1749 printf("DEBUG %s/%d: wait method : sigpause\n", __FILE__, __LINE__);
1751 /* note: don't do the sigon() for CRAY in this case. why? -- roehrich 6/11/97 */
1752 if( aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL )
1753 sigrelse( aiocbp->aio_sigevent.sigev_signo );
1755 printf("DEBUG %s/%d: sigev_notify != SIGEV_SIGNAL\n", __FILE__, __LINE__ );
1761 } else if ( method & LIO_WAIT_SIGACTIVE ) {
1762 if ( Debug_level > 2 )
1763 printf("DEBUG %s/%d: wait method : sigactive\n", __FILE__, __LINE__);
1767 if( aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL )
1768 sigrelse( aiocbp->aio_sigevent.sigev_signo );
1770 printf("DEBUG %s/%d: sigev_notify != SIGEV_SIGNAL\n", __FILE__, __LINE__ );
1774 /* loop waiting for signal */
1775 while ( Received_signal == Rec_signal ){
1779 sigrelse( aiocbp->aio_sigevent.sigev_signo );
1783 } else if ( method & LIO_WAIT_NONE ) {
1784 if ( Debug_level > 2 )
1785 printf("DEBUG %s/%d: wait method : none\n", __FILE__, __LINE__);
1786 /* It's broken because the aiocb/iosw is an automatic variable in
1787 * lio_{read,write}_buffer, so when the function returns and the
1788 * I/O completes there will be nowhere to write the I/O status.
1789 * It doesn't cause a problem on unicos--probably because of some
1790 * compiler quirk, or an accident. It causes POSIX async I/O
1791 * to core dump some threads. spr/pv 705909. 6/27/97 roehrich
1793 sprintf(Errormsg, "%s/%d LIO_WAIT_NONE was selected (this is broken)\n",
1794 __FILE__, __LINE__ );
1802 if( Debug_level > 2 )
1803 printf("DEBUG %s/%d: no wait method was chosen\n", __FILE__, __LINE__ );
1809 } /* end of lio_wait4asyncio */
1811 #endif /* ifndef linux */
1814 /***********************************************************************
1815 * The following code is provided as unit test.
1816 * Just define add "-DUNIT_TEST=1" to the cc line.
1819 ***********************************************************************/
1820 struct unit_info_t {
1825 { LIO_IO_SYNC, 0, "sync io" },
1826 { LIO_IO_SYNCV, 0, "sync readv/writev" },
1827 { LIO_IO_SYNCP, 0, "sync pread/pwrite" },
1828 { LIO_IO_ASYNC, 0, "async io, def wait" },
1829 { LIO_IO_SLISTIO, 0, "sync listio" },
1830 { LIO_IO_ALISTIO, 0, "async listio, def wait" },
1831 { LIO_IO_ASYNC|LIO_WAIT_ACTIVE, 0, "async active" },
1832 { LIO_IO_ASYNC|LIO_WAIT_RECALL, 0, "async recall/suspend" },
1833 { LIO_IO_ASYNC|LIO_WAIT_SIGPAUSE, SIGUSR1, "async sigpause" },
1834 { LIO_IO_ASYNC|LIO_WAIT_SIGACTIVE, SIGUSR1, "async sigactive" },
1835 { LIO_IO_ALISTIO|LIO_WAIT_ACTIVE, 0, "async listio active" },
1836 { LIO_IO_ALISTIO|LIO_WAIT_RECALL, 0, "async listio recall" },
1837 { LIO_IO_ALISTIO|LIO_WAIT_SIGACTIVE, SIGUSR1, "async listio sigactive" },
1838 { LIO_IO_ALISTIO|LIO_WAIT_SIGPAUSE, SIGUSR1, "async listio sigpause" },
1839 { LIO_IO_ASYNC, SIGUSR2, "async io, def wait, sigusr2" },
1840 { LIO_IO_ALISTIO, SIGUSR2, "async listio, def wait, sigusr2" },
1848 extern char *optarg;
1859 int exit_status = 0;
1862 char *symbols = NULL;
1865 while( (c = getopt(argc,argv,"s:di:")) != -1 ){
1867 case 's': symbols = optarg; break;
1868 case 'd': ++die_on_err; break;
1869 case 'i': iter = atoi(optarg); break;
1873 if ((fd=open("unit_test_file", O_CREAT|O_RDWR|O_TRUNC, 0777)) == -1 ) {
1874 perror("open(unit_test_file, O_CREAT|O_RDWR|O_TRUNC, 0777) failed");
1880 if ( symbols != NULL ) {
1881 if ( (method=lio_parse_io_arg2(symbols, &err)) == -1 ){
1882 printf("lio_parse_io_arg2(%s, &err) failed, bad token starting at %s\n",
1888 printf("lio_parse_io_arg2(%s, &err) returned %#o\n", symbols, method);
1891 for(ind=0; ind < iter; ind++ ) {
1892 memset( buffer, 'A', 4096 );
1893 if( lseek(fd, 0, 0) == -1 ){
1894 printf("lseek(fd,0,0), %d, failed, errno %d\n",
1898 if ((ret=lio_write_buffer(fd, method, buffer,
1899 size, SIGUSR1, &err, 0)) != size ) {
1900 printf("lio_write_buffer returned -1, err = %s\n", err);
1902 printf("lio_write_buffer returned %d\n", ret);
1904 memset( buffer, 'B', 4096 );
1905 if( lseek(fd, 0, 0) == -1 ){
1906 printf("lseek(fd,0,0), %d, failed, errno %d\n",
1910 if ((ret=lio_read_buffer(fd, method, buffer,
1911 size, SIGUSR2, &err, 0)) != size ) {
1912 printf("lio_read_buffer returned -1, err = %s\n", err);
1914 printf("lio_read_buffer returned %d\n", ret);
1916 for( i = 0; i < 4096; ++i ){
1917 if( buffer[i] != 'A' ){
1918 printf(" buffer[%d] = %d\n", i, buffer[i] );
1929 unlink("unit_test_file");
1933 for(ind=0; ind < sizeof(Unit_info)/sizeof(struct unit_info_t); ind++ ) {
1935 printf("\n********* write %s ***************\n", Unit_info[ind].str);
1936 if( lseek(fd, 0, 0) == -1 ){
1937 printf("lseek(fd,0,0), %d, failed, errno %d\n",
1942 memset( buffer, 'A', 4096 );
1943 if ((ret=lio_write_buffer(fd, Unit_info[ind].method, buffer,
1944 size, Unit_info[ind].sig, &err, 0)) != size ) {
1945 printf(">>>>> lio_write_buffer(fd,0%x,buffer,%d,%d,err,0) returned -1,\n err = %s\n",
1946 Unit_info[ind].method, size, Unit_info[ind].sig, err);
1951 printf("lio_write_buffer returned %d\n", ret);
1954 printf("\n********* read %s ***************\n", Unit_info[ind].str);
1955 if( lseek(fd, 0, 0) == -1 ){
1956 printf("lseek(fd,0,0), %d, failed, errno %d\n",
1960 memset( buffer, 'B', 4096 );
1961 if ((ret=lio_read_buffer(fd, Unit_info[ind].method, buffer,
1962 size, Unit_info[ind].sig, &err, 0)) != size ) {
1963 printf(">>>>> lio_read_buffer(fd,0%x,buffer,%d,%d,err,0) returned -1,\n err = %s\n",
1964 Unit_info[ind].method, size, Unit_info[ind].sig, err);
1969 printf("lio_read_buffer returned %d\n", ret);
1972 for( i = 0; i < 4096; ++i ){
1973 if( buffer[i] != 'A' ){
1974 printf(" buffer[%d] = %d\n", i, buffer[i] );
1988 unlink("unit_test_file");