blob: 9104a72a9254b06992e13bb4b089f25f1c9ceb8b [file] [log] [blame]
whrb973f2b2000-05-05 19:34:50 +00001/*
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
vapier45a8ba02009-07-20 10:59:32 +00003 *
whrb973f2b2000-05-05 19:34:50 +00004 * 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.
vapier45a8ba02009-07-20 10:59:32 +00007 *
whrb973f2b2000-05-05 19:34:50 +00008 * 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.
vapier45a8ba02009-07-20 10:59:32 +000011 *
whrb973f2b2000-05-05 19:34:50 +000012 * 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.
vapier45a8ba02009-07-20 10:59:32 +000018 *
whrb973f2b2000-05-05 19:34:50 +000019 * You should have received a copy of the GNU General Public License along
Wanlong Gaofed96412012-10-24 10:10:29 +080020 * with this program; if not, write the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
vapier45a8ba02009-07-20 10:59:32 +000022 *
whrb973f2b2000-05-05 19:34:50 +000023 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
vapier45a8ba02009-07-20 10:59:32 +000025 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
whrb973f2b2000-05-05 19:34:50 +000030 * 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
subrata_modakea37be82008-12-11 13:17:49 +000081#ifdef __linux__
Garrett Cooper9ef7f2d2011-04-08 22:44:06 -070082#ifndef _GNU_SOURCE
subrata_modakea37be82008-12-11 13:17:49 +000083#define _GNU_SOURCE
Garrett Cooper9ef7f2d2011-04-08 22:44:06 -070084#endif
subrata_modakea37be82008-12-11 13:17:49 +000085#define _LARGEFILE64_SOURCE
86#endif
Mike Frysinger28606c12010-08-17 17:22:45 -040087#include "config.h"
whrb973f2b2000-05-05 19:34:50 +000088#include <stdio.h>
89#include <ctype.h>
90#include <fcntl.h>
whrb973f2b2000-05-05 19:34:50 +000091#include <unistd.h>
whrb973f2b2000-05-05 19:34:50 +000092#include <sys/types.h>
93#include <sys/stat.h>
vapier45a8ba02009-07-20 10:59:32 +000094#include <sys/time.h>
whrb973f2b2000-05-05 19:34:50 +000095#include <sys/param.h>
96#include <errno.h>
97#include <sys/types.h>
98#include <sys/file.h>
99#include <signal.h>
subrata_modak94d177a2008-12-22 07:33:02 +0000100#include <stdint.h>
whrb973f2b2000-05-05 19:34:50 +0000101#ifdef CRAY
102#include <sys/secparm.h>
103#include <sys/iosw.h>
104#include <sys/listio.h>
105#else
106/* for linux or sgi */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800107#include <sys/uio.h> /* readv(2)/writev(2) */
108#include <string.h> /* bzero */
whrb973f2b2000-05-05 19:34:50 +0000109#endif
mridgef7298c72005-12-05 19:14:37 +0000110#if defined(__linux__) || defined(__sun) || defined(__hpux) || defined(_AIX)
robbiew906676d2005-08-02 16:57:19 +0000111#if !defined(UCLINUX) && !defined(__UCLIBC__)
whrb973f2b2000-05-05 19:34:50 +0000112#include <aio.h>
113#endif
robbiewd34d5812005-07-11 22:28:09 +0000114#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800115#include <stdlib.h> /* atoi, abs */
whrb973f2b2000-05-05 19:34:50 +0000116
117#include "tlibio.h" /* defines LIO* marcos */
Garrett Cooper9ef7f2d2011-04-08 22:44:06 -0700118#include "random_range.h"
whrb973f2b2000-05-05 19:34:50 +0000119
120#ifndef PATH_MAX
121#define PATH_MAX MAXPATHLEN
122#endif
123
Wanlong Gao354ebb42012-12-07 10:10:04 +0800124#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 */
whrb973f2b2000-05-05 19:34:50 +0000130#endif
131
whrb973f2b2000-05-05 19:34:50 +0000132static void lio_async_signal_handler();
whrb973f2b2000-05-05 19:34:50 +0000133#ifdef sgi
134static void lio_async_callback_handler();
135#endif
136
137/*
138 * Define the structure as used in lio_parse_arg1 and lio_help1
139 */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800140struct lio_info_type Lio_info1[] = {
141 {"s", LIO_IO_SYNC, "sync i/o"},
142 {"p", LIO_IO_ASYNC | LIO_WAIT_SIGACTIVE,
143 "async i/o using a loop to wait for a signal"},
144 {"b", LIO_IO_ASYNC | LIO_WAIT_SIGPAUSE, "async i/o using pause"},
145 {"a", LIO_IO_ASYNC | LIO_WAIT_RECALL,
146 "async i/o using recall/aio_suspend"},
subrata_modak26e07d52009-02-26 06:33:39 +0000147#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +0800148 {"r",
149 LIO_RANDOM | LIO_IO_TYPES | LIO_WAIT_TYPES,
150 "random sync i/o types and wait methods"},
151 {"R",
152 LIO_RANDOM | LIO_IO_ATYPES | LIO_WAIT_ATYPES,
153 "random i/o types and wait methods"},
whrb973f2b2000-05-05 19:34:50 +0000154#else
Wanlong Gao354ebb42012-12-07 10:10:04 +0800155 {"r",
156 LIO_RANDOM | LIO_IO_TYPES | LIO_WAIT_TYPES,
157 "random i/o types and wait methods"},
158 {"R",
159 LIO_RANDOM | LIO_IO_TYPES | LIO_WAIT_TYPES,
160 "random i/o types and wait methods"},
whrb973f2b2000-05-05 19:34:50 +0000161#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800162 {"l", LIO_IO_SLISTIO | LIO_WAIT_RECALL, "single stride sync listio"},
163 {"L", LIO_IO_ALISTIO | LIO_WAIT_RECALL,
164 "single stride async listio using recall"},
165 {"X", LIO_IO_ALISTIO | LIO_WAIT_SIGPAUSE,
166 "single stride async listio using pause"},
167 {"v", LIO_IO_SYNCV, "single buffer sync readv/writev"},
168 {"P", LIO_IO_SYNCP, "sync pread/pwrite"},
whrb973f2b2000-05-05 19:34:50 +0000169};
170
171/*
172 * Define the structure used by lio_parse_arg2 and lio_help2
173 */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800174struct lio_info_type Lio_info2[] = {
175 {"sync", LIO_IO_SYNC, "sync i/o (read/write)"},
176 {"async", LIO_IO_ASYNC, "async i/o (reada/writea/aio_read/aio_write)"},
177 {"slistio", LIO_IO_SLISTIO, "single stride sync listio"},
178 {"alistio", LIO_IO_ALISTIO, "single stride async listio"},
179 {"syncv", LIO_IO_SYNCV, "single buffer sync readv/writev"},
180 {"syncp", LIO_IO_SYNCP, "pread/pwrite"},
181 {"active", LIO_WAIT_ACTIVE, "spin on status/control values"},
182 {"recall", LIO_WAIT_RECALL,
183 "use recall(2)/aio_suspend(3) to wait for i/o to complete"},
184 {"sigactive", LIO_WAIT_SIGACTIVE, "spin waiting for signal"},
185 {"sigpause", LIO_WAIT_SIGPAUSE, "call pause(2) to wait for signal"},
whrb973f2b2000-05-05 19:34:50 +0000186/* nowait is a touchy thing, it's an accident that this implementation worked at all. 6/27/97 roehrich */
187/* { "nowait", LIO_WAIT_NONE, "do not wait for async io to complete" },*/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800188 {"random", LIO_RANDOM, "set random bit"},
189 {"randomall",
190 LIO_RANDOM | LIO_IO_TYPES | LIO_WAIT_TYPES,
191 "all random i/o types and wait methods (except nowait)"},
whrb973f2b2000-05-05 19:34:50 +0000192};
193
194char Lio_SysCall[PATH_MAX]; /* string containing last i/o system call */
195
196static volatile int Received_signal = 0; /* number of signals received */
197static volatile int Rec_signal;
subrata_modak26e07d52009-02-26 06:33:39 +0000198#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
whrb973f2b2000-05-05 19:34:50 +0000199static volatile int Received_callback = 0; /* number of callbacks received */
200static volatile int Rec_callback;
201#endif
202static char Errormsg[500];
203static int Debug_level = 0;
204
whrb973f2b2000-05-05 19:34:50 +0000205/***********************************************************************
206 * stride_bounds()
207 *
208 * Determine the bounds of a strided request, normalized to offset. Returns
209 * the number of bytes needed to satisfy the request, and optionally sets
vapier45a8ba02009-07-20 10:59:32 +0000210 * *min and *max to the mininum and maximum bytes referenced, normalized
whrb973f2b2000-05-05 19:34:50 +0000211 * around offset.
212 *
213 * Returns -1 on error - the only possible error conditions are illegal values
214 * for nstrides and/or bytes_per_stride - both parameters must be >= 0.
215 *
216 * (maule, 11/16/95)
217 ***********************************************************************/
218
Wanlong Gao354ebb42012-12-07 10:10:04 +0800219int stride_bounds(offset, stride, nstrides, bytes_per_stride, min, max)
220int offset;
221int stride;
222int nstrides;
223int bytes_per_stride;
224int *min;
225int *max;
whrb973f2b2000-05-05 19:34:50 +0000226{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800227 int nbytes, min_byte, max_byte;
whrb973f2b2000-05-05 19:34:50 +0000228
229 /*
230 * sanity checks ...
231 */
232
233 if (nstrides < 0 || bytes_per_stride < 0) {
234 return -1;
235 }
236
237 if (stride == 0) {
238 stride = bytes_per_stride;
239 }
240
241 /*
242 * Determine the # of bytes needed to satisfy the request. This
243 * value, along with the offset argument, determines the min and max
244 * bytes referenced.
245 */
246
Wanlong Gao354ebb42012-12-07 10:10:04 +0800247 nbytes = abs(stride) * (nstrides - 1) + bytes_per_stride;
whrb973f2b2000-05-05 19:34:50 +0000248
249 if (stride < 0) {
250 max_byte = offset + bytes_per_stride - 1;
251 min_byte = max_byte - nbytes + 1;
252 } else {
253 min_byte = offset;
254 max_byte = min_byte + nbytes - 1;
255 }
vapier45a8ba02009-07-20 10:59:32 +0000256
whrb973f2b2000-05-05 19:34:50 +0000257 if (min != NULL) {
258 *min = min_byte;
259 }
vapier45a8ba02009-07-20 10:59:32 +0000260
whrb973f2b2000-05-05 19:34:50 +0000261 if (max != NULL) {
262 *max = max_byte;
263 }
264
265 return nbytes;
266}
267
268/***********************************************************************
269 * This function will allow someone to set the debug level.
270 ***********************************************************************/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800271int lio_set_debug(level)
whrb973f2b2000-05-05 19:34:50 +0000272{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800273 int old;
whrb973f2b2000-05-05 19:34:50 +0000274
Wanlong Gao354ebb42012-12-07 10:10:04 +0800275 old = Debug_level;
276 Debug_level = level;
277 return old;
whrb973f2b2000-05-05 19:34:50 +0000278}
279
280/***********************************************************************
281 * This function will parse a string and return desired io-method.
282 * Only the first character of the string is used.
283 *
284 * This function does not provide for meaningful option arguments,
285 * but it supports current growfiles/btlk interface.
286 *
287 * (rrl 04/96)
288 ***********************************************************************/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800289int lio_parse_io_arg1(char *string)
whrb973f2b2000-05-05 19:34:50 +0000290{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800291 unsigned int ind;
292 int found = 0;
293 int mask = 0;
whrb973f2b2000-05-05 19:34:50 +0000294
Wanlong Gao354ebb42012-12-07 10:10:04 +0800295 /*
296 * Determine if token is a valid string.
297 */
298 for (ind = 0; ind < sizeof(Lio_info1) / sizeof(struct lio_info_type);
299 ind++) {
300 if (strcmp(string, Lio_info1[ind].token) == 0) {
301 mask |= Lio_info1[ind].bits;
302 found = 1;
303 break;
304 }
305 }
whrb973f2b2000-05-05 19:34:50 +0000306
Wanlong Gao354ebb42012-12-07 10:10:04 +0800307 if (found == 0) {
308 return -1;
309 }
whrb973f2b2000-05-05 19:34:50 +0000310
Wanlong Gao354ebb42012-12-07 10:10:04 +0800311 return mask;
whrb973f2b2000-05-05 19:34:50 +0000312
313}
314
315/***********************************************************************
316 * This function will print a help message describing the characters
317 * that can be parsed by lio_parse_io_arg1().
318 * They will be printed one per line.
319 * (rrl 04/96)
320 ***********************************************************************/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800321void lio_help1(char *prefix)
whrb973f2b2000-05-05 19:34:50 +0000322{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800323 unsigned int ind;
whrb973f2b2000-05-05 19:34:50 +0000324
Wanlong Gao354ebb42012-12-07 10:10:04 +0800325 for (ind = 0; ind < sizeof(Lio_info1) / sizeof(struct lio_info_type);
326 ind++) {
327 printf("%s %s : %s\n", prefix, Lio_info1[ind].token,
328 Lio_info1[ind].desc);
329 }
whrb973f2b2000-05-05 19:34:50 +0000330
Wanlong Gao354ebb42012-12-07 10:10:04 +0800331 return;
whrb973f2b2000-05-05 19:34:50 +0000332}
333
334/***********************************************************************
335 * This function will parse a string and return the desired io-method.
336 * This function will take a comma separated list of io type and wait
337 * method tokens as defined in Lio_info2[]. If a token does not match
338 * any of the tokens in Lio_info2[], it will be coverted to a number.
339 * If it was a number, those bits are also set.
vapier45a8ba02009-07-20 10:59:32 +0000340 *
whrb973f2b2000-05-05 19:34:50 +0000341 * (rrl 04/96)
342 ***********************************************************************/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800343int lio_parse_io_arg2(char *string, char **badtoken)
whrb973f2b2000-05-05 19:34:50 +0000344{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800345 char *token = string;
346 char *cc = token;
347 char savecc;
348 int found;
349 int mask = 0;
whrb973f2b2000-05-05 19:34:50 +0000350
Wanlong Gao354ebb42012-12-07 10:10:04 +0800351 int tmp;
352 unsigned int ind;
353 char chr;
whrb973f2b2000-05-05 19:34:50 +0000354
Wanlong Gao354ebb42012-12-07 10:10:04 +0800355 if (token == NULL)
356 return -1;
whrb973f2b2000-05-05 19:34:50 +0000357
Wanlong Gao354ebb42012-12-07 10:10:04 +0800358 for (;;) {
359 for (; ((*cc != ',') && (*cc != '\0')); cc++) ;
360 savecc = *cc;
361 *cc = '\0';
whrb973f2b2000-05-05 19:34:50 +0000362
Wanlong Gao354ebb42012-12-07 10:10:04 +0800363 found = 0;
whrb973f2b2000-05-05 19:34:50 +0000364
Wanlong Gao354ebb42012-12-07 10:10:04 +0800365 /*
366 * Determine if token is a valid string or number and if
367 * so, add the bits to the mask.
368 */
369 for (ind = 0;
370 ind < sizeof(Lio_info2) / sizeof(struct lio_info_type);
371 ind++) {
372 if (strcmp(token, Lio_info2[ind].token) == 0) {
373 mask |= Lio_info2[ind].bits;
374 found = 1;
375 break;
376 }
377 }
whrb973f2b2000-05-05 19:34:50 +0000378
Wanlong Gao354ebb42012-12-07 10:10:04 +0800379 /*
380 * If token does not match one of the defined tokens, determine
381 * if it is a number, if so, add the bits.
382 */
383 if (!found) {
384 if (sscanf(token, "%i%c", &tmp, &chr) == 1) {
385 mask |= tmp;
386 found = 1;
387 }
388 }
whrb973f2b2000-05-05 19:34:50 +0000389
Wanlong Gao354ebb42012-12-07 10:10:04 +0800390 *cc = savecc;
whrb973f2b2000-05-05 19:34:50 +0000391
Wanlong Gao354ebb42012-12-07 10:10:04 +0800392 if (!found) { /* token is not valid */
393 if (badtoken != NULL)
394 *badtoken = token;
395 return (-1);
396 }
whrb973f2b2000-05-05 19:34:50 +0000397
Wanlong Gao354ebb42012-12-07 10:10:04 +0800398 if (savecc == '\0')
399 break;
whrb973f2b2000-05-05 19:34:50 +0000400
Wanlong Gao354ebb42012-12-07 10:10:04 +0800401 token = ++cc;
402 }
whrb973f2b2000-05-05 19:34:50 +0000403
Wanlong Gao354ebb42012-12-07 10:10:04 +0800404 return mask;
whrb973f2b2000-05-05 19:34:50 +0000405}
406
407/***********************************************************************
408 * This function will print a help message describing the tokens
409 * that can be parsed by lio_parse_io_arg2().
410 * It will print them one per line.
411 *
412 * (rrl 04/96)
413 ***********************************************************************/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800414void lio_help2(char *prefix)
whrb973f2b2000-05-05 19:34:50 +0000415{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800416 unsigned int ind;
whrb973f2b2000-05-05 19:34:50 +0000417
Wanlong Gao354ebb42012-12-07 10:10:04 +0800418 for (ind = 0; ind < sizeof(Lio_info2) / sizeof(struct lio_info_type);
419 ind++) {
420 printf("%s %s : %s\n", prefix, Lio_info2[ind].token,
421 Lio_info2[ind].desc);
422 }
423 return;
whrb973f2b2000-05-05 19:34:50 +0000424}
425
whrb973f2b2000-05-05 19:34:50 +0000426/***********************************************************************
427 * This is an internal signal handler.
428 * If the handler is called, it will increment the Received_signal
429 * global variable.
430 ***********************************************************************/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800431static void lio_async_signal_handler(int sig)
whrb973f2b2000-05-05 19:34:50 +0000432{
Garrett Cooper903910d2010-11-23 09:27:44 -0800433 if (Debug_level)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800434 printf
435 ("DEBUG %s/%d: received signal %d, a signal caught %d times\n",
436 __FILE__, __LINE__, sig, Received_signal + 1);
whrb973f2b2000-05-05 19:34:50 +0000437
438 Received_signal++;
439
440 return;
441}
whrb973f2b2000-05-05 19:34:50 +0000442
subrata_modak26e07d52009-02-26 06:33:39 +0000443#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
whrb973f2b2000-05-05 19:34:50 +0000444/***********************************************************************
445 * This is an internal callback handler.
446 * If the handler is called, it will increment the Received_callback
447 * global variable.
448 ***********************************************************************/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800449static void lio_async_callback_handler(sigval_t sigval)
whrb973f2b2000-05-05 19:34:50 +0000450{
Garrett Cooper903910d2010-11-23 09:27:44 -0800451 if (Debug_level)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800452 printf
453 ("DEBUG %s/%d: received callback, nbytes=%ld, a callback called %d times\n",
454 __FILE__, __LINE__, (long)sigval.sival_int,
455 Received_callback + 1);
whrb973f2b2000-05-05 19:34:50 +0000456
457 Received_callback++;
458
459 return;
460}
461#endif /* sgi */
462
463/***********************************************************************
464 * lio_random_methods
465 * This function will randomly choose an io type and wait method
466 * from set of io types and wait methods. Since this information
467 * is stored in a bitmask, it randomly chooses an io type from
468 * the io type bits specified and does the same for wait methods.
469 *
470 * Return Value
471 * This function will return a value with all non choosen io type
vapier45a8ba02009-07-20 10:59:32 +0000472 * and wait method bits cleared. The LIO_RANDOM bit is also
whrb973f2b2000-05-05 19:34:50 +0000473 * cleared. All other bits are left unchanged.
474 *
475 * (rrl 04/96)
476 ***********************************************************************/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800477int lio_random_methods(long curr_mask)
whrb973f2b2000-05-05 19:34:50 +0000478{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800479 int mask = 0;
whrb973f2b2000-05-05 19:34:50 +0000480
Wanlong Gao354ebb42012-12-07 10:10:04 +0800481 /* remove random select, io type, and wait method bits from curr_mask */
482 mask = curr_mask & (~(LIO_IO_TYPES | LIO_WAIT_TYPES | LIO_RANDOM));
whrb973f2b2000-05-05 19:34:50 +0000483
Wanlong Gao354ebb42012-12-07 10:10:04 +0800484 /* randomly select io type from specified io types */
485 mask = mask | random_bit(curr_mask & LIO_IO_TYPES);
whrb973f2b2000-05-05 19:34:50 +0000486
Wanlong Gao354ebb42012-12-07 10:10:04 +0800487 /* randomly select wait methods from specified wait methods */
488 mask = mask | random_bit(curr_mask & LIO_WAIT_TYPES);
whrb973f2b2000-05-05 19:34:50 +0000489
Wanlong Gao354ebb42012-12-07 10:10:04 +0800490 return mask;
whrb973f2b2000-05-05 19:34:50 +0000491}
492
subrata_modakea37be82008-12-11 13:17:49 +0000493static void wait4sync_io(int fd, int read)
494{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800495 fd_set s;
496 FD_ZERO(&s);
497 FD_SET(fd, &s);
subrata_modakea37be82008-12-11 13:17:49 +0000498
Wanlong Gao354ebb42012-12-07 10:10:04 +0800499 select(fd + 1, read ? &s : NULL, read ? NULL : &s, NULL, NULL);
subrata_modakea37be82008-12-11 13:17:49 +0000500}
501
whrb973f2b2000-05-05 19:34:50 +0000502/***********************************************************************
vapier45a8ba02009-07-20 10:59:32 +0000503 * Generic write function
whrb973f2b2000-05-05 19:34:50 +0000504 * This function can be used to do a write using write(2), writea(2),
505 * aio_write(3), writev(2), pwrite(2),
506 * or single stride listio(2)/lio_listio(3).
507 * By setting the desired bits in the method
508 * bitmask, the caller can control the type of write and the wait method
509 * that will be used. If no io type bits are set, write will be used.
510 *
511 * If async io was attempted and no wait method bits are set then the
512 * wait method is: recall(2) for writea(2) and listio(2); aio_suspend(3) for
513 * aio_write(3) and lio_listio(3).
514 *
vapier45a8ba02009-07-20 10:59:32 +0000515 * If multiple wait methods are specified,
whrb973f2b2000-05-05 19:34:50 +0000516 * only one wait method will be used. The order is predetermined.
517 *
518 * If the call specifies a signal and one of the two signal wait methods,
519 * a signal handler for the signal is set. This will reset an already
vapier45a8ba02009-07-20 10:59:32 +0000520 * set handler for this signal.
whrb973f2b2000-05-05 19:34:50 +0000521 *
522 * If the LIO_RANDOM method bit is set, this function will randomly
523 * choose a io type and wait method from bits in the method argument.
524 *
525 * If an error is encountered, an error message will be generated
526 * in a internal static buffer. If errmsg is not NULL, it will
527 * be updated to point to the static buffer, allowing the caller
528 * to print the error message.
529 *
530 * Return Value
531 * If a system call fails, -errno is returned.
532 * If LIO_WAIT_NONE bit is set, the return value is the return value
533 * of the system call.
534 * If the io did not fail, the amount of data written is returned.
535 * If the size the system call say was written is different
536 * then what was asked to be written, errmsg is updated for
537 * this error condition. The return value is still the amount
vapier45a8ba02009-07-20 10:59:32 +0000538 * the system call says was written.
whrb973f2b2000-05-05 19:34:50 +0000539 *
540 * (rrl 04/96)
541 ***********************************************************************/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800542int lio_write_buffer(fd, method, buffer, size, sig, errmsg, wrd)
543int fd; /* open file descriptor */
544int method; /* contains io type and wait method bitmask */
545char *buffer; /* pointer to buffer */
546int size; /* the size of the io */
547int sig; /* signal to use if async io */
548char **errmsg; /* char pointer that will be updated to point to err message */
549long wrd; /* to allow future features, use zero for now */
whrb973f2b2000-05-05 19:34:50 +0000550{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800551 int ret = 0; /* syscall return or used to get random method */
552 char *io_type; /* Holds string of type of io */
553 int omethod = method;
554 int listio_cmd; /* Holds the listio/lio_listio cmd */
whrb973f2b2000-05-05 19:34:50 +0000555#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +0800556 struct listreq request; /* Used when a listio is wanted */
557 struct iosw status, *statptr[1];
whrb973f2b2000-05-05 19:34:50 +0000558#else
Wanlong Gao354ebb42012-12-07 10:10:04 +0800559 /* for linux or sgi */
560 struct iovec iov; /* iovec for writev(2) */
whrb973f2b2000-05-05 19:34:50 +0000561#endif
subrata_modakea37be82008-12-11 13:17:49 +0000562#if defined (sgi)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800563 aiocb_t aiocbp; /* POSIX aio control block */
564 aiocb_t *aiolist[1]; /* list of aio control blocks for lio_listio */
565 off64_t poffset; /* pwrite(2) offset */
whrb973f2b2000-05-05 19:34:50 +0000566#endif
subrata_modak26e07d52009-02-26 06:33:39 +0000567#if defined(__linux__) && !defined(__UCLIBC__)
subrata_modakea37be82008-12-11 13:17:49 +0000568 struct aiocb aiocbp; /* POSIX aio control block */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800569 struct aiocb *aiolist[1]; /* list of aio control blocks for lio_listio */
subrata_modakea37be82008-12-11 13:17:49 +0000570 off64_t poffset; /* pwrite(2) offset */
571#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800572 /*
573 * If LIO_RANDOM bit specified, get new method randomly.
574 */
575 if (method & LIO_RANDOM) {
576 if (Debug_level > 3)
577 printf("DEBUG %s/%d: method mask to choose from: %#o\n",
578 __FILE__, __LINE__, method);
579 method = lio_random_methods(method);
580 if (Debug_level > 2)
581 printf("DEBUG %s/%d: random chosen method %#o\n",
582 __FILE__, __LINE__, method);
583 }
whrb973f2b2000-05-05 19:34:50 +0000584
Wanlong Gao354ebb42012-12-07 10:10:04 +0800585 if (errmsg != NULL)
586 *errmsg = Errormsg;
whrb973f2b2000-05-05 19:34:50 +0000587
Wanlong Gao354ebb42012-12-07 10:10:04 +0800588 Rec_signal = Received_signal; /* get the current number of signals received */
subrata_modak26e07d52009-02-26 06:33:39 +0000589#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +0800590 Rec_callback = Received_callback; /* get the current number of callbacks received */
whrb973f2b2000-05-05 19:34:50 +0000591#endif
592
593#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +0800594 memset(&status, 0x00, sizeof(struct iosw));
595 memset(&request, 0x00, sizeof(struct listreq));
596 statptr[0] = &status;
whrb973f2b2000-05-05 19:34:50 +0000597#else
Wanlong Gao354ebb42012-12-07 10:10:04 +0800598 /* for linux or sgi */
599 memset(&iov, 0x00, sizeof(struct iovec));
600 iov.iov_base = buffer;
601 iov.iov_len = size;
whrb973f2b2000-05-05 19:34:50 +0000602#endif
subrata_modak26e07d52009-02-26 06:33:39 +0000603#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
subrata_modakea37be82008-12-11 13:17:49 +0000604#if defined(sgi)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800605 memset(&aiocbp, 0x00, sizeof(aiocb_t));
subrata_modakea37be82008-12-11 13:17:49 +0000606#else
607 memset(&aiocbp, 0x00, sizeof(struct aiocb));
608#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800609 aiocbp.aio_fildes = fd;
610 aiocbp.aio_nbytes = size;
611 aiocbp.aio_buf = buffer;
whrb973f2b2000-05-05 19:34:50 +0000612/* aiocbp.aio_offset = lseek( fd, 0, SEEK_CUR ); -- set below */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800613 aiocbp.aio_sigevent.sigev_notify = SIGEV_NONE;
614 aiocbp.aio_sigevent.sigev_signo = 0;
subrata_modakea37be82008-12-11 13:17:49 +0000615#ifdef sgi
Wanlong Gao354ebb42012-12-07 10:10:04 +0800616 aiocbp.aio_sigevent.sigev_func = NULL;
617 aiocbp.aio_sigevent.sigev_value.sival_int = 0;
subrata_modak26e07d52009-02-26 06:33:39 +0000618#elif defined(__linux__) && !defined(__UCLIBC__)
subrata_modakea37be82008-12-11 13:17:49 +0000619 aiocbp.aio_sigevent.sigev_notify_function = NULL;
620 aiocbp.aio_sigevent.sigev_notify_attributes = 0;
621#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800622 aiolist[0] = &aiocbp;
whrb973f2b2000-05-05 19:34:50 +0000623
Wanlong Gao354ebb42012-12-07 10:10:04 +0800624 if ((ret = lseek(fd, 0, SEEK_CUR)) == -1) {
625 ret = 0;
626 /* If there is an error and it is not ESPIPE then kick out the error.
627 * If the fd is a fifo then we have to make sure that
628 * lio_random_methods() didn't select pwrite/pread; if it did then
629 * switch to write/read.
630 */
631 if (errno == ESPIPE) {
632 if (method & LIO_IO_SYNCP) {
633 if (omethod & LIO_RANDOM) {
634 method &= ~LIO_IO_SYNCP;
635 method |= LIO_IO_SYNC;
636 if (Debug_level > 2)
637 printf
638 ("DEBUG %s/%d: random chosen method switched to %#o for fifo\n",
639 __FILE__, __LINE__,
640 method);
641 } else if (Debug_level) {
642 printf
643 ("DEBUG %s/%d: pwrite will fail when it writes to a fifo\n",
644 __FILE__, __LINE__);
645 }
whrb973f2b2000-05-05 19:34:50 +0000646 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800647 /* else: let it ride */
648 } else {
649 sprintf(Errormsg,
650 "%s/%d lseek(fd=%d,0,SEEK_CUR) failed, errno=%d %s",
651 __FILE__, __LINE__, fd, errno, strerror(errno));
652 return -errno;
whrb973f2b2000-05-05 19:34:50 +0000653 }
whrb973f2b2000-05-05 19:34:50 +0000654 }
subrata_modak26e07d52009-02-26 06:33:39 +0000655#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +0800656 poffset = (off64_t) ret;
subrata_modakea37be82008-12-11 13:17:49 +0000657#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800658 aiocbp.aio_offset = ret;
whrb973f2b2000-05-05 19:34:50 +0000659
660#endif
661
Wanlong Gao354ebb42012-12-07 10:10:04 +0800662 /*
663 * If the LIO_USE_SIGNAL bit is not set, only use the signal
664 * if the LIO_WAIT_SIGPAUSE or the LIO_WAIT_SIGACTIVE bits are bit.
665 * Otherwise there is not necessary a signal handler to trap
666 * the signal.
whrb973f2b2000-05-05 19:34:50 +0000667 */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800668 if (sig && !(method & LIO_USE_SIGNAL) && !(method & LIO_WAIT_SIGTYPES)) {
669
670 sig = 0; /* ignore signal parameter */
671 }
672#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
673 if (sig && (method & LIO_WAIT_CBTYPES))
674 sig = 0; /* ignore signal parameter */
675#endif
676
677 /*
678 * only setup signal hander if sig was specified and
679 * a sig wait method was specified.
680 * Doing this will change the handler for this signal. The
681 * old signal handler will not be restored.
682 *** restoring the signal handler could be added ***
683 */
684
685 if (sig && (method & LIO_WAIT_SIGTYPES)) {
686#ifdef CRAY
687 sigctl(SCTL_REG, sig, lio_async_signal_handler);
688#endif
689#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
690 aiocbp.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
691 aiocbp.aio_sigevent.sigev_signo = sig;
692 sigset(sig, lio_async_signal_handler);
693#endif /* sgi */
694 }
695#if defined(sgi)
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_CALLBACK;
701 aiocbp.aio_sigevent.sigev_func = lio_async_callback_handler;
702 aiocbp.aio_sigevent.sigev_value.sival_int = size;
703 }
whrb973f2b2000-05-05 19:34:50 +0000704#endif
subrata_modak26e07d52009-02-26 06:33:39 +0000705#if defined(__linux__) && !defined(__UCLIBC__)
Garrett Cooper903910d2010-11-23 09:27:44 -0800706 else if (method & LIO_WAIT_CBTYPES) {
subrata_modakea37be82008-12-11 13:17:49 +0000707 /* sival_int just has to be something that I can use
708 * to identify the callback, and "size" happens to be handy...
709 */
710 aiocbp.aio_sigevent.sigev_notify = SIGEV_THREAD;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800711 aiocbp.aio_sigevent.sigev_notify_function =
712 lio_async_callback_handler;
713 aiocbp.aio_sigevent.sigev_notify_attributes =
714 (void *)(uintptr_t) size;
subrata_modakea37be82008-12-11 13:17:49 +0000715 }
716#endif
whrb973f2b2000-05-05 19:34:50 +0000717 /*
Wanlong Gao354ebb42012-12-07 10:10:04 +0800718 * Determine the system call that will be called and produce
719 * the string of the system call and place it in Lio_SysCall.
720 * Also update the io_type char pointer to give brief description
721 * of system call. Execute the system call and check for
722 * system call failure. If sync i/o, return the number of
723 * bytes written/read.
724 */
whrb973f2b2000-05-05 19:34:50 +0000725
Wanlong Gao354ebb42012-12-07 10:10:04 +0800726 if ((method & LIO_IO_SYNC)
727 || (method & (LIO_IO_TYPES | LIO_IO_ATYPES)) == 0) {
728 /*
729 * write(2) is used if LIO_IO_SYNC bit is set or not none
730 * of the LIO_IO_TYPES bits are set (default).
731 */
whrb973f2b2000-05-05 19:34:50 +0000732
Wanlong Gao354ebb42012-12-07 10:10:04 +0800733 sprintf(Lio_SysCall, "write(%d, buf, %d)", fd, size);
734 io_type = "write";
whrb973f2b2000-05-05 19:34:50 +0000735
Wanlong Gao354ebb42012-12-07 10:10:04 +0800736 if (Debug_level) {
737 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
738 Lio_SysCall);
739 }
740 while (1) {
741 if (((ret = write(fd, buffer, size)) == -1)
742 && errno != EAGAIN && errno != EINTR) {
743 sprintf(Errormsg,
744 "%s/%d write(%d, buf, %d) ret:-1, errno=%d %s",
745 __FILE__, __LINE__, fd, size, errno,
746 strerror(errno));
747 return -errno;
748 }
whrb973f2b2000-05-05 19:34:50 +0000749
Wanlong Gao354ebb42012-12-07 10:10:04 +0800750 if (ret != -1) {
751 if (ret != size) {
752 sprintf(Errormsg,
753 "%s/%d write(%d, buf, %d) returned=%d",
754 __FILE__, __LINE__,
755 fd, size, ret);
756 size -= ret;
757 buffer += ret;
758 } else {
759 if (Debug_level > 1)
760 printf
761 ("DEBUG %s/%d: write completed without error (ret %d)\n",
762 __FILE__, __LINE__, ret);
whrb973f2b2000-05-05 19:34:50 +0000763
Wanlong Gao354ebb42012-12-07 10:10:04 +0800764 return ret;
765 }
766 }
767 wait4sync_io(fd, 0);
768 }
whrb973f2b2000-05-05 19:34:50 +0000769
whrb973f2b2000-05-05 19:34:50 +0000770 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800771
772 else if (method & LIO_IO_ASYNC) {
773#ifdef CRAY
774 sprintf(Lio_SysCall,
775 "writea(%d, buf, %d, &status, %d)", fd, size, sig);
776 io_type = "writea";
777
778 if (Debug_level) {
779 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
780 Lio_SysCall);
781 }
782
783 sigoff();
784 if ((ret = writea(fd, buffer, size, &status, sig)) == -1) {
785 sprintf(Errormsg,
786 "%s/%d writea(%d, buf, %d, &stat, %d) ret:-1, errno=%d %s",
787 __FILE__, __LINE__,
788 fd, size, sig, errno, strerror(errno));
789 sigon();
790 return -errno;
791 }
whrb973f2b2000-05-05 19:34:50 +0000792#endif
subrata_modak26e07d52009-02-26 06:33:39 +0000793#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +0800794 sprintf(Lio_SysCall,
795 "aio_write(fildes=%d, buf, nbytes=%d, signo=%d)", fd,
796 size, sig);
797 io_type = "aio_write";
whrb973f2b2000-05-05 19:34:50 +0000798
Wanlong Gao354ebb42012-12-07 10:10:04 +0800799 if (Debug_level) {
800 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
801 Lio_SysCall);
802 }
whrb973f2b2000-05-05 19:34:50 +0000803
Wanlong Gao354ebb42012-12-07 10:10:04 +0800804 if (sig)
805 sighold(sig);
806 if ((ret = aio_write(&aiocbp)) == -1) {
807 sprintf(Errormsg,
808 "%s/%d aio_write(fildes=%d, buf, nbytes=%d, signo=%d) ret:-1, errno=%d %s",
809 __FILE__, __LINE__,
810 fd, size, sig, errno, strerror(errno));
811 if (sig)
812 sigrelse(sig);
813 return -errno;
814 }
whrb973f2b2000-05-05 19:34:50 +0000815#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800816 }
817 /* LIO_IO_ASYNC */
818 else if (method & LIO_IO_SLISTIO) {
whrb973f2b2000-05-05 19:34:50 +0000819#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +0800820 request.li_opcode = LO_WRITE;
821 request.li_fildes = fd;
822 request.li_buf = buffer;
823 request.li_nbyte = size;
824 request.li_status = &status;
825 request.li_signo = sig;
826 request.li_nstride = 0;
827 request.li_filstride = 0;
828 request.li_memstride = 0;
whrb973f2b2000-05-05 19:34:50 +0000829
Wanlong Gao354ebb42012-12-07 10:10:04 +0800830 listio_cmd = LC_WAIT;
831 io_type = "listio(2) sync write";
whrb973f2b2000-05-05 19:34:50 +0000832
Wanlong Gao354ebb42012-12-07 10:10:04 +0800833 sprintf(Lio_SysCall,
834 "listio(LC_WAIT, &req, 1) LO_WRITE, fd:%d, nbyte:%d",
835 fd, size);
whrb973f2b2000-05-05 19:34:50 +0000836
Wanlong Gao354ebb42012-12-07 10:10:04 +0800837 if (Debug_level) {
838 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
839 Lio_SysCall);
840 }
whrb973f2b2000-05-05 19:34:50 +0000841
Wanlong Gao354ebb42012-12-07 10:10:04 +0800842 sigoff();
843 if (listio(listio_cmd, &request, 1) == -1) {
844 sprintf(Errormsg,
845 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
846 __FILE__, __LINE__, Lio_SysCall, fd, size,
847 errno, strerror(errno));
848 sigon();
849 return -errno;
850 }
whrb973f2b2000-05-05 19:34:50 +0000851
Wanlong Gao354ebb42012-12-07 10:10:04 +0800852 if (Debug_level > 1)
853 printf("DEBUG %s/%d: %s did not return -1\n",
854 __FILE__, __LINE__, Lio_SysCall);
whrb973f2b2000-05-05 19:34:50 +0000855
Wanlong Gao354ebb42012-12-07 10:10:04 +0800856 ret = lio_check_asyncio(io_type, size, &status);
857 return ret;
whrb973f2b2000-05-05 19:34:50 +0000858
859#endif
subrata_modak26e07d52009-02-26 06:33:39 +0000860#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
whrb973f2b2000-05-05 19:34:50 +0000861
Wanlong Gao354ebb42012-12-07 10:10:04 +0800862 aiocbp.aio_lio_opcode = LIO_WRITE;
863 listio_cmd = LIO_WAIT;
864 io_type = "lio_listio(3) sync write";
whrb973f2b2000-05-05 19:34:50 +0000865
Wanlong Gao354ebb42012-12-07 10:10:04 +0800866 sprintf(Lio_SysCall,
867 "lio_listio(LIO_WAIT, aiolist, 1, NULL) LIO_WRITE, fd:%d, nbyte:%d, sig:%d",
868 fd, size, sig);
whrb973f2b2000-05-05 19:34:50 +0000869
Wanlong Gao354ebb42012-12-07 10:10:04 +0800870 if (Debug_level) {
871 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
872 Lio_SysCall);
873 }
whrb973f2b2000-05-05 19:34:50 +0000874
Wanlong Gao354ebb42012-12-07 10:10:04 +0800875 if (sig)
876 sighold(sig);
877 if (lio_listio(listio_cmd, aiolist, 1, NULL) == -1) {
878 sprintf(Errormsg,
879 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
880 __FILE__, __LINE__, Lio_SysCall, fd, size,
881 errno, strerror(errno));
882 if (sig)
883 sigrelse(sig);
884 return -errno;
885 }
whrb973f2b2000-05-05 19:34:50 +0000886
Wanlong Gao354ebb42012-12-07 10:10:04 +0800887 if (Debug_level > 1)
888 printf("DEBUG %s/%d: %s did not return -1\n",
889 __FILE__, __LINE__, Lio_SysCall);
whrb973f2b2000-05-05 19:34:50 +0000890
Wanlong Gao354ebb42012-12-07 10:10:04 +0800891 ret = lio_check_asyncio(io_type, size, &aiocbp, method);
892 return ret;
whrb973f2b2000-05-05 19:34:50 +0000893#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800894 }
895 /* LIO_IO_SLISTIO */
896 else if (method & LIO_IO_ALISTIO) {
whrb973f2b2000-05-05 19:34:50 +0000897#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +0800898 request.li_opcode = LO_WRITE;
899 request.li_fildes = fd;
900 request.li_buf = buffer;
901 request.li_nbyte = size;
902 request.li_status = &status;
903 request.li_signo = sig;
904 request.li_nstride = 0;
905 request.li_filstride = 0;
906 request.li_memstride = 0;
whrb973f2b2000-05-05 19:34:50 +0000907
Wanlong Gao354ebb42012-12-07 10:10:04 +0800908 listio_cmd = LC_START;
909 io_type = "listio(2) async write";
whrb973f2b2000-05-05 19:34:50 +0000910
Wanlong Gao354ebb42012-12-07 10:10:04 +0800911 sprintf(Lio_SysCall,
912 "listio(LC_START, &req, 1) LO_WRITE, fd:%d, nbyte:%d",
913 fd, size);
whrb973f2b2000-05-05 19:34:50 +0000914
Wanlong Gao354ebb42012-12-07 10:10:04 +0800915 if (Debug_level) {
916 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
917 Lio_SysCall);
918 }
whrb973f2b2000-05-05 19:34:50 +0000919
Wanlong Gao354ebb42012-12-07 10:10:04 +0800920 sigoff();
921 if (listio(listio_cmd, &request, 1) == -1) {
922 sprintf(Errormsg,
923 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
924 __FILE__, __LINE__, Lio_SysCall, fd, size,
925 errno, strerror(errno));
926 sigon();
927 return -errno;
928 }
whrb973f2b2000-05-05 19:34:50 +0000929#endif
subrata_modak26e07d52009-02-26 06:33:39 +0000930#if defined (sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +0800931 aiocbp.aio_lio_opcode = LIO_WRITE;
932 listio_cmd = LIO_NOWAIT;
933 io_type = "lio_listio(3) async write";
whrb973f2b2000-05-05 19:34:50 +0000934
Wanlong Gao354ebb42012-12-07 10:10:04 +0800935 sprintf(Lio_SysCall,
936 "lio_listio(LIO_NOWAIT, aiolist, 1, NULL) LIO_WRITE, fd:%d, nbyte:%d",
937 fd, size);
whrb973f2b2000-05-05 19:34:50 +0000938
Wanlong Gao354ebb42012-12-07 10:10:04 +0800939 if (Debug_level) {
940 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
941 Lio_SysCall);
942 }
whrb973f2b2000-05-05 19:34:50 +0000943
Wanlong Gao354ebb42012-12-07 10:10:04 +0800944 if (sig)
945 sighold(sig);
946 if (lio_listio(listio_cmd, aiolist, 1, NULL) == -1) {
947 sprintf(Errormsg,
948 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
949 __FILE__, __LINE__, Lio_SysCall, fd, size,
950 errno, strerror(errno));
951 if (sig)
952 sigrelse(sig);
953 return -errno;
954 }
whrb973f2b2000-05-05 19:34:50 +0000955#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800956 }
957 /* LIO_IO_ALISTIO */
whrb973f2b2000-05-05 19:34:50 +0000958#ifndef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +0800959 else if (method & LIO_IO_SYNCV) {
960 io_type = "writev(2)";
whrb973f2b2000-05-05 19:34:50 +0000961
Wanlong Gao354ebb42012-12-07 10:10:04 +0800962 sprintf(Lio_SysCall, "writev(%d, &iov, 1) nbyte:%d", fd, size);
whrb973f2b2000-05-05 19:34:50 +0000963
Wanlong Gao354ebb42012-12-07 10:10:04 +0800964 if (Debug_level) {
965 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
966 Lio_SysCall);
967 }
968 if ((ret = writev(fd, &iov, 1)) == -1) {
969 sprintf(Errormsg,
970 "%s/%d writev(%d, iov, 1) nbyte:%d ret:-1, errno=%d %s",
971 __FILE__, __LINE__, fd, size, errno,
972 strerror(errno));
973 return -errno;
974 }
whrb973f2b2000-05-05 19:34:50 +0000975
Wanlong Gao354ebb42012-12-07 10:10:04 +0800976 if (ret != size) {
977 sprintf(Errormsg,
978 "%s/%d writev(%d, iov, 1) nbyte:%d returned=%d",
979 __FILE__, __LINE__, fd, size, ret);
980 } else if (Debug_level > 1)
981 printf
982 ("DEBUG %s/%d: writev completed without error (ret %d)\n",
983 __FILE__, __LINE__, ret);
whrb973f2b2000-05-05 19:34:50 +0000984
Wanlong Gao354ebb42012-12-07 10:10:04 +0800985 return ret;
986 } /* LIO_IO_SYNCV */
whrb973f2b2000-05-05 19:34:50 +0000987#endif
988
subrata_modak26e07d52009-02-26 06:33:39 +0000989#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +0800990 else if (method & LIO_IO_SYNCP) {
991 io_type = "pwrite(2)";
whrb973f2b2000-05-05 19:34:50 +0000992
Wanlong Gao354ebb42012-12-07 10:10:04 +0800993 sprintf(Lio_SysCall,
994 "pwrite(%d, buf, %d, %lld)", fd, size,
995 (long long)poffset);
whrb973f2b2000-05-05 19:34:50 +0000996
Wanlong Gao354ebb42012-12-07 10:10:04 +0800997 if (Debug_level) {
998 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
999 Lio_SysCall);
1000 }
1001 if ((ret = pwrite(fd, buffer, size, poffset)) == -1) {
1002 sprintf(Errormsg,
1003 "%s/%d pwrite(%d, buf, %d, %lld) ret:-1, errno=%d %s",
1004 __FILE__, __LINE__, fd, size,
1005 (long long)poffset, errno, strerror(errno));
1006 return -errno;
1007 }
whrb973f2b2000-05-05 19:34:50 +00001008
Wanlong Gao354ebb42012-12-07 10:10:04 +08001009 if (ret != size) {
1010 sprintf(Errormsg,
1011 "%s/%d pwrite(%d, buf, %d, %lld) returned=%d",
1012 __FILE__, __LINE__,
1013 fd, size, (long long)poffset, ret);
1014 } else if (Debug_level > 1)
1015 printf
1016 ("DEBUG %s/%d: pwrite completed without error (ret %d)\n",
1017 __FILE__, __LINE__, ret);
whrb973f2b2000-05-05 19:34:50 +00001018
Wanlong Gao354ebb42012-12-07 10:10:04 +08001019 return ret;
1020 } /* LIO_IO_SYNCP */
whrb973f2b2000-05-05 19:34:50 +00001021#endif
1022
Wanlong Gao354ebb42012-12-07 10:10:04 +08001023 else {
1024 printf("DEBUG %s/%d: No I/O method chosen\n", __FILE__,
1025 __LINE__);
1026 return -1;
1027 }
whrb973f2b2000-05-05 19:34:50 +00001028
Wanlong Gao354ebb42012-12-07 10:10:04 +08001029 /*
1030 * wait for async io to complete.
1031 */
whrb973f2b2000-05-05 19:34:50 +00001032#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +08001033 ret = lio_wait4asyncio(method, fd, statptr);
whrb973f2b2000-05-05 19:34:50 +00001034#endif
subrata_modak26e07d52009-02-26 06:33:39 +00001035#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +08001036 ret = lio_wait4asyncio(method, fd, &aiocbp);
whrb973f2b2000-05-05 19:34:50 +00001037#endif
1038
Wanlong Gao354ebb42012-12-07 10:10:04 +08001039 /*
1040 * If there was an error waiting for async i/o to complete,
1041 * return the error value (errno) to the caller.
1042 * Note: Errormsg should already have been updated.
1043 */
1044 if (ret < 0) {
1045 return ret;
1046 }
1047
1048 /*
1049 * If i/o was not waited for (may not have been completed at this time),
1050 * return the size that was requested.
1051 */
1052 if (ret == 1)
1053 return size;
1054
1055 /*
1056 * check that async io was successful.
1057 * Note: if the there was an system call failure, -errno
1058 * was returned and Errormsg should already have been updated.
1059 * If amount i/o was different than size, Errormsg should already
1060 * have been updated but the actual i/o size if returned.
1061 */
1062
1063#ifdef CRAY
1064 ret = lio_check_asyncio(io_type, size, &status);
1065#endif
1066#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1067 ret = lio_check_asyncio(io_type, size, &aiocbp, method);
1068#endif
1069
whrb973f2b2000-05-05 19:34:50 +00001070 return ret;
Wanlong Gao354ebb42012-12-07 10:10:04 +08001071} /* end of lio_write_buffer */
whrb973f2b2000-05-05 19:34:50 +00001072
1073/***********************************************************************
vapier45a8ba02009-07-20 10:59:32 +00001074 * Generic read function
whrb973f2b2000-05-05 19:34:50 +00001075 * This function can be used to do a read using read(2), reada(2),
1076 * aio_read(3), readv(2), pread(2),
1077 * or single stride listio(2)/lio_listio(3).
1078 * By setting the desired bits in the method
1079 * bitmask, the caller can control the type of read and the wait method
1080 * that will be used. If no io type bits are set, read will be used.
1081 *
1082 * If async io was attempted and no wait method bits are set then the
1083 * wait method is: recall(2) for reada(2) and listio(2); aio_suspend(3) for
1084 * aio_read(3) and lio_listio(3).
1085 *
vapier45a8ba02009-07-20 10:59:32 +00001086 * If multiple wait methods are specified,
whrb973f2b2000-05-05 19:34:50 +00001087 * only one wait method will be used. The order is predetermined.
1088 *
1089 * If the call specifies a signal and one of the two signal wait methods,
1090 * a signal handler for the signal is set. This will reset an already
vapier45a8ba02009-07-20 10:59:32 +00001091 * set handler for this signal.
whrb973f2b2000-05-05 19:34:50 +00001092 *
1093 * If the LIO_RANDOM method bit is set, this function will randomly
1094 * choose a io type and wait method from bits in the method argument.
1095 *
1096 * If an error is encountered, an error message will be generated
1097 * in a internal static buffer. If errmsg is not NULL, it will
1098 * be updated to point to the static buffer, allowing the caller
1099 * to print the error message.
1100 *
1101 * Return Value
1102 * If a system call fails, -errno is returned.
1103 * If LIO_WAIT_NONE bit is set, the return value is the return value
1104 * of the system call.
1105 * If the io did not fail, the amount of data written is returned.
1106 * If the size the system call say was written is different
1107 * then what was asked to be written, errmsg is updated for
1108 * this error condition. The return value is still the amount
vapier45a8ba02009-07-20 10:59:32 +00001109 * the system call says was written.
whrb973f2b2000-05-05 19:34:50 +00001110 *
1111 * (rrl 04/96)
1112 ***********************************************************************/
Wanlong Gao354ebb42012-12-07 10:10:04 +08001113int lio_read_buffer(fd, method, buffer, size, sig, errmsg, wrd)
1114int fd; /* open file descriptor */
1115int method; /* contains io type and wait method bitmask */
1116char *buffer; /* pointer to buffer */
1117int size; /* the size of the io */
1118int sig; /* signal to use if async io */
1119char **errmsg; /* char pointer that will be updated to point to err message */
1120long wrd; /* to allow future features, use zero for now */
whrb973f2b2000-05-05 19:34:50 +00001121{
Wanlong Gao354ebb42012-12-07 10:10:04 +08001122 int ret = 0; /* syscall return or used to get random method */
1123 char *io_type; /* Holds string of type of io */
1124 int listio_cmd; /* Holds the listio/lio_listio cmd */
1125 int omethod = method;
whrb973f2b2000-05-05 19:34:50 +00001126#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +08001127 struct listreq request; /* Used when a listio is wanted */
1128 struct iosw status, *statptr[1];
whrb973f2b2000-05-05 19:34:50 +00001129#else
Wanlong Gao354ebb42012-12-07 10:10:04 +08001130 /* for linux or sgi */
1131 struct iovec iov; /* iovec for readv(2) */
whrb973f2b2000-05-05 19:34:50 +00001132#endif
1133#ifdef sgi
Wanlong Gao354ebb42012-12-07 10:10:04 +08001134 aiocb_t aiocbp; /* POSIX aio control block */
1135 aiocb_t *aiolist[1]; /* list of aio control blocks for lio_listio */
1136 off64_t poffset; /* pread(2) offset */
whrb973f2b2000-05-05 19:34:50 +00001137#endif
subrata_modak26e07d52009-02-26 06:33:39 +00001138#if defined (__linux__) && !defined(__UCLIBC__)
subrata_modakea37be82008-12-11 13:17:49 +00001139 struct aiocb aiocbp; /* POSIX aio control block */
Wanlong Gao354ebb42012-12-07 10:10:04 +08001140 struct aiocb *aiolist[1]; /* list of aio control blocks for lio_listio */
subrata_modakea37be82008-12-11 13:17:49 +00001141 off64_t poffset; /* pread(2) offset */
1142#endif
whrb973f2b2000-05-05 19:34:50 +00001143
Wanlong Gao354ebb42012-12-07 10:10:04 +08001144 /*
1145 * If LIO_RANDOM bit specified, get new method randomly.
1146 */
1147 if (method & LIO_RANDOM) {
1148 if (Debug_level > 3)
1149 printf("DEBUG %s/%d: method mask to choose from: %#o\n",
1150 __FILE__, __LINE__, method);
1151 method = lio_random_methods(method);
1152 if (Debug_level > 2)
1153 printf("DEBUG %s/%d: random chosen method %#o\n",
1154 __FILE__, __LINE__, method);
1155 }
whrb973f2b2000-05-05 19:34:50 +00001156
Wanlong Gao354ebb42012-12-07 10:10:04 +08001157 if (errmsg != NULL)
1158 *errmsg = Errormsg;
whrb973f2b2000-05-05 19:34:50 +00001159
Wanlong Gao354ebb42012-12-07 10:10:04 +08001160 Rec_signal = Received_signal; /* get the current number of signals received */
subrata_modak26e07d52009-02-26 06:33:39 +00001161#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +08001162 Rec_callback = Received_callback; /* get the current number of callbacks received */
whrb973f2b2000-05-05 19:34:50 +00001163#endif
1164
1165#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +08001166 memset(&status, 0x00, sizeof(struct iosw));
1167 memset(&request, 0x00, sizeof(struct listreq));
1168 statptr[0] = &status;
whrb973f2b2000-05-05 19:34:50 +00001169#else
Wanlong Gao354ebb42012-12-07 10:10:04 +08001170 /* for linux or sgi */
1171 memset(&iov, 0x00, sizeof(struct iovec));
1172 iov.iov_base = buffer;
1173 iov.iov_len = size;
whrb973f2b2000-05-05 19:34:50 +00001174#endif
subrata_modak26e07d52009-02-26 06:33:39 +00001175#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
subrata_modakea37be82008-12-11 13:17:49 +00001176#if defined(sgi)
Wanlong Gao354ebb42012-12-07 10:10:04 +08001177 memset(&aiocbp, 0x00, sizeof(aiocb_t));
subrata_modakea37be82008-12-11 13:17:49 +00001178#else
1179 memset(&aiocbp, 0x00, sizeof(struct aiocb));
1180#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +08001181 aiocbp.aio_fildes = fd;
1182 aiocbp.aio_nbytes = size;
1183 aiocbp.aio_buf = buffer;
whrb973f2b2000-05-05 19:34:50 +00001184/* aiocbp.aio_offset = lseek( fd, 0, SEEK_CUR ); -- set below */
Wanlong Gao354ebb42012-12-07 10:10:04 +08001185 aiocbp.aio_sigevent.sigev_notify = SIGEV_NONE;
1186 aiocbp.aio_sigevent.sigev_signo = 0;
subrata_modakea37be82008-12-11 13:17:49 +00001187#ifdef sgi
Wanlong Gao354ebb42012-12-07 10:10:04 +08001188 aiocbp.aio_sigevent.sigev_func = NULL;
1189 aiocbp.aio_sigevent.sigev_value.sival_int = 0;
subrata_modak26e07d52009-02-26 06:33:39 +00001190#elif defined(__linux__) && !defined(__UCLIBC__)
subrata_modakea37be82008-12-11 13:17:49 +00001191 aiocbp.aio_sigevent.sigev_notify_function = NULL;
1192 aiocbp.aio_sigevent.sigev_notify_attributes = 0;
1193#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +08001194 aiolist[0] = &aiocbp;
whrb973f2b2000-05-05 19:34:50 +00001195
Wanlong Gao354ebb42012-12-07 10:10:04 +08001196 if ((ret = lseek(fd, 0, SEEK_CUR)) == -1) {
1197 ret = 0;
1198 /* If there is an error and it is not ESPIPE then kick out the error.
1199 * If the fd is a fifo then we have to make sure that
1200 * lio_random_methods() didn't select pwrite/pread; if it did then
1201 * switch to write/read.
1202 */
1203 if (errno == ESPIPE) {
1204 if (method & LIO_IO_SYNCP) {
1205 if (omethod & LIO_RANDOM) {
1206 method &= ~LIO_IO_SYNCP;
1207 method |= LIO_IO_SYNC;
1208 if (Debug_level > 2)
1209 printf
1210 ("DEBUG %s/%d: random chosen method switched to %#o for fifo\n",
1211 __FILE__, __LINE__,
1212 method);
1213 } else if (Debug_level) {
1214 printf
1215 ("DEBUG %s/%d: pread will fail when it reads from a fifo\n",
1216 __FILE__, __LINE__);
1217 }
whrb973f2b2000-05-05 19:34:50 +00001218 }
Wanlong Gao354ebb42012-12-07 10:10:04 +08001219 /* else: let it ride */
1220 } else {
1221 sprintf(Errormsg,
1222 "%s/%d lseek(fd=%d,0,SEEK_CUR) failed, errno=%d %s",
1223 __FILE__, __LINE__, fd, errno, strerror(errno));
1224 return -errno;
whrb973f2b2000-05-05 19:34:50 +00001225 }
whrb973f2b2000-05-05 19:34:50 +00001226 }
subrata_modak26e07d52009-02-26 06:33:39 +00001227#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +08001228 poffset = (off64_t) ret;
subrata_modakea37be82008-12-11 13:17:49 +00001229#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +08001230 aiocbp.aio_offset = ret;
whrb973f2b2000-05-05 19:34:50 +00001231
1232#endif
1233
Wanlong Gao354ebb42012-12-07 10:10:04 +08001234 /*
1235 * If the LIO_USE_SIGNAL bit is not set, only use the signal
1236 * if the LIO_WAIT_SIGPAUSE or the LIO_WAIT_SIGACTIVE bits are set.
1237 * Otherwise there is not necessarily a signal handler to trap
1238 * the signal.
1239 */
1240 if (sig && !(method & LIO_USE_SIGNAL) && !(method & LIO_WAIT_SIGTYPES)) {
whrb973f2b2000-05-05 19:34:50 +00001241
Wanlong Gao354ebb42012-12-07 10:10:04 +08001242 sig = 0; /* ignore signal parameter */
1243 }
subrata_modak26e07d52009-02-26 06:33:39 +00001244#if defined(sgi) || (defined(__linux__)&& !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +08001245 if (sig && (method & LIO_WAIT_CBTYPES))
1246 sig = 0; /* ignore signal parameter */
whrb973f2b2000-05-05 19:34:50 +00001247#endif
1248
Wanlong Gao354ebb42012-12-07 10:10:04 +08001249 /*
1250 * only setup signal hander if sig was specified and
1251 * a sig wait method was specified.
1252 * Doing this will change the handler for this signal. The
1253 * old signal handler will not be restored.
1254 *** restoring the signal handler could be added ***
1255 */
whrb973f2b2000-05-05 19:34:50 +00001256
Wanlong Gao354ebb42012-12-07 10:10:04 +08001257 if (sig && (method & LIO_WAIT_SIGTYPES)) {
whrb973f2b2000-05-05 19:34:50 +00001258#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +08001259 sigctl(SCTL_REG, sig, lio_async_signal_handler);
whrb973f2b2000-05-05 19:34:50 +00001260#endif
subrata_modak26e07d52009-02-26 06:33:39 +00001261#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +08001262 aiocbp.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
1263 aiocbp.aio_sigevent.sigev_signo = sig;
1264 sigset(sig, lio_async_signal_handler);
whrb973f2b2000-05-05 19:34:50 +00001265#endif /* CRAY */
Wanlong Gao354ebb42012-12-07 10:10:04 +08001266 }
subrata_modakea37be82008-12-11 13:17:49 +00001267#if defined(sgi)
Wanlong Gao354ebb42012-12-07 10:10:04 +08001268 else if (method & LIO_WAIT_CBTYPES) {
1269 aiocbp.aio_sigevent.sigev_notify = SIGEV_CALLBACK;
1270 aiocbp.aio_sigevent.sigev_func = 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_value.sival_int = size;
1275 }
whrb973f2b2000-05-05 19:34:50 +00001276#endif
subrata_modak26e07d52009-02-26 06:33:39 +00001277#if defined(__linux__) && !defined(__UCLIBC__)
Garrett Cooper903910d2010-11-23 09:27:44 -08001278 else if (method & LIO_WAIT_CBTYPES) {
subrata_modakea37be82008-12-11 13:17:49 +00001279 aiocbp.aio_sigevent.sigev_notify = SIGEV_THREAD;
Wanlong Gao354ebb42012-12-07 10:10:04 +08001280 aiocbp.aio_sigevent.sigev_notify_function =
1281 lio_async_callback_handler;
subrata_modakea37be82008-12-11 13:17:49 +00001282 /* sival_int just has to be something that I can use
1283 * to identify the callback, and "size" happens to be handy...
1284 */
Wanlong Gao354ebb42012-12-07 10:10:04 +08001285 aiocbp.aio_sigevent.sigev_notify_attributes =
1286 (void *)(uintptr_t) size;
subrata_modakea37be82008-12-11 13:17:49 +00001287 }
1288#endif
whrb973f2b2000-05-05 19:34:50 +00001289
whrb973f2b2000-05-05 19:34:50 +00001290 /*
Wanlong Gao354ebb42012-12-07 10:10:04 +08001291 * Determine the system call that will be called and produce
1292 * the string of the system call and place it in Lio_SysCall.
1293 * Also update the io_type char pointer to give brief description
1294 * of system call. Execute the system call and check for
1295 * system call failure. If sync i/o, return the number of
1296 * bytes written/read.
1297 */
whrb973f2b2000-05-05 19:34:50 +00001298
Wanlong Gao354ebb42012-12-07 10:10:04 +08001299 if ((method & LIO_IO_SYNC)
1300 || (method & (LIO_IO_TYPES | LIO_IO_ATYPES)) == 0) {
1301 /*
1302 * read(2) is used if LIO_IO_SYNC bit is set or not none
1303 * of the LIO_IO_TYPES bits are set (default).
1304 */
whrb973f2b2000-05-05 19:34:50 +00001305
Wanlong Gao354ebb42012-12-07 10:10:04 +08001306 sprintf(Lio_SysCall, "read(%d, buf, %d)", fd, size);
1307 io_type = "read";
whrb973f2b2000-05-05 19:34:50 +00001308
Wanlong Gao354ebb42012-12-07 10:10:04 +08001309 if (Debug_level) {
1310 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1311 Lio_SysCall);
1312 }
whrb973f2b2000-05-05 19:34:50 +00001313
Wanlong Gao354ebb42012-12-07 10:10:04 +08001314 while (1) {
1315 if (((ret = read(fd, buffer, size)) == -1)
1316 && errno != EINTR && errno != EAGAIN) {
1317 sprintf(Errormsg,
1318 "%s/%d read(%d, buf, %d) ret:-1, errno=%d %s",
1319 __FILE__, __LINE__, fd, size, errno,
1320 strerror(errno));
1321 return -errno;
1322 }
subrata_modakea37be82008-12-11 13:17:49 +00001323
Wanlong Gao354ebb42012-12-07 10:10:04 +08001324 if (ret == 0)
1325 return 0;
1326 if (ret != -1) {
1327 if (ret != size) {
1328 sprintf(Errormsg,
1329 "%s/%d read(%d, buf, %d) returned=%d",
1330 __FILE__, __LINE__,
1331 fd, size, ret);
1332 size -= ret;
1333 buffer += ret;
1334 } else {
1335 if (Debug_level > 1)
1336 printf
1337 ("DEBUG %s/%d: read completed without error (ret %d)\n",
1338 __FILE__, __LINE__, ret);
whrb973f2b2000-05-05 19:34:50 +00001339
Wanlong Gao354ebb42012-12-07 10:10:04 +08001340 return ret;
1341 }
1342 }
1343 wait4sync_io(fd, 1);
1344 }
whrb973f2b2000-05-05 19:34:50 +00001345
whrb973f2b2000-05-05 19:34:50 +00001346 }
Wanlong Gao354ebb42012-12-07 10:10:04 +08001347
1348 else if (method & LIO_IO_ASYNC) {
1349#ifdef CRAY
1350 sprintf(Lio_SysCall,
1351 "reada(%d, buf, %d, &status, %d)", fd, size, sig);
1352 io_type = "reada";
1353
1354 if (Debug_level) {
1355 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1356 Lio_SysCall);
1357 }
1358
1359 sigoff();
1360 if ((ret = reada(fd, buffer, size, &status, sig)) == -1) {
1361 sprintf(Errormsg,
1362 "%s/%d reada(%d, buf, %d, &stat, %d) ret:-1, errno=%d %s",
1363 __FILE__, __LINE__,
1364 fd, size, sig, errno, strerror(errno));
1365 sigon();
1366 return -errno;
1367 }
whrb973f2b2000-05-05 19:34:50 +00001368#endif
subrata_modak26e07d52009-02-26 06:33:39 +00001369#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +08001370 sprintf(Lio_SysCall,
1371 "aio_read(fildes=%d, buf, nbytes=%d, signo=%d)", fd,
1372 size, sig);
1373 io_type = "aio_read";
whrb973f2b2000-05-05 19:34:50 +00001374
Wanlong Gao354ebb42012-12-07 10:10:04 +08001375 if (Debug_level) {
1376 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1377 Lio_SysCall);
1378 }
whrb973f2b2000-05-05 19:34:50 +00001379
Wanlong Gao354ebb42012-12-07 10:10:04 +08001380 if (sig)
1381 sighold(sig);
1382 if ((ret = aio_read(&aiocbp)) == -1) {
1383 sprintf(Errormsg,
1384 "%s/%d aio_read(fildes=%d, buf, nbytes=%d, signo=%d) ret:-1, errno=%d %s",
1385 __FILE__, __LINE__,
1386 fd, size, sig, errno, strerror(errno));
1387 if (sig)
1388 sigrelse(sig);
1389 return -errno;
1390 }
1391#endif
whrb973f2b2000-05-05 19:34:50 +00001392 }
Wanlong Gao354ebb42012-12-07 10:10:04 +08001393 /* LIO_IO_ASYNC */
1394 else if (method & LIO_IO_SLISTIO) {
whrb973f2b2000-05-05 19:34:50 +00001395#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +08001396 request.li_opcode = LO_READ;
1397 request.li_fildes = fd;
1398 request.li_buf = buffer;
1399 request.li_nbyte = size;
1400 request.li_status = &status;
1401 request.li_signo = sig;
1402 request.li_nstride = 0;
1403 request.li_filstride = 0;
1404 request.li_memstride = 0;
whrb973f2b2000-05-05 19:34:50 +00001405
Wanlong Gao354ebb42012-12-07 10:10:04 +08001406 listio_cmd = LC_WAIT;
1407 io_type = "listio(2) sync read";
whrb973f2b2000-05-05 19:34:50 +00001408
Wanlong Gao354ebb42012-12-07 10:10:04 +08001409 sprintf(Lio_SysCall,
1410 "listio(LC_WAIT, &req, 1) LO_READ, fd:%d, nbyte:%d",
1411 fd, size);
whrb973f2b2000-05-05 19:34:50 +00001412
Wanlong Gao354ebb42012-12-07 10:10:04 +08001413 if (Debug_level) {
1414 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1415 Lio_SysCall);
1416 }
whrb973f2b2000-05-05 19:34:50 +00001417
Wanlong Gao354ebb42012-12-07 10:10:04 +08001418 sigoff();
1419 if (listio(listio_cmd, &request, 1) == -1) {
1420 sprintf(Errormsg,
1421 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1422 __FILE__, __LINE__, Lio_SysCall, fd, size,
1423 errno, strerror(errno));
1424 sigon();
1425 return -errno;
1426 }
whrb973f2b2000-05-05 19:34:50 +00001427
Wanlong Gao354ebb42012-12-07 10:10:04 +08001428 if (Debug_level > 1)
1429 printf("DEBUG %s/%d: %s did not return -1\n",
1430 __FILE__, __LINE__, Lio_SysCall);
whrb973f2b2000-05-05 19:34:50 +00001431
Wanlong Gao354ebb42012-12-07 10:10:04 +08001432 ret = lio_check_asyncio(io_type, size, &status);
1433 return ret;
whrb973f2b2000-05-05 19:34:50 +00001434#endif
subrata_modak26e07d52009-02-26 06:33:39 +00001435#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +08001436 aiocbp.aio_lio_opcode = LIO_READ;
1437 listio_cmd = LIO_WAIT;
1438 io_type = "lio_listio(3) sync read";
whrb973f2b2000-05-05 19:34:50 +00001439
Wanlong Gao354ebb42012-12-07 10:10:04 +08001440 sprintf(Lio_SysCall,
1441 "lio_listio(LIO_WAIT, aiolist, 1, NULL) LIO_READ, fd:%d, nbyte:%d",
1442 fd, size);
whrb973f2b2000-05-05 19:34:50 +00001443
Wanlong Gao354ebb42012-12-07 10:10:04 +08001444 if (Debug_level) {
1445 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1446 Lio_SysCall);
1447 }
whrb973f2b2000-05-05 19:34:50 +00001448
Wanlong Gao354ebb42012-12-07 10:10:04 +08001449 if (sig)
1450 sighold(sig);
1451 if (lio_listio(listio_cmd, aiolist, 1, NULL) == -1) {
1452 sprintf(Errormsg,
1453 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1454 __FILE__, __LINE__, Lio_SysCall, fd, size,
1455 errno, strerror(errno));
1456 if (sig)
1457 sigrelse(sig);
1458 return -errno;
1459 }
whrb973f2b2000-05-05 19:34:50 +00001460
Wanlong Gao354ebb42012-12-07 10:10:04 +08001461 if (Debug_level > 1)
1462 printf("DEBUG %s/%d: %s did not return -1\n",
1463 __FILE__, __LINE__, Lio_SysCall);
whrb973f2b2000-05-05 19:34:50 +00001464
Wanlong Gao354ebb42012-12-07 10:10:04 +08001465 ret = lio_check_asyncio(io_type, size, &aiocbp, method);
1466 return ret;
whrb973f2b2000-05-05 19:34:50 +00001467#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +08001468 }
1469 /* LIO_IO_SLISTIO */
1470 else if (method & LIO_IO_ALISTIO) {
whrb973f2b2000-05-05 19:34:50 +00001471#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +08001472 request.li_opcode = LO_READ;
1473 request.li_fildes = fd;
1474 request.li_buf = buffer;
1475 request.li_nbyte = size;
1476 request.li_status = &status;
1477 request.li_signo = sig;
1478 request.li_nstride = 0;
1479 request.li_filstride = 0;
1480 request.li_memstride = 0;
whrb973f2b2000-05-05 19:34:50 +00001481
Wanlong Gao354ebb42012-12-07 10:10:04 +08001482 listio_cmd = LC_START;
1483 io_type = "listio(2) async read";
whrb973f2b2000-05-05 19:34:50 +00001484
Wanlong Gao354ebb42012-12-07 10:10:04 +08001485 sprintf(Lio_SysCall,
1486 "listio(LC_START, &req, 1) LO_READ, fd:%d, nbyte:%d",
1487 fd, size);
whrb973f2b2000-05-05 19:34:50 +00001488
Wanlong Gao354ebb42012-12-07 10:10:04 +08001489 if (Debug_level) {
1490 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1491 Lio_SysCall);
1492 }
whrb973f2b2000-05-05 19:34:50 +00001493
Wanlong Gao354ebb42012-12-07 10:10:04 +08001494 sigoff();
1495 if (listio(listio_cmd, &request, 1) == -1) {
1496 sprintf(Errormsg,
1497 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1498 __FILE__, __LINE__, Lio_SysCall, fd, size,
1499 errno, strerror(errno));
1500 sigon();
1501 return -errno;
1502 }
whrb973f2b2000-05-05 19:34:50 +00001503#endif
subrata_modak26e07d52009-02-26 06:33:39 +00001504#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +08001505 aiocbp.aio_lio_opcode = LIO_READ;
1506 listio_cmd = LIO_NOWAIT;
1507 io_type = "lio_listio(3) async read";
whrb973f2b2000-05-05 19:34:50 +00001508
Wanlong Gao354ebb42012-12-07 10:10:04 +08001509 sprintf(Lio_SysCall,
1510 "lio_listio(LIO_NOWAIT, aiolist, 1, NULL) LIO_READ, fd:%d, nbyte:%d",
1511 fd, size);
whrb973f2b2000-05-05 19:34:50 +00001512
Wanlong Gao354ebb42012-12-07 10:10:04 +08001513 if (Debug_level) {
1514 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1515 Lio_SysCall);
1516 }
whrb973f2b2000-05-05 19:34:50 +00001517
Wanlong Gao354ebb42012-12-07 10:10:04 +08001518 if (sig)
1519 sighold(sig);
1520 if (lio_listio(listio_cmd, aiolist, 1, NULL) == -1) {
1521 sprintf(Errormsg,
1522 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1523 __FILE__, __LINE__, Lio_SysCall, fd, size,
1524 errno, strerror(errno));
1525 if (sig)
1526 sigrelse(sig);
1527 return -errno;
1528 }
whrb973f2b2000-05-05 19:34:50 +00001529#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +08001530 }
1531 /* LIO_IO_ALISTIO */
whrb973f2b2000-05-05 19:34:50 +00001532#ifndef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +08001533 else if (method & LIO_IO_SYNCV) {
1534 io_type = "readv(2)";
whrb973f2b2000-05-05 19:34:50 +00001535
Wanlong Gao354ebb42012-12-07 10:10:04 +08001536 sprintf(Lio_SysCall, "readv(%d, &iov, 1) nbyte:%d", fd, size);
whrb973f2b2000-05-05 19:34:50 +00001537
Wanlong Gao354ebb42012-12-07 10:10:04 +08001538 if (Debug_level) {
1539 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1540 Lio_SysCall);
1541 }
1542 if ((ret = readv(fd, &iov, 1)) == -1) {
1543 sprintf(Errormsg,
1544 "%s/%d readv(%d, iov, 1) nbyte:%d ret:-1, errno=%d %s",
1545 __FILE__, __LINE__, fd, size, errno,
1546 strerror(errno));
1547 return -errno;
1548 }
whrb973f2b2000-05-05 19:34:50 +00001549
Wanlong Gao354ebb42012-12-07 10:10:04 +08001550 if (ret != size) {
1551 sprintf(Errormsg,
1552 "%s/%d readv(%d, iov, 1) nbyte:%d returned=%d",
1553 __FILE__, __LINE__, fd, size, ret);
1554 } else if (Debug_level > 1)
1555 printf
1556 ("DEBUG %s/%d: readv completed without error (ret %d)\n",
1557 __FILE__, __LINE__, ret);
whrb973f2b2000-05-05 19:34:50 +00001558
Wanlong Gao354ebb42012-12-07 10:10:04 +08001559 return ret;
1560 } /* LIO_IO_SYNCV */
whrb973f2b2000-05-05 19:34:50 +00001561#endif
1562
subrata_modak26e07d52009-02-26 06:33:39 +00001563#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +08001564 else if (method & LIO_IO_SYNCP) {
1565 io_type = "pread(2)";
whrb973f2b2000-05-05 19:34:50 +00001566
Wanlong Gao354ebb42012-12-07 10:10:04 +08001567 sprintf(Lio_SysCall,
1568 "pread(%d, buf, %d, %lld)", fd, size,
1569 (long long)poffset);
whrb973f2b2000-05-05 19:34:50 +00001570
Wanlong Gao354ebb42012-12-07 10:10:04 +08001571 if (Debug_level) {
1572 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1573 Lio_SysCall);
1574 }
1575 if ((ret = pread(fd, buffer, size, poffset)) == -1) {
1576 sprintf(Errormsg,
1577 "%s/%d pread(%d, buf, %d, %lld) ret:-1, errno=%d %s",
1578 __FILE__, __LINE__, fd, size,
1579 (long long)poffset, errno, strerror(errno));
1580 return -errno;
1581 }
whrb973f2b2000-05-05 19:34:50 +00001582
Wanlong Gao354ebb42012-12-07 10:10:04 +08001583 if (ret != size) {
1584 sprintf(Errormsg,
1585 "%s/%d pread(%d, buf, %d, %lld) returned=%d",
1586 __FILE__, __LINE__,
1587 fd, size, (long long)poffset, ret);
1588 } else if (Debug_level > 1)
1589 printf
1590 ("DEBUG %s/%d: pread completed without error (ret %d)\n",
1591 __FILE__, __LINE__, ret);
whrb973f2b2000-05-05 19:34:50 +00001592
Wanlong Gao354ebb42012-12-07 10:10:04 +08001593 return ret;
1594 } /* LIO_IO_SYNCP */
whrb973f2b2000-05-05 19:34:50 +00001595#endif
1596
Wanlong Gao354ebb42012-12-07 10:10:04 +08001597 else {
1598 printf("DEBUG %s/%d: No I/O method chosen\n", __FILE__,
1599 __LINE__);
1600 return -1;
1601 }
whrb973f2b2000-05-05 19:34:50 +00001602
Wanlong Gao354ebb42012-12-07 10:10:04 +08001603 /*
1604 * wait for async io to complete.
1605 * Note: Sync io should have returned prior to getting here.
1606 */
whrb973f2b2000-05-05 19:34:50 +00001607#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +08001608 ret = lio_wait4asyncio(method, fd, statptr);
whrb973f2b2000-05-05 19:34:50 +00001609#endif
subrata_modak26e07d52009-02-26 06:33:39 +00001610#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +08001611 ret = lio_wait4asyncio(method, fd, &aiocbp);
whrb973f2b2000-05-05 19:34:50 +00001612#endif
1613
Wanlong Gao354ebb42012-12-07 10:10:04 +08001614 /*
1615 * If there was an error waiting for async i/o to complete,
1616 * return the error value (errno) to the caller.
1617 * Note: Errormsg should already have been updated.
1618 */
1619 if (ret < 0) {
1620 return ret;
1621 }
1622
1623 /*
1624 * If i/o was not waited for (may not have been completed at this time),
1625 * return the size that was requested.
1626 */
1627 if (ret == 1)
1628 return size;
1629
1630 /*
1631 * check that async io was successful.
1632 * Note: if the there was an system call failure, -errno
1633 * was returned and Errormsg should already have been updated.
1634 * If amount i/o was different than size, Errormsg should already
1635 * have been updated but the actual i/o size if returned.
1636 */
1637
1638#ifdef CRAY
1639 ret = lio_check_asyncio(io_type, size, &status);
1640#endif
1641#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1642 ret = lio_check_asyncio(io_type, size, &aiocbp, method);
1643#endif
1644
whrb973f2b2000-05-05 19:34:50 +00001645 return ret;
Wanlong Gao354ebb42012-12-07 10:10:04 +08001646} /* end of lio_read_buffer */
whrb973f2b2000-05-05 19:34:50 +00001647
subrata_modakea37be82008-12-11 13:17:49 +00001648#if !defined(__sun) && !defined(__hpux) && !defined(_AIX)
whrb973f2b2000-05-05 19:34:50 +00001649/***********************************************************************
1650 * This function will check that async io was successful.
1651 * It can also be used to check sync listio since it uses the
1652 * same method.
1653 *
1654 * Return Values
1655 * If status.sw_error is set, -status.sw_error is returned.
1656 * Otherwise sw_count's field value is returned.
1657 *
1658 * (rrl 04/96)
1659 ***********************************************************************/
whrb973f2b2000-05-05 19:34:50 +00001660#ifdef CRAY
subrata_modak26e07d52009-02-26 06:33:39 +00001661int lio_check_asyncio(char *io_type, int size, struct iosw *status)
subrata_modakea37be82008-12-11 13:17:49 +00001662#elif defined(sgi)
Wanlong Gao354ebb42012-12-07 10:10:04 +08001663int lio_check_asyncio(char *io_type, int size, aiocb_t * aiocbp, int method)
subrata_modak26e07d52009-02-26 06:33:39 +00001664#elif defined(__linux__) && !defined(__UCLIBC__)
Wanlong Gao354ebb42012-12-07 10:10:04 +08001665int lio_check_asyncio(char *io_type, int size, struct aiocb *aiocbp, int method)
whrb973f2b2000-05-05 19:34:50 +00001666{
Wanlong Gao354ebb42012-12-07 10:10:04 +08001667 int ret;
whrb973f2b2000-05-05 19:34:50 +00001668
1669#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +08001670 if (status->sw_error) {
1671 sprintf(Errormsg,
1672 "%s/%d %s, sw_error set = %d %s, sw_count = %d",
1673 __FILE__, __LINE__, io_type,
1674 status->sw_error, strerror(status->sw_error),
1675 status->sw_count);
1676 return -status->sw_error;
1677 } else if (status->sw_count != size) {
1678 sprintf(Errormsg,
1679 "%s/%d %s, sw_count not as expected(%d), but actual:%d",
1680 __FILE__, __LINE__, io_type, size, status->sw_count);
1681 } else if (Debug_level > 1) {
1682 printf
1683 ("DEBUG %s/%d: %s completed without error (sw_error == 0, sw_count == %d)\n",
1684 __FILE__, __LINE__, io_type, status->sw_count);
1685 }
whrb973f2b2000-05-05 19:34:50 +00001686
Wanlong Gao354ebb42012-12-07 10:10:04 +08001687 return status->sw_count;
whrb973f2b2000-05-05 19:34:50 +00001688
1689#else
1690
Wanlong Gao354ebb42012-12-07 10:10:04 +08001691 int cnt = 1;
whrb973f2b2000-05-05 19:34:50 +00001692
Wanlong Gao354ebb42012-12-07 10:10:04 +08001693 /* The I/O may have been synchronous with signal completion. It doesn't
1694 * make sense, but the combination could be generated. Release the
1695 * completion signal here otherwise it'll hang around and bite us
1696 * later.
1697 */
1698 if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL)
1699 sigrelse(aiocbp->aio_sigevent.sigev_signo);
whrb973f2b2000-05-05 19:34:50 +00001700
Wanlong Gao354ebb42012-12-07 10:10:04 +08001701 ret = aio_error(aiocbp);
whrb973f2b2000-05-05 19:34:50 +00001702
Wanlong Gao354ebb42012-12-07 10:10:04 +08001703 while (ret == EINPROGRESS) {
1704 ret = aio_error(aiocbp);
1705 ++cnt;
1706 }
1707 if (cnt > 1) {
1708 sprintf(Errormsg,
1709 "%s/%d %s, aio_error had to loop on EINPROGRESS, cnt=%d; random method %#o; sigev_notify=%s",
1710 __FILE__, __LINE__, io_type, cnt, method,
1711 (aiocbp->aio_sigevent.sigev_notify ==
1712 SIGEV_SIGNAL ? "signal" : aiocbp->aio_sigevent.
1713 sigev_notify == SIGEV_NONE ? "none" :
mridgee6508f82005-01-04 21:00:17 +00001714#ifdef SIGEV_CALLBACK
Wanlong Gao354ebb42012-12-07 10:10:04 +08001715 aiocbp->aio_sigevent.sigev_notify ==
1716 SIGEV_CALLBACK ? "callback" :
mridgee6508f82005-01-04 21:00:17 +00001717#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +08001718 aiocbp->aio_sigevent.sigev_notify ==
1719 SIGEV_THREAD ? "thread" : "unknown"));
1720 return -ret;
1721 }
whrb973f2b2000-05-05 19:34:50 +00001722
Wanlong Gao354ebb42012-12-07 10:10:04 +08001723 if (ret != 0) {
1724 sprintf(Errormsg,
1725 "%s/%d %s, aio_error = %d %s; random method %#o",
1726 __FILE__, __LINE__, io_type,
1727 ret, strerror(ret), method);
1728 return -ret;
1729 }
1730 ret = aio_return(aiocbp);
1731 if (ret != size) {
1732 sprintf(Errormsg,
1733 "%s/%d %s, aio_return not as expected(%d), but actual:%d",
1734 __FILE__, __LINE__, io_type, size, ret);
whrb973f2b2000-05-05 19:34:50 +00001735
1736#ifdef BUG1_workaround
Wanlong Gao354ebb42012-12-07 10:10:04 +08001737 if (ret == 0) {
1738 ret = size;
1739 if (Debug_level > 1) {
1740 printf
1741 ("WARN %s/%d: %s completed with bug1_workaround (aio_error == 0, aio_return now == %d)\n",
1742 __FILE__, __LINE__, io_type, ret);
1743 }
whrb973f2b2000-05-05 19:34:50 +00001744 }
whrb973f2b2000-05-05 19:34:50 +00001745#endif /* BUG1_workaround */
1746
Wanlong Gao354ebb42012-12-07 10:10:04 +08001747 } else if (Debug_level > 1) {
1748 printf
1749 ("DEBUG %s/%d: %s completed without error (aio_error == 0, aio_return == %d)\n",
1750 __FILE__, __LINE__, io_type, ret);
1751 }
whrb973f2b2000-05-05 19:34:50 +00001752
Wanlong Gao354ebb42012-12-07 10:10:04 +08001753 return ret;
whrb973f2b2000-05-05 19:34:50 +00001754
1755#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +08001756} /* end of lio_check_asyncio */
subrata_modak26e07d52009-02-26 06:33:39 +00001757#endif
whrb973f2b2000-05-05 19:34:50 +00001758
1759/***********************************************************************
1760 *
1761 * This function will wait for async io to complete.
1762 * If multiple wait methods are specified, the order is predetermined
1763 * to LIO_WAIT_RECALL,
1764 * LIO_WAIT_ACTIVE, LIO_WAIT_SIGPAUSE, LIO_WAIT_SIGACTIVE,
1765 * then LIO_WAIT_NONE.
1766 *
1767 * If no wait method was specified the default wait method is: recall(2)
1768 * or aio_suspend(3), as appropriate.
1769 *
1770 * Return Values
1771 * <0: errno of failed recall
1772 * 0 : async io was completed
1773 * 1 : async was not waited for, io may not have completed.
1774 *
1775 * (rrl 04/96)
1776 ***********************************************************************/
whrb973f2b2000-05-05 19:34:50 +00001777#ifdef CRAY
subrata_modak26e07d52009-02-26 06:33:39 +00001778int lio_wait4asyncio(int method, int fd, struct iosw **statptr)
subrata_modakea37be82008-12-11 13:17:49 +00001779#elif defined(sgi)
Wanlong Gao354ebb42012-12-07 10:10:04 +08001780int lio_wait4asyncio(int method, int fd, aiocb_t * aiocbp)
subrata_modak26e07d52009-02-26 06:33:39 +00001781#elif defined(__linux__) && !defined(__UCLIBC__)
Wanlong Gao354ebb42012-12-07 10:10:04 +08001782int lio_wait4asyncio(int method, int fd, struct aiocb *aiocbp)
whrb973f2b2000-05-05 19:34:50 +00001783{
Wanlong Gao354ebb42012-12-07 10:10:04 +08001784 int cnt;
whrb973f2b2000-05-05 19:34:50 +00001785#ifdef sgi
Wanlong Gao354ebb42012-12-07 10:10:04 +08001786 int ret;
1787 const aiocb_t *aioary[1];
whrb973f2b2000-05-05 19:34:50 +00001788#endif
subrata_modak26e07d52009-02-26 06:33:39 +00001789#if defined(__linux__)&& !defined(__UCLIBC__)
subrata_modakea37be82008-12-11 13:17:49 +00001790 int ret;
1791 const struct aiocb *aioary[1];
1792#endif
whrb973f2b2000-05-05 19:34:50 +00001793
Wanlong Gao354ebb42012-12-07 10:10:04 +08001794 if ((method & LIO_WAIT_RECALL)
subrata_modak26e07d52009-02-26 06:33:39 +00001795#if defined(sgi) || (defined(__linux__)&& !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +08001796 || (method & LIO_WAIT_CBSUSPEND)
1797 || (method & LIO_WAIT_SIGSUSPEND)
whrb973f2b2000-05-05 19:34:50 +00001798#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +08001799 || ((method & LIO_WAIT_TYPES) == 0)) {
1800 /*
1801 * If method has LIO_WAIT_RECALL bit set or method does
1802 * not have any wait method bits set (default), use recall/aio_suspend.
1803 */
whrb973f2b2000-05-05 19:34:50 +00001804#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +08001805 if (Debug_level > 2)
1806 printf("DEBUG %s/%d: wait method : recall\n", __FILE__,
1807 __LINE__);
1808 sigon();
1809 if (recall(fd, 1, statptr)) {
1810 sprintf(Errormsg,
1811 "%s/%d recall(%d, 1, stat) failed, errno:%d %s",
1812 __FILE__, __LINE__, fd, errno, strerror(errno));
whrb973f2b2000-05-05 19:34:50 +00001813 return -errno;
1814 }
whrb973f2b2000-05-05 19:34:50 +00001815#else
Wanlong Gao354ebb42012-12-07 10:10:04 +08001816 if (Debug_level > 2)
1817 printf
1818 ("DEBUG %s/%d: wait method : aio_suspend, sigev_notify=%s\n",
1819 __FILE__, __LINE__,
1820 (aiocbp->aio_sigevent.sigev_notify ==
1821 SIGEV_SIGNAL ? "signal" : aiocbp->aio_sigevent.
1822 sigev_notify == SIGEV_NONE ? "none" :
1823#ifdef SIGEV_CALLBACK
1824 aiocbp->aio_sigevent.sigev_notify ==
1825 SIGEV_CALLBACK ? "callback" :
1826#endif
1827 aiocbp->aio_sigevent.sigev_notify ==
1828 SIGEV_THREAD ? "thread" : "unknown"));
1829
1830 aioary[0] = aiocbp;
1831 ret = aio_suspend(aioary, 1, NULL);
1832 if ((ret == -1) && (errno == EINTR)) {
1833 if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL) {
1834 if (Debug_level > 2) {
1835 printf
1836 ("DEBUG %s/%d: aio_suspend received EINTR, sigev_notify=SIGEV_SIGNAL -- ok\n",
1837 __FILE__, __LINE__);
1838 }
1839 } else {
1840 sprintf(Errormsg,
1841 "%s/%d aio_suspend received EINTR, sigev_notify=%s, not ok\n",
1842 __FILE__, __LINE__,
1843 (aiocbp->aio_sigevent.sigev_notify ==
1844 SIGEV_SIGNAL ? "signal" : aiocbp->
1845 aio_sigevent.sigev_notify ==
1846 SIGEV_NONE ? "none" :
1847#ifdef SIGEV_CALLBACK
1848 aiocbp->aio_sigevent.sigev_notify ==
1849 SIGEV_CALLBACK ? "callback" :
1850#endif
1851 aiocbp->aio_sigevent.sigev_notify ==
1852 SIGEV_THREAD ? "thread" : "unknown"));
1853 return -errno;
1854 }
1855 } else if (ret) {
1856 sprintf(Errormsg,
1857 "%s/%d aio_suspend(fildes=%d, aioary, 1, NULL) failed, errno:%d %s",
1858 __FILE__, __LINE__, fd, errno, strerror(errno));
1859 return -errno;
whrb973f2b2000-05-05 19:34:50 +00001860 }
Wanlong Gao354ebb42012-12-07 10:10:04 +08001861#endif
1862
1863 } else if (method & LIO_WAIT_ACTIVE) {
1864 if (Debug_level > 2)
1865 printf("DEBUG %s/%d: wait method : active\n", __FILE__,
1866 __LINE__);
1867#ifdef CRAY
1868 sigon();
1869 /*
1870 * loop until sw_flag, sw_count or sw_error field elements
1871 * change to non-zero.
1872 */
1873 cnt = 0;
1874 while ((*statptr)->sw_flag == 0 &&
1875 (*statptr)->sw_count == 0 && (*statptr)->sw_error == 0) {
1876 cnt++;
1877 }
1878#else
1879 /* loop while aio_error() returns EINPROGRESS */
1880 cnt = 0;
1881 while (1) {
1882 ret = aio_error(aiocbp);
1883 if ((ret == 0) || (ret != EINPROGRESS)) {
1884 break;
1885 }
1886 ++cnt;
1887 }
whrb973f2b2000-05-05 19:34:50 +00001888
1889#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +08001890 if (Debug_level > 5 && cnt && (cnt % 50) == 0)
1891 printf("DEBUG %s/%d: wait active cnt = %d\n",
1892 __FILE__, __LINE__, cnt);
whrb973f2b2000-05-05 19:34:50 +00001893
Wanlong Gao354ebb42012-12-07 10:10:04 +08001894 } else if (method & LIO_WAIT_SIGPAUSE) {
1895 if (Debug_level > 2)
1896 printf("DEBUG %s/%d: wait method : sigpause\n",
1897 __FILE__, __LINE__);
whrb973f2b2000-05-05 19:34:50 +00001898#ifdef sgi
Wanlong Gao354ebb42012-12-07 10:10:04 +08001899 /* note: don't do the sigon() for CRAY in this case. why? -- roehrich 6/11/97 */
1900 if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL)
1901 sigrelse(aiocbp->aio_sigevent.sigev_signo);
1902 else {
1903 printf("DEBUG %s/%d: sigev_notify != SIGEV_SIGNAL\n",
1904 __FILE__, __LINE__);
1905 return -1;
1906 }
whrb973f2b2000-05-05 19:34:50 +00001907#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +08001908 pause();
whrb973f2b2000-05-05 19:34:50 +00001909
Wanlong Gao354ebb42012-12-07 10:10:04 +08001910 } else if (method & LIO_WAIT_SIGACTIVE) {
1911 if (Debug_level > 2)
1912 printf("DEBUG %s/%d: wait method : sigactive\n",
1913 __FILE__, __LINE__);
whrb973f2b2000-05-05 19:34:50 +00001914#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +08001915 sigon();
whrb973f2b2000-05-05 19:34:50 +00001916#else
Wanlong Gao354ebb42012-12-07 10:10:04 +08001917 if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL)
1918 sigrelse(aiocbp->aio_sigevent.sigev_signo);
1919 else {
1920 printf("DEBUG %s/%d: sigev_notify != SIGEV_SIGNAL\n",
1921 __FILE__, __LINE__);
1922 return -1;
1923 }
whrb973f2b2000-05-05 19:34:50 +00001924#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +08001925 /* loop waiting for signal */
1926 while (Received_signal == Rec_signal) {
whrb973f2b2000-05-05 19:34:50 +00001927#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +08001928 sigon();
whrb973f2b2000-05-05 19:34:50 +00001929#else
Wanlong Gao354ebb42012-12-07 10:10:04 +08001930 sigrelse(aiocbp->aio_sigevent.sigev_signo);
whrb973f2b2000-05-05 19:34:50 +00001931#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +08001932 }
whrb973f2b2000-05-05 19:34:50 +00001933
Wanlong Gao354ebb42012-12-07 10:10:04 +08001934 } else if (method & LIO_WAIT_NONE) {
1935 if (Debug_level > 2)
1936 printf("DEBUG %s/%d: wait method : none\n", __FILE__,
1937 __LINE__);
1938 /* It's broken because the aiocb/iosw is an automatic variable in
1939 * lio_{read,write}_buffer, so when the function returns and the
1940 * I/O completes there will be nowhere to write the I/O status.
1941 * It doesn't cause a problem on unicos--probably because of some
1942 * compiler quirk, or an accident. It causes POSIX async I/O
1943 * to core dump some threads. spr/pv 705909. 6/27/97 roehrich
1944 */
1945 sprintf(Errormsg,
1946 "%s/%d LIO_WAIT_NONE was selected (this is broken)\n",
1947 __FILE__, __LINE__);
whrb973f2b2000-05-05 19:34:50 +00001948#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +08001949 sigon();
whrb973f2b2000-05-05 19:34:50 +00001950#endif
1951/* return 1;*/
Wanlong Gao354ebb42012-12-07 10:10:04 +08001952 return -1;
1953 } else {
1954 if (Debug_level > 2)
1955 printf("DEBUG %s/%d: no wait method was chosen\n",
1956 __FILE__, __LINE__);
1957 return -1;
1958 }
whrb973f2b2000-05-05 19:34:50 +00001959
Wanlong Gao354ebb42012-12-07 10:10:04 +08001960 return 0;
whrb973f2b2000-05-05 19:34:50 +00001961
Wanlong Gao354ebb42012-12-07 10:10:04 +08001962} /* end of lio_wait4asyncio */
whrb973f2b2000-05-05 19:34:50 +00001963
1964#endif /* ifndef linux */
subrata_modak26e07d52009-02-26 06:33:39 +00001965#endif
whrb973f2b2000-05-05 19:34:50 +00001966
1967#if UNIT_TEST
1968/***********************************************************************
1969 * The following code is provided as unit test.
1970 * Just define add "-DUNIT_TEST=1" to the cc line.
vapier45a8ba02009-07-20 10:59:32 +00001971 *
whrb973f2b2000-05-05 19:34:50 +00001972 * (rrl 04/96)
1973 ***********************************************************************/
1974struct unit_info_t {
Wanlong Gao354ebb42012-12-07 10:10:04 +08001975 int method;
1976 int sig;
1977 char *str;
1978} Unit_info[] = {
1979 {
1980 LIO_IO_SYNC, 0, "sync io"}, {
1981 LIO_IO_SYNCV, 0, "sync readv/writev"}, {
1982 LIO_IO_SYNCP, 0, "sync pread/pwrite"}, {
1983 LIO_IO_ASYNC, 0, "async io, def wait"}, {
1984 LIO_IO_SLISTIO, 0, "sync listio"}, {
1985 LIO_IO_ALISTIO, 0, "async listio, def wait"}, {
1986 LIO_IO_ASYNC | LIO_WAIT_ACTIVE, 0, "async active"}, {
1987 LIO_IO_ASYNC | LIO_WAIT_RECALL, 0, "async recall/suspend"}, {
1988 LIO_IO_ASYNC | LIO_WAIT_SIGPAUSE, SIGUSR1, "async sigpause"}, {
1989 LIO_IO_ASYNC | LIO_WAIT_SIGACTIVE, SIGUSR1, "async sigactive"}, {
1990 LIO_IO_ALISTIO | LIO_WAIT_ACTIVE, 0, "async listio active"}, {
1991 LIO_IO_ALISTIO | LIO_WAIT_RECALL, 0, "async listio recall"}, {
1992 LIO_IO_ALISTIO | LIO_WAIT_SIGACTIVE, SIGUSR1, "async listio sigactive"},
1993 {
1994 LIO_IO_ALISTIO | LIO_WAIT_SIGPAUSE, SIGUSR1, "async listio sigpause"},
1995 {
1996 LIO_IO_ASYNC, SIGUSR2, "async io, def wait, sigusr2"}, {
1997LIO_IO_ALISTIO, SIGUSR2, "async listio, def wait, sigusr2"},};
whrb973f2b2000-05-05 19:34:50 +00001998
Wanlong Gao354ebb42012-12-07 10:10:04 +08001999int main(argc, argv)
whrb973f2b2000-05-05 19:34:50 +00002000int argc;
2001char **argv;
2002{
Wanlong Gao354ebb42012-12-07 10:10:04 +08002003 extern char *optarg;
2004 extern int optind;
whrb973f2b2000-05-05 19:34:50 +00002005
Wanlong Gao354ebb42012-12-07 10:10:04 +08002006 int fd;
2007 char *err;
2008 char buffer[4096];
2009 int size = 4096;
2010 int ret;
2011 int ind;
2012 int iter = 3;
2013 int method;
2014 int exit_status = 0;
2015 int c;
2016 int i;
2017 char *symbols = NULL;
2018 int die_on_err = 0;
whrb973f2b2000-05-05 19:34:50 +00002019
Wanlong Gao354ebb42012-12-07 10:10:04 +08002020 while ((c = getopt(argc, argv, "s:di:")) != -1) {
2021 switch (c) {
2022 case 's':
2023 symbols = optarg;
2024 break;
2025 case 'd':
2026 ++die_on_err;
2027 break;
2028 case 'i':
2029 iter = atoi(optarg);
whrb973f2b2000-05-05 19:34:50 +00002030 break;
2031 }
whrb973f2b2000-05-05 19:34:50 +00002032 }
2033
Wanlong Gao354ebb42012-12-07 10:10:04 +08002034 if ((fd =
2035 open("unit_test_file", O_CREAT | O_RDWR | O_TRUNC, 0777)) == -1) {
2036 perror
2037 ("open(unit_test_file, O_CREAT|O_RDWR|O_TRUNC, 0777) failed");
2038 exit(1);
whrb973f2b2000-05-05 19:34:50 +00002039 }
2040
Wanlong Gao354ebb42012-12-07 10:10:04 +08002041 Debug_level = 9;
2042
2043 if (symbols != NULL) {
2044 if ((method = lio_parse_io_arg2(symbols, &err)) == -1) {
2045 printf
2046 ("lio_parse_io_arg2(%s, &err) failed, bad token starting at %s\n",
2047 symbols, err);
2048 if (die_on_err)
2049 exit(1);
2050 } else
2051 printf("lio_parse_io_arg2(%s, &err) returned %#o\n",
2052 symbols, method);
2053
2054 exit_status = 0;
2055 for (ind = 0; ind < iter; ind++) {
2056 memset(buffer, 'A', 4096);
2057 if (lseek(fd, 0, 0) == -1) {
2058 printf("lseek(fd,0,0), %d, failed, errno %d\n",
2059 __LINE__, errno);
2060 ++exit_status;
2061 }
2062 if ((ret = lio_write_buffer(fd, method, buffer,
2063 size, SIGUSR1, &err,
2064 0)) != size) {
2065 printf
2066 ("lio_write_buffer returned -1, err = %s\n",
2067 err);
2068 } else
2069 printf("lio_write_buffer returned %d\n", ret);
2070
2071 memset(buffer, 'B', 4096);
2072 if (lseek(fd, 0, 0) == -1) {
2073 printf("lseek(fd,0,0), %d, failed, errno %d\n",
2074 __LINE__, errno);
2075 ++exit_status;
2076 }
2077 if ((ret = lio_read_buffer(fd, method, buffer,
2078 size, SIGUSR2, &err,
2079 0)) != size) {
2080 printf
2081 ("lio_read_buffer returned -1, err = %s\n",
2082 err);
2083 } else
2084 printf("lio_read_buffer returned %d\n", ret);
2085
2086 for (i = 0; i < 4096; ++i) {
2087 if (buffer[i] != 'A') {
2088 printf(" buffer[%d] = %d\n", i,
2089 buffer[i]);
2090 ++exit_status;
2091 break;
2092 }
2093 }
2094
2095 if (exit_status)
2096 exit(exit_status);
2097
2098 }
2099
2100 unlink("unit_test_file");
2101 exit(0);
whrb973f2b2000-05-05 19:34:50 +00002102 }
2103
Wanlong Gao354ebb42012-12-07 10:10:04 +08002104 for (ind = 0; ind < sizeof(Unit_info) / sizeof(struct unit_info_t);
2105 ind++) {
whrb973f2b2000-05-05 19:34:50 +00002106
Wanlong Gao354ebb42012-12-07 10:10:04 +08002107 printf("\n********* write %s ***************\n",
2108 Unit_info[ind].str);
2109 if (lseek(fd, 0, 0) == -1) {
2110 printf("lseek(fd,0,0), %d, failed, errno %d\n",
2111 __LINE__, errno);
2112 ++exit_status;
2113 }
2114
2115 memset(buffer, 'A', 4096);
2116 if ((ret = lio_write_buffer(fd, Unit_info[ind].method, buffer,
2117 size, Unit_info[ind].sig, &err,
2118 0)) != size) {
2119 printf
2120 (">>>>> lio_write_buffer(fd,0%x,buffer,%d,%d,err,0) returned -1,\n err = %s\n",
2121 Unit_info[ind].method, size, Unit_info[ind].sig,
2122 err);
whrb973f2b2000-05-05 19:34:50 +00002123 ++exit_status;
Garrett Cooper903910d2010-11-23 09:27:44 -08002124 if (die_on_err)
whrb973f2b2000-05-05 19:34:50 +00002125 exit(exit_status);
Wanlong Gao354ebb42012-12-07 10:10:04 +08002126 } else {
2127 printf("lio_write_buffer returned %d\n", ret);
whrb973f2b2000-05-05 19:34:50 +00002128 }
whrb973f2b2000-05-05 19:34:50 +00002129
Wanlong Gao354ebb42012-12-07 10:10:04 +08002130 printf("\n********* read %s ***************\n",
2131 Unit_info[ind].str);
2132 if (lseek(fd, 0, 0) == -1) {
2133 printf("lseek(fd,0,0), %d, failed, errno %d\n",
2134 __LINE__, errno);
2135 ++exit_status;
2136 }
2137 memset(buffer, 'B', 4096);
2138 if ((ret = lio_read_buffer(fd, Unit_info[ind].method, buffer,
2139 size, Unit_info[ind].sig, &err,
2140 0)) != size) {
2141 printf
2142 (">>>>> lio_read_buffer(fd,0%x,buffer,%d,%d,err,0) returned -1,\n err = %s\n",
2143 Unit_info[ind].method, size, Unit_info[ind].sig,
2144 err);
2145 ++exit_status;
2146 if (die_on_err)
2147 exit(exit_status);
2148 } else {
2149 printf("lio_read_buffer returned %d\n", ret);
2150 }
whrb973f2b2000-05-05 19:34:50 +00002151
Wanlong Gao354ebb42012-12-07 10:10:04 +08002152 for (i = 0; i < 4096; ++i) {
2153 if (buffer[i] != 'A') {
2154 printf(" buffer[%d] = %d\n", i, buffer[i]);
2155 ++exit_status;
2156 if (die_on_err)
2157 exit(exit_status);
2158 break;
2159 }
2160 }
whrb973f2b2000-05-05 19:34:50 +00002161
Wanlong Gao354ebb42012-12-07 10:10:04 +08002162 fflush(stdout);
2163 fflush(stderr);
2164 sleep(1);
whrb973f2b2000-05-05 19:34:50 +00002165
Wanlong Gao354ebb42012-12-07 10:10:04 +08002166 }
2167
2168 unlink("unit_test_file");
2169
2170 exit(exit_status);
whrb973f2b2000-05-05 19:34:50 +00002171}
Garrett Cooper9ef7f2d2011-04-08 22:44:06 -07002172#endif