1 /*
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
3 *
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.
7 *
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.
11 *
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.
18 *
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.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
31 */
32 /*
33 *
34 * Lib i/o
35 *
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.
41 *
42 * This file contains functions for writing/reading to/from open files
43 * Prototypes:
44 *
45 * Functions declared in this module - see individual function code for
46 * usage comments:
47 *
48 * int stride_bounds(int offset, int stride, int nstrides,
49 * int bytes_per_stride, int *min, int *max);
50
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);
55 *
56 * #ifdef CRAY
57 * int lio_wait4asyncio(int method, int fd, struct iosw **statptr)
58 * int lio_check_asyncio(char *io_type, int size, struct iosw *status)
59 * #endif
60 * #ifdef sgi
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)
63 * #endif
64 *
65 * int lio_parse_io_arg1(char *string)
66 * void lio_help1(char *prefix);
67 *
68 * int lio_parse_io_arg2(char *string, char **badtoken)
69 * void lio_help2(char *prefix);
70 *
71 * int lio_set_debug(int level);
72 *
73 * char Lio_SysCall[];
74 * struct lio_info_type Lio_info1[];
75 * struct lio_info_type Lio_info2[];
76 *
77 * Author : Richard Logan
78 *
79 */
80
81 #ifdef __linux__
82 #ifndef _GNU_SOURCE
83 #define _GNU_SOURCE
84 #endif
85 #define _LARGEFILE64_SOURCE
86 #endif
87 #include "config.h"
88 #include <stdio.h>
89 #include <ctype.h>
90 #include <fcntl.h>
91 #include <unistd.h>
92 #include <sys/types.h>
93 #include <sys/stat.h>
94 #include <sys/time.h>
95 #include <sys/param.h>
96 #include <errno.h>
97 #include <sys/types.h>
98 #include <sys/file.h>
99 #include <signal.h>
100 #include <stdint.h>
101 #ifdef CRAY
102 #include <sys/secparm.h>
103 #include <sys/iosw.h>
104 #include <sys/listio.h>
105 #else
106 /* for linux or sgi */
107 #include <sys/uio.h> /* readv(2)/writev(2) */
108 #include <string.h>
109 #endif
110 #if defined(__linux__) || defined(__sun) || defined(__hpux) || defined(_AIX)
111 #if !defined(UCLINUX) && !defined(__UCLIBC__)
112 #include <aio.h>
113 #endif
114 #endif
115 #include <stdlib.h> /* atoi, abs */
116
117 #include "tlibio.h" /* defines LIO* marcos */
118 #include "random_range.h"
119
120 #ifndef PATH_MAX
121 #define PATH_MAX MAXPATHLEN
122 #endif
123
124 #if 0 /* disabled until it's needed -- roehrich 6/11/97 */
125 #define BUG1_workaround 1 /* Work around a condition where aio_return gives
126 * a value of zero but there is no errno followup
127 * and the read/write operation actually did its
128 * job. spr/pv 705244
129 */
130 #endif
131
132
133 /*
134 * Define the structure as used in lio_parse_arg1 and lio_help1
135 */
136 struct lio_info_type Lio_info1[] = {
137 {"s", LIO_IO_SYNC, "sync i/o"},
138 {"p", LIO_IO_ASYNC | LIO_WAIT_SIGACTIVE,
139 "async i/o using a loop to wait for a signal"},
140 {"b", LIO_IO_ASYNC | LIO_WAIT_SIGPAUSE, "async i/o using pause"},
141 {"a", LIO_IO_ASYNC | LIO_WAIT_RECALL,
142 "async i/o using recall/aio_suspend"},
143 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
144 {"r",
145 LIO_RANDOM | LIO_IO_TYPES | LIO_WAIT_TYPES,
146 "random sync i/o types and wait methods"},
147 {"R",
148 LIO_RANDOM | LIO_IO_ATYPES | LIO_WAIT_ATYPES,
149 "random i/o types and wait methods"},
150 #else
151 {"r",
152 LIO_RANDOM | LIO_IO_TYPES | LIO_WAIT_TYPES,
153 "random i/o types and wait methods"},
154 {"R",
155 LIO_RANDOM | LIO_IO_TYPES | LIO_WAIT_TYPES,
156 "random i/o types and wait methods"},
157 #endif
158 {"l", LIO_IO_SLISTIO | LIO_WAIT_RECALL, "single stride sync listio"},
159 {"L", LIO_IO_ALISTIO | LIO_WAIT_RECALL,
160 "single stride async listio using recall"},
161 {"X", LIO_IO_ALISTIO | LIO_WAIT_SIGPAUSE,
162 "single stride async listio using pause"},
163 {"v", LIO_IO_SYNCV, "single buffer sync readv/writev"},
164 {"P", LIO_IO_SYNCP, "sync pread/pwrite"},
165 };
166
167 /*
168 * Define the structure used by lio_parse_arg2 and lio_help2
169 */
170 struct lio_info_type Lio_info2[] = {
171 {"sync", LIO_IO_SYNC, "sync i/o (read/write)"},
172 {"async", LIO_IO_ASYNC, "async i/o (reada/writea/aio_read/aio_write)"},
173 {"slistio", LIO_IO_SLISTIO, "single stride sync listio"},
174 {"alistio", LIO_IO_ALISTIO, "single stride async listio"},
175 {"syncv", LIO_IO_SYNCV, "single buffer sync readv/writev"},
176 {"syncp", LIO_IO_SYNCP, "pread/pwrite"},
177 {"active", LIO_WAIT_ACTIVE, "spin on status/control values"},
178 {"recall", LIO_WAIT_RECALL,
179 "use recall(2)/aio_suspend(3) to wait for i/o to complete"},
180 {"sigactive", LIO_WAIT_SIGACTIVE, "spin waiting for signal"},
181 {"sigpause", LIO_WAIT_SIGPAUSE, "call pause(2) to wait for signal"},
182 /* nowait is a touchy thing, it's an accident that this implementation worked at all. 6/27/97 roehrich */
183 /* { "nowait", LIO_WAIT_NONE, "do not wait for async io to complete" },*/
184 {"random", LIO_RANDOM, "set random bit"},
185 {"randomall",
186 LIO_RANDOM | LIO_IO_TYPES | LIO_WAIT_TYPES,
187 "all random i/o types and wait methods (except nowait)"},
188 };
189
190 char Lio_SysCall[PATH_MAX]; /* string containing last i/o system call */
191
192 static volatile int Received_signal = 0; /* number of signals received */
193 static volatile int Rec_signal;
194 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
195 static volatile int Received_callback = 0; /* number of callbacks received */
196 static volatile int Rec_callback;
197 #endif
198 static char Errormsg[500];
199 static int Debug_level = 0;
200
201 /***********************************************************************
202 * stride_bounds()
203 *
204 * Determine the bounds of a strided request, normalized to offset. Returns
205 * the number of bytes needed to satisfy the request, and optionally sets
206 * *min and *max to the mininum and maximum bytes referenced, normalized
207 * around offset.
208 *
209 * Returns -1 on error - the only possible error conditions are illegal values
210 * for nstrides and/or bytes_per_stride - both parameters must be >= 0.
211 *
212 * (maule, 11/16/95)
213 ***********************************************************************/
214
stride_bounds(int offset,int stride,int nstrides,int bytes_per_stride,int * min,int * max)215 int stride_bounds(int offset, int stride, int nstrides, int bytes_per_stride,
216 int *min, int *max)
217 {
218 int nbytes, min_byte, max_byte;
219
220 /*
221 * sanity checks ...
222 */
223
224 if (nstrides < 0 || bytes_per_stride < 0) {
225 return -1;
226 }
227
228 if (stride == 0) {
229 stride = bytes_per_stride;
230 }
231
232 /*
233 * Determine the # of bytes needed to satisfy the request. This
234 * value, along with the offset argument, determines the min and max
235 * bytes referenced.
236 */
237
238 nbytes = abs(stride) * (nstrides - 1) + bytes_per_stride;
239
240 if (stride < 0) {
241 max_byte = offset + bytes_per_stride - 1;
242 min_byte = max_byte - nbytes + 1;
243 } else {
244 min_byte = offset;
245 max_byte = min_byte + nbytes - 1;
246 }
247
248 if (min != NULL) {
249 *min = min_byte;
250 }
251
252 if (max != NULL) {
253 *max = max_byte;
254 }
255
256 return nbytes;
257 }
258
259 /***********************************************************************
260 * This function will allow someone to set the debug level.
261 ***********************************************************************/
lio_set_debug(int level)262 int lio_set_debug(int level)
263 {
264 int old;
265
266 old = Debug_level;
267 Debug_level = level;
268 return old;
269 }
270
271 /***********************************************************************
272 * This function will parse a string and return desired io-method.
273 * Only the first character of the string is used.
274 *
275 * This function does not provide for meaningful option arguments,
276 * but it supports current growfiles/btlk interface.
277 *
278 * (rrl 04/96)
279 ***********************************************************************/
lio_parse_io_arg1(char * string)280 int lio_parse_io_arg1(char *string)
281 {
282 unsigned int ind;
283 int found = 0;
284 int mask = 0;
285
286 /*
287 * Determine if token is a valid string.
288 */
289 for (ind = 0; ind < sizeof(Lio_info1) / sizeof(struct lio_info_type);
290 ind++) {
291 if (strcmp(string, Lio_info1[ind].token) == 0) {
292 mask |= Lio_info1[ind].bits;
293 found = 1;
294 break;
295 }
296 }
297
298 if (found == 0) {
299 return -1;
300 }
301
302 return mask;
303
304 }
305
306 /***********************************************************************
307 * This function will print a help message describing the characters
308 * that can be parsed by lio_parse_io_arg1().
309 * They will be printed one per line.
310 * (rrl 04/96)
311 ***********************************************************************/
lio_help1(char * prefix)312 void lio_help1(char *prefix)
313 {
314 unsigned int ind;
315
316 for (ind = 0; ind < sizeof(Lio_info1) / sizeof(struct lio_info_type);
317 ind++) {
318 printf("%s %s : %s\n", prefix, Lio_info1[ind].token,
319 Lio_info1[ind].desc);
320 }
321
322 return;
323 }
324
325 /***********************************************************************
326 * This function will parse a string and return the desired io-method.
327 * This function will take a comma separated list of io type and wait
328 * method tokens as defined in Lio_info2[]. If a token does not match
329 * any of the tokens in Lio_info2[], it will be coverted to a number.
330 * If it was a number, those bits are also set.
331 *
332 * (rrl 04/96)
333 ***********************************************************************/
lio_parse_io_arg2(char * string,char ** badtoken)334 int lio_parse_io_arg2(char *string, char **badtoken)
335 {
336 char *token = string;
337 char *cc = token;
338 char savecc;
339 int found;
340 int mask = 0;
341
342 int tmp;
343 unsigned int ind;
344 char chr;
345
346 if (token == NULL)
347 return -1;
348
349 for (;;) {
350 for (; ((*cc != ',') && (*cc != '\0')); cc++) ;
351 savecc = *cc;
352 *cc = '\0';
353
354 found = 0;
355
356 /*
357 * Determine if token is a valid string or number and if
358 * so, add the bits to the mask.
359 */
360 for (ind = 0;
361 ind < sizeof(Lio_info2) / sizeof(struct lio_info_type);
362 ind++) {
363 if (strcmp(token, Lio_info2[ind].token) == 0) {
364 mask |= Lio_info2[ind].bits;
365 found = 1;
366 break;
367 }
368 }
369
370 /*
371 * If token does not match one of the defined tokens, determine
372 * if it is a number, if so, add the bits.
373 */
374 if (!found) {
375 if (sscanf(token, "%i%c", &tmp, &chr) == 1) {
376 mask |= tmp;
377 found = 1;
378 }
379 }
380
381 *cc = savecc;
382
383 if (!found) { /* token is not valid */
384 if (badtoken != NULL)
385 *badtoken = token;
386 return (-1);
387 }
388
389 if (savecc == '\0')
390 break;
391
392 token = ++cc;
393 }
394
395 return mask;
396 }
397
398 /***********************************************************************
399 * This function will print a help message describing the tokens
400 * that can be parsed by lio_parse_io_arg2().
401 * It will print them one per line.
402 *
403 * (rrl 04/96)
404 ***********************************************************************/
lio_help2(char * prefix)405 void lio_help2(char *prefix)
406 {
407 unsigned int ind;
408
409 for (ind = 0; ind < sizeof(Lio_info2) / sizeof(struct lio_info_type);
410 ind++) {
411 printf("%s %s : %s\n", prefix, Lio_info2[ind].token,
412 Lio_info2[ind].desc);
413 }
414 return;
415 }
416
417 /***********************************************************************
418 * This is an internal signal handler.
419 * If the handler is called, it will increment the Received_signal
420 * global variable.
421 ***********************************************************************/
lio_async_signal_handler(int sig)422 static void lio_async_signal_handler(int sig)
423 {
424 if (Debug_level)
425 printf
426 ("DEBUG %s/%d: received signal %d, a signal caught %d times\n",
427 __FILE__, __LINE__, sig, Received_signal + 1);
428
429 Received_signal++;
430
431 return;
432 }
433
434 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
435 /***********************************************************************
436 * This is an internal callback handler.
437 * If the handler is called, it will increment the Received_callback
438 * global variable.
439 ***********************************************************************/
lio_async_callback_handler(union sigval sigval)440 static void lio_async_callback_handler(union sigval sigval)
441 {
442 if (Debug_level)
443 printf
444 ("DEBUG %s/%d: received callback, nbytes=%ld, a callback called %d times\n",
445 __FILE__, __LINE__, (long)sigval.sival_int,
446 Received_callback + 1);
447
448 Received_callback++;
449
450 return;
451 }
452 #endif /* sgi */
453
454 /***********************************************************************
455 * lio_random_methods
456 * This function will randomly choose an io type and wait method
457 * from set of io types and wait methods. Since this information
458 * is stored in a bitmask, it randomly chooses an io type from
459 * the io type bits specified and does the same for wait methods.
460 *
461 * Return Value
462 * This function will return a value with all non choosen io type
463 * and wait method bits cleared. The LIO_RANDOM bit is also
464 * cleared. All other bits are left unchanged.
465 *
466 * (rrl 04/96)
467 ***********************************************************************/
lio_random_methods(long curr_mask)468 int lio_random_methods(long curr_mask)
469 {
470 int mask = 0;
471
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));
474
475 /* randomly select io type from specified io types */
476 mask = mask | random_bit(curr_mask & LIO_IO_TYPES);
477
478 /* randomly select wait methods from specified wait methods */
479 mask = mask | random_bit(curr_mask & LIO_WAIT_TYPES);
480
481 return mask;
482 }
483
wait4sync_io(int fd,int read)484 static void wait4sync_io(int fd, int read)
485 {
486 fd_set s;
487 FD_ZERO(&s);
488 FD_SET(fd, &s);
489
490 select(fd + 1, read ? &s : NULL, read ? NULL : &s, NULL, NULL);
491 }
492
493 /***********************************************************************
494 * Generic write function
495 * This function can be used to do a write using write(2), writea(2),
496 * aio_write(3), writev(2), pwrite(2),
497 * or single stride listio(2)/lio_listio(3).
498 * By setting the desired bits in the method
499 * bitmask, the caller can control the type of write and the wait method
500 * that will be used. If no io type bits are set, write will be used.
501 *
502 * If async io was attempted and no wait method bits are set then the
503 * wait method is: recall(2) for writea(2) and listio(2); aio_suspend(3) for
504 * aio_write(3) and lio_listio(3).
505 *
506 * If multiple wait methods are specified,
507 * only one wait method will be used. The order is predetermined.
508 *
509 * If the call specifies a signal and one of the two signal wait methods,
510 * a signal handler for the signal is set. This will reset an already
511 * set handler for this signal.
512 *
513 * If the LIO_RANDOM method bit is set, this function will randomly
514 * choose a io type and wait method from bits in the method argument.
515 *
516 * If an error is encountered, an error message will be generated
517 * in a internal static buffer. If errmsg is not NULL, it will
518 * be updated to point to the static buffer, allowing the caller
519 * to print the error message.
520 *
521 * Return Value
522 * If a system call fails, -errno is returned.
523 * If LIO_WAIT_NONE bit is set, the return value is the return value
524 * of the system call.
525 * If the io did not fail, the amount of data written is returned.
526 * If the size the system call say was written is different
527 * then what was asked to be written, errmsg is updated for
528 * this error condition. The return value is still the amount
529 * the system call says was written.
530 *
531 * (rrl 04/96)
532 ***********************************************************************/
lio_write_buffer(int fd,int method,char * buffer,int size,int sig,char ** errmsg,long wrd)533 int lio_write_buffer(int fd, /* open file descriptor */
534 int method, /* contains io type and wait method bitmask */
535 char *buffer, /* pointer to buffer */
536 int size, /* the size of the io */
537 int sig, /* signal to use if async io */
538 char **errmsg, /* char pointer that will be updated to point to err message */
539 long wrd) /* to allow future features, use zero for now */
540 {
541 int ret = 0; /* syscall return or used to get random method */
542 char *io_type; /* Holds string of type of io */
543 int omethod = method;
544 int listio_cmd; /* Holds the listio/lio_listio cmd */
545 #ifdef CRAY
546 struct listreq request; /* Used when a listio is wanted */
547 struct iosw status, *statptr[1];
548 #else
549 /* for linux or sgi */
550 struct iovec iov; /* iovec for writev(2) */
551 #endif
552 #if defined (sgi)
553 aiocb_t aiocbp; /* POSIX aio control block */
554 aiocb_t *aiolist[1]; /* list of aio control blocks for lio_listio */
555 off64_t poffset; /* pwrite(2) offset */
556 #endif
557 #if defined(__linux__) && !defined(__UCLIBC__)
558 struct aiocb aiocbp; /* POSIX aio control block */
559 struct aiocb *aiolist[1]; /* list of aio control blocks for lio_listio */
560 off64_t poffset; /* pwrite(2) offset */
561 #endif
562 /*
563 * If LIO_RANDOM bit specified, get new method randomly.
564 */
565 if (method & LIO_RANDOM) {
566 if (Debug_level > 3)
567 printf("DEBUG %s/%d: method mask to choose from: %#o\n",
568 __FILE__, __LINE__, method);
569 method = lio_random_methods(method);
570 if (Debug_level > 2)
571 printf("DEBUG %s/%d: random chosen method %#o\n",
572 __FILE__, __LINE__, method);
573 }
574
575 if (errmsg != NULL)
576 *errmsg = Errormsg;
577
578 Rec_signal = Received_signal; /* get the current number of signals received */
579 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
580 Rec_callback = Received_callback; /* get the current number of callbacks received */
581 #endif
582
583 #ifdef CRAY
584 memset(&status, 0x00, sizeof(struct iosw));
585 memset(&request, 0x00, sizeof(struct listreq));
586 statptr[0] = &status;
587 #else
588 /* for linux or sgi */
589 memset(&iov, 0x00, sizeof(struct iovec));
590 iov.iov_base = buffer;
591 iov.iov_len = size;
592 #endif
593 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
594 #if defined(sgi)
595 memset(&aiocbp, 0x00, sizeof(aiocb_t));
596 #else
597 memset(&aiocbp, 0x00, sizeof(struct aiocb));
598 #endif
599 aiocbp.aio_fildes = fd;
600 aiocbp.aio_nbytes = size;
601 aiocbp.aio_buf = buffer;
602 /* aiocbp.aio_offset = lseek( fd, 0, SEEK_CUR ); -- set below */
603 aiocbp.aio_sigevent.sigev_notify = SIGEV_NONE;
604 aiocbp.aio_sigevent.sigev_signo = 0;
605 #ifdef sgi
606 aiocbp.aio_sigevent.sigev_func = NULL;
607 aiocbp.aio_sigevent.sigev_value.sival_int = 0;
608 #elif defined(__linux__) && !defined(__UCLIBC__)
609 aiocbp.aio_sigevent.sigev_notify_function = NULL;
610 aiocbp.aio_sigevent.sigev_notify_attributes = 0;
611 #endif
612 aiolist[0] = &aiocbp;
613
614 if ((ret = lseek(fd, 0, SEEK_CUR)) == -1) {
615 ret = 0;
616 /* If there is an error and it is not ESPIPE then kick out the error.
617 * If the fd is a fifo then we have to make sure that
618 * lio_random_methods() didn't select pwrite/pread; if it did then
619 * switch to write/read.
620 */
621 if (errno == ESPIPE) {
622 if (method & LIO_IO_SYNCP) {
623 if (omethod & LIO_RANDOM) {
624 method &= ~LIO_IO_SYNCP;
625 method |= LIO_IO_SYNC;
626 if (Debug_level > 2)
627 printf
628 ("DEBUG %s/%d: random chosen method switched to %#o for fifo\n",
629 __FILE__, __LINE__,
630 method);
631 } else if (Debug_level) {
632 printf
633 ("DEBUG %s/%d: pwrite will fail when it writes to a fifo\n",
634 __FILE__, __LINE__);
635 }
636 }
637 /* else: let it ride */
638 } else {
639 sprintf(Errormsg,
640 "%s/%d lseek(fd=%d,0,SEEK_CUR) failed, errno=%d %s",
641 __FILE__, __LINE__, fd, errno, strerror(errno));
642 return -errno;
643 }
644 }
645 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
646 poffset = (off64_t) ret;
647 #endif
648 aiocbp.aio_offset = ret;
649
650 #endif
651
652 /*
653 * If the LIO_USE_SIGNAL bit is not set, only use the signal
654 * if the LIO_WAIT_SIGPAUSE or the LIO_WAIT_SIGACTIVE bits are bit.
655 * Otherwise there is not necessary a signal handler to trap
656 * the signal.
657 */
658 if (sig && !(method & LIO_USE_SIGNAL) && !(method & LIO_WAIT_SIGTYPES)) {
659
660 sig = 0; /* ignore signal parameter */
661 }
662 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
663 if (sig && (method & LIO_WAIT_CBTYPES))
664 sig = 0; /* ignore signal parameter */
665 #endif
666
667 /*
668 * only setup signal hander if sig was specified and
669 * a sig wait method was specified.
670 * Doing this will change the handler for this signal. The
671 * old signal handler will not be restored.
672 *** restoring the signal handler could be added ***
673 */
674
675 if (sig && (method & LIO_WAIT_SIGTYPES)) {
676 #ifdef CRAY
677 sigctl(SCTL_REG, sig, lio_async_signal_handler);
678 #endif
679 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
680 aiocbp.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
681 aiocbp.aio_sigevent.sigev_signo = sig;
682 sigset(sig, lio_async_signal_handler);
683 #endif /* sgi */
684 }
685 #if defined(sgi)
686 else if (method & LIO_WAIT_CBTYPES) {
687 /* sival_int just has to be something that I can use
688 * to identify the callback, and "size" happens to be handy...
689 */
690 aiocbp.aio_sigevent.sigev_notify = SIGEV_CALLBACK;
691 aiocbp.aio_sigevent.sigev_func = lio_async_callback_handler;
692 aiocbp.aio_sigevent.sigev_value.sival_int = size;
693 }
694 #endif
695 #if defined(__linux__) && !defined(__UCLIBC__)
696 else if (method & LIO_WAIT_CBTYPES) {
697 /* sival_int just has to be something that I can use
698 * to identify the callback, and "size" happens to be handy...
699 */
700 aiocbp.aio_sigevent.sigev_notify = SIGEV_THREAD;
701 aiocbp.aio_sigevent.sigev_notify_function =
702 lio_async_callback_handler;
703 aiocbp.aio_sigevent.sigev_notify_attributes =
704 (void *)(uintptr_t) size;
705 }
706 #endif
707 /*
708 * Determine the system call that will be called and produce
709 * the string of the system call and place it in Lio_SysCall.
710 * Also update the io_type char pointer to give brief description
711 * of system call. Execute the system call and check for
712 * system call failure. If sync i/o, return the number of
713 * bytes written/read.
714 */
715
716 if ((method & LIO_IO_SYNC)
717 || (method & (LIO_IO_TYPES | LIO_IO_ATYPES)) == 0) {
718 /*
719 * write(2) is used if LIO_IO_SYNC bit is set or not none
720 * of the LIO_IO_TYPES bits are set (default).
721 */
722
723 sprintf(Lio_SysCall, "write(%d, buf, %d)", fd, size);
724 io_type = "write";
725
726 if (Debug_level) {
727 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
728 Lio_SysCall);
729 }
730 while (1) {
731 if (((ret = write(fd, buffer, size)) == -1)
732 && errno != EAGAIN && errno != EINTR) {
733 sprintf(Errormsg,
734 "%s/%d write(%d, buf, %d) ret:-1, errno=%d %s",
735 __FILE__, __LINE__, fd, size, errno,
736 strerror(errno));
737 return -errno;
738 }
739
740 if (ret != -1) {
741 if (ret != size) {
742 sprintf(Errormsg,
743 "%s/%d write(%d, buf, %d) returned=%d",
744 __FILE__, __LINE__,
745 fd, size, ret);
746 size -= ret;
747 buffer += ret;
748 } else {
749 if (Debug_level > 1)
750 printf
751 ("DEBUG %s/%d: write completed without error (ret %d)\n",
752 __FILE__, __LINE__, ret);
753
754 return ret;
755 }
756 }
757 wait4sync_io(fd, 0);
758 }
759
760 }
761
762 else if (method & LIO_IO_ASYNC) {
763 #ifdef CRAY
764 sprintf(Lio_SysCall,
765 "writea(%d, buf, %d, &status, %d)", fd, size, sig);
766 io_type = "writea";
767
768 if (Debug_level) {
769 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
770 Lio_SysCall);
771 }
772
773 sigoff();
774 if ((ret = writea(fd, buffer, size, &status, sig)) == -1) {
775 sprintf(Errormsg,
776 "%s/%d writea(%d, buf, %d, &stat, %d) ret:-1, errno=%d %s",
777 __FILE__, __LINE__,
778 fd, size, sig, errno, strerror(errno));
779 sigon();
780 return -errno;
781 }
782 #endif
783 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
784 sprintf(Lio_SysCall,
785 "aio_write(fildes=%d, buf, nbytes=%d, signo=%d)", fd,
786 size, sig);
787 io_type = "aio_write";
788
789 if (Debug_level) {
790 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
791 Lio_SysCall);
792 }
793
794 if (sig)
795 sighold(sig);
796 if ((ret = aio_write(&aiocbp)) == -1) {
797 sprintf(Errormsg,
798 "%s/%d aio_write(fildes=%d, buf, nbytes=%d, signo=%d) ret:-1, errno=%d %s",
799 __FILE__, __LINE__,
800 fd, size, sig, errno, strerror(errno));
801 if (sig)
802 sigrelse(sig);
803 return -errno;
804 }
805 #endif
806 }
807 /* LIO_IO_ASYNC */
808 else if (method & LIO_IO_SLISTIO) {
809 #ifdef CRAY
810 request.li_opcode = LO_WRITE;
811 request.li_fildes = fd;
812 request.li_buf = buffer;
813 request.li_nbyte = size;
814 request.li_status = &status;
815 request.li_signo = sig;
816 request.li_nstride = 0;
817 request.li_filstride = 0;
818 request.li_memstride = 0;
819
820 listio_cmd = LC_WAIT;
821 io_type = "listio(2) sync write";
822
823 sprintf(Lio_SysCall,
824 "listio(LC_WAIT, &req, 1) LO_WRITE, fd:%d, nbyte:%d",
825 fd, size);
826
827 if (Debug_level) {
828 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
829 Lio_SysCall);
830 }
831
832 sigoff();
833 if (listio(listio_cmd, &request, 1) == -1) {
834 sprintf(Errormsg,
835 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
836 __FILE__, __LINE__, Lio_SysCall, fd, size,
837 errno, strerror(errno));
838 sigon();
839 return -errno;
840 }
841
842 if (Debug_level > 1)
843 printf("DEBUG %s/%d: %s did not return -1\n",
844 __FILE__, __LINE__, Lio_SysCall);
845
846 ret = lio_check_asyncio(io_type, size, &status);
847 return ret;
848
849 #endif
850 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
851
852 aiocbp.aio_lio_opcode = LIO_WRITE;
853 listio_cmd = LIO_WAIT;
854 io_type = "lio_listio(3) sync write";
855
856 sprintf(Lio_SysCall,
857 "lio_listio(LIO_WAIT, aiolist, 1, NULL) LIO_WRITE, fd:%d, nbyte:%d, sig:%d",
858 fd, size, sig);
859
860 if (Debug_level) {
861 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
862 Lio_SysCall);
863 }
864
865 if (sig)
866 sighold(sig);
867 if (lio_listio(listio_cmd, aiolist, 1, NULL) == -1) {
868 sprintf(Errormsg,
869 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
870 __FILE__, __LINE__, Lio_SysCall, fd, size,
871 errno, strerror(errno));
872 if (sig)
873 sigrelse(sig);
874 return -errno;
875 }
876
877 if (Debug_level > 1)
878 printf("DEBUG %s/%d: %s did not return -1\n",
879 __FILE__, __LINE__, Lio_SysCall);
880
881 ret = lio_check_asyncio(io_type, size, &aiocbp, method);
882 return ret;
883 #endif
884 }
885 /* LIO_IO_SLISTIO */
886 else if (method & LIO_IO_ALISTIO) {
887 #ifdef CRAY
888 request.li_opcode = LO_WRITE;
889 request.li_fildes = fd;
890 request.li_buf = buffer;
891 request.li_nbyte = size;
892 request.li_status = &status;
893 request.li_signo = sig;
894 request.li_nstride = 0;
895 request.li_filstride = 0;
896 request.li_memstride = 0;
897
898 listio_cmd = LC_START;
899 io_type = "listio(2) async write";
900
901 sprintf(Lio_SysCall,
902 "listio(LC_START, &req, 1) LO_WRITE, fd:%d, nbyte:%d",
903 fd, size);
904
905 if (Debug_level) {
906 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
907 Lio_SysCall);
908 }
909
910 sigoff();
911 if (listio(listio_cmd, &request, 1) == -1) {
912 sprintf(Errormsg,
913 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
914 __FILE__, __LINE__, Lio_SysCall, fd, size,
915 errno, strerror(errno));
916 sigon();
917 return -errno;
918 }
919 #endif
920 #if defined (sgi) || (defined(__linux__) && !defined(__UCLIBC__))
921 aiocbp.aio_lio_opcode = LIO_WRITE;
922 listio_cmd = LIO_NOWAIT;
923 io_type = "lio_listio(3) async write";
924
925 sprintf(Lio_SysCall,
926 "lio_listio(LIO_NOWAIT, aiolist, 1, NULL) LIO_WRITE, fd:%d, nbyte:%d",
927 fd, size);
928
929 if (Debug_level) {
930 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
931 Lio_SysCall);
932 }
933
934 if (sig)
935 sighold(sig);
936 if (lio_listio(listio_cmd, aiolist, 1, NULL) == -1) {
937 sprintf(Errormsg,
938 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
939 __FILE__, __LINE__, Lio_SysCall, fd, size,
940 errno, strerror(errno));
941 if (sig)
942 sigrelse(sig);
943 return -errno;
944 }
945 #endif
946 }
947 /* LIO_IO_ALISTIO */
948 #ifndef CRAY
949 else if (method & LIO_IO_SYNCV) {
950 io_type = "writev(2)";
951
952 sprintf(Lio_SysCall, "writev(%d, &iov, 1) nbyte:%d", fd, size);
953
954 if (Debug_level) {
955 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
956 Lio_SysCall);
957 }
958 if ((ret = writev(fd, &iov, 1)) == -1) {
959 sprintf(Errormsg,
960 "%s/%d writev(%d, iov, 1) nbyte:%d ret:-1, errno=%d %s",
961 __FILE__, __LINE__, fd, size, errno,
962 strerror(errno));
963 return -errno;
964 }
965
966 if (ret != size) {
967 sprintf(Errormsg,
968 "%s/%d writev(%d, iov, 1) nbyte:%d returned=%d",
969 __FILE__, __LINE__, fd, size, ret);
970 } else if (Debug_level > 1)
971 printf
972 ("DEBUG %s/%d: writev completed without error (ret %d)\n",
973 __FILE__, __LINE__, ret);
974
975 return ret;
976 } /* LIO_IO_SYNCV */
977 #endif
978
979 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
980 else if (method & LIO_IO_SYNCP) {
981 io_type = "pwrite(2)";
982
983 sprintf(Lio_SysCall,
984 "pwrite(%d, buf, %d, %lld)", fd, size,
985 (long long)poffset);
986
987 if (Debug_level) {
988 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
989 Lio_SysCall);
990 }
991 if ((ret = pwrite(fd, buffer, size, poffset)) == -1) {
992 sprintf(Errormsg,
993 "%s/%d pwrite(%d, buf, %d, %lld) ret:-1, errno=%d %s",
994 __FILE__, __LINE__, fd, size,
995 (long long)poffset, errno, strerror(errno));
996 return -errno;
997 }
998
999 if (ret != size) {
1000 sprintf(Errormsg,
1001 "%s/%d pwrite(%d, buf, %d, %lld) returned=%d",
1002 __FILE__, __LINE__,
1003 fd, size, (long long)poffset, ret);
1004 } else if (Debug_level > 1)
1005 printf
1006 ("DEBUG %s/%d: pwrite completed without error (ret %d)\n",
1007 __FILE__, __LINE__, ret);
1008
1009 return ret;
1010 } /* LIO_IO_SYNCP */
1011 #endif
1012
1013 else {
1014 printf("DEBUG %s/%d: No I/O method chosen\n", __FILE__,
1015 __LINE__);
1016 return -1;
1017 }
1018
1019 /*
1020 * wait for async io to complete.
1021 */
1022 #ifdef CRAY
1023 ret = lio_wait4asyncio(method, fd, statptr);
1024 #endif
1025 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1026 ret = lio_wait4asyncio(method, fd, &aiocbp);
1027 #endif
1028
1029 /*
1030 * If there was an error waiting for async i/o to complete,
1031 * return the error value (errno) to the caller.
1032 * Note: Errormsg should already have been updated.
1033 */
1034 if (ret < 0) {
1035 return ret;
1036 }
1037
1038 /*
1039 * If i/o was not waited for (may not have been completed at this time),
1040 * return the size that was requested.
1041 */
1042 if (ret == 1)
1043 return size;
1044
1045 /*
1046 * check that async io was successful.
1047 * Note: if the there was an system call failure, -errno
1048 * was returned and Errormsg should already have been updated.
1049 * If amount i/o was different than size, Errormsg should already
1050 * have been updated but the actual i/o size if returned.
1051 */
1052
1053 #ifdef CRAY
1054 ret = lio_check_asyncio(io_type, size, &status);
1055 #endif
1056 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1057 ret = lio_check_asyncio(io_type, size, &aiocbp, method);
1058 #endif
1059
1060 return ret;
1061 } /* end of lio_write_buffer */
1062
1063 /***********************************************************************
1064 * Generic read function
1065 * This function can be used to do a read using read(2), reada(2),
1066 * aio_read(3), readv(2), pread(2),
1067 * or single stride listio(2)/lio_listio(3).
1068 * By setting the desired bits in the method
1069 * bitmask, the caller can control the type of read and the wait method
1070 * that will be used. If no io type bits are set, read will be used.
1071 *
1072 * If async io was attempted and no wait method bits are set then the
1073 * wait method is: recall(2) for reada(2) and listio(2); aio_suspend(3) for
1074 * aio_read(3) and lio_listio(3).
1075 *
1076 * If multiple wait methods are specified,
1077 * only one wait method will be used. The order is predetermined.
1078 *
1079 * If the call specifies a signal and one of the two signal wait methods,
1080 * a signal handler for the signal is set. This will reset an already
1081 * set handler for this signal.
1082 *
1083 * If the LIO_RANDOM method bit is set, this function will randomly
1084 * choose a io type and wait method from bits in the method argument.
1085 *
1086 * If an error is encountered, an error message will be generated
1087 * in a internal static buffer. If errmsg is not NULL, it will
1088 * be updated to point to the static buffer, allowing the caller
1089 * to print the error message.
1090 *
1091 * Return Value
1092 * If a system call fails, -errno is returned.
1093 * If LIO_WAIT_NONE bit is set, the return value is the return value
1094 * of the system call.
1095 * If the io did not fail, the amount of data written is returned.
1096 * If the size the system call say was written is different
1097 * then what was asked to be written, errmsg is updated for
1098 * this error condition. The return value is still the amount
1099 * the system call says was written.
1100 *
1101 * (rrl 04/96)
1102 ***********************************************************************/
lio_read_buffer(int fd,int method,char * buffer,int size,int sig,char ** errmsg,long wrd)1103 int lio_read_buffer(int fd, /* open file descriptor */
1104 int method, /* contains io type and wait method bitmask*/
1105 char *buffer, /* pointer to buffer */
1106 int size, /* the size of the io */
1107 int sig, /* signal to use if async io */
1108 char **errmsg, /* char pointer that will be updated to point to err message */
1109 long wrd) /* to allow future features, use zero for now */
1110 {
1111 int ret = 0; /* syscall return or used to get random method */
1112 char *io_type; /* Holds string of type of io */
1113 int listio_cmd; /* Holds the listio/lio_listio cmd */
1114 int omethod = method;
1115 #ifdef CRAY
1116 struct listreq request; /* Used when a listio is wanted */
1117 struct iosw status, *statptr[1];
1118 #else
1119 /* for linux or sgi */
1120 struct iovec iov; /* iovec for readv(2) */
1121 #endif
1122 #ifdef sgi
1123 aiocb_t aiocbp; /* POSIX aio control block */
1124 aiocb_t *aiolist[1]; /* list of aio control blocks for lio_listio */
1125 off64_t poffset; /* pread(2) offset */
1126 #endif
1127 #if defined (__linux__) && !defined(__UCLIBC__)
1128 struct aiocb aiocbp; /* POSIX aio control block */
1129 struct aiocb *aiolist[1]; /* list of aio control blocks for lio_listio */
1130 off64_t poffset; /* pread(2) offset */
1131 #endif
1132
1133 /*
1134 * If LIO_RANDOM bit specified, get new method randomly.
1135 */
1136 if (method & LIO_RANDOM) {
1137 if (Debug_level > 3)
1138 printf("DEBUG %s/%d: method mask to choose from: %#o\n",
1139 __FILE__, __LINE__, method);
1140 method = lio_random_methods(method);
1141 if (Debug_level > 2)
1142 printf("DEBUG %s/%d: random chosen method %#o\n",
1143 __FILE__, __LINE__, method);
1144 }
1145
1146 if (errmsg != NULL)
1147 *errmsg = Errormsg;
1148
1149 Rec_signal = Received_signal; /* get the current number of signals received */
1150 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1151 Rec_callback = Received_callback; /* get the current number of callbacks received */
1152 #endif
1153
1154 #ifdef CRAY
1155 memset(&status, 0x00, sizeof(struct iosw));
1156 memset(&request, 0x00, sizeof(struct listreq));
1157 statptr[0] = &status;
1158 #else
1159 /* for linux or sgi */
1160 memset(&iov, 0x00, sizeof(struct iovec));
1161 iov.iov_base = buffer;
1162 iov.iov_len = size;
1163 #endif
1164 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1165 #if defined(sgi)
1166 memset(&aiocbp, 0x00, sizeof(aiocb_t));
1167 #else
1168 memset(&aiocbp, 0x00, sizeof(struct aiocb));
1169 #endif
1170 aiocbp.aio_fildes = fd;
1171 aiocbp.aio_nbytes = size;
1172 aiocbp.aio_buf = buffer;
1173 /* aiocbp.aio_offset = lseek( fd, 0, SEEK_CUR ); -- set below */
1174 aiocbp.aio_sigevent.sigev_notify = SIGEV_NONE;
1175 aiocbp.aio_sigevent.sigev_signo = 0;
1176 #ifdef sgi
1177 aiocbp.aio_sigevent.sigev_func = NULL;
1178 aiocbp.aio_sigevent.sigev_value.sival_int = 0;
1179 #elif defined(__linux__) && !defined(__UCLIBC__)
1180 aiocbp.aio_sigevent.sigev_notify_function = NULL;
1181 aiocbp.aio_sigevent.sigev_notify_attributes = 0;
1182 #endif
1183 aiolist[0] = &aiocbp;
1184
1185 if ((ret = lseek(fd, 0, SEEK_CUR)) == -1) {
1186 ret = 0;
1187 /* If there is an error and it is not ESPIPE then kick out the error.
1188 * If the fd is a fifo then we have to make sure that
1189 * lio_random_methods() didn't select pwrite/pread; if it did then
1190 * switch to write/read.
1191 */
1192 if (errno == ESPIPE) {
1193 if (method & LIO_IO_SYNCP) {
1194 if (omethod & LIO_RANDOM) {
1195 method &= ~LIO_IO_SYNCP;
1196 method |= LIO_IO_SYNC;
1197 if (Debug_level > 2)
1198 printf
1199 ("DEBUG %s/%d: random chosen method switched to %#o for fifo\n",
1200 __FILE__, __LINE__,
1201 method);
1202 } else if (Debug_level) {
1203 printf
1204 ("DEBUG %s/%d: pread will fail when it reads from a fifo\n",
1205 __FILE__, __LINE__);
1206 }
1207 }
1208 /* else: let it ride */
1209 } else {
1210 sprintf(Errormsg,
1211 "%s/%d lseek(fd=%d,0,SEEK_CUR) failed, errno=%d %s",
1212 __FILE__, __LINE__, fd, errno, strerror(errno));
1213 return -errno;
1214 }
1215 }
1216 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1217 poffset = (off64_t) ret;
1218 #endif
1219 aiocbp.aio_offset = ret;
1220
1221 #endif
1222
1223 /*
1224 * If the LIO_USE_SIGNAL bit is not set, only use the signal
1225 * if the LIO_WAIT_SIGPAUSE or the LIO_WAIT_SIGACTIVE bits are set.
1226 * Otherwise there is not necessarily a signal handler to trap
1227 * the signal.
1228 */
1229 if (sig && !(method & LIO_USE_SIGNAL) && !(method & LIO_WAIT_SIGTYPES)) {
1230
1231 sig = 0; /* ignore signal parameter */
1232 }
1233 #if defined(sgi) || (defined(__linux__)&& !defined(__UCLIBC__))
1234 if (sig && (method & LIO_WAIT_CBTYPES))
1235 sig = 0; /* ignore signal parameter */
1236 #endif
1237
1238 /*
1239 * only setup signal hander if sig was specified and
1240 * a sig wait method was specified.
1241 * Doing this will change the handler for this signal. The
1242 * old signal handler will not be restored.
1243 *** restoring the signal handler could be added ***
1244 */
1245
1246 if (sig && (method & LIO_WAIT_SIGTYPES)) {
1247 #ifdef CRAY
1248 sigctl(SCTL_REG, sig, lio_async_signal_handler);
1249 #endif
1250 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1251 aiocbp.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
1252 aiocbp.aio_sigevent.sigev_signo = sig;
1253 sigset(sig, lio_async_signal_handler);
1254 #endif /* CRAY */
1255 }
1256 #if defined(sgi)
1257 else if (method & LIO_WAIT_CBTYPES) {
1258 aiocbp.aio_sigevent.sigev_notify = SIGEV_CALLBACK;
1259 aiocbp.aio_sigevent.sigev_func = lio_async_callback_handler;
1260 /* sival_int just has to be something that I can use
1261 * to identify the callback, and "size" happens to be handy...
1262 */
1263 aiocbp.aio_sigevent.sigev_value.sival_int = size;
1264 }
1265 #endif
1266 #if defined(__linux__) && !defined(__UCLIBC__)
1267 else if (method & LIO_WAIT_CBTYPES) {
1268 aiocbp.aio_sigevent.sigev_notify = SIGEV_THREAD;
1269 aiocbp.aio_sigevent.sigev_notify_function =
1270 lio_async_callback_handler;
1271 /* sival_int just has to be something that I can use
1272 * to identify the callback, and "size" happens to be handy...
1273 */
1274 aiocbp.aio_sigevent.sigev_notify_attributes =
1275 (void *)(uintptr_t) size;
1276 }
1277 #endif
1278
1279 /*
1280 * Determine the system call that will be called and produce
1281 * the string of the system call and place it in Lio_SysCall.
1282 * Also update the io_type char pointer to give brief description
1283 * of system call. Execute the system call and check for
1284 * system call failure. If sync i/o, return the number of
1285 * bytes written/read.
1286 */
1287
1288 if ((method & LIO_IO_SYNC)
1289 || (method & (LIO_IO_TYPES | LIO_IO_ATYPES)) == 0) {
1290 /*
1291 * read(2) is used if LIO_IO_SYNC bit is set or not none
1292 * of the LIO_IO_TYPES bits are set (default).
1293 */
1294
1295 sprintf(Lio_SysCall, "read(%d, buf, %d)", fd, size);
1296 io_type = "read";
1297
1298 if (Debug_level) {
1299 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1300 Lio_SysCall);
1301 }
1302
1303 while (1) {
1304 if (((ret = read(fd, buffer, size)) == -1)
1305 && errno != EINTR && errno != EAGAIN) {
1306 sprintf(Errormsg,
1307 "%s/%d read(%d, buf, %d) ret:-1, errno=%d %s",
1308 __FILE__, __LINE__, fd, size, errno,
1309 strerror(errno));
1310 return -errno;
1311 }
1312
1313 if (ret == 0)
1314 return 0;
1315 if (ret != -1) {
1316 if (ret != size) {
1317 sprintf(Errormsg,
1318 "%s/%d read(%d, buf, %d) returned=%d",
1319 __FILE__, __LINE__,
1320 fd, size, ret);
1321 size -= ret;
1322 buffer += ret;
1323 } else {
1324 if (Debug_level > 1)
1325 printf
1326 ("DEBUG %s/%d: read completed without error (ret %d)\n",
1327 __FILE__, __LINE__, ret);
1328
1329 return ret;
1330 }
1331 }
1332 wait4sync_io(fd, 1);
1333 }
1334
1335 }
1336
1337 else if (method & LIO_IO_ASYNC) {
1338 #ifdef CRAY
1339 sprintf(Lio_SysCall,
1340 "reada(%d, buf, %d, &status, %d)", fd, size, sig);
1341 io_type = "reada";
1342
1343 if (Debug_level) {
1344 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1345 Lio_SysCall);
1346 }
1347
1348 sigoff();
1349 if ((ret = reada(fd, buffer, size, &status, sig)) == -1) {
1350 sprintf(Errormsg,
1351 "%s/%d reada(%d, buf, %d, &stat, %d) ret:-1, errno=%d %s",
1352 __FILE__, __LINE__,
1353 fd, size, sig, errno, strerror(errno));
1354 sigon();
1355 return -errno;
1356 }
1357 #endif
1358 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1359 sprintf(Lio_SysCall,
1360 "aio_read(fildes=%d, buf, nbytes=%d, signo=%d)", fd,
1361 size, sig);
1362 io_type = "aio_read";
1363
1364 if (Debug_level) {
1365 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1366 Lio_SysCall);
1367 }
1368
1369 if (sig)
1370 sighold(sig);
1371 if ((ret = aio_read(&aiocbp)) == -1) {
1372 sprintf(Errormsg,
1373 "%s/%d aio_read(fildes=%d, buf, nbytes=%d, signo=%d) ret:-1, errno=%d %s",
1374 __FILE__, __LINE__,
1375 fd, size, sig, errno, strerror(errno));
1376 if (sig)
1377 sigrelse(sig);
1378 return -errno;
1379 }
1380 #endif
1381 }
1382 /* LIO_IO_ASYNC */
1383 else if (method & LIO_IO_SLISTIO) {
1384 #ifdef CRAY
1385 request.li_opcode = LO_READ;
1386 request.li_fildes = fd;
1387 request.li_buf = buffer;
1388 request.li_nbyte = size;
1389 request.li_status = &status;
1390 request.li_signo = sig;
1391 request.li_nstride = 0;
1392 request.li_filstride = 0;
1393 request.li_memstride = 0;
1394
1395 listio_cmd = LC_WAIT;
1396 io_type = "listio(2) sync read";
1397
1398 sprintf(Lio_SysCall,
1399 "listio(LC_WAIT, &req, 1) LO_READ, fd:%d, nbyte:%d",
1400 fd, size);
1401
1402 if (Debug_level) {
1403 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1404 Lio_SysCall);
1405 }
1406
1407 sigoff();
1408 if (listio(listio_cmd, &request, 1) == -1) {
1409 sprintf(Errormsg,
1410 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1411 __FILE__, __LINE__, Lio_SysCall, fd, size,
1412 errno, strerror(errno));
1413 sigon();
1414 return -errno;
1415 }
1416
1417 if (Debug_level > 1)
1418 printf("DEBUG %s/%d: %s did not return -1\n",
1419 __FILE__, __LINE__, Lio_SysCall);
1420
1421 ret = lio_check_asyncio(io_type, size, &status);
1422 return ret;
1423 #endif
1424 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1425 aiocbp.aio_lio_opcode = LIO_READ;
1426 listio_cmd = LIO_WAIT;
1427 io_type = "lio_listio(3) sync read";
1428
1429 sprintf(Lio_SysCall,
1430 "lio_listio(LIO_WAIT, aiolist, 1, NULL) LIO_READ, fd:%d, nbyte:%d",
1431 fd, size);
1432
1433 if (Debug_level) {
1434 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1435 Lio_SysCall);
1436 }
1437
1438 if (sig)
1439 sighold(sig);
1440 if (lio_listio(listio_cmd, aiolist, 1, NULL) == -1) {
1441 sprintf(Errormsg,
1442 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1443 __FILE__, __LINE__, Lio_SysCall, fd, size,
1444 errno, strerror(errno));
1445 if (sig)
1446 sigrelse(sig);
1447 return -errno;
1448 }
1449
1450 if (Debug_level > 1)
1451 printf("DEBUG %s/%d: %s did not return -1\n",
1452 __FILE__, __LINE__, Lio_SysCall);
1453
1454 ret = lio_check_asyncio(io_type, size, &aiocbp, method);
1455 return ret;
1456 #endif
1457 }
1458 /* LIO_IO_SLISTIO */
1459 else if (method & LIO_IO_ALISTIO) {
1460 #ifdef CRAY
1461 request.li_opcode = LO_READ;
1462 request.li_fildes = fd;
1463 request.li_buf = buffer;
1464 request.li_nbyte = size;
1465 request.li_status = &status;
1466 request.li_signo = sig;
1467 request.li_nstride = 0;
1468 request.li_filstride = 0;
1469 request.li_memstride = 0;
1470
1471 listio_cmd = LC_START;
1472 io_type = "listio(2) async read";
1473
1474 sprintf(Lio_SysCall,
1475 "listio(LC_START, &req, 1) LO_READ, fd:%d, nbyte:%d",
1476 fd, size);
1477
1478 if (Debug_level) {
1479 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1480 Lio_SysCall);
1481 }
1482
1483 sigoff();
1484 if (listio(listio_cmd, &request, 1) == -1) {
1485 sprintf(Errormsg,
1486 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1487 __FILE__, __LINE__, Lio_SysCall, fd, size,
1488 errno, strerror(errno));
1489 sigon();
1490 return -errno;
1491 }
1492 #endif
1493 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1494 aiocbp.aio_lio_opcode = LIO_READ;
1495 listio_cmd = LIO_NOWAIT;
1496 io_type = "lio_listio(3) async read";
1497
1498 sprintf(Lio_SysCall,
1499 "lio_listio(LIO_NOWAIT, aiolist, 1, NULL) LIO_READ, fd:%d, nbyte:%d",
1500 fd, size);
1501
1502 if (Debug_level) {
1503 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1504 Lio_SysCall);
1505 }
1506
1507 if (sig)
1508 sighold(sig);
1509 if (lio_listio(listio_cmd, aiolist, 1, NULL) == -1) {
1510 sprintf(Errormsg,
1511 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1512 __FILE__, __LINE__, Lio_SysCall, fd, size,
1513 errno, strerror(errno));
1514 if (sig)
1515 sigrelse(sig);
1516 return -errno;
1517 }
1518 #endif
1519 }
1520 /* LIO_IO_ALISTIO */
1521 #ifndef CRAY
1522 else if (method & LIO_IO_SYNCV) {
1523 io_type = "readv(2)";
1524
1525 sprintf(Lio_SysCall, "readv(%d, &iov, 1) nbyte:%d", fd, size);
1526
1527 if (Debug_level) {
1528 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1529 Lio_SysCall);
1530 }
1531 if ((ret = readv(fd, &iov, 1)) == -1) {
1532 sprintf(Errormsg,
1533 "%s/%d readv(%d, iov, 1) nbyte:%d ret:-1, errno=%d %s",
1534 __FILE__, __LINE__, fd, size, errno,
1535 strerror(errno));
1536 return -errno;
1537 }
1538
1539 if (ret != size) {
1540 sprintf(Errormsg,
1541 "%s/%d readv(%d, iov, 1) nbyte:%d returned=%d",
1542 __FILE__, __LINE__, fd, size, ret);
1543 } else if (Debug_level > 1)
1544 printf
1545 ("DEBUG %s/%d: readv completed without error (ret %d)\n",
1546 __FILE__, __LINE__, ret);
1547
1548 return ret;
1549 } /* LIO_IO_SYNCV */
1550 #endif
1551
1552 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1553 else if (method & LIO_IO_SYNCP) {
1554 io_type = "pread(2)";
1555
1556 sprintf(Lio_SysCall,
1557 "pread(%d, buf, %d, %lld)", fd, size,
1558 (long long)poffset);
1559
1560 if (Debug_level) {
1561 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1562 Lio_SysCall);
1563 }
1564 if ((ret = pread(fd, buffer, size, poffset)) == -1) {
1565 sprintf(Errormsg,
1566 "%s/%d pread(%d, buf, %d, %lld) ret:-1, errno=%d %s",
1567 __FILE__, __LINE__, fd, size,
1568 (long long)poffset, errno, strerror(errno));
1569 return -errno;
1570 }
1571
1572 if (ret != size) {
1573 sprintf(Errormsg,
1574 "%s/%d pread(%d, buf, %d, %lld) returned=%d",
1575 __FILE__, __LINE__,
1576 fd, size, (long long)poffset, ret);
1577 } else if (Debug_level > 1)
1578 printf
1579 ("DEBUG %s/%d: pread completed without error (ret %d)\n",
1580 __FILE__, __LINE__, ret);
1581
1582 return ret;
1583 } /* LIO_IO_SYNCP */
1584 #endif
1585
1586 else {
1587 printf("DEBUG %s/%d: No I/O method chosen\n", __FILE__,
1588 __LINE__);
1589 return -1;
1590 }
1591
1592 /*
1593 * wait for async io to complete.
1594 * Note: Sync io should have returned prior to getting here.
1595 */
1596 #ifdef CRAY
1597 ret = lio_wait4asyncio(method, fd, statptr);
1598 #endif
1599 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1600 ret = lio_wait4asyncio(method, fd, &aiocbp);
1601 #endif
1602
1603 /*
1604 * If there was an error waiting for async i/o to complete,
1605 * return the error value (errno) to the caller.
1606 * Note: Errormsg should already have been updated.
1607 */
1608 if (ret < 0) {
1609 return ret;
1610 }
1611
1612 /*
1613 * If i/o was not waited for (may not have been completed at this time),
1614 * return the size that was requested.
1615 */
1616 if (ret == 1)
1617 return size;
1618
1619 /*
1620 * check that async io was successful.
1621 * Note: if the there was an system call failure, -errno
1622 * was returned and Errormsg should already have been updated.
1623 * If amount i/o was different than size, Errormsg should already
1624 * have been updated but the actual i/o size if returned.
1625 */
1626
1627 #ifdef CRAY
1628 ret = lio_check_asyncio(io_type, size, &status);
1629 #endif
1630 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1631 ret = lio_check_asyncio(io_type, size, &aiocbp, method);
1632 #endif
1633
1634 return ret;
1635 } /* end of lio_read_buffer */
1636
1637 #if !defined(__sun) && !defined(__hpux) && !defined(_AIX)
1638 /***********************************************************************
1639 * This function will check that async io was successful.
1640 * It can also be used to check sync listio since it uses the
1641 * same method.
1642 *
1643 * Return Values
1644 * If status.sw_error is set, -status.sw_error is returned.
1645 * Otherwise sw_count's field value is returned.
1646 *
1647 * (rrl 04/96)
1648 ***********************************************************************/
1649 #ifdef CRAY
1650 int lio_check_asyncio(char *io_type, int size, struct iosw *status)
1651 #elif defined(sgi)
1652 int lio_check_asyncio(char *io_type, int size, aiocb_t * aiocbp, int method)
1653 #elif defined(__linux__) && !defined(__UCLIBC__)
1654 int lio_check_asyncio(char *io_type, int size, struct aiocb *aiocbp, int method)
1655 {
1656 int ret;
1657
1658 #ifdef CRAY
1659 if (status->sw_error) {
1660 sprintf(Errormsg,
1661 "%s/%d %s, sw_error set = %d %s, sw_count = %d",
1662 __FILE__, __LINE__, io_type,
1663 status->sw_error, strerror(status->sw_error),
1664 status->sw_count);
1665 return -status->sw_error;
1666 } else if (status->sw_count != size) {
1667 sprintf(Errormsg,
1668 "%s/%d %s, sw_count not as expected(%d), but actual:%d",
1669 __FILE__, __LINE__, io_type, size, status->sw_count);
1670 } else if (Debug_level > 1) {
1671 printf
1672 ("DEBUG %s/%d: %s completed without error (sw_error == 0, sw_count == %d)\n",
1673 __FILE__, __LINE__, io_type, status->sw_count);
1674 }
1675
1676 return status->sw_count;
1677
1678 #else
1679
1680 int cnt = 1;
1681
1682 /* The I/O may have been synchronous with signal completion. It doesn't
1683 * make sense, but the combination could be generated. Release the
1684 * completion signal here otherwise it'll hang around and bite us
1685 * later.
1686 */
1687 if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL)
1688 sigrelse(aiocbp->aio_sigevent.sigev_signo);
1689
1690 ret = aio_error(aiocbp);
1691
1692 while (ret == EINPROGRESS) {
1693 ret = aio_error(aiocbp);
1694 ++cnt;
1695 }
1696 if (cnt > 1) {
1697 sprintf(Errormsg,
1698 "%s/%d %s, aio_error had to loop on EINPROGRESS, cnt=%d; random method %#o; sigev_notify=%s",
1699 __FILE__, __LINE__, io_type, cnt, method,
1700 (aiocbp->aio_sigevent.sigev_notify ==
1701 SIGEV_SIGNAL ? "signal" : aiocbp->aio_sigevent.
1702 sigev_notify == SIGEV_NONE ? "none" :
1703 #ifdef SIGEV_CALLBACK
1704 aiocbp->aio_sigevent.sigev_notify ==
1705 SIGEV_CALLBACK ? "callback" :
1706 #endif
1707 aiocbp->aio_sigevent.sigev_notify ==
1708 SIGEV_THREAD ? "thread" : "unknown"));
1709 return -ret;
1710 }
1711
1712 if (ret != 0) {
1713 sprintf(Errormsg,
1714 "%s/%d %s, aio_error = %d %s; random method %#o",
1715 __FILE__, __LINE__, io_type,
1716 ret, strerror(ret), method);
1717 return -ret;
1718 }
1719 ret = aio_return(aiocbp);
1720 if (ret != size) {
1721 sprintf(Errormsg,
1722 "%s/%d %s, aio_return not as expected(%d), but actual:%d",
1723 __FILE__, __LINE__, io_type, size, ret);
1724
1725 #ifdef BUG1_workaround
1726 if (ret == 0) {
1727 ret = size;
1728 if (Debug_level > 1) {
1729 printf
1730 ("WARN %s/%d: %s completed with bug1_workaround (aio_error == 0, aio_return now == %d)\n",
1731 __FILE__, __LINE__, io_type, ret);
1732 }
1733 }
1734 #endif /* BUG1_workaround */
1735
1736 } else if (Debug_level > 1) {
1737 printf
1738 ("DEBUG %s/%d: %s completed without error (aio_error == 0, aio_return == %d)\n",
1739 __FILE__, __LINE__, io_type, ret);
1740 }
1741
1742 return ret;
1743
1744 #endif
1745 } /* end of lio_check_asyncio */
1746 #endif
1747
1748 /***********************************************************************
1749 *
1750 * This function will wait for async io to complete.
1751 * If multiple wait methods are specified, the order is predetermined
1752 * to LIO_WAIT_RECALL,
1753 * LIO_WAIT_ACTIVE, LIO_WAIT_SIGPAUSE, LIO_WAIT_SIGACTIVE,
1754 * then LIO_WAIT_NONE.
1755 *
1756 * If no wait method was specified the default wait method is: recall(2)
1757 * or aio_suspend(3), as appropriate.
1758 *
1759 * Return Values
1760 * <0: errno of failed recall
1761 * 0 : async io was completed
1762 * 1 : async was not waited for, io may not have completed.
1763 *
1764 * (rrl 04/96)
1765 ***********************************************************************/
1766 #ifdef CRAY
1767 int lio_wait4asyncio(int method, int fd, struct iosw **statptr)
1768 #elif defined(sgi)
1769 int lio_wait4asyncio(int method, int fd, aiocb_t * aiocbp)
1770 #elif defined(__linux__) && !defined(__UCLIBC__)
1771 int lio_wait4asyncio(int method, int fd, struct aiocb *aiocbp)
1772 {
1773 int cnt;
1774 #ifdef sgi
1775 int ret;
1776 const aiocb_t *aioary[1];
1777 #endif
1778 #if defined(__linux__)&& !defined(__UCLIBC__)
1779 int ret;
1780 const struct aiocb *aioary[1];
1781 #endif
1782
1783 if ((method & LIO_WAIT_RECALL)
1784 #if defined(sgi) || (defined(__linux__)&& !defined(__UCLIBC__))
1785 || (method & LIO_WAIT_CBSUSPEND)
1786 || (method & LIO_WAIT_SIGSUSPEND)
1787 #endif
1788 || ((method & LIO_WAIT_TYPES) == 0)) {
1789 /*
1790 * If method has LIO_WAIT_RECALL bit set or method does
1791 * not have any wait method bits set (default), use recall/aio_suspend.
1792 */
1793 #ifdef CRAY
1794 if (Debug_level > 2)
1795 printf("DEBUG %s/%d: wait method : recall\n", __FILE__,
1796 __LINE__);
1797 sigon();
1798 if (recall(fd, 1, statptr)) {
1799 sprintf(Errormsg,
1800 "%s/%d recall(%d, 1, stat) failed, errno:%d %s",
1801 __FILE__, __LINE__, fd, errno, strerror(errno));
1802 return -errno;
1803 }
1804 #else
1805 if (Debug_level > 2)
1806 printf
1807 ("DEBUG %s/%d: wait method : aio_suspend, sigev_notify=%s\n",
1808 __FILE__, __LINE__,
1809 (aiocbp->aio_sigevent.sigev_notify ==
1810 SIGEV_SIGNAL ? "signal" : aiocbp->aio_sigevent.
1811 sigev_notify == SIGEV_NONE ? "none" :
1812 #ifdef SIGEV_CALLBACK
1813 aiocbp->aio_sigevent.sigev_notify ==
1814 SIGEV_CALLBACK ? "callback" :
1815 #endif
1816 aiocbp->aio_sigevent.sigev_notify ==
1817 SIGEV_THREAD ? "thread" : "unknown"));
1818
1819 aioary[0] = aiocbp;
1820 ret = aio_suspend(aioary, 1, NULL);
1821 if ((ret == -1) && (errno == EINTR)) {
1822 if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL) {
1823 if (Debug_level > 2) {
1824 printf
1825 ("DEBUG %s/%d: aio_suspend received EINTR, sigev_notify=SIGEV_SIGNAL -- ok\n",
1826 __FILE__, __LINE__);
1827 }
1828 } else {
1829 sprintf(Errormsg,
1830 "%s/%d aio_suspend received EINTR, sigev_notify=%s, not ok\n",
1831 __FILE__, __LINE__,
1832 (aiocbp->aio_sigevent.sigev_notify ==
1833 SIGEV_SIGNAL ? "signal" : aiocbp->
1834 aio_sigevent.sigev_notify ==
1835 SIGEV_NONE ? "none" :
1836 #ifdef SIGEV_CALLBACK
1837 aiocbp->aio_sigevent.sigev_notify ==
1838 SIGEV_CALLBACK ? "callback" :
1839 #endif
1840 aiocbp->aio_sigevent.sigev_notify ==
1841 SIGEV_THREAD ? "thread" : "unknown"));
1842 return -errno;
1843 }
1844 } else if (ret) {
1845 sprintf(Errormsg,
1846 "%s/%d aio_suspend(fildes=%d, aioary, 1, NULL) failed, errno:%d %s",
1847 __FILE__, __LINE__, fd, errno, strerror(errno));
1848 return -errno;
1849 }
1850 #endif
1851
1852 } else if (method & LIO_WAIT_ACTIVE) {
1853 if (Debug_level > 2)
1854 printf("DEBUG %s/%d: wait method : active\n", __FILE__,
1855 __LINE__);
1856 #ifdef CRAY
1857 sigon();
1858 /*
1859 * loop until sw_flag, sw_count or sw_error field elements
1860 * change to non-zero.
1861 */
1862 cnt = 0;
1863 while ((*statptr)->sw_flag == 0 &&
1864 (*statptr)->sw_count == 0 && (*statptr)->sw_error == 0) {
1865 cnt++;
1866 }
1867 #else
1868 /* loop while aio_error() returns EINPROGRESS */
1869 cnt = 0;
1870 while (1) {
1871 ret = aio_error(aiocbp);
1872 if (ret != EINPROGRESS) {
1873 break;
1874 }
1875 ++cnt;
1876 }
1877
1878 #endif
1879 if (Debug_level > 5 && cnt && (cnt % 50) == 0)
1880 printf("DEBUG %s/%d: wait active cnt = %d\n",
1881 __FILE__, __LINE__, cnt);
1882
1883 } else if (method & LIO_WAIT_SIGPAUSE) {
1884 if (Debug_level > 2)
1885 printf("DEBUG %s/%d: wait method : sigpause\n",
1886 __FILE__, __LINE__);
1887 #ifdef sgi
1888 /* note: don't do the sigon() for CRAY in this case. why? -- roehrich 6/11/97 */
1889 if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL)
1890 sigrelse(aiocbp->aio_sigevent.sigev_signo);
1891 else {
1892 printf("DEBUG %s/%d: sigev_notify != SIGEV_SIGNAL\n",
1893 __FILE__, __LINE__);
1894 return -1;
1895 }
1896 #endif
1897 pause();
1898
1899 } else if (method & LIO_WAIT_SIGACTIVE) {
1900 if (Debug_level > 2)
1901 printf("DEBUG %s/%d: wait method : sigactive\n",
1902 __FILE__, __LINE__);
1903 #ifdef CRAY
1904 sigon();
1905 #else
1906 if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL)
1907 sigrelse(aiocbp->aio_sigevent.sigev_signo);
1908 else {
1909 printf("DEBUG %s/%d: sigev_notify != SIGEV_SIGNAL\n",
1910 __FILE__, __LINE__);
1911 return -1;
1912 }
1913 #endif
1914 /* loop waiting for signal */
1915 while (Received_signal == Rec_signal) {
1916 #ifdef CRAY
1917 sigon();
1918 #else
1919 sigrelse(aiocbp->aio_sigevent.sigev_signo);
1920 #endif
1921 }
1922
1923 } else if (method & LIO_WAIT_NONE) {
1924 if (Debug_level > 2)
1925 printf("DEBUG %s/%d: wait method : none\n", __FILE__,
1926 __LINE__);
1927 /* It's broken because the aiocb/iosw is an automatic variable in
1928 * lio_{read,write}_buffer, so when the function returns and the
1929 * I/O completes there will be nowhere to write the I/O status.
1930 * It doesn't cause a problem on unicos--probably because of some
1931 * compiler quirk, or an accident. It causes POSIX async I/O
1932 * to core dump some threads. spr/pv 705909. 6/27/97 roehrich
1933 */
1934 sprintf(Errormsg,
1935 "%s/%d LIO_WAIT_NONE was selected (this is broken)\n",
1936 __FILE__, __LINE__);
1937 #ifdef CRAY
1938 sigon();
1939 #endif
1940 /* return 1;*/
1941 return -1;
1942 } else {
1943 if (Debug_level > 2)
1944 printf("DEBUG %s/%d: no wait method was chosen\n",
1945 __FILE__, __LINE__);
1946 return -1;
1947 }
1948
1949 return 0;
1950
1951 } /* end of lio_wait4asyncio */
1952
1953 #endif /* ifndef linux */
1954 #endif
1955
1956 #if UNIT_TEST
1957 /***********************************************************************
1958 * The following code is provided as unit test.
1959 * Just define add "-DUNIT_TEST=1" to the cc line.
1960 *
1961 * (rrl 04/96)
1962 ***********************************************************************/
1963 struct unit_info_t {
1964 int method;
1965 int sig;
1966 char *str;
1967 } Unit_info[] = {
1968 {
1969 LIO_IO_SYNC, 0, "sync io"}, {
1970 LIO_IO_SYNCV, 0, "sync readv/writev"}, {
1971 LIO_IO_SYNCP, 0, "sync pread/pwrite"}, {
1972 LIO_IO_ASYNC, 0, "async io, def wait"}, {
1973 LIO_IO_SLISTIO, 0, "sync listio"}, {
1974 LIO_IO_ALISTIO, 0, "async listio, def wait"}, {
1975 LIO_IO_ASYNC | LIO_WAIT_ACTIVE, 0, "async active"}, {
1976 LIO_IO_ASYNC | LIO_WAIT_RECALL, 0, "async recall/suspend"}, {
1977 LIO_IO_ASYNC | LIO_WAIT_SIGPAUSE, SIGUSR1, "async sigpause"}, {
1978 LIO_IO_ASYNC | LIO_WAIT_SIGACTIVE, SIGUSR1, "async sigactive"}, {
1979 LIO_IO_ALISTIO | LIO_WAIT_ACTIVE, 0, "async listio active"}, {
1980 LIO_IO_ALISTIO | LIO_WAIT_RECALL, 0, "async listio recall"}, {
1981 LIO_IO_ALISTIO | LIO_WAIT_SIGACTIVE, SIGUSR1, "async listio sigactive"},
1982 {
1983 LIO_IO_ALISTIO | LIO_WAIT_SIGPAUSE, SIGUSR1, "async listio sigpause"},
1984 {
1985 LIO_IO_ASYNC, SIGUSR2, "async io, def wait, sigusr2"}, {
1986 LIO_IO_ALISTIO, SIGUSR2, "async listio, def wait, sigusr2"},};
1987
main(argc,argv)1988 int main(argc, argv)
1989 int argc;
1990 char **argv;
1991 {
1992 extern char *optarg;
1993 extern int optind;
1994
1995 int fd;
1996 char *err;
1997 char buffer[4096];
1998 int size = 4096;
1999 int ret;
2000 int ind;
2001 int iter = 3;
2002 int method;
2003 int exit_status = 0;
2004 int c;
2005 int i;
2006 char *symbols = NULL;
2007 int die_on_err = 0;
2008
2009 while ((c = getopt(argc, argv, "s:di:")) != -1) {
2010 switch (c) {
2011 case 's':
2012 symbols = optarg;
2013 break;
2014 case 'd':
2015 ++die_on_err;
2016 break;
2017 case 'i':
2018 iter = atoi(optarg);
2019 break;
2020 }
2021 }
2022
2023 if ((fd =
2024 open("unit_test_file", O_CREAT | O_RDWR | O_TRUNC, 0777)) == -1) {
2025 perror
2026 ("open(unit_test_file, O_CREAT|O_RDWR|O_TRUNC, 0777) failed");
2027 exit(1);
2028 }
2029
2030 Debug_level = 9;
2031
2032 if (symbols != NULL) {
2033 if ((method = lio_parse_io_arg2(symbols, &err)) == -1) {
2034 printf
2035 ("lio_parse_io_arg2(%s, &err) failed, bad token starting at %s\n",
2036 symbols, err);
2037 if (die_on_err)
2038 exit(1);
2039 } else
2040 printf("lio_parse_io_arg2(%s, &err) returned %#o\n",
2041 symbols, method);
2042
2043 exit_status = 0;
2044 for (ind = 0; ind < iter; ind++) {
2045 memset(buffer, 'A', 4096);
2046 if (lseek(fd, 0, 0) == -1) {
2047 printf("lseek(fd,0,0), %d, failed, errno %d\n",
2048 __LINE__, errno);
2049 ++exit_status;
2050 }
2051 if ((ret = lio_write_buffer(fd, method, buffer,
2052 size, SIGUSR1, &err,
2053 0)) != size) {
2054 printf
2055 ("lio_write_buffer returned -1, err = %s\n",
2056 err);
2057 } else
2058 printf("lio_write_buffer returned %d\n", ret);
2059
2060 memset(buffer, 'B', 4096);
2061 if (lseek(fd, 0, 0) == -1) {
2062 printf("lseek(fd,0,0), %d, failed, errno %d\n",
2063 __LINE__, errno);
2064 ++exit_status;
2065 }
2066 if ((ret = lio_read_buffer(fd, method, buffer,
2067 size, SIGUSR2, &err,
2068 0)) != size) {
2069 printf
2070 ("lio_read_buffer returned -1, err = %s\n",
2071 err);
2072 } else
2073 printf("lio_read_buffer returned %d\n", ret);
2074
2075 for (i = 0; i < 4096; ++i) {
2076 if (buffer[i] != 'A') {
2077 printf(" buffer[%d] = %d\n", i,
2078 buffer[i]);
2079 ++exit_status;
2080 break;
2081 }
2082 }
2083
2084 if (exit_status)
2085 exit(exit_status);
2086
2087 }
2088
2089 unlink("unit_test_file");
2090 exit(0);
2091 }
2092
2093 for (ind = 0; ind < sizeof(Unit_info) / sizeof(struct unit_info_t);
2094 ind++) {
2095
2096 printf("\n********* write %s ***************\n",
2097 Unit_info[ind].str);
2098 if (lseek(fd, 0, 0) == -1) {
2099 printf("lseek(fd,0,0), %d, failed, errno %d\n",
2100 __LINE__, errno);
2101 ++exit_status;
2102 }
2103
2104 memset(buffer, 'A', 4096);
2105 if ((ret = lio_write_buffer(fd, Unit_info[ind].method, buffer,
2106 size, Unit_info[ind].sig, &err,
2107 0)) != size) {
2108 printf
2109 (">>>>> lio_write_buffer(fd,0%x,buffer,%d,%d,err,0) returned -1,\n err = %s\n",
2110 Unit_info[ind].method, size, Unit_info[ind].sig,
2111 err);
2112 ++exit_status;
2113 if (die_on_err)
2114 exit(exit_status);
2115 } else {
2116 printf("lio_write_buffer returned %d\n", ret);
2117 }
2118
2119 printf("\n********* read %s ***************\n",
2120 Unit_info[ind].str);
2121 if (lseek(fd, 0, 0) == -1) {
2122 printf("lseek(fd,0,0), %d, failed, errno %d\n",
2123 __LINE__, errno);
2124 ++exit_status;
2125 }
2126 memset(buffer, 'B', 4096);
2127 if ((ret = lio_read_buffer(fd, Unit_info[ind].method, buffer,
2128 size, Unit_info[ind].sig, &err,
2129 0)) != size) {
2130 printf
2131 (">>>>> lio_read_buffer(fd,0%x,buffer,%d,%d,err,0) returned -1,\n err = %s\n",
2132 Unit_info[ind].method, size, Unit_info[ind].sig,
2133 err);
2134 ++exit_status;
2135 if (die_on_err)
2136 exit(exit_status);
2137 } else {
2138 printf("lio_read_buffer returned %d\n", ret);
2139 }
2140
2141 for (i = 0; i < 4096; ++i) {
2142 if (buffer[i] != 'A') {
2143 printf(" buffer[%d] = %d\n", i, buffer[i]);
2144 ++exit_status;
2145 if (die_on_err)
2146 exit(exit_status);
2147 break;
2148 }
2149 }
2150
2151 fflush(stdout);
2152 fflush(stderr);
2153 sleep(1);
2154
2155 }
2156
2157 unlink("unit_test_file");
2158
2159 exit(exit_status);
2160 }
2161 #endif
2162