1/* 2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of version 2 of the GNU General Public License as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it would be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 * 12 * Further, this software is distributed without any warranty that it is 13 * free of the rightful claim of any third person regarding infringement 14 * or the like. Any license provided herein, whether implied or 15 * otherwise, applies only to this software file. Patent licenses, if 16 * any, provided herein do not apply to combinations of this program with 17 * other software, or any other product whatsoever. 18 * 19 * You should have received a copy of the GNU General Public License along 20 * with this program; if not, write the Free Software Foundation, Inc., 21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 22 * 23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 24 * Mountain View, CA 94043, or: 25 * 26 * http://www.sgi.com 27 * 28 * For further information regarding this notice, see: 29 * 30 * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ 31 */ 32/* 33 * 34 * Lib i/o 35 * 36 * This file contains several functions to doing reads and writes. 37 * It was written so that a single function could be called in a test 38 * program and only a io type field value would have to change to 39 * do different types of io. There is even a couple of functions that 40 * will allow you to parse a string to determine the iotype. 41 * 42 * This file contains functions for writing/reading to/from open files 43 * Prototypes: 44 * 45 * Functions declared in this module - see individual function code for 46 * usage comments: 47 * 48 * int stride_bounds(int offset, int stride, int nstrides, 49 * int bytes_per_stride, int *min, int *max); 50 51 * int lio_write_buffer(int fd, int method, char *buffer, int size, 52 * char **errmsg, long wrd); 53 * int lio_read_buffer(int fd, int method, char *buffer, int size, 54 * char **errmsg, long wrd); 55 * 56 * #ifdef CRAY 57 * int lio_wait4asyncio(int method, int fd, struct iosw **statptr) 58 * int lio_check_asyncio(char *io_type, int size, struct iosw *status) 59 * #endif 60 * #ifdef sgi 61 * int lio_wait4asyncio(int method, int fd, aiocb_t *aiocbp) 62 * int lio_check_asyncio(char *io_type, int size, aiocb_t *aiocbp, int method) 63 * #endif 64 * 65 * int lio_parse_io_arg1(char *string) 66 * void lio_help1(char *prefix); 67 * 68 * int lio_parse_io_arg2(char *string, char **badtoken) 69 * void lio_help2(char *prefix); 70 * 71 * int lio_set_debug(int level); 72 * 73 * char Lio_SysCall[]; 74 * struct lio_info_type Lio_info1[]; 75 * struct lio_info_type Lio_info2[]; 76 * 77 * Author : Richard Logan 78 * 79 */ 80 81#ifdef __linux__ 82#ifndef _GNU_SOURCE 83#define _GNU_SOURCE 84#endif 85#define _LARGEFILE64_SOURCE 86#endif 87#include "config.h" 88#include <stdio.h> 89#include <ctype.h> 90#include <fcntl.h> 91#include <unistd.h> 92#include <sys/types.h> 93#include <sys/stat.h> 94#include <sys/time.h> 95#include <sys/param.h> 96#include <errno.h> 97#include <sys/types.h> 98#include <sys/file.h> 99#include <signal.h> 100#include <stdint.h> 101#ifdef CRAY 102#include <sys/secparm.h> 103#include <sys/iosw.h> 104#include <sys/listio.h> 105#else 106/* for linux or sgi */ 107#include <sys/uio.h> /* readv(2)/writev(2) */ 108#include <string.h> 109#endif 110#if defined(__linux__) || defined(__sun) || defined(__hpux) || defined(_AIX) 111#if !defined(UCLINUX) && !defined(__UCLIBC__) 112#include <aio.h> 113#endif 114#endif 115#include <stdlib.h> /* atoi, abs */ 116 117#include "tlibio.h" /* defines LIO* marcos */ 118#include "random_range.h" 119 120#ifndef PATH_MAX 121#define PATH_MAX MAXPATHLEN 122#endif 123 124#if 0 /* disabled until it's needed -- roehrich 6/11/97 */ 125#define BUG1_workaround 1 /* Work around a condition where aio_return gives 126 * a value of zero but there is no errno followup 127 * and the read/write operation actually did its 128 * job. spr/pv 705244 129 */ 130#endif 131 132 133/* 134 * Define the structure as used in lio_parse_arg1 and lio_help1 135 */ 136struct 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 */ 170struct 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 190char Lio_SysCall[PATH_MAX]; /* string containing last i/o system call */ 191 192static volatile int Received_signal = 0; /* number of signals received */ 193static volatile int Rec_signal; 194#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__)) 195static volatile int Received_callback = 0; /* number of callbacks received */ 196static volatile int Rec_callback; 197#endif 198static char Errormsg[PATH_MAX*2]; 199static 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 215int 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 ***********************************************************************/ 262int 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 ***********************************************************************/ 280int 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 ***********************************************************************/ 312void 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 ***********************************************************************/ 334int 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 ***********************************************************************/ 405void 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 ***********************************************************************/ 422static 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 ***********************************************************************/ 440static 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 ***********************************************************************/ 468int 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 484static 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 ***********************************************************************/ 533int 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 ***********************************************************************/ 1108int 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 1660int lio_check_asyncio(char *io_type, int size, struct iosw *status) 1661#elif defined(sgi) 1662int lio_check_asyncio(char *io_type, int size, aiocb_t * aiocbp, int method) 1663#elif defined(__linux__) && !defined(__UCLIBC__) 1664int 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 1777int lio_wait4asyncio(int method, int fd, struct iosw **statptr) 1778#elif defined(sgi) 1779int lio_wait4asyncio(int method, int fd, aiocb_t * aiocbp) 1780#elif defined(__linux__) && !defined(__UCLIBC__) 1781int 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 ***********************************************************************/ 1973struct 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"}, { 1996LIO_IO_ALISTIO, SIGUSR2, "async listio, def wait, sigusr2"},}; 1997 1998int main(argc, argv) 1999int argc; 2000char **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