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) */
106 #include <stdlib.h> /* atoi, abs */
108 #include "tlibio.h" /* defines LIO* marcos */
111 #define PATH_MAX MAXPATHLEN
114 #if 0 /* disabled until it's needed -- roehrich 6/11/97 */
115 #define BUG1_workaround 1 /* Work around a condition where aio_return gives
116 * a value of zero but there is no errno followup
117 * and the read/write operation actually did its
124 static void lio_async_signal_handler();
127 static void lio_async_callback_handler();
131 * Define the structure as used in lio_parse_arg1 and lio_help1
133 struct lio_info_type Lio_info1[] = {
134 { "s", LIO_IO_SYNC, "sync i/o" },
135 { "p", LIO_IO_ASYNC|LIO_WAIT_SIGACTIVE, "async i/o using a loop to wait for a signal" },
136 { "b", LIO_IO_ASYNC|LIO_WAIT_SIGPAUSE, "async i/o using pause" },
137 { "a", LIO_IO_ASYNC|LIO_WAIT_RECALL, "async i/o using recall/aio_suspend" },
140 LIO_RANDOM|LIO_IO_TYPES|LIO_WAIT_TYPES, "random sync i/o types and wait methods" },
142 LIO_RANDOM|LIO_IO_ATYPES|LIO_WAIT_ATYPES, "random i/o types and wait methods" },
145 LIO_RANDOM|LIO_IO_TYPES|LIO_WAIT_TYPES, "random i/o types and wait methods" },
147 LIO_RANDOM|LIO_IO_TYPES|LIO_WAIT_TYPES, "random i/o types and wait methods" },
149 { "l", LIO_IO_SLISTIO|LIO_WAIT_RECALL, "single stride sync listio" },
150 { "L", LIO_IO_ALISTIO|LIO_WAIT_RECALL, "single stride async listio using recall" },
151 { "X", LIO_IO_ALISTIO|LIO_WAIT_SIGPAUSE, "single stride async listio using pause" },
152 { "v", LIO_IO_SYNCV, "single buffer sync readv/writev" },
153 { "P", LIO_IO_SYNCP, "sync pread/pwrite" },
157 * Define the structure used by lio_parse_arg2 and lio_help2
159 struct lio_info_type Lio_info2[] = {
160 { "sync", LIO_IO_SYNC, "sync i/o (read/write)"},
161 { "async", LIO_IO_ASYNC, "async i/o (reada/writea/aio_read/aio_write)" },
162 { "slistio", LIO_IO_SLISTIO, "single stride sync listio" },
163 { "alistio", LIO_IO_ALISTIO, "single stride async listio" },
164 { "syncv", LIO_IO_SYNCV, "single buffer sync readv/writev"},
165 { "syncp", LIO_IO_SYNCP, "pread/pwrite"},
166 { "active", LIO_WAIT_ACTIVE, "spin on status/control values" },
167 { "recall", LIO_WAIT_RECALL, "use recall(2)/aio_suspend(3) to wait for i/o to complete" },
168 { "sigactive", LIO_WAIT_SIGACTIVE, "spin waiting for signal" },
169 { "sigpause", LIO_WAIT_SIGPAUSE, "call pause(2) to wait for signal" },
170 /* nowait is a touchy thing, it's an accident that this implementation worked at all. 6/27/97 roehrich */
171 /* { "nowait", LIO_WAIT_NONE, "do not wait for async io to complete" },*/
172 { "random", LIO_RANDOM, "set random bit" },
174 LIO_RANDOM|LIO_IO_TYPES|LIO_WAIT_TYPES,
175 "all random i/o types and wait methods (except nowait)" },
178 char Lio_SysCall[PATH_MAX]; /* string containing last i/o system call */
180 static volatile int Received_signal = 0; /* number of signals received */
181 static volatile int Rec_signal;
183 static volatile int Received_callback = 0; /* number of callbacks received */
184 static volatile int Rec_callback;
186 static char Errormsg[500];
187 static int Debug_level = 0;
191 /***********************************************************************
194 * Determine the bounds of a strided request, normalized to offset. Returns
195 * the number of bytes needed to satisfy the request, and optionally sets
196 * *min and *max to the mininum and maximum bytes referenced, normalized
199 * Returns -1 on error - the only possible error conditions are illegal values
200 * for nstrides and/or bytes_per_stride - both parameters must be >= 0.
203 ***********************************************************************/
206 stride_bounds(offset, stride, nstrides, bytes_per_stride, min, max)
210 int bytes_per_stride;
214 int nbytes, min_byte, max_byte;
220 if (nstrides < 0 || bytes_per_stride < 0) {
225 stride = bytes_per_stride;
229 * Determine the # of bytes needed to satisfy the request. This
230 * value, along with the offset argument, determines the min and max
235 nbytes = abs(stride) * (nstrides-1) + bytes_per_stride;
238 max_byte = offset + bytes_per_stride - 1;
239 min_byte = max_byte - nbytes + 1;
242 max_byte = min_byte + nbytes - 1;
256 /***********************************************************************
257 * This function will allow someone to set the debug level.
258 ***********************************************************************/
269 /***********************************************************************
270 * This function will parse a string and return desired io-method.
271 * Only the first character of the string is used.
273 * This function does not provide for meaningful option arguments,
274 * but it supports current growfiles/btlk interface.
277 ***********************************************************************/
279 lio_parse_io_arg1(char *string)
286 * Determine if token is a valid string.
288 for(ind=0; ind<sizeof(Lio_info1)/sizeof(struct lio_info_type); ind++) {
289 if ( strcmp(string, Lio_info1[ind].token) == 0 ) {
290 mask |= Lio_info1[ind].bits;
304 /***********************************************************************
305 * This function will print a help message describing the characters
306 * that can be parsed by lio_parse_io_arg1().
307 * They will be printed one per line.
309 ***********************************************************************/
311 lio_help1(char *prefix)
315 for(ind=0; ind<sizeof(Lio_info1)/sizeof(struct lio_info_type); ind++) {
316 printf("%s %s : %s\n", prefix,
317 Lio_info1[ind].token, Lio_info1[ind].desc);
323 /***********************************************************************
324 * This function will parse a string and return the desired io-method.
325 * This function will take a comma separated list of io type and wait
326 * method tokens as defined in Lio_info2[]. If a token does not match
327 * any of the tokens in Lio_info2[], it will be coverted to a number.
328 * If it was a number, those bits are also set.
331 ***********************************************************************/
333 lio_parse_io_arg2(char *string, char **badtoken)
335 char *token = string;
349 for (; ((*cc != ',') && (*cc != '\0')); cc++);
356 * Determine if token is a valid string or number and if
357 * so, add the bits to the mask.
359 for(ind=0; ind<sizeof(Lio_info2)/sizeof(struct lio_info_type); ind++) {
360 if ( strcmp(token, Lio_info2[ind].token) == 0 ) {
361 mask |= Lio_info2[ind].bits;
368 * If token does not match one of the defined tokens, determine
369 * if it is a number, if so, add the bits.
372 if (sscanf(token, "%i%c", &tmp, &chr) == 1 ) {
380 if (!found) { /* token is not valid */
381 if ( badtoken != NULL)
395 /***********************************************************************
396 * This function will print a help message describing the tokens
397 * that can be parsed by lio_parse_io_arg2().
398 * It will print them one per line.
401 ***********************************************************************/
403 lio_help2(char *prefix)
407 for(ind=0; ind<sizeof(Lio_info2)/sizeof(struct lio_info_type); ind++) {
408 printf("%s %s : %s\n", prefix,
409 Lio_info2[ind].token, Lio_info2[ind].desc);
415 /***********************************************************************
416 * This is an internal signal handler.
417 * If the handler is called, it will increment the Received_signal
419 ***********************************************************************/
421 lio_async_signal_handler(int sig)
424 printf("DEBUG %s/%d: received signal %d, a signal caught %d times\n",
425 __FILE__, __LINE__, sig, Received_signal+1);
434 /***********************************************************************
435 * This is an internal callback handler.
436 * If the handler is called, it will increment the Received_callback
438 ***********************************************************************/
440 lio_async_callback_handler(sigval_t sigval)
443 printf("DEBUG %s/%d: received callback, nbytes=%d, a callback called %d times\n",
444 __FILE__, __LINE__, sigval.sival_int, Received_callback+1);
452 /***********************************************************************
454 * This function will randomly choose an io type and wait method
455 * from set of io types and wait methods. Since this information
456 * is stored in a bitmask, it randomly chooses an io type from
457 * the io type bits specified and does the same for wait methods.
460 * This function will return a value with all non choosen io type
461 * and wait method bits cleared. The LIO_RANDOM bit is also
462 * cleared. All other bits are left unchanged.
465 ***********************************************************************/
467 lio_random_methods(long curr_mask)
472 /* remove random select, io type, and wait method bits from curr_mask */
473 mask = curr_mask & (~(LIO_IO_TYPES | LIO_WAIT_TYPES | LIO_RANDOM));
475 /* randomly select io type from specified io types */
476 mask = mask | random_bit(curr_mask & LIO_IO_TYPES);
478 /* randomly select wait methods from specified wait methods */
479 mask = mask | random_bit(curr_mask & LIO_WAIT_TYPES);
484 /***********************************************************************
485 * Generic write function
486 * This function can be used to do a write using write(2), writea(2),
487 * aio_write(3), writev(2), pwrite(2),
488 * or single stride listio(2)/lio_listio(3).
489 * By setting the desired bits in the method
490 * bitmask, the caller can control the type of write and the wait method
491 * that will be used. If no io type bits are set, write will be used.
493 * If async io was attempted and no wait method bits are set then the
494 * wait method is: recall(2) for writea(2) and listio(2); aio_suspend(3) for
495 * aio_write(3) and lio_listio(3).
497 * If multiple wait methods are specified,
498 * only one wait method will be used. The order is predetermined.
500 * If the call specifies a signal and one of the two signal wait methods,
501 * a signal handler for the signal is set. This will reset an already
502 * set handler for this signal.
504 * If the LIO_RANDOM method bit is set, this function will randomly
505 * choose a io type and wait method from bits in the method argument.
507 * If an error is encountered, an error message will be generated
508 * in a internal static buffer. If errmsg is not NULL, it will
509 * be updated to point to the static buffer, allowing the caller
510 * to print the error message.
513 * If a system call fails, -errno is returned.
514 * If LIO_WAIT_NONE bit is set, the return value is the return value
515 * of the system call.
516 * If the io did not fail, the amount of data written is returned.
517 * If the size the system call say was written is different
518 * then what was asked to be written, errmsg is updated for
519 * this error condition. The return value is still the amount
520 * the system call says was written.
523 ***********************************************************************/
525 lio_write_buffer(fd, method, buffer, size, sig, errmsg, wrd)
526 int fd; /* open file descriptor */
527 int method; /* contains io type and wait method bitmask */
528 char *buffer; /* pointer to buffer */
529 int size; /* the size of the io */
530 int sig; /* signal to use if async io */
531 char **errmsg; /* char pointer that will be updated to point to err message */
532 long wrd; /* to allow future features, use zero for now */
534 int ret = 0; /* syscall return or used to get random method */
535 char *io_type; /* Holds string of type of io */
537 int omethod = method;
538 int listio_cmd; /* Holds the listio/lio_listio cmd */
541 struct listreq request; /* Used when a listio is wanted */
542 struct iosw status, *statptr[1];
544 /* for linux or sgi */
545 struct iovec iov; /* iovec for writev(2) */
548 aiocb_t aiocbp; /* POSIX aio control block */
549 aiocb_t *aiolist[1]; /* list of aio control blocks for lio_listio */
550 off64_t poffset; /* pwrite(2) offset */
554 * If LIO_RANDOM bit specified, get new method randomly.
556 if ( method & LIO_RANDOM ) {
557 if( Debug_level > 3 )
558 printf("DEBUG %s/%d: method mask to choose from: %#o\n", __FILE__, __LINE__, method );
559 method = lio_random_methods(method);
560 if ( Debug_level > 2 )
561 printf("DEBUG %s/%d: random chosen method %#o\n", __FILE__, __LINE__, method);
564 if ( errmsg != NULL )
567 Rec_signal=Received_signal; /* get the current number of signals received */
569 Rec_callback=Received_callback; /* get the current number of callbacks received */
573 bzero(&status, sizeof(struct iosw));
574 bzero(&request, sizeof(struct listreq));
575 statptr[0] = &status;
577 /* for linux or sgi */
578 bzero(&iov, sizeof(struct iovec));
579 iov.iov_base = buffer;
583 bzero(&aiocbp, sizeof(aiocb_t));
584 aiocbp.aio_fildes = fd;
585 aiocbp.aio_nbytes = size;
586 aiocbp.aio_buf = buffer;
587 /* aiocbp.aio_offset = lseek( fd, 0, SEEK_CUR ); -- set below */
588 aiocbp.aio_sigevent.sigev_notify = SIGEV_NONE;
589 aiocbp.aio_sigevent.sigev_signo = 0;
590 aiocbp.aio_sigevent.sigev_func = NULL;
591 aiocbp.aio_sigevent.sigev_value.sival_int = 0;
592 aiolist[0] = &aiocbp;
594 if( (ret = lseek( fd, 0, SEEK_CUR )) == -1 ){
596 /* If there is an error and it is not ESPIPE then kick out the error.
597 * If the fd is a fifo then we have to make sure that
598 * lio_random_methods() didn't select pwrite/pread; if it did then
599 * switch to write/read.
601 if( errno == ESPIPE ){
602 if( method & LIO_IO_SYNCP ){
603 if( omethod & LIO_RANDOM ){
604 method &= ~LIO_IO_SYNCP;
605 method |= LIO_IO_SYNC;
606 if( Debug_level > 2 )
607 printf("DEBUG %s/%d: random chosen method switched to %#o for fifo\n", __FILE__, __LINE__, method );
609 else if( Debug_level ){
610 printf("DEBUG %s/%d: pwrite will fail when it writes to a fifo\n",
611 __FILE__, __LINE__ );
614 /* else: let it ride */
617 sprintf(Errormsg, "%s/%d lseek(fd=%d,0,SEEK_CUR) failed, errno=%d %s",
618 __FILE__, __LINE__, fd, errno, strerror(errno));
622 poffset = (off64_t)ret;
623 aiocbp.aio_offset = ret;
628 * If the LIO_USE_SIGNAL bit is not set, only use the signal
629 * if the LIO_WAIT_SIGPAUSE or the LIO_WAIT_SIGACTIVE bits are bit.
630 * Otherwise there is not necessary a signal handler to trap
633 if ( sig && !(method & LIO_USE_SIGNAL) &&
634 ! (method & LIO_WAIT_SIGTYPES) ){
636 sig=0; /* ignore signal parameter */
640 if ( sig && (method & LIO_WAIT_CBTYPES) )
641 sig=0; /* ignore signal parameter */
645 * only setup signal hander if sig was specified and
646 * a sig wait method was specified.
647 * Doing this will change the handler for this signal. The
648 * old signal handler will not be restored.
649 *** restoring the signal handler could be added ***
652 if ( sig && (method & LIO_WAIT_SIGTYPES) ){
654 sigctl(SCTL_REG, sig, lio_async_signal_handler);
657 aiocbp.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
658 aiocbp.aio_sigevent.sigev_signo = sig;
659 sigset(sig, lio_async_signal_handler);
663 else if( method & LIO_WAIT_CBTYPES ){
664 /* sival_int just has to be something that I can use
665 * to identify the callback, and "size" happens to be handy...
667 aiocbp.aio_sigevent.sigev_notify = SIGEV_CALLBACK;
668 aiocbp.aio_sigevent.sigev_func = lio_async_callback_handler;
669 aiocbp.aio_sigevent.sigev_value.sival_int = size;
674 * Determine the system call that will be called and produce
675 * the string of the system call and place it in Lio_SysCall.
676 * Also update the io_type char pointer to give brief description
677 * of system call. Execute the system call and check for
678 * system call failure. If sync i/o, return the number of
679 * bytes written/read.
682 if ( (method & LIO_IO_SYNC) || (method & LIO_IO_TYPES) == 0 ){
684 * write(2) is used if LIO_IO_SYNC bit is set or not none
685 * of the LIO_IO_TYPES bits are set (default).
689 "write(%d, buf, %d)", fd, size);
693 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
696 if ((ret = write(fd, buffer, size)) == -1) {
697 sprintf(Errormsg, "%s/%d write(%d, buf, %d) ret:-1, errno=%d %s",
699 fd, size, errno, strerror(errno));
705 "%s/%d write(%d, buf, %d) returned=%d",
709 else if ( Debug_level > 1 )
710 printf("DEBUG %s/%d: write completed without error (ret %d)\n",
711 __FILE__, __LINE__, ret);
717 else if ( method & LIO_IO_ASYNC ) {
720 "writea(%d, buf, %d, &status, %d)", fd, size, sig);
724 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
728 if ((ret = writea(fd, buffer, size, &status, sig)) == -1) {
730 "%s/%d writea(%d, buf, %d, &stat, %d) ret:-1, errno=%d %s",
732 fd, size, sig, errno, strerror(errno));
739 "aio_write(fildes=%d, buf, nbytes=%d, signo=%d)", fd, size, sig);
743 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
748 if ((ret = aio_write(&aiocbp)) == -1) {
750 "%s/%d aio_write(fildes=%d, buf, nbytes=%d, signo=%d) ret:-1, errno=%d %s",
752 fd, size, sig, errno, strerror(errno));
760 else if ( method & LIO_IO_SLISTIO ) {
762 request.li_opcode = LO_WRITE;
763 request.li_fildes = fd;
764 request.li_buf = buffer;
765 request.li_nbyte = size;
766 request.li_status = &status;
767 request.li_signo = sig;
768 request.li_nstride = 0;
769 request.li_filstride = 0;
770 request.li_memstride = 0;
773 io_type="listio(2) sync write";
776 "listio(LC_WAIT, &req, 1) LO_WRITE, fd:%d, nbyte:%d",
780 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
784 if ( listio(listio_cmd, &request, 1) == -1 ) {
785 sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
787 Lio_SysCall, fd, size, errno, strerror(errno));
792 if ( Debug_level > 1 )
793 printf("DEBUG %s/%d: %s did not return -1\n",
794 __FILE__, __LINE__, Lio_SysCall);
796 ret=lio_check_asyncio(io_type, size, &status);
802 aiocbp.aio_lio_opcode = LIO_WRITE;
804 io_type="lio_listio(3) sync write";
807 "lio_listio(LIO_WAIT, aiolist, 1, NULL) LIO_WRITE, fd:%d, nbyte:%d, sig:%d",
811 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
816 if ( lio_listio(listio_cmd, aiolist, 1, NULL) == -1 ) {
817 sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
819 Lio_SysCall, fd, size, errno, strerror(errno));
825 if ( Debug_level > 1 )
826 printf("DEBUG %s/%d: %s did not return -1\n",
827 __FILE__, __LINE__, Lio_SysCall);
829 ret=lio_check_asyncio(io_type, size, &aiocbp, method);
832 } /* LIO_IO_SLISTIO */
834 else if ( method & LIO_IO_ALISTIO ) {
836 request.li_opcode = LO_WRITE;
837 request.li_fildes = fd;
838 request.li_buf = buffer;
839 request.li_nbyte = size;
840 request.li_status = &status;
841 request.li_signo = sig;
842 request.li_nstride = 0;
843 request.li_filstride = 0;
844 request.li_memstride = 0;
847 io_type="listio(2) async write";
850 "listio(LC_START, &req, 1) LO_WRITE, fd:%d, nbyte:%d",
854 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
858 if ( listio(listio_cmd, &request, 1) == -1 ) {
859 sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
861 Lio_SysCall, fd, size, errno, strerror(errno));
867 aiocbp.aio_lio_opcode = LIO_WRITE;
868 listio_cmd=LIO_NOWAIT;
869 io_type="lio_listio(3) async write";
872 "lio_listio(LIO_NOWAIT, aiolist, 1, NULL) LIO_WRITE, fd:%d, nbyte:%d",
876 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
881 if ( lio_listio(listio_cmd, aiolist, 1, NULL) == -1 ) {
882 sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
884 Lio_SysCall, fd, size, errno, strerror(errno));
890 }/* LIO_IO_ALISTIO */
893 else if ( method & LIO_IO_SYNCV ) {
897 "writev(%d, &iov, 1) nbyte:%d", fd, size);
900 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
902 if ((ret = writev(fd, &iov, 1)) == -1) {
903 sprintf(Errormsg, "%s/%d writev(%d, iov, 1) nbyte:%d ret:-1, errno=%d %s",
905 fd, size, errno, strerror(errno));
911 "%s/%d writev(%d, iov, 1) nbyte:%d returned=%d",
915 else if ( Debug_level > 1 )
916 printf("DEBUG %s/%d: writev completed without error (ret %d)\n",
917 __FILE__, __LINE__, ret);
924 else if ( method & LIO_IO_SYNCP ) {
928 "pwrite(%d, buf, %d, %lld)", fd, size, poffset);
931 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
933 if ((ret = pwrite(fd, buffer, size, poffset)) == -1) {
934 sprintf(Errormsg, "%s/%d pwrite(%d, buf, %d, %lld) ret:-1, errno=%d %s",
936 fd, size, poffset, errno, strerror(errno));
942 "%s/%d pwrite(%d, buf, %d, %lld) returned=%d",
944 fd, size, poffset, ret);
946 else if ( Debug_level > 1 )
947 printf("DEBUG %s/%d: pwrite completed without error (ret %d)\n",
948 __FILE__, __LINE__, ret);
955 printf("DEBUG %s/%d: No I/O method chosen\n", __FILE__, __LINE__ );
960 * wait for async io to complete.
963 ret=lio_wait4asyncio(method, fd, statptr);
966 ret=lio_wait4asyncio(method, fd, &aiocbp);
970 * If there was an error waiting for async i/o to complete,
971 * return the error value (errno) to the caller.
972 * Note: Errormsg should already have been updated.
979 * If i/o was not waited for (may not have been completed at this time),
980 * return the size that was requested.
986 * check that async io was successful.
987 * Note: if the there was an system call failure, -errno
988 * was returned and Errormsg should already have been updated.
989 * If amount i/o was different than size, Errormsg should already
990 * have been updated but the actual i/o size if returned.
994 ret=lio_check_asyncio(io_type, size, &status);
997 ret=lio_check_asyncio(io_type, size, &aiocbp, method);
1001 } /* end of lio_write_buffer */
1003 /***********************************************************************
1004 * Generic read function
1005 * This function can be used to do a read using read(2), reada(2),
1006 * aio_read(3), readv(2), pread(2),
1007 * or single stride listio(2)/lio_listio(3).
1008 * By setting the desired bits in the method
1009 * bitmask, the caller can control the type of read and the wait method
1010 * that will be used. If no io type bits are set, read will be used.
1012 * If async io was attempted and no wait method bits are set then the
1013 * wait method is: recall(2) for reada(2) and listio(2); aio_suspend(3) for
1014 * aio_read(3) and lio_listio(3).
1016 * If multiple wait methods are specified,
1017 * only one wait method will be used. The order is predetermined.
1019 * If the call specifies a signal and one of the two signal wait methods,
1020 * a signal handler for the signal is set. This will reset an already
1021 * set handler for this signal.
1023 * If the LIO_RANDOM method bit is set, this function will randomly
1024 * choose a io type and wait method from bits in the method argument.
1026 * If an error is encountered, an error message will be generated
1027 * in a internal static buffer. If errmsg is not NULL, it will
1028 * be updated to point to the static buffer, allowing the caller
1029 * to print the error message.
1032 * If a system call fails, -errno is returned.
1033 * If LIO_WAIT_NONE bit is set, the return value is the return value
1034 * of the system call.
1035 * If the io did not fail, the amount of data written is returned.
1036 * If the size the system call say was written is different
1037 * then what was asked to be written, errmsg is updated for
1038 * this error condition. The return value is still the amount
1039 * the system call says was written.
1042 ***********************************************************************/
1044 lio_read_buffer(fd, method, buffer, size, sig, errmsg, wrd)
1045 int fd; /* open file descriptor */
1046 int method; /* contains io type and wait method bitmask */
1047 char *buffer; /* pointer to buffer */
1048 int size; /* the size of the io */
1049 int sig; /* signal to use if async io */
1050 char **errmsg; /* char pointer that will be updated to point to err message */
1051 long wrd; /* to allow future features, use zero for now */
1053 int ret = 0; /* syscall return or used to get random method */
1054 char *io_type; /* Holds string of type of io */
1056 int listio_cmd; /* Holds the listio/lio_listio cmd */
1057 int omethod = method;
1060 struct listreq request; /* Used when a listio is wanted */
1061 struct iosw status, *statptr[1];
1063 /* for linux or sgi */
1064 struct iovec iov; /* iovec for readv(2) */
1067 aiocb_t aiocbp; /* POSIX aio control block */
1068 aiocb_t *aiolist[1]; /* list of aio control blocks for lio_listio */
1069 off64_t poffset; /* pread(2) offset */
1073 * If LIO_RANDOM bit specified, get new method randomly.
1075 if ( method & LIO_RANDOM ) {
1076 if( Debug_level > 3 )
1077 printf("DEBUG %s/%d: method mask to choose from: %#o\n", __FILE__, __LINE__, method );
1078 method = lio_random_methods(method);
1079 if ( Debug_level > 2 )
1080 printf("DEBUG %s/%d: random chosen method %#o\n", __FILE__, __LINE__, method);
1083 if ( errmsg != NULL )
1086 Rec_signal=Received_signal; /* get the current number of signals received */
1088 Rec_callback=Received_callback; /* get the current number of callbacks received */
1092 bzero(&status, sizeof(struct iosw));
1093 bzero(&request, sizeof(struct listreq));
1094 statptr[0] = &status;
1096 /* for linux or sgi */
1097 bzero(&iov, sizeof(struct iovec));
1098 iov.iov_base = buffer;
1102 bzero(&aiocbp, sizeof(aiocb_t));
1103 aiocbp.aio_fildes = fd;
1104 aiocbp.aio_nbytes = size;
1105 aiocbp.aio_buf = buffer;
1106 /* aiocbp.aio_offset = lseek( fd, 0, SEEK_CUR ); -- set below */
1107 aiocbp.aio_sigevent.sigev_notify = SIGEV_NONE;
1108 aiocbp.aio_sigevent.sigev_signo = 0;
1109 aiocbp.aio_sigevent.sigev_func = NULL;
1110 aiocbp.aio_sigevent.sigev_value.sival_int = 0;
1111 aiolist[0] = &aiocbp;
1113 if( (ret = lseek( fd, 0, SEEK_CUR )) == -1 ){
1115 /* If there is an error and it is not ESPIPE then kick out the error.
1116 * If the fd is a fifo then we have to make sure that
1117 * lio_random_methods() didn't select pwrite/pread; if it did then
1118 * switch to write/read.
1120 if( errno == ESPIPE ){
1121 if( method & LIO_IO_SYNCP ){
1122 if( omethod & LIO_RANDOM ){
1123 method &= ~LIO_IO_SYNCP;
1124 method |= LIO_IO_SYNC;
1125 if( Debug_level > 2 )
1126 printf("DEBUG %s/%d: random chosen method switched to %#o for fifo\n", __FILE__, __LINE__, method );
1128 else if( Debug_level ){
1129 printf("DEBUG %s/%d: pread will fail when it reads from a fifo\n",
1130 __FILE__, __LINE__ );
1133 /* else: let it ride */
1136 sprintf(Errormsg, "%s/%d lseek(fd=%d,0,SEEK_CUR) failed, errno=%d %s",
1137 __FILE__, __LINE__, fd, errno, strerror(errno));
1141 poffset = (off64_t)ret;
1142 aiocbp.aio_offset = ret;
1147 * If the LIO_USE_SIGNAL bit is not set, only use the signal
1148 * if the LIO_WAIT_SIGPAUSE or the LIO_WAIT_SIGACTIVE bits are set.
1149 * Otherwise there is not necessarily a signal handler to trap
1152 if ( sig && !(method & LIO_USE_SIGNAL) &&
1153 ! (method & LIO_WAIT_SIGTYPES) ){
1155 sig=0; /* ignore signal parameter */
1159 if ( sig && (method & LIO_WAIT_CBTYPES) )
1160 sig=0; /* ignore signal parameter */
1164 * only setup signal hander if sig was specified and
1165 * a sig wait method was specified.
1166 * Doing this will change the handler for this signal. The
1167 * old signal handler will not be restored.
1168 *** restoring the signal handler could be added ***
1171 if ( sig && (method & LIO_WAIT_SIGTYPES) ){
1173 sigctl(SCTL_REG, sig, lio_async_signal_handler);
1176 aiocbp.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
1177 aiocbp.aio_sigevent.sigev_signo = sig;
1178 sigset(sig, lio_async_signal_handler);
1182 else if( method & LIO_WAIT_CBTYPES ){
1183 aiocbp.aio_sigevent.sigev_notify = SIGEV_CALLBACK;
1184 aiocbp.aio_sigevent.sigev_func = lio_async_callback_handler;
1185 /* sival_int just has to be something that I can use
1186 * to identify the callback, and "size" happens to be handy...
1188 aiocbp.aio_sigevent.sigev_value.sival_int = size;
1193 * Determine the system call that will be called and produce
1194 * the string of the system call and place it in Lio_SysCall.
1195 * Also update the io_type char pointer to give brief description
1196 * of system call. Execute the system call and check for
1197 * system call failure. If sync i/o, return the number of
1198 * bytes written/read.
1201 if ( (method & LIO_IO_SYNC) || (method & LIO_IO_TYPES) == 0 ){
1203 * read(2) is used if LIO_IO_SYNC bit is set or not none
1204 * of the LIO_IO_TYPES bits are set (default).
1207 sprintf(Lio_SysCall,
1208 "read(%d, buf, %d)", fd, size);
1211 if ( Debug_level ) {
1212 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
1215 if ((ret = read(fd, buffer, size)) == -1) {
1216 sprintf(Errormsg, "%s/%d read(%d, buf, %d) ret:-1, errno=%d %s",
1218 fd, size, errno, strerror(errno));
1222 if ( ret != size ) {
1224 "%s/%d read(%d, buf, %d) returned=%d",
1228 else if ( Debug_level > 1 )
1229 printf("DEBUG %s/%d: read completed without error (ret %d)\n",
1230 __FILE__, __LINE__, ret);
1236 else if ( method & LIO_IO_ASYNC ) {
1238 sprintf(Lio_SysCall,
1239 "reada(%d, buf, %d, &status, %d)", fd, size, sig);
1242 if ( Debug_level ) {
1243 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
1247 if ((ret = reada(fd, buffer, size, &status, sig)) == -1) {
1249 "%s/%d reada(%d, buf, %d, &stat, %d) ret:-1, errno=%d %s",
1251 fd, size, sig, errno, strerror(errno));
1257 sprintf(Lio_SysCall,
1258 "aio_read(fildes=%d, buf, nbytes=%d, signo=%d)", fd, size, sig);
1261 if ( Debug_level ) {
1262 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
1267 if ((ret = aio_read(&aiocbp)) == -1) {
1269 "%s/%d aio_read(fildes=%d, buf, nbytes=%d, signo=%d) ret:-1, errno=%d %s",
1271 fd, size, sig, errno, strerror(errno));
1277 } /* LIO_IO_ASYNC */
1279 else if ( method & LIO_IO_SLISTIO ) {
1281 request.li_opcode = LO_READ;
1282 request.li_fildes = fd;
1283 request.li_buf = buffer;
1284 request.li_nbyte = size;
1285 request.li_status = &status;
1286 request.li_signo = sig;
1287 request.li_nstride = 0;
1288 request.li_filstride = 0;
1289 request.li_memstride = 0;
1292 io_type="listio(2) sync read";
1294 sprintf(Lio_SysCall,
1295 "listio(LC_WAIT, &req, 1) LO_READ, fd:%d, nbyte:%d",
1298 if ( Debug_level ) {
1299 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
1303 if ( listio(listio_cmd, &request, 1) == -1 ) {
1304 sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1306 Lio_SysCall, fd, size, errno, strerror(errno));
1311 if ( Debug_level > 1 )
1312 printf("DEBUG %s/%d: %s did not return -1\n",
1313 __FILE__, __LINE__, Lio_SysCall);
1315 ret=lio_check_asyncio(io_type, size, &status);
1319 aiocbp.aio_lio_opcode = LIO_READ;
1320 listio_cmd=LIO_WAIT;
1321 io_type="lio_listio(3) sync read";
1323 sprintf(Lio_SysCall,
1324 "lio_listio(LIO_WAIT, aiolist, 1, NULL) LIO_READ, fd:%d, nbyte:%d",
1327 if ( Debug_level ) {
1328 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
1333 if ( lio_listio(listio_cmd, aiolist, 1, NULL) == -1 ) {
1334 sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1336 Lio_SysCall, fd, size, errno, strerror(errno));
1342 if ( Debug_level > 1 )
1343 printf("DEBUG %s/%d: %s did not return -1\n",
1344 __FILE__, __LINE__, Lio_SysCall);
1346 ret=lio_check_asyncio(io_type, size, &aiocbp, method);
1349 }/* LIO_IO_SLISTIO */
1351 else if ( method & LIO_IO_ALISTIO ) {
1353 request.li_opcode = LO_READ;
1354 request.li_fildes = fd;
1355 request.li_buf = buffer;
1356 request.li_nbyte = size;
1357 request.li_status = &status;
1358 request.li_signo = sig;
1359 request.li_nstride = 0;
1360 request.li_filstride = 0;
1361 request.li_memstride = 0;
1363 listio_cmd=LC_START;
1364 io_type="listio(2) async read";
1366 sprintf(Lio_SysCall,
1367 "listio(LC_START, &req, 1) LO_READ, fd:%d, nbyte:%d",
1370 if ( Debug_level ) {
1371 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
1375 if ( listio(listio_cmd, &request, 1) == -1 ) {
1376 sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1378 Lio_SysCall, fd, size, errno, strerror(errno));
1384 aiocbp.aio_lio_opcode = LIO_READ;
1385 listio_cmd=LIO_NOWAIT;
1386 io_type="lio_listio(3) async read";
1388 sprintf(Lio_SysCall,
1389 "lio_listio(LIO_NOWAIT, aiolist, 1, NULL) LIO_READ, fd:%d, nbyte:%d",
1392 if ( Debug_level ) {
1393 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
1398 if ( lio_listio(listio_cmd, aiolist, 1, NULL) == -1 ) {
1399 sprintf(Errormsg, "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1401 Lio_SysCall, fd, size, errno, strerror(errno));
1407 } /* LIO_IO_ALISTIO */
1410 else if ( method & LIO_IO_SYNCV ) {
1413 sprintf(Lio_SysCall,
1414 "readv(%d, &iov, 1) nbyte:%d", fd, size);
1416 if ( Debug_level ) {
1417 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
1419 if ((ret = readv(fd, &iov, 1)) == -1) {
1420 sprintf(Errormsg, "%s/%d readv(%d, iov, 1) nbyte:%d ret:-1, errno=%d %s",
1422 fd, size, errno, strerror(errno));
1426 if ( ret != size ) {
1428 "%s/%d readv(%d, iov, 1) nbyte:%d returned=%d",
1432 else if ( Debug_level > 1 )
1433 printf("DEBUG %s/%d: readv completed without error (ret %d)\n",
1434 __FILE__, __LINE__, ret);
1437 } /* LIO_IO_SYNCV */
1441 else if ( method & LIO_IO_SYNCP ) {
1444 sprintf(Lio_SysCall,
1445 "pread(%d, buf, %d, %lld)", fd, size, poffset);
1447 if ( Debug_level ) {
1448 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__, Lio_SysCall);
1450 if ((ret = pread(fd, buffer, size, poffset)) == -1) {
1451 sprintf(Errormsg, "%s/%d pread(%d, buf, %d, %lld) ret:-1, errno=%d %s",
1453 fd, size, poffset, errno, strerror(errno));
1457 if ( ret != size ) {
1459 "%s/%d pread(%d, buf, %d, %lld) returned=%d",
1461 fd, size, poffset, ret);
1463 else if ( Debug_level > 1 )
1464 printf("DEBUG %s/%d: pread completed without error (ret %d)\n",
1465 __FILE__, __LINE__, ret);
1468 } /* LIO_IO_SYNCP */
1472 printf("DEBUG %s/%d: No I/O method chosen\n", __FILE__, __LINE__ );
1477 * wait for async io to complete.
1478 * Note: Sync io should have returned prior to getting here.
1481 ret=lio_wait4asyncio(method, fd, statptr);
1484 ret=lio_wait4asyncio(method, fd, &aiocbp);
1488 * If there was an error waiting for async i/o to complete,
1489 * return the error value (errno) to the caller.
1490 * Note: Errormsg should already have been updated.
1497 * If i/o was not waited for (may not have been completed at this time),
1498 * return the size that was requested.
1504 * check that async io was successful.
1505 * Note: if the there was an system call failure, -errno
1506 * was returned and Errormsg should already have been updated.
1507 * If amount i/o was different than size, Errormsg should already
1508 * have been updated but the actual i/o size if returned.
1512 ret=lio_check_asyncio(io_type, size, &status);
1515 ret=lio_check_asyncio(io_type, size, &aiocbp, method);
1519 } /* end of lio_read_buffer */
1523 /***********************************************************************
1524 * This function will check that async io was successful.
1525 * It can also be used to check sync listio since it uses the
1529 * If status.sw_error is set, -status.sw_error is returned.
1530 * Otherwise sw_count's field value is returned.
1533 ***********************************************************************/
1536 lio_check_asyncio(char *io_type, int size, struct iosw *status)
1538 lio_check_asyncio(char *io_type, int size, aiocb_t *aiocbp, int method)
1544 if ( status->sw_error ) {
1546 "%s/%d %s, sw_error set = %d %s, sw_count = %d",
1547 __FILE__, __LINE__, io_type,
1548 status->sw_error, strerror(status->sw_error), status->sw_count);
1549 return -status->sw_error;
1551 else if ( status->sw_count != size ) {
1553 "%s/%d %s, sw_count not as expected(%d), but actual:%d",
1554 __FILE__, __LINE__, io_type,
1555 size, status->sw_count);
1557 else if ( Debug_level > 1 ) {
1558 printf("DEBUG %s/%d: %s completed without error (sw_error == 0, sw_count == %d)\n",
1559 __FILE__, __LINE__, io_type, status->sw_count);
1562 return status->sw_count;
1568 /* The I/O may have been synchronous with signal completion. It doesn't
1569 * make sense, but the combination could be generated. Release the
1570 * completion signal here otherwise it'll hang around and bite us
1573 if( aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL )
1574 sigrelse( aiocbp->aio_sigevent.sigev_signo );
1576 ret = aio_error( aiocbp );
1578 while( ret == EINPROGRESS ){
1579 ret = aio_error( aiocbp );
1584 "%s/%d %s, aio_error had to loop on EINPROGRESS, cnt=%d; random method %#o; sigev_notify=%s",
1585 __FILE__, __LINE__, io_type, cnt, method,
1586 (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL ? "signal" :
1587 aiocbp->aio_sigevent.sigev_notify == SIGEV_NONE ? "none" :
1588 aiocbp->aio_sigevent.sigev_notify == SIGEV_CALLBACK ? "callback" :
1595 "%s/%d %s, aio_error = %d %s; random method %#o",
1596 __FILE__, __LINE__, io_type,
1601 ret = aio_return( aiocbp );
1604 "%s/%d %s, aio_return not as expected(%d), but actual:%d",
1605 __FILE__, __LINE__, io_type,
1608 #ifdef BUG1_workaround
1611 if( Debug_level > 1 ){
1612 printf("WARN %s/%d: %s completed with bug1_workaround (aio_error == 0, aio_return now == %d)\n",
1613 __FILE__, __LINE__, io_type, ret);
1616 #endif /* BUG1_workaround */
1619 else if( Debug_level > 1 ){
1620 printf("DEBUG %s/%d: %s completed without error (aio_error == 0, aio_return == %d)\n",
1621 __FILE__, __LINE__, io_type, ret);
1628 } /* end of lio_check_asyncio */
1631 /***********************************************************************
1633 * This function will wait for async io to complete.
1634 * If multiple wait methods are specified, the order is predetermined
1635 * to LIO_WAIT_RECALL,
1636 * LIO_WAIT_ACTIVE, LIO_WAIT_SIGPAUSE, LIO_WAIT_SIGACTIVE,
1637 * then LIO_WAIT_NONE.
1639 * If no wait method was specified the default wait method is: recall(2)
1640 * or aio_suspend(3), as appropriate.
1643 * <0: errno of failed recall
1644 * 0 : async io was completed
1645 * 1 : async was not waited for, io may not have completed.
1648 ***********************************************************************/
1651 lio_wait4asyncio(int method, int fd, struct iosw **statptr)
1653 lio_wait4asyncio(int method, int fd, aiocb_t *aiocbp)
1659 const aiocb_t *aioary[1];
1662 if ( (method & LIO_WAIT_RECALL)
1664 || (method & LIO_WAIT_CBSUSPEND)
1665 || (method & LIO_WAIT_SIGSUSPEND)
1667 || ((method & LIO_WAIT_TYPES) == 0) ){
1669 * If method has LIO_WAIT_RECALL bit set or method does
1670 * not have any wait method bits set (default), use recall/aio_suspend.
1673 if ( Debug_level > 2 )
1674 printf("DEBUG %s/%d: wait method : recall\n", __FILE__, __LINE__);
1676 if ( recall(fd, 1, statptr) ) {
1677 sprintf(Errormsg, "%s/%d recall(%d, 1, stat) failed, errno:%d %s",
1679 fd, errno, strerror(errno));
1683 if ( Debug_level > 2 )
1684 printf("DEBUG %s/%d: wait method : aio_suspend, sigev_notify=%s\n", __FILE__, __LINE__,
1685 (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL ? "signal" :
1686 aiocbp->aio_sigevent.sigev_notify == SIGEV_NONE ? "none" :
1687 aiocbp->aio_sigevent.sigev_notify == SIGEV_CALLBACK ? "callback" :
1691 ret = aio_suspend( aioary, 1, NULL );
1692 if( (ret == -1) && (errno == EINTR) ){
1693 if( aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL ){
1694 if( Debug_level > 2 ){
1695 printf("DEBUG %s/%d: aio_suspend received EINTR, sigev_notify=SIGEV_SIGNAL -- ok\n",
1696 __FILE__, __LINE__ );
1700 sprintf(Errormsg, "%s/%d aio_suspend received EINTR, sigev_notify=%s, not ok\n",
1702 (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL ? "signal" :
1703 aiocbp->aio_sigevent.sigev_notify == SIGEV_NONE ? "none" :
1704 aiocbp->aio_sigevent.sigev_notify == SIGEV_CALLBACK ? "callback" :
1710 sprintf(Errormsg, "%s/%d aio_suspend(fildes=%d, aioary, 1, NULL) failed, errno:%d %s",
1712 fd, errno, strerror(errno));
1717 } else if ( method & LIO_WAIT_ACTIVE ) {
1718 if ( Debug_level > 2 )
1719 printf("DEBUG %s/%d: wait method : active\n", __FILE__, __LINE__);
1723 * loop until sw_flag, sw_count or sw_error field elements
1724 * change to non-zero.
1727 while ( (*statptr)->sw_flag == 0 &&
1728 (*statptr)->sw_count == 0 &&
1729 (*statptr)->sw_error == 0 ) {
1733 /* loop while aio_error() returns EINPROGRESS */
1736 ret = aio_error( aiocbp );
1737 if( (ret == 0) || (ret != EINPROGRESS) ){
1744 if ( Debug_level > 5 && cnt && (cnt % 50) == 0 )
1745 printf("DEBUG %s/%d: wait active cnt = %d\n",
1746 __FILE__, __LINE__, cnt);
1748 } else if ( method & LIO_WAIT_SIGPAUSE ) {
1749 if ( Debug_level > 2 )
1750 printf("DEBUG %s/%d: wait method : sigpause\n", __FILE__, __LINE__);
1752 /* note: don't do the sigon() for CRAY in this case. why? -- roehrich 6/11/97 */
1753 if( aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL )
1754 sigrelse( aiocbp->aio_sigevent.sigev_signo );
1756 printf("DEBUG %s/%d: sigev_notify != SIGEV_SIGNAL\n", __FILE__, __LINE__ );
1762 } else if ( method & LIO_WAIT_SIGACTIVE ) {
1763 if ( Debug_level > 2 )
1764 printf("DEBUG %s/%d: wait method : sigactive\n", __FILE__, __LINE__);
1768 if( aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL )
1769 sigrelse( aiocbp->aio_sigevent.sigev_signo );
1771 printf("DEBUG %s/%d: sigev_notify != SIGEV_SIGNAL\n", __FILE__, __LINE__ );
1775 /* loop waiting for signal */
1776 while ( Received_signal == Rec_signal ){
1780 sigrelse( aiocbp->aio_sigevent.sigev_signo );
1784 } else if ( method & LIO_WAIT_NONE ) {
1785 if ( Debug_level > 2 )
1786 printf("DEBUG %s/%d: wait method : none\n", __FILE__, __LINE__);
1787 /* It's broken because the aiocb/iosw is an automatic variable in
1788 * lio_{read,write}_buffer, so when the function returns and the
1789 * I/O completes there will be nowhere to write the I/O status.
1790 * It doesn't cause a problem on unicos--probably because of some
1791 * compiler quirk, or an accident. It causes POSIX async I/O
1792 * to core dump some threads. spr/pv 705909. 6/27/97 roehrich
1794 sprintf(Errormsg, "%s/%d LIO_WAIT_NONE was selected (this is broken)\n",
1795 __FILE__, __LINE__ );
1803 if( Debug_level > 2 )
1804 printf("DEBUG %s/%d: no wait method was chosen\n", __FILE__, __LINE__ );
1810 } /* end of lio_wait4asyncio */
1812 #endif /* ifndef linux */
1815 /***********************************************************************
1816 * The following code is provided as unit test.
1817 * Just define add "-DUNIT_TEST=1" to the cc line.
1820 ***********************************************************************/
1821 struct unit_info_t {
1826 { LIO_IO_SYNC, 0, "sync io" },
1827 { LIO_IO_SYNCV, 0, "sync readv/writev" },
1828 { LIO_IO_SYNCP, 0, "sync pread/pwrite" },
1829 { LIO_IO_ASYNC, 0, "async io, def wait" },
1830 { LIO_IO_SLISTIO, 0, "sync listio" },
1831 { LIO_IO_ALISTIO, 0, "async listio, def wait" },
1832 { LIO_IO_ASYNC|LIO_WAIT_ACTIVE, 0, "async active" },
1833 { LIO_IO_ASYNC|LIO_WAIT_RECALL, 0, "async recall/suspend" },
1834 { LIO_IO_ASYNC|LIO_WAIT_SIGPAUSE, SIGUSR1, "async sigpause" },
1835 { LIO_IO_ASYNC|LIO_WAIT_SIGACTIVE, SIGUSR1, "async sigactive" },
1836 { LIO_IO_ALISTIO|LIO_WAIT_ACTIVE, 0, "async listio active" },
1837 { LIO_IO_ALISTIO|LIO_WAIT_RECALL, 0, "async listio recall" },
1838 { LIO_IO_ALISTIO|LIO_WAIT_SIGACTIVE, SIGUSR1, "async listio sigactive" },
1839 { LIO_IO_ALISTIO|LIO_WAIT_SIGPAUSE, SIGUSR1, "async listio sigpause" },
1840 { LIO_IO_ASYNC, SIGUSR2, "async io, def wait, sigusr2" },
1841 { LIO_IO_ALISTIO, SIGUSR2, "async listio, def wait, sigusr2" },
1849 extern char *optarg;
1860 int exit_status = 0;
1863 char *symbols = NULL;
1866 while( (c = getopt(argc,argv,"s:di:")) != -1 ){
1868 case 's': symbols = optarg; break;
1869 case 'd': ++die_on_err; break;
1870 case 'i': iter = atoi(optarg); break;
1874 if ((fd=open("unit_test_file", O_CREAT|O_RDWR|O_TRUNC, 0777)) == -1 ) {
1875 perror("open(unit_test_file, O_CREAT|O_RDWR|O_TRUNC, 0777) failed");
1881 if ( symbols != NULL ) {
1882 if ( (method=lio_parse_io_arg2(symbols, &err)) == -1 ){
1883 printf("lio_parse_io_arg2(%s, &err) failed, bad token starting at %s\n",
1889 printf("lio_parse_io_arg2(%s, &err) returned %#o\n", symbols, method);
1892 for(ind=0; ind < iter; ind++ ) {
1893 memset( buffer, 'A', 4096 );
1894 if( lseek(fd, 0, 0) == -1 ){
1895 printf("lseek(fd,0,0), %d, failed, errno %d\n",
1899 if ((ret=lio_write_buffer(fd, method, buffer,
1900 size, SIGUSR1, &err, 0)) != size ) {
1901 printf("lio_write_buffer returned -1, err = %s\n", err);
1903 printf("lio_write_buffer returned %d\n", ret);
1905 memset( buffer, 'B', 4096 );
1906 if( lseek(fd, 0, 0) == -1 ){
1907 printf("lseek(fd,0,0), %d, failed, errno %d\n",
1911 if ((ret=lio_read_buffer(fd, method, buffer,
1912 size, SIGUSR2, &err, 0)) != size ) {
1913 printf("lio_read_buffer returned -1, err = %s\n", err);
1915 printf("lio_read_buffer returned %d\n", ret);
1917 for( i = 0; i < 4096; ++i ){
1918 if( buffer[i] != 'A' ){
1919 printf(" buffer[%d] = %d\n", i, buffer[i] );
1930 unlink("unit_test_file");
1934 for(ind=0; ind < sizeof(Unit_info)/sizeof(struct unit_info_t); ind++ ) {
1936 printf("\n********* write %s ***************\n", Unit_info[ind].str);
1937 if( lseek(fd, 0, 0) == -1 ){
1938 printf("lseek(fd,0,0), %d, failed, errno %d\n",
1943 memset( buffer, 'A', 4096 );
1944 if ((ret=lio_write_buffer(fd, Unit_info[ind].method, buffer,
1945 size, Unit_info[ind].sig, &err, 0)) != size ) {
1946 printf(">>>>> lio_write_buffer(fd,0%x,buffer,%d,%d,err,0) returned -1,\n err = %s\n",
1947 Unit_info[ind].method, size, Unit_info[ind].sig, err);
1952 printf("lio_write_buffer returned %d\n", ret);
1955 printf("\n********* read %s ***************\n", Unit_info[ind].str);
1956 if( lseek(fd, 0, 0) == -1 ){
1957 printf("lseek(fd,0,0), %d, failed, errno %d\n",
1961 memset( buffer, 'B', 4096 );
1962 if ((ret=lio_read_buffer(fd, Unit_info[ind].method, buffer,
1963 size, Unit_info[ind].sig, &err, 0)) != size ) {
1964 printf(">>>>> lio_read_buffer(fd,0%x,buffer,%d,%d,err,0) returned -1,\n err = %s\n",
1965 Unit_info[ind].method, size, Unit_info[ind].sig, err);
1970 printf("lio_read_buffer returned %d\n", ret);
1973 for( i = 0; i < 4096; ++i ){
1974 if( buffer[i] != 'A' ){
1975 printf(" buffer[%d] = %d\n", i, buffer[i] );
1989 unlink("unit_test_file");