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 #ifndef __UCLIBC__
112 #include <aio.h>
113 #endif
114 #endif
115 #include <stdlib.h> /* atoi, abs */
116
117 #include "tlibio.h" /* defines LIO* macros */
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[PATH_MAX*2];
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 /* as we cycle writes in case of partial writes, we have to report up
543 * total bytes written
544 */
545 int totally_written = 0;
546 char *io_type; /* Holds string of type of io */
547 int omethod = method;
548 int listio_cmd; /* Holds the listio/lio_listio cmd */
549 #ifdef CRAY
550 struct listreq request; /* Used when a listio is wanted */
551 struct iosw status, *statptr[1];
552 #else
553 /* for linux or sgi */
554 struct iovec iov; /* iovec for writev(2) */
555 #endif
556 #if defined (sgi)
557 aiocb_t aiocbp; /* POSIX aio control block */
558 aiocb_t *aiolist[1]; /* list of aio control blocks for lio_listio */
559 off64_t poffset; /* pwrite(2) offset */
560 #endif
561 #if defined(__linux__) && !defined(__UCLIBC__)
562 struct aiocb aiocbp; /* POSIX aio control block */
563 struct aiocb *aiolist[1]; /* list of aio control blocks for lio_listio */
564 off64_t poffset; /* pwrite(2) offset */
565 #endif
566 /*
567 * If LIO_RANDOM bit specified, get new method randomly.
568 */
569 if (method & LIO_RANDOM) {
570 if (Debug_level > 3)
571 printf("DEBUG %s/%d: method mask to choose from: %#o\n",
572 __FILE__, __LINE__, method);
573 method = lio_random_methods(method);
574 if (Debug_level > 2)
575 printf("DEBUG %s/%d: random chosen method %#o\n",
576 __FILE__, __LINE__, method);
577 }
578
579 if (errmsg != NULL)
580 *errmsg = Errormsg;
581
582 Rec_signal = Received_signal; /* get the current number of signals received */
583 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
584 Rec_callback = Received_callback; /* get the current number of callbacks received */
585 #endif
586
587 #ifdef CRAY
588 memset(&status, 0x00, sizeof(struct iosw));
589 memset(&request, 0x00, sizeof(struct listreq));
590 statptr[0] = &status;
591 #else
592 /* for linux or sgi */
593 memset(&iov, 0x00, sizeof(struct iovec));
594 iov.iov_base = buffer;
595 iov.iov_len = size;
596 #endif
597 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
598 #if defined(sgi)
599 memset(&aiocbp, 0x00, sizeof(aiocb_t));
600 #else
601 memset(&aiocbp, 0x00, sizeof(struct aiocb));
602 #endif
603 aiocbp.aio_fildes = fd;
604 aiocbp.aio_nbytes = size;
605 aiocbp.aio_buf = buffer;
606 /* aiocbp.aio_offset = lseek( fd, 0, SEEK_CUR ); -- set below */
607 aiocbp.aio_sigevent.sigev_notify = SIGEV_NONE;
608 aiocbp.aio_sigevent.sigev_signo = 0;
609 #ifdef sgi
610 aiocbp.aio_sigevent.sigev_func = NULL;
611 aiocbp.aio_sigevent.sigev_value.sival_int = 0;
612 #elif defined(__linux__) && !defined(__UCLIBC__)
613 aiocbp.aio_sigevent.sigev_notify_function = NULL;
614 aiocbp.aio_sigevent.sigev_notify_attributes = 0;
615 #endif
616 aiolist[0] = &aiocbp;
617
618 if ((ret = lseek(fd, 0, SEEK_CUR)) == -1) {
619 ret = 0;
620 /* If there is an error and it is not ESPIPE then kick out the error.
621 * If the fd is a fifo then we have to make sure that
622 * lio_random_methods() didn't select pwrite/pread; if it did then
623 * switch to write/read.
624 */
625 if (errno == ESPIPE) {
626 if (method & LIO_IO_SYNCP) {
627 if (omethod & LIO_RANDOM) {
628 method &= ~LIO_IO_SYNCP;
629 method |= LIO_IO_SYNC;
630 if (Debug_level > 2)
631 printf
632 ("DEBUG %s/%d: random chosen method switched to %#o for fifo\n",
633 __FILE__, __LINE__,
634 method);
635 } else if (Debug_level) {
636 printf
637 ("DEBUG %s/%d: pwrite will fail when it writes to a fifo\n",
638 __FILE__, __LINE__);
639 }
640 }
641 /* else: let it ride */
642 } else {
643 sprintf(Errormsg,
644 "%s/%d lseek(fd=%d,0,SEEK_CUR) failed, errno=%d %s",
645 __FILE__, __LINE__, fd, errno, strerror(errno));
646 return -errno;
647 }
648 }
649 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
650 poffset = (off64_t) ret;
651 #endif
652 aiocbp.aio_offset = ret;
653
654 #endif
655
656 /*
657 * If the LIO_USE_SIGNAL bit is not set, only use the signal
658 * if the LIO_WAIT_SIGPAUSE or the LIO_WAIT_SIGACTIVE bits are bit.
659 * Otherwise there is not necessary a signal handler to trap
660 * the signal.
661 */
662 if (sig && !(method & LIO_USE_SIGNAL) && !(method & LIO_WAIT_SIGTYPES)) {
663
664 sig = 0; /* ignore signal parameter */
665 }
666 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
667 if (sig && (method & LIO_WAIT_CBTYPES))
668 sig = 0; /* ignore signal parameter */
669 #endif
670
671 /*
672 * only setup signal hander if sig was specified and
673 * a sig wait method was specified.
674 * Doing this will change the handler for this signal. The
675 * old signal handler will not be restored.
676 *** restoring the signal handler could be added ***
677 */
678
679 if (sig && (method & LIO_WAIT_SIGTYPES)) {
680 #ifdef CRAY
681 sigctl(SCTL_REG, sig, lio_async_signal_handler);
682 #endif
683 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
684 aiocbp.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
685 aiocbp.aio_sigevent.sigev_signo = sig;
686 sigset(sig, lio_async_signal_handler);
687 #endif /* sgi */
688 }
689 #if defined(sgi)
690 else if (method & LIO_WAIT_CBTYPES) {
691 /* sival_int just has to be something that I can use
692 * to identify the callback, and "size" happens to be handy...
693 */
694 aiocbp.aio_sigevent.sigev_notify = SIGEV_CALLBACK;
695 aiocbp.aio_sigevent.sigev_func = lio_async_callback_handler;
696 aiocbp.aio_sigevent.sigev_value.sival_int = size;
697 }
698 #endif
699 #if defined(__linux__) && !defined(__UCLIBC__)
700 else if (method & LIO_WAIT_CBTYPES) {
701 /* sival_int just has to be something that I can use
702 * to identify the callback, and "size" happens to be handy...
703 */
704 aiocbp.aio_sigevent.sigev_notify = SIGEV_THREAD;
705 aiocbp.aio_sigevent.sigev_notify_function =
706 lio_async_callback_handler;
707 aiocbp.aio_sigevent.sigev_notify_attributes =
708 (void *)(uintptr_t) size;
709 }
710 #endif
711 /*
712 * Determine the system call that will be called and produce
713 * the string of the system call and place it in Lio_SysCall.
714 * Also update the io_type char pointer to give brief description
715 * of system call. Execute the system call and check for
716 * system call failure. If sync i/o, return the number of
717 * bytes written/read.
718 */
719
720 if ((method & LIO_IO_SYNC)
721 || (method & (LIO_IO_TYPES | LIO_IO_ATYPES)) == 0) {
722 /*
723 * write(2) is used if LIO_IO_SYNC bit is set or not none
724 * of the LIO_IO_TYPES bits are set (default).
725 */
726
727 sprintf(Lio_SysCall, "write(%d, buf, %d)", fd, size);
728 io_type = "write";
729
730 if (Debug_level) {
731 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
732 Lio_SysCall);
733 }
734 while (1) {
735 if (((ret = write(fd, buffer, size)) == -1)
736 && errno != EAGAIN && errno != EINTR) {
737 sprintf(Errormsg,
738 "%s/%d write(%d, buf, %d) ret:-1, errno=%d %s",
739 __FILE__, __LINE__, fd, size, errno,
740 strerror(errno));
741 return -errno;
742 }
743
744 if (ret != -1) {
745 if (ret != size) {
746 sprintf(Errormsg,
747 "%s/%d write(%d, buf, %d) returned=%d",
748 __FILE__, __LINE__,
749 fd, size, ret);
750 size -= ret;
751 buffer += ret;
752 totally_written += ret;
753 } else {
754 if (Debug_level > 1)
755 printf
756 ("DEBUG %s/%d: write completed without error (ret %d)\n",
757 __FILE__, __LINE__, ret);
758
759 return totally_written + ret;
760 }
761 }
762 wait4sync_io(fd, 0);
763 }
764
765 }
766
767 else if (method & LIO_IO_ASYNC) {
768 #ifdef CRAY
769 sprintf(Lio_SysCall,
770 "writea(%d, buf, %d, &status, %d)", fd, size, sig);
771 io_type = "writea";
772
773 if (Debug_level) {
774 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
775 Lio_SysCall);
776 }
777
778 sigoff();
779 if ((ret = writea(fd, buffer, size, &status, sig)) == -1) {
780 sprintf(Errormsg,
781 "%s/%d writea(%d, buf, %d, &stat, %d) ret:-1, errno=%d %s",
782 __FILE__, __LINE__,
783 fd, size, sig, errno, strerror(errno));
784 sigon();
785 return -errno;
786 }
787 #endif
788 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
789 sprintf(Lio_SysCall,
790 "aio_write(fildes=%d, buf, nbytes=%d, signo=%d)", fd,
791 size, sig);
792 io_type = "aio_write";
793
794 if (Debug_level) {
795 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
796 Lio_SysCall);
797 }
798
799 if (sig)
800 sighold(sig);
801 if ((ret = aio_write(&aiocbp)) == -1) {
802 sprintf(Errormsg,
803 "%s/%d aio_write(fildes=%d, buf, nbytes=%d, signo=%d) ret:-1, errno=%d %s",
804 __FILE__, __LINE__,
805 fd, size, sig, errno, strerror(errno));
806 if (sig)
807 sigrelse(sig);
808 return -errno;
809 }
810 #endif
811 }
812 /* LIO_IO_ASYNC */
813 else if (method & LIO_IO_SLISTIO) {
814 #ifdef CRAY
815 request.li_opcode = LO_WRITE;
816 request.li_fildes = fd;
817 request.li_buf = buffer;
818 request.li_nbyte = size;
819 request.li_status = &status;
820 request.li_signo = sig;
821 request.li_nstride = 0;
822 request.li_filstride = 0;
823 request.li_memstride = 0;
824
825 listio_cmd = LC_WAIT;
826 io_type = "listio(2) sync write";
827
828 sprintf(Lio_SysCall,
829 "listio(LC_WAIT, &req, 1) LO_WRITE, fd:%d, nbyte:%d",
830 fd, size);
831
832 if (Debug_level) {
833 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
834 Lio_SysCall);
835 }
836
837 sigoff();
838 if (listio(listio_cmd, &request, 1) == -1) {
839 sprintf(Errormsg,
840 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
841 __FILE__, __LINE__, Lio_SysCall, fd, size,
842 errno, strerror(errno));
843 sigon();
844 return -errno;
845 }
846
847 if (Debug_level > 1)
848 printf("DEBUG %s/%d: %s did not return -1\n",
849 __FILE__, __LINE__, Lio_SysCall);
850
851 ret = lio_check_asyncio(io_type, size, &status);
852 return ret;
853
854 #endif
855 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
856
857 aiocbp.aio_lio_opcode = LIO_WRITE;
858 listio_cmd = LIO_WAIT;
859 io_type = "lio_listio(3) sync write";
860
861 sprintf(Lio_SysCall,
862 "lio_listio(LIO_WAIT, aiolist, 1, NULL) LIO_WRITE, fd:%d, nbyte:%d, sig:%d",
863 fd, size, sig);
864
865 if (Debug_level) {
866 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
867 Lio_SysCall);
868 }
869
870 if (sig)
871 sighold(sig);
872 if (lio_listio(listio_cmd, aiolist, 1, NULL) == -1) {
873 sprintf(Errormsg,
874 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
875 __FILE__, __LINE__, Lio_SysCall, fd, size,
876 errno, strerror(errno));
877 if (sig)
878 sigrelse(sig);
879 return -errno;
880 }
881
882 if (Debug_level > 1)
883 printf("DEBUG %s/%d: %s did not return -1\n",
884 __FILE__, __LINE__, Lio_SysCall);
885
886 ret = lio_check_asyncio(io_type, size, &aiocbp, method);
887 return ret;
888 #endif
889 }
890 /* LIO_IO_SLISTIO */
891 else if (method & LIO_IO_ALISTIO) {
892 #ifdef CRAY
893 request.li_opcode = LO_WRITE;
894 request.li_fildes = fd;
895 request.li_buf = buffer;
896 request.li_nbyte = size;
897 request.li_status = &status;
898 request.li_signo = sig;
899 request.li_nstride = 0;
900 request.li_filstride = 0;
901 request.li_memstride = 0;
902
903 listio_cmd = LC_START;
904 io_type = "listio(2) async write";
905
906 sprintf(Lio_SysCall,
907 "listio(LC_START, &req, 1) LO_WRITE, fd:%d, nbyte:%d",
908 fd, size);
909
910 if (Debug_level) {
911 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
912 Lio_SysCall);
913 }
914
915 sigoff();
916 if (listio(listio_cmd, &request, 1) == -1) {
917 sprintf(Errormsg,
918 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
919 __FILE__, __LINE__, Lio_SysCall, fd, size,
920 errno, strerror(errno));
921 sigon();
922 return -errno;
923 }
924 #endif
925 #if defined (sgi) || (defined(__linux__) && !defined(__UCLIBC__))
926 aiocbp.aio_lio_opcode = LIO_WRITE;
927 listio_cmd = LIO_NOWAIT;
928 io_type = "lio_listio(3) async write";
929
930 sprintf(Lio_SysCall,
931 "lio_listio(LIO_NOWAIT, aiolist, 1, NULL) LIO_WRITE, fd:%d, nbyte:%d",
932 fd, size);
933
934 if (Debug_level) {
935 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
936 Lio_SysCall);
937 }
938
939 if (sig)
940 sighold(sig);
941 if (lio_listio(listio_cmd, aiolist, 1, NULL) == -1) {
942 sprintf(Errormsg,
943 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
944 __FILE__, __LINE__, Lio_SysCall, fd, size,
945 errno, strerror(errno));
946 if (sig)
947 sigrelse(sig);
948 return -errno;
949 }
950 #endif
951 }
952 /* LIO_IO_ALISTIO */
953 #ifndef CRAY
954 else if (method & LIO_IO_SYNCV) {
955 io_type = "writev(2)";
956
957 sprintf(Lio_SysCall, "writev(%d, &iov, 1) nbyte:%d", fd, size);
958
959 if (Debug_level) {
960 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
961 Lio_SysCall);
962 }
963 if ((ret = writev(fd, &iov, 1)) == -1) {
964 sprintf(Errormsg,
965 "%s/%d writev(%d, iov, 1) nbyte:%d ret:-1, errno=%d %s",
966 __FILE__, __LINE__, fd, size, errno,
967 strerror(errno));
968 return -errno;
969 }
970
971 if (ret != size) {
972 sprintf(Errormsg,
973 "%s/%d writev(%d, iov, 1) nbyte:%d returned=%d",
974 __FILE__, __LINE__, fd, size, ret);
975 } else if (Debug_level > 1)
976 printf
977 ("DEBUG %s/%d: writev completed without error (ret %d)\n",
978 __FILE__, __LINE__, ret);
979
980 return ret;
981 } /* LIO_IO_SYNCV */
982 #endif
983
984 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
985 else if (method & LIO_IO_SYNCP) {
986 io_type = "pwrite(2)";
987
988 sprintf(Lio_SysCall,
989 "pwrite(%d, buf, %d, %lld)", fd, size,
990 (long long)poffset);
991
992 if (Debug_level) {
993 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
994 Lio_SysCall);
995 }
996 if ((ret = pwrite(fd, buffer, size, poffset)) == -1) {
997 sprintf(Errormsg,
998 "%s/%d pwrite(%d, buf, %d, %lld) ret:-1, errno=%d %s",
999 __FILE__, __LINE__, fd, size,
1000 (long long)poffset, errno, strerror(errno));
1001 return -errno;
1002 }
1003
1004 if (ret != size) {
1005 sprintf(Errormsg,
1006 "%s/%d pwrite(%d, buf, %d, %lld) returned=%d",
1007 __FILE__, __LINE__,
1008 fd, size, (long long)poffset, ret);
1009 } else if (Debug_level > 1)
1010 printf
1011 ("DEBUG %s/%d: pwrite completed without error (ret %d)\n",
1012 __FILE__, __LINE__, ret);
1013
1014 return ret;
1015 } /* LIO_IO_SYNCP */
1016 #endif
1017
1018 else {
1019 printf("DEBUG %s/%d: No I/O method chosen\n", __FILE__,
1020 __LINE__);
1021 return -1;
1022 }
1023
1024 /*
1025 * wait for async io to complete.
1026 */
1027 #ifdef CRAY
1028 ret = lio_wait4asyncio(method, fd, statptr);
1029 #endif
1030 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1031 ret = lio_wait4asyncio(method, fd, &aiocbp);
1032 #endif
1033
1034 /*
1035 * If there was an error waiting for async i/o to complete,
1036 * return the error value (errno) to the caller.
1037 * Note: Errormsg should already have been updated.
1038 */
1039 if (ret < 0) {
1040 return ret;
1041 }
1042
1043 /*
1044 * If i/o was not waited for (may not have been completed at this time),
1045 * return the size that was requested.
1046 */
1047 if (ret == 1)
1048 return size;
1049
1050 /*
1051 * check that async io was successful.
1052 * Note: if the there was an system call failure, -errno
1053 * was returned and Errormsg should already have been updated.
1054 * If amount i/o was different than size, Errormsg should already
1055 * have been updated but the actual i/o size if returned.
1056 */
1057
1058 #ifdef CRAY
1059 ret = lio_check_asyncio(io_type, size, &status);
1060 #endif
1061 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1062 ret = lio_check_asyncio(io_type, size, &aiocbp, method);
1063 #endif
1064
1065 return ret;
1066 } /* end of lio_write_buffer */
1067
1068 /***********************************************************************
1069 * Generic read function
1070 * This function can be used to do a read using read(2), reada(2),
1071 * aio_read(3), readv(2), pread(2),
1072 * or single stride listio(2)/lio_listio(3).
1073 * By setting the desired bits in the method
1074 * bitmask, the caller can control the type of read and the wait method
1075 * that will be used. If no io type bits are set, read will be used.
1076 *
1077 * If async io was attempted and no wait method bits are set then the
1078 * wait method is: recall(2) for reada(2) and listio(2); aio_suspend(3) for
1079 * aio_read(3) and lio_listio(3).
1080 *
1081 * If multiple wait methods are specified,
1082 * only one wait method will be used. The order is predetermined.
1083 *
1084 * If the call specifies a signal and one of the two signal wait methods,
1085 * a signal handler for the signal is set. This will reset an already
1086 * set handler for this signal.
1087 *
1088 * If the LIO_RANDOM method bit is set, this function will randomly
1089 * choose a io type and wait method from bits in the method argument.
1090 *
1091 * If an error is encountered, an error message will be generated
1092 * in a internal static buffer. If errmsg is not NULL, it will
1093 * be updated to point to the static buffer, allowing the caller
1094 * to print the error message.
1095 *
1096 * Return Value
1097 * If a system call fails, -errno is returned.
1098 * If LIO_WAIT_NONE bit is set, the return value is the return value
1099 * of the system call.
1100 * If the io did not fail, the amount of data written is returned.
1101 * If the size the system call say was written is different
1102 * then what was asked to be written, errmsg is updated for
1103 * this error condition. The return value is still the amount
1104 * the system call says was written.
1105 *
1106 * (rrl 04/96)
1107 ***********************************************************************/
lio_read_buffer(int fd,int method,char * buffer,int size,int sig,char ** errmsg,long wrd)1108 int lio_read_buffer(int fd, /* open file descriptor */
1109 int method, /* contains io type and wait method bitmask*/
1110 char *buffer, /* pointer to buffer */
1111 int size, /* the size of the io */
1112 int sig, /* signal to use if async io */
1113 char **errmsg, /* char pointer that will be updated to point to err message */
1114 long wrd) /* to allow future features, use zero for now */
1115 {
1116 int ret = 0; /* syscall return or used to get random method */
1117 /* as we cycle reads in case of partial reads, we have to report up
1118 * total bytes read
1119 */
1120 int totally_read = 0;
1121 char *io_type; /* Holds string of type of io */
1122 int listio_cmd; /* Holds the listio/lio_listio cmd */
1123 int omethod = method;
1124 #ifdef CRAY
1125 struct listreq request; /* Used when a listio is wanted */
1126 struct iosw status, *statptr[1];
1127 #else
1128 /* for linux or sgi */
1129 struct iovec iov; /* iovec for readv(2) */
1130 #endif
1131 #ifdef sgi
1132 aiocb_t aiocbp; /* POSIX aio control block */
1133 aiocb_t *aiolist[1]; /* list of aio control blocks for lio_listio */
1134 off64_t poffset; /* pread(2) offset */
1135 #endif
1136 #if defined (__linux__) && !defined(__UCLIBC__)
1137 struct aiocb aiocbp; /* POSIX aio control block */
1138 struct aiocb *aiolist[1]; /* list of aio control blocks for lio_listio */
1139 off64_t poffset; /* pread(2) offset */
1140 #endif
1141
1142 /*
1143 * If LIO_RANDOM bit specified, get new method randomly.
1144 */
1145 if (method & LIO_RANDOM) {
1146 if (Debug_level > 3)
1147 printf("DEBUG %s/%d: method mask to choose from: %#o\n",
1148 __FILE__, __LINE__, method);
1149 method = lio_random_methods(method);
1150 if (Debug_level > 2)
1151 printf("DEBUG %s/%d: random chosen method %#o\n",
1152 __FILE__, __LINE__, method);
1153 }
1154
1155 if (errmsg != NULL)
1156 *errmsg = Errormsg;
1157
1158 Rec_signal = Received_signal; /* get the current number of signals received */
1159 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1160 Rec_callback = Received_callback; /* get the current number of callbacks received */
1161 #endif
1162
1163 #ifdef CRAY
1164 memset(&status, 0x00, sizeof(struct iosw));
1165 memset(&request, 0x00, sizeof(struct listreq));
1166 statptr[0] = &status;
1167 #else
1168 /* for linux or sgi */
1169 memset(&iov, 0x00, sizeof(struct iovec));
1170 iov.iov_base = buffer;
1171 iov.iov_len = size;
1172 #endif
1173 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1174 #if defined(sgi)
1175 memset(&aiocbp, 0x00, sizeof(aiocb_t));
1176 #else
1177 memset(&aiocbp, 0x00, sizeof(struct aiocb));
1178 #endif
1179 aiocbp.aio_fildes = fd;
1180 aiocbp.aio_nbytes = size;
1181 aiocbp.aio_buf = buffer;
1182 /* aiocbp.aio_offset = lseek( fd, 0, SEEK_CUR ); -- set below */
1183 aiocbp.aio_sigevent.sigev_notify = SIGEV_NONE;
1184 aiocbp.aio_sigevent.sigev_signo = 0;
1185 #ifdef sgi
1186 aiocbp.aio_sigevent.sigev_func = NULL;
1187 aiocbp.aio_sigevent.sigev_value.sival_int = 0;
1188 #elif defined(__linux__) && !defined(__UCLIBC__)
1189 aiocbp.aio_sigevent.sigev_notify_function = NULL;
1190 aiocbp.aio_sigevent.sigev_notify_attributes = 0;
1191 #endif
1192 aiolist[0] = &aiocbp;
1193
1194 if ((ret = lseek(fd, 0, SEEK_CUR)) == -1) {
1195 ret = 0;
1196 /* If there is an error and it is not ESPIPE then kick out the error.
1197 * If the fd is a fifo then we have to make sure that
1198 * lio_random_methods() didn't select pwrite/pread; if it did then
1199 * switch to write/read.
1200 */
1201 if (errno == ESPIPE) {
1202 if (method & LIO_IO_SYNCP) {
1203 if (omethod & LIO_RANDOM) {
1204 method &= ~LIO_IO_SYNCP;
1205 method |= LIO_IO_SYNC;
1206 if (Debug_level > 2)
1207 printf
1208 ("DEBUG %s/%d: random chosen method switched to %#o for fifo\n",
1209 __FILE__, __LINE__,
1210 method);
1211 } else if (Debug_level) {
1212 printf
1213 ("DEBUG %s/%d: pread will fail when it reads from a fifo\n",
1214 __FILE__, __LINE__);
1215 }
1216 }
1217 /* else: let it ride */
1218 } else {
1219 sprintf(Errormsg,
1220 "%s/%d lseek(fd=%d,0,SEEK_CUR) failed, errno=%d %s",
1221 __FILE__, __LINE__, fd, errno, strerror(errno));
1222 return -errno;
1223 }
1224 }
1225 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1226 poffset = (off64_t) ret;
1227 #endif
1228 aiocbp.aio_offset = ret;
1229
1230 #endif
1231
1232 /*
1233 * If the LIO_USE_SIGNAL bit is not set, only use the signal
1234 * if the LIO_WAIT_SIGPAUSE or the LIO_WAIT_SIGACTIVE bits are set.
1235 * Otherwise there is not necessarily a signal handler to trap
1236 * the signal.
1237 */
1238 if (sig && !(method & LIO_USE_SIGNAL) && !(method & LIO_WAIT_SIGTYPES)) {
1239
1240 sig = 0; /* ignore signal parameter */
1241 }
1242 #if defined(sgi) || (defined(__linux__)&& !defined(__UCLIBC__))
1243 if (sig && (method & LIO_WAIT_CBTYPES))
1244 sig = 0; /* ignore signal parameter */
1245 #endif
1246
1247 /*
1248 * only setup signal hander if sig was specified and
1249 * a sig wait method was specified.
1250 * Doing this will change the handler for this signal. The
1251 * old signal handler will not be restored.
1252 *** restoring the signal handler could be added ***
1253 */
1254
1255 if (sig && (method & LIO_WAIT_SIGTYPES)) {
1256 #ifdef CRAY
1257 sigctl(SCTL_REG, sig, lio_async_signal_handler);
1258 #endif
1259 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1260 aiocbp.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
1261 aiocbp.aio_sigevent.sigev_signo = sig;
1262 sigset(sig, lio_async_signal_handler);
1263 #endif /* CRAY */
1264 }
1265 #if defined(sgi)
1266 else if (method & LIO_WAIT_CBTYPES) {
1267 aiocbp.aio_sigevent.sigev_notify = SIGEV_CALLBACK;
1268 aiocbp.aio_sigevent.sigev_func = lio_async_callback_handler;
1269 /* sival_int just has to be something that I can use
1270 * to identify the callback, and "size" happens to be handy...
1271 */
1272 aiocbp.aio_sigevent.sigev_value.sival_int = size;
1273 }
1274 #endif
1275 #if defined(__linux__) && !defined(__UCLIBC__)
1276 else if (method & LIO_WAIT_CBTYPES) {
1277 aiocbp.aio_sigevent.sigev_notify = SIGEV_THREAD;
1278 aiocbp.aio_sigevent.sigev_notify_function =
1279 lio_async_callback_handler;
1280 /* sival_int just has to be something that I can use
1281 * to identify the callback, and "size" happens to be handy...
1282 */
1283 aiocbp.aio_sigevent.sigev_notify_attributes =
1284 (void *)(uintptr_t) size;
1285 }
1286 #endif
1287
1288 /*
1289 * Determine the system call that will be called and produce
1290 * the string of the system call and place it in Lio_SysCall.
1291 * Also update the io_type char pointer to give brief description
1292 * of system call. Execute the system call and check for
1293 * system call failure. If sync i/o, return the number of
1294 * bytes written/read.
1295 */
1296
1297 if ((method & LIO_IO_SYNC)
1298 || (method & (LIO_IO_TYPES | LIO_IO_ATYPES)) == 0) {
1299 /*
1300 * read(2) is used if LIO_IO_SYNC bit is set or not none
1301 * of the LIO_IO_TYPES bits are set (default).
1302 */
1303
1304 sprintf(Lio_SysCall, "read(%d, buf, %d)", fd, size);
1305 io_type = "read";
1306
1307 if (Debug_level) {
1308 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1309 Lio_SysCall);
1310 }
1311
1312 while (1) {
1313 if (((ret = read(fd, buffer, size)) == -1)
1314 && errno != EINTR && errno != EAGAIN) {
1315 sprintf(Errormsg,
1316 "%s/%d read(%d, buf, %d) ret:-1, errno=%d %s",
1317 __FILE__, __LINE__, fd, size, errno,
1318 strerror(errno));
1319 return -errno;
1320 }
1321
1322 if (ret == 0)
1323 return 0;
1324 if (ret != -1) {
1325 if (ret != size) {
1326 sprintf(Errormsg,
1327 "%s/%d read(%d, buf, %d) returned=%d",
1328 __FILE__, __LINE__,
1329 fd, size, ret);
1330 size -= ret;
1331 buffer += ret;
1332 totally_read += ret;
1333 } else {
1334 if (Debug_level > 1)
1335 printf
1336 ("DEBUG %s/%d: read completed without error (ret %d)\n",
1337 __FILE__, __LINE__, ret);
1338
1339 return totally_read + ret;
1340 }
1341 }
1342 wait4sync_io(fd, 1);
1343 }
1344
1345 }
1346
1347 else if (method & LIO_IO_ASYNC) {
1348 #ifdef CRAY
1349 sprintf(Lio_SysCall,
1350 "reada(%d, buf, %d, &status, %d)", fd, size, sig);
1351 io_type = "reada";
1352
1353 if (Debug_level) {
1354 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1355 Lio_SysCall);
1356 }
1357
1358 sigoff();
1359 if ((ret = reada(fd, buffer, size, &status, sig)) == -1) {
1360 sprintf(Errormsg,
1361 "%s/%d reada(%d, buf, %d, &stat, %d) ret:-1, errno=%d %s",
1362 __FILE__, __LINE__,
1363 fd, size, sig, errno, strerror(errno));
1364 sigon();
1365 return -errno;
1366 }
1367 #endif
1368 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1369 sprintf(Lio_SysCall,
1370 "aio_read(fildes=%d, buf, nbytes=%d, signo=%d)", fd,
1371 size, sig);
1372 io_type = "aio_read";
1373
1374 if (Debug_level) {
1375 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1376 Lio_SysCall);
1377 }
1378
1379 if (sig)
1380 sighold(sig);
1381 if ((ret = aio_read(&aiocbp)) == -1) {
1382 sprintf(Errormsg,
1383 "%s/%d aio_read(fildes=%d, buf, nbytes=%d, signo=%d) ret:-1, errno=%d %s",
1384 __FILE__, __LINE__,
1385 fd, size, sig, errno, strerror(errno));
1386 if (sig)
1387 sigrelse(sig);
1388 return -errno;
1389 }
1390 #endif
1391 }
1392 /* LIO_IO_ASYNC */
1393 else if (method & LIO_IO_SLISTIO) {
1394 #ifdef CRAY
1395 request.li_opcode = LO_READ;
1396 request.li_fildes = fd;
1397 request.li_buf = buffer;
1398 request.li_nbyte = size;
1399 request.li_status = &status;
1400 request.li_signo = sig;
1401 request.li_nstride = 0;
1402 request.li_filstride = 0;
1403 request.li_memstride = 0;
1404
1405 listio_cmd = LC_WAIT;
1406 io_type = "listio(2) sync read";
1407
1408 sprintf(Lio_SysCall,
1409 "listio(LC_WAIT, &req, 1) LO_READ, fd:%d, nbyte:%d",
1410 fd, size);
1411
1412 if (Debug_level) {
1413 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1414 Lio_SysCall);
1415 }
1416
1417 sigoff();
1418 if (listio(listio_cmd, &request, 1) == -1) {
1419 sprintf(Errormsg,
1420 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1421 __FILE__, __LINE__, Lio_SysCall, fd, size,
1422 errno, strerror(errno));
1423 sigon();
1424 return -errno;
1425 }
1426
1427 if (Debug_level > 1)
1428 printf("DEBUG %s/%d: %s did not return -1\n",
1429 __FILE__, __LINE__, Lio_SysCall);
1430
1431 ret = lio_check_asyncio(io_type, size, &status);
1432 return ret;
1433 #endif
1434 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1435 aiocbp.aio_lio_opcode = LIO_READ;
1436 listio_cmd = LIO_WAIT;
1437 io_type = "lio_listio(3) sync read";
1438
1439 sprintf(Lio_SysCall,
1440 "lio_listio(LIO_WAIT, aiolist, 1, NULL) LIO_READ, fd:%d, nbyte:%d",
1441 fd, size);
1442
1443 if (Debug_level) {
1444 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1445 Lio_SysCall);
1446 }
1447
1448 if (sig)
1449 sighold(sig);
1450 if (lio_listio(listio_cmd, aiolist, 1, NULL) == -1) {
1451 sprintf(Errormsg,
1452 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1453 __FILE__, __LINE__, Lio_SysCall, fd, size,
1454 errno, strerror(errno));
1455 if (sig)
1456 sigrelse(sig);
1457 return -errno;
1458 }
1459
1460 if (Debug_level > 1)
1461 printf("DEBUG %s/%d: %s did not return -1\n",
1462 __FILE__, __LINE__, Lio_SysCall);
1463
1464 ret = lio_check_asyncio(io_type, size, &aiocbp, method);
1465 return ret;
1466 #endif
1467 }
1468 /* LIO_IO_SLISTIO */
1469 else if (method & LIO_IO_ALISTIO) {
1470 #ifdef CRAY
1471 request.li_opcode = LO_READ;
1472 request.li_fildes = fd;
1473 request.li_buf = buffer;
1474 request.li_nbyte = size;
1475 request.li_status = &status;
1476 request.li_signo = sig;
1477 request.li_nstride = 0;
1478 request.li_filstride = 0;
1479 request.li_memstride = 0;
1480
1481 listio_cmd = LC_START;
1482 io_type = "listio(2) async read";
1483
1484 sprintf(Lio_SysCall,
1485 "listio(LC_START, &req, 1) LO_READ, fd:%d, nbyte:%d",
1486 fd, size);
1487
1488 if (Debug_level) {
1489 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1490 Lio_SysCall);
1491 }
1492
1493 sigoff();
1494 if (listio(listio_cmd, &request, 1) == -1) {
1495 sprintf(Errormsg,
1496 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1497 __FILE__, __LINE__, Lio_SysCall, fd, size,
1498 errno, strerror(errno));
1499 sigon();
1500 return -errno;
1501 }
1502 #endif
1503 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1504 aiocbp.aio_lio_opcode = LIO_READ;
1505 listio_cmd = LIO_NOWAIT;
1506 io_type = "lio_listio(3) async read";
1507
1508 sprintf(Lio_SysCall,
1509 "lio_listio(LIO_NOWAIT, aiolist, 1, NULL) LIO_READ, fd:%d, nbyte:%d",
1510 fd, size);
1511
1512 if (Debug_level) {
1513 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1514 Lio_SysCall);
1515 }
1516
1517 if (sig)
1518 sighold(sig);
1519 if (lio_listio(listio_cmd, aiolist, 1, NULL) == -1) {
1520 sprintf(Errormsg,
1521 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1522 __FILE__, __LINE__, Lio_SysCall, fd, size,
1523 errno, strerror(errno));
1524 if (sig)
1525 sigrelse(sig);
1526 return -errno;
1527 }
1528 #endif
1529 }
1530 /* LIO_IO_ALISTIO */
1531 #ifndef CRAY
1532 else if (method & LIO_IO_SYNCV) {
1533 io_type = "readv(2)";
1534
1535 sprintf(Lio_SysCall, "readv(%d, &iov, 1) nbyte:%d", fd, size);
1536
1537 if (Debug_level) {
1538 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1539 Lio_SysCall);
1540 }
1541 if ((ret = readv(fd, &iov, 1)) == -1) {
1542 sprintf(Errormsg,
1543 "%s/%d readv(%d, iov, 1) nbyte:%d ret:-1, errno=%d %s",
1544 __FILE__, __LINE__, fd, size, errno,
1545 strerror(errno));
1546 return -errno;
1547 }
1548
1549 if (ret != size) {
1550 sprintf(Errormsg,
1551 "%s/%d readv(%d, iov, 1) nbyte:%d returned=%d",
1552 __FILE__, __LINE__, fd, size, ret);
1553 } else if (Debug_level > 1)
1554 printf
1555 ("DEBUG %s/%d: readv completed without error (ret %d)\n",
1556 __FILE__, __LINE__, ret);
1557
1558 return ret;
1559 } /* LIO_IO_SYNCV */
1560 #endif
1561
1562 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1563 else if (method & LIO_IO_SYNCP) {
1564 io_type = "pread(2)";
1565
1566 sprintf(Lio_SysCall,
1567 "pread(%d, buf, %d, %lld)", fd, size,
1568 (long long)poffset);
1569
1570 if (Debug_level) {
1571 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1572 Lio_SysCall);
1573 }
1574 if ((ret = pread(fd, buffer, size, poffset)) == -1) {
1575 sprintf(Errormsg,
1576 "%s/%d pread(%d, buf, %d, %lld) ret:-1, errno=%d %s",
1577 __FILE__, __LINE__, fd, size,
1578 (long long)poffset, errno, strerror(errno));
1579 return -errno;
1580 }
1581
1582 if (ret != size) {
1583 sprintf(Errormsg,
1584 "%s/%d pread(%d, buf, %d, %lld) returned=%d",
1585 __FILE__, __LINE__,
1586 fd, size, (long long)poffset, ret);
1587 } else if (Debug_level > 1)
1588 printf
1589 ("DEBUG %s/%d: pread completed without error (ret %d)\n",
1590 __FILE__, __LINE__, ret);
1591
1592 return ret;
1593 } /* LIO_IO_SYNCP */
1594 #endif
1595
1596 else {
1597 printf("DEBUG %s/%d: No I/O method chosen\n", __FILE__,
1598 __LINE__);
1599 return -1;
1600 }
1601
1602 /*
1603 * wait for async io to complete.
1604 * Note: Sync io should have returned prior to getting here.
1605 */
1606 #ifdef CRAY
1607 ret = lio_wait4asyncio(method, fd, statptr);
1608 #endif
1609 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1610 ret = lio_wait4asyncio(method, fd, &aiocbp);
1611 #endif
1612
1613 /*
1614 * If there was an error waiting for async i/o to complete,
1615 * return the error value (errno) to the caller.
1616 * Note: Errormsg should already have been updated.
1617 */
1618 if (ret < 0) {
1619 return ret;
1620 }
1621
1622 /*
1623 * If i/o was not waited for (may not have been completed at this time),
1624 * return the size that was requested.
1625 */
1626 if (ret == 1)
1627 return size;
1628
1629 /*
1630 * check that async io was successful.
1631 * Note: if the there was an system call failure, -errno
1632 * was returned and Errormsg should already have been updated.
1633 * If amount i/o was different than size, Errormsg should already
1634 * have been updated but the actual i/o size if returned.
1635 */
1636
1637 #ifdef CRAY
1638 ret = lio_check_asyncio(io_type, size, &status);
1639 #endif
1640 #if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1641 ret = lio_check_asyncio(io_type, size, &aiocbp, method);
1642 #endif
1643
1644 return ret;
1645 } /* end of lio_read_buffer */
1646
1647 #if !defined(__sun) && !defined(__hpux) && !defined(_AIX)
1648 /***********************************************************************
1649 * This function will check that async io was successful.
1650 * It can also be used to check sync listio since it uses the
1651 * same method.
1652 *
1653 * Return Values
1654 * If status.sw_error is set, -status.sw_error is returned.
1655 * Otherwise sw_count's field value is returned.
1656 *
1657 * (rrl 04/96)
1658 ***********************************************************************/
1659 #ifdef CRAY
1660 int lio_check_asyncio(char *io_type, int size, struct iosw *status)
1661 #elif defined(sgi)
1662 int lio_check_asyncio(char *io_type, int size, aiocb_t * aiocbp, int method)
1663 #elif defined(__linux__) && !defined(__UCLIBC__)
1664 int lio_check_asyncio(char *io_type, int size, struct aiocb *aiocbp, int method)
1665 {
1666 int ret;
1667
1668 #ifdef CRAY
1669 if (status->sw_error) {
1670 sprintf(Errormsg,
1671 "%s/%d %s, sw_error set = %d %s, sw_count = %d",
1672 __FILE__, __LINE__, io_type,
1673 status->sw_error, strerror(status->sw_error),
1674 status->sw_count);
1675 return -status->sw_error;
1676 } else if (status->sw_count != size) {
1677 sprintf(Errormsg,
1678 "%s/%d %s, sw_count not as expected(%d), but actual:%d",
1679 __FILE__, __LINE__, io_type, size, status->sw_count);
1680 } else if (Debug_level > 1) {
1681 printf
1682 ("DEBUG %s/%d: %s completed without error (sw_error == 0, sw_count == %d)\n",
1683 __FILE__, __LINE__, io_type, status->sw_count);
1684 }
1685
1686 return status->sw_count;
1687
1688 #else
1689
1690 int cnt = 1;
1691
1692 /* The I/O may have been synchronous with signal completion. It doesn't
1693 * make sense, but the combination could be generated. Release the
1694 * completion signal here otherwise it'll hang around and bite us
1695 * later.
1696 */
1697 if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL)
1698 sigrelse(aiocbp->aio_sigevent.sigev_signo);
1699
1700 ret = aio_error(aiocbp);
1701
1702 while (ret == EINPROGRESS) {
1703 ret = aio_error(aiocbp);
1704 ++cnt;
1705 }
1706 if (cnt > 1) {
1707 sprintf(Errormsg,
1708 "%s/%d %s, aio_error had to loop on EINPROGRESS, cnt=%d; random method %#o; sigev_notify=%s",
1709 __FILE__, __LINE__, io_type, cnt, method,
1710 (aiocbp->aio_sigevent.sigev_notify ==
1711 SIGEV_SIGNAL ? "signal" : aiocbp->aio_sigevent.
1712 sigev_notify == SIGEV_NONE ? "none" :
1713 #ifdef SIGEV_CALLBACK
1714 aiocbp->aio_sigevent.sigev_notify ==
1715 SIGEV_CALLBACK ? "callback" :
1716 #endif
1717 aiocbp->aio_sigevent.sigev_notify ==
1718 SIGEV_THREAD ? "thread" : "unknown"));
1719 return -ret;
1720 }
1721
1722 if (ret != 0) {
1723 sprintf(Errormsg,
1724 "%s/%d %s, aio_error = %d %s; random method %#o",
1725 __FILE__, __LINE__, io_type,
1726 ret, strerror(ret), method);
1727 return -ret;
1728 }
1729 ret = aio_return(aiocbp);
1730 if (ret != size) {
1731 sprintf(Errormsg,
1732 "%s/%d %s, aio_return not as expected(%d), but actual:%d",
1733 __FILE__, __LINE__, io_type, size, ret);
1734
1735 #ifdef BUG1_workaround
1736 if (ret == 0) {
1737 ret = size;
1738 if (Debug_level > 1) {
1739 printf
1740 ("WARN %s/%d: %s completed with bug1_workaround (aio_error == 0, aio_return now == %d)\n",
1741 __FILE__, __LINE__, io_type, ret);
1742 }
1743 }
1744 #endif /* BUG1_workaround */
1745
1746 } else if (Debug_level > 1) {
1747 printf
1748 ("DEBUG %s/%d: %s completed without error (aio_error == 0, aio_return == %d)\n",
1749 __FILE__, __LINE__, io_type, ret);
1750 }
1751
1752 return ret;
1753
1754 #endif
1755 } /* end of lio_check_asyncio */
1756 #endif
1757
1758 /***********************************************************************
1759 *
1760 * This function will wait for async io to complete.
1761 * If multiple wait methods are specified, the order is predetermined
1762 * to LIO_WAIT_RECALL,
1763 * LIO_WAIT_ACTIVE, LIO_WAIT_SIGPAUSE, LIO_WAIT_SIGACTIVE,
1764 * then LIO_WAIT_NONE.
1765 *
1766 * If no wait method was specified the default wait method is: recall(2)
1767 * or aio_suspend(3), as appropriate.
1768 *
1769 * Return Values
1770 * <0: errno of failed recall
1771 * 0 : async io was completed
1772 * 1 : async was not waited for, io may not have completed.
1773 *
1774 * (rrl 04/96)
1775 ***********************************************************************/
1776 #ifdef CRAY
1777 int lio_wait4asyncio(int method, int fd, struct iosw **statptr)
1778 #elif defined(sgi)
1779 int lio_wait4asyncio(int method, int fd, aiocb_t * aiocbp)
1780 #elif defined(__linux__) && !defined(__UCLIBC__)
1781 int lio_wait4asyncio(int method, int fd, struct aiocb *aiocbp)
1782 {
1783 int cnt;
1784 #ifdef sgi
1785 int ret;
1786 const aiocb_t *aioary[1];
1787 #endif
1788 #if defined(__linux__)&& !defined(__UCLIBC__)
1789 int ret;
1790 const struct aiocb *aioary[1];
1791 #endif
1792
1793 if ((method & LIO_WAIT_RECALL)
1794 #if defined(sgi) || (defined(__linux__)&& !defined(__UCLIBC__))
1795 || (method & LIO_WAIT_CBSUSPEND)
1796 || (method & LIO_WAIT_SIGSUSPEND)
1797 #endif
1798 || ((method & LIO_WAIT_TYPES) == 0)) {
1799 /*
1800 * If method has LIO_WAIT_RECALL bit set or method does
1801 * not have any wait method bits set (default), use recall/aio_suspend.
1802 */
1803 #ifdef CRAY
1804 if (Debug_level > 2)
1805 printf("DEBUG %s/%d: wait method : recall\n", __FILE__,
1806 __LINE__);
1807 sigon();
1808 if (recall(fd, 1, statptr)) {
1809 sprintf(Errormsg,
1810 "%s/%d recall(%d, 1, stat) failed, errno:%d %s",
1811 __FILE__, __LINE__, fd, errno, strerror(errno));
1812 return -errno;
1813 }
1814 #else
1815 if (Debug_level > 2)
1816 printf
1817 ("DEBUG %s/%d: wait method : aio_suspend, sigev_notify=%s\n",
1818 __FILE__, __LINE__,
1819 (aiocbp->aio_sigevent.sigev_notify ==
1820 SIGEV_SIGNAL ? "signal" : aiocbp->aio_sigevent.
1821 sigev_notify == SIGEV_NONE ? "none" :
1822 #ifdef SIGEV_CALLBACK
1823 aiocbp->aio_sigevent.sigev_notify ==
1824 SIGEV_CALLBACK ? "callback" :
1825 #endif
1826 aiocbp->aio_sigevent.sigev_notify ==
1827 SIGEV_THREAD ? "thread" : "unknown"));
1828
1829 aioary[0] = aiocbp;
1830 ret = aio_suspend(aioary, 1, NULL);
1831 if ((ret == -1) && (errno == EINTR)) {
1832 if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL) {
1833 if (Debug_level > 2) {
1834 printf
1835 ("DEBUG %s/%d: aio_suspend received EINTR, sigev_notify=SIGEV_SIGNAL -- ok\n",
1836 __FILE__, __LINE__);
1837 }
1838 } else {
1839 sprintf(Errormsg,
1840 "%s/%d aio_suspend received EINTR, sigev_notify=%s, not ok\n",
1841 __FILE__, __LINE__,
1842 (aiocbp->aio_sigevent.sigev_notify ==
1843 SIGEV_SIGNAL ? "signal" : aiocbp->
1844 aio_sigevent.sigev_notify ==
1845 SIGEV_NONE ? "none" :
1846 #ifdef SIGEV_CALLBACK
1847 aiocbp->aio_sigevent.sigev_notify ==
1848 SIGEV_CALLBACK ? "callback" :
1849 #endif
1850 aiocbp->aio_sigevent.sigev_notify ==
1851 SIGEV_THREAD ? "thread" : "unknown"));
1852 return -errno;
1853 }
1854 } else if (ret) {
1855 sprintf(Errormsg,
1856 "%s/%d aio_suspend(fildes=%d, aioary, 1, NULL) failed, errno:%d %s",
1857 __FILE__, __LINE__, fd, errno, strerror(errno));
1858 return -errno;
1859 }
1860 #endif
1861
1862 } else if (method & LIO_WAIT_ACTIVE) {
1863 if (Debug_level > 2)
1864 printf("DEBUG %s/%d: wait method : active\n", __FILE__,
1865 __LINE__);
1866 #ifdef CRAY
1867 sigon();
1868 /*
1869 * loop until sw_flag, sw_count or sw_error field elements
1870 * change to non-zero.
1871 */
1872 cnt = 0;
1873 while ((*statptr)->sw_flag == 0 &&
1874 (*statptr)->sw_count == 0 && (*statptr)->sw_error == 0) {
1875 cnt++;
1876 }
1877 #else
1878 /* loop while aio_error() returns EINPROGRESS */
1879 cnt = 0;
1880 while (1) {
1881 ret = aio_error(aiocbp);
1882 if (ret != EINPROGRESS) {
1883 break;
1884 }
1885 ++cnt;
1886 }
1887
1888 #endif
1889 if (Debug_level > 5 && cnt && (cnt % 50) == 0)
1890 printf("DEBUG %s/%d: wait active cnt = %d\n",
1891 __FILE__, __LINE__, cnt);
1892
1893 } else if (method & LIO_WAIT_SIGPAUSE) {
1894 if (Debug_level > 2)
1895 printf("DEBUG %s/%d: wait method : sigpause\n",
1896 __FILE__, __LINE__);
1897 #ifdef sgi
1898 /* note: don't do the sigon() for CRAY in this case. why? -- roehrich 6/11/97 */
1899 if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL)
1900 sigrelse(aiocbp->aio_sigevent.sigev_signo);
1901 else {
1902 printf("DEBUG %s/%d: sigev_notify != SIGEV_SIGNAL\n",
1903 __FILE__, __LINE__);
1904 return -1;
1905 }
1906 #endif
1907 pause();
1908
1909 } else if (method & LIO_WAIT_SIGACTIVE) {
1910 if (Debug_level > 2)
1911 printf("DEBUG %s/%d: wait method : sigactive\n",
1912 __FILE__, __LINE__);
1913 #ifdef CRAY
1914 sigon();
1915 #else
1916 if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL)
1917 sigrelse(aiocbp->aio_sigevent.sigev_signo);
1918 else {
1919 printf("DEBUG %s/%d: sigev_notify != SIGEV_SIGNAL\n",
1920 __FILE__, __LINE__);
1921 return -1;
1922 }
1923 #endif
1924 /* loop waiting for signal */
1925 while (Received_signal == Rec_signal) {
1926 #ifdef CRAY
1927 sigon();
1928 #else
1929 sigrelse(aiocbp->aio_sigevent.sigev_signo);
1930 #endif
1931 }
1932
1933 } else if (method & LIO_WAIT_NONE) {
1934 if (Debug_level > 2)
1935 printf("DEBUG %s/%d: wait method : none\n", __FILE__,
1936 __LINE__);
1937 /* It's broken because the aiocb/iosw is an automatic variable in
1938 * lio_{read,write}_buffer, so when the function returns and the
1939 * I/O completes there will be nowhere to write the I/O status.
1940 * It doesn't cause a problem on unicos--probably because of some
1941 * compiler quirk, or an accident. It causes POSIX async I/O
1942 * to core dump some threads. spr/pv 705909. 6/27/97 roehrich
1943 */
1944 sprintf(Errormsg,
1945 "%s/%d LIO_WAIT_NONE was selected (this is broken)\n",
1946 __FILE__, __LINE__);
1947 #ifdef CRAY
1948 sigon();
1949 #endif
1950 /* return 1;*/
1951 return -1;
1952 } else {
1953 if (Debug_level > 2)
1954 printf("DEBUG %s/%d: no wait method was chosen\n",
1955 __FILE__, __LINE__);
1956 return -1;
1957 }
1958
1959 return 0;
1960
1961 } /* end of lio_wait4asyncio */
1962
1963 #endif /* ifndef linux */
1964 #endif
1965
1966 #if UNIT_TEST
1967 /***********************************************************************
1968 * The following code is provided as unit test.
1969 * Just define add "-DUNIT_TEST=1" to the cc line.
1970 *
1971 * (rrl 04/96)
1972 ***********************************************************************/
1973 struct unit_info_t {
1974 int method;
1975 int sig;
1976 char *str;
1977 } Unit_info[] = {
1978 {
1979 LIO_IO_SYNC, 0, "sync io"}, {
1980 LIO_IO_SYNCV, 0, "sync readv/writev"}, {
1981 LIO_IO_SYNCP, 0, "sync pread/pwrite"}, {
1982 LIO_IO_ASYNC, 0, "async io, def wait"}, {
1983 LIO_IO_SLISTIO, 0, "sync listio"}, {
1984 LIO_IO_ALISTIO, 0, "async listio, def wait"}, {
1985 LIO_IO_ASYNC | LIO_WAIT_ACTIVE, 0, "async active"}, {
1986 LIO_IO_ASYNC | LIO_WAIT_RECALL, 0, "async recall/suspend"}, {
1987 LIO_IO_ASYNC | LIO_WAIT_SIGPAUSE, SIGUSR1, "async sigpause"}, {
1988 LIO_IO_ASYNC | LIO_WAIT_SIGACTIVE, SIGUSR1, "async sigactive"}, {
1989 LIO_IO_ALISTIO | LIO_WAIT_ACTIVE, 0, "async listio active"}, {
1990 LIO_IO_ALISTIO | LIO_WAIT_RECALL, 0, "async listio recall"}, {
1991 LIO_IO_ALISTIO | LIO_WAIT_SIGACTIVE, SIGUSR1, "async listio sigactive"},
1992 {
1993 LIO_IO_ALISTIO | LIO_WAIT_SIGPAUSE, SIGUSR1, "async listio sigpause"},
1994 {
1995 LIO_IO_ASYNC, SIGUSR2, "async io, def wait, sigusr2"}, {
1996 LIO_IO_ALISTIO, SIGUSR2, "async listio, def wait, sigusr2"},};
1997
main(argc,argv)1998 int main(argc, argv)
1999 int argc;
2000 char **argv;
2001 {
2002 extern char *optarg;
2003 extern int optind;
2004
2005 int fd;
2006 char *err;
2007 char buffer[4096];
2008 int size = 4096;
2009 int ret;
2010 int ind;
2011 int iter = 3;
2012 int method;
2013 int exit_status = 0;
2014 int c;
2015 int i;
2016 char *symbols = NULL;
2017 int die_on_err = 0;
2018
2019 while ((c = getopt(argc, argv, "s:di:")) != -1) {
2020 switch (c) {
2021 case 's':
2022 symbols = optarg;
2023 break;
2024 case 'd':
2025 ++die_on_err;
2026 break;
2027 case 'i':
2028 iter = atoi(optarg);
2029 break;
2030 }
2031 }
2032
2033 if ((fd =
2034 open("unit_test_file", O_CREAT | O_RDWR | O_TRUNC, 0777)) == -1) {
2035 perror
2036 ("open(unit_test_file, O_CREAT|O_RDWR|O_TRUNC, 0777) failed");
2037 exit(1);
2038 }
2039
2040 Debug_level = 9;
2041
2042 if (symbols != NULL) {
2043 if ((method = lio_parse_io_arg2(symbols, &err)) == -1) {
2044 printf
2045 ("lio_parse_io_arg2(%s, &err) failed, bad token starting at %s\n",
2046 symbols, err);
2047 if (die_on_err)
2048 exit(1);
2049 } else
2050 printf("lio_parse_io_arg2(%s, &err) returned %#o\n",
2051 symbols, method);
2052
2053 exit_status = 0;
2054 for (ind = 0; ind < iter; ind++) {
2055 memset(buffer, 'A', 4096);
2056 if (lseek(fd, 0, 0) == -1) {
2057 printf("lseek(fd,0,0), %d, failed, errno %d\n",
2058 __LINE__, errno);
2059 ++exit_status;
2060 }
2061 if ((ret = lio_write_buffer(fd, method, buffer,
2062 size, SIGUSR1, &err,
2063 0)) != size) {
2064 printf
2065 ("lio_write_buffer returned -1, err = %s\n",
2066 err);
2067 } else
2068 printf("lio_write_buffer returned %d\n", ret);
2069
2070 memset(buffer, 'B', 4096);
2071 if (lseek(fd, 0, 0) == -1) {
2072 printf("lseek(fd,0,0), %d, failed, errno %d\n",
2073 __LINE__, errno);
2074 ++exit_status;
2075 }
2076 if ((ret = lio_read_buffer(fd, method, buffer,
2077 size, SIGUSR2, &err,
2078 0)) != size) {
2079 printf
2080 ("lio_read_buffer returned -1, err = %s\n",
2081 err);
2082 } else
2083 printf("lio_read_buffer returned %d\n", ret);
2084
2085 for (i = 0; i < 4096; ++i) {
2086 if (buffer[i] != 'A') {
2087 printf(" buffer[%d] = %d\n", i,
2088 buffer[i]);
2089 ++exit_status;
2090 break;
2091 }
2092 }
2093
2094 if (exit_status)
2095 exit(exit_status);
2096
2097 }
2098
2099 unlink("unit_test_file");
2100 exit(0);
2101 }
2102
2103 for (ind = 0; ind < sizeof(Unit_info) / sizeof(struct unit_info_t);
2104 ind++) {
2105
2106 printf("\n********* write %s ***************\n",
2107 Unit_info[ind].str);
2108 if (lseek(fd, 0, 0) == -1) {
2109 printf("lseek(fd,0,0), %d, failed, errno %d\n",
2110 __LINE__, errno);
2111 ++exit_status;
2112 }
2113
2114 memset(buffer, 'A', 4096);
2115 if ((ret = lio_write_buffer(fd, Unit_info[ind].method, buffer,
2116 size, Unit_info[ind].sig, &err,
2117 0)) != size) {
2118 printf
2119 (">>>>> lio_write_buffer(fd,0%x,buffer,%d,%d,err,0) returned -1,\n err = %s\n",
2120 Unit_info[ind].method, size, Unit_info[ind].sig,
2121 err);
2122 ++exit_status;
2123 if (die_on_err)
2124 exit(exit_status);
2125 } else {
2126 printf("lio_write_buffer returned %d\n", ret);
2127 }
2128
2129 printf("\n********* read %s ***************\n",
2130 Unit_info[ind].str);
2131 if (lseek(fd, 0, 0) == -1) {
2132 printf("lseek(fd,0,0), %d, failed, errno %d\n",
2133 __LINE__, errno);
2134 ++exit_status;
2135 }
2136 memset(buffer, 'B', 4096);
2137 if ((ret = lio_read_buffer(fd, Unit_info[ind].method, buffer,
2138 size, Unit_info[ind].sig, &err,
2139 0)) != size) {
2140 printf
2141 (">>>>> lio_read_buffer(fd,0%x,buffer,%d,%d,err,0) returned -1,\n err = %s\n",
2142 Unit_info[ind].method, size, Unit_info[ind].sig,
2143 err);
2144 ++exit_status;
2145 if (die_on_err)
2146 exit(exit_status);
2147 } else {
2148 printf("lio_read_buffer returned %d\n", ret);
2149 }
2150
2151 for (i = 0; i < 4096; ++i) {
2152 if (buffer[i] != 'A') {
2153 printf(" buffer[%d] = %d\n", i, buffer[i]);
2154 ++exit_status;
2155 if (die_on_err)
2156 exit(exit_status);
2157 break;
2158 }
2159 }
2160
2161 fflush(stdout);
2162 fflush(stderr);
2163 sleep(1);
2164
2165 }
2166
2167 unlink("unit_test_file");
2168
2169 exit(exit_status);
2170 }
2171 #endif
2172