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> /* bzero */ 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 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 ***********************************************************************/ 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 ***********************************************************************/ 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 ***********************************************************************/ 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 ***********************************************************************/ 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 ***********************************************************************/ 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 ***********************************************************************/ 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 ***********************************************************************/ 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 ***********************************************************************/ 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 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 ***********************************************************************/ 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 ***********************************************************************/ 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 == 0) || (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 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