blob: 163ca2b81cd0e027222452ede460c82ef47318da [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 +0000132
133/*
134 * Define the structure as used in lio_parse_arg1 and lio_help1
135 */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800136struct lio_info_type Lio_info1[] = {
137 {"s", LIO_IO_SYNC, "sync i/o"},
138 {"p", LIO_IO_ASYNC | LIO_WAIT_SIGACTIVE,
139 "async i/o using a loop to wait for a signal"},
140 {"b", LIO_IO_ASYNC | LIO_WAIT_SIGPAUSE, "async i/o using pause"},
141 {"a", LIO_IO_ASYNC | LIO_WAIT_RECALL,
142 "async i/o using recall/aio_suspend"},
subrata_modak26e07d52009-02-26 06:33:39 +0000143#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +0800144 {"r",
145 LIO_RANDOM | LIO_IO_TYPES | LIO_WAIT_TYPES,
146 "random sync i/o types and wait methods"},
147 {"R",
148 LIO_RANDOM | LIO_IO_ATYPES | LIO_WAIT_ATYPES,
149 "random i/o types and wait methods"},
whrb973f2b2000-05-05 19:34:50 +0000150#else
Wanlong Gao354ebb42012-12-07 10:10:04 +0800151 {"r",
152 LIO_RANDOM | LIO_IO_TYPES | LIO_WAIT_TYPES,
153 "random i/o types and wait methods"},
154 {"R",
155 LIO_RANDOM | LIO_IO_TYPES | LIO_WAIT_TYPES,
156 "random i/o types and wait methods"},
whrb973f2b2000-05-05 19:34:50 +0000157#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800158 {"l", LIO_IO_SLISTIO | LIO_WAIT_RECALL, "single stride sync listio"},
159 {"L", LIO_IO_ALISTIO | LIO_WAIT_RECALL,
160 "single stride async listio using recall"},
161 {"X", LIO_IO_ALISTIO | LIO_WAIT_SIGPAUSE,
162 "single stride async listio using pause"},
163 {"v", LIO_IO_SYNCV, "single buffer sync readv/writev"},
164 {"P", LIO_IO_SYNCP, "sync pread/pwrite"},
whrb973f2b2000-05-05 19:34:50 +0000165};
166
167/*
168 * Define the structure used by lio_parse_arg2 and lio_help2
169 */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800170struct lio_info_type Lio_info2[] = {
171 {"sync", LIO_IO_SYNC, "sync i/o (read/write)"},
172 {"async", LIO_IO_ASYNC, "async i/o (reada/writea/aio_read/aio_write)"},
173 {"slistio", LIO_IO_SLISTIO, "single stride sync listio"},
174 {"alistio", LIO_IO_ALISTIO, "single stride async listio"},
175 {"syncv", LIO_IO_SYNCV, "single buffer sync readv/writev"},
176 {"syncp", LIO_IO_SYNCP, "pread/pwrite"},
177 {"active", LIO_WAIT_ACTIVE, "spin on status/control values"},
178 {"recall", LIO_WAIT_RECALL,
179 "use recall(2)/aio_suspend(3) to wait for i/o to complete"},
180 {"sigactive", LIO_WAIT_SIGACTIVE, "spin waiting for signal"},
181 {"sigpause", LIO_WAIT_SIGPAUSE, "call pause(2) to wait for signal"},
whrb973f2b2000-05-05 19:34:50 +0000182/* nowait is a touchy thing, it's an accident that this implementation worked at all. 6/27/97 roehrich */
183/* { "nowait", LIO_WAIT_NONE, "do not wait for async io to complete" },*/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800184 {"random", LIO_RANDOM, "set random bit"},
185 {"randomall",
186 LIO_RANDOM | LIO_IO_TYPES | LIO_WAIT_TYPES,
187 "all random i/o types and wait methods (except nowait)"},
whrb973f2b2000-05-05 19:34:50 +0000188};
189
190char Lio_SysCall[PATH_MAX]; /* string containing last i/o system call */
191
192static volatile int Received_signal = 0; /* number of signals received */
193static volatile int Rec_signal;
subrata_modak26e07d52009-02-26 06:33:39 +0000194#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
whrb973f2b2000-05-05 19:34:50 +0000195static volatile int Received_callback = 0; /* number of callbacks received */
196static volatile int Rec_callback;
197#endif
198static char Errormsg[500];
199static int Debug_level = 0;
200
whrb973f2b2000-05-05 19:34:50 +0000201/***********************************************************************
202 * stride_bounds()
203 *
204 * Determine the bounds of a strided request, normalized to offset. Returns
205 * the number of bytes needed to satisfy the request, and optionally sets
vapier45a8ba02009-07-20 10:59:32 +0000206 * *min and *max to the mininum and maximum bytes referenced, normalized
whrb973f2b2000-05-05 19:34:50 +0000207 * around offset.
208 *
209 * Returns -1 on error - the only possible error conditions are illegal values
210 * for nstrides and/or bytes_per_stride - both parameters must be >= 0.
211 *
212 * (maule, 11/16/95)
213 ***********************************************************************/
214
Stanislav Kholmanskikh87aa2dc2014-04-11 11:45:19 +0400215int stride_bounds(int offset, int stride, int nstrides, int bytes_per_stride,
216 int *min, int *max)
whrb973f2b2000-05-05 19:34:50 +0000217{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800218 int nbytes, min_byte, max_byte;
whrb973f2b2000-05-05 19:34:50 +0000219
220 /*
221 * sanity checks ...
222 */
223
224 if (nstrides < 0 || bytes_per_stride < 0) {
225 return -1;
226 }
227
228 if (stride == 0) {
229 stride = bytes_per_stride;
230 }
231
232 /*
233 * Determine the # of bytes needed to satisfy the request. This
234 * value, along with the offset argument, determines the min and max
235 * bytes referenced.
236 */
237
Wanlong Gao354ebb42012-12-07 10:10:04 +0800238 nbytes = abs(stride) * (nstrides - 1) + bytes_per_stride;
whrb973f2b2000-05-05 19:34:50 +0000239
240 if (stride < 0) {
241 max_byte = offset + bytes_per_stride - 1;
242 min_byte = max_byte - nbytes + 1;
243 } else {
244 min_byte = offset;
245 max_byte = min_byte + nbytes - 1;
246 }
vapier45a8ba02009-07-20 10:59:32 +0000247
whrb973f2b2000-05-05 19:34:50 +0000248 if (min != NULL) {
249 *min = min_byte;
250 }
vapier45a8ba02009-07-20 10:59:32 +0000251
whrb973f2b2000-05-05 19:34:50 +0000252 if (max != NULL) {
253 *max = max_byte;
254 }
255
256 return nbytes;
257}
258
259/***********************************************************************
260 * This function will allow someone to set the debug level.
261 ***********************************************************************/
Stanislav Kholmanskikh87aa2dc2014-04-11 11:45:19 +0400262int lio_set_debug(int level)
whrb973f2b2000-05-05 19:34:50 +0000263{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800264 int old;
whrb973f2b2000-05-05 19:34:50 +0000265
Wanlong Gao354ebb42012-12-07 10:10:04 +0800266 old = Debug_level;
267 Debug_level = level;
268 return old;
whrb973f2b2000-05-05 19:34:50 +0000269}
270
271/***********************************************************************
272 * This function will parse a string and return desired io-method.
273 * Only the first character of the string is used.
274 *
275 * This function does not provide for meaningful option arguments,
276 * but it supports current growfiles/btlk interface.
277 *
278 * (rrl 04/96)
279 ***********************************************************************/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800280int lio_parse_io_arg1(char *string)
whrb973f2b2000-05-05 19:34:50 +0000281{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800282 unsigned int ind;
283 int found = 0;
284 int mask = 0;
whrb973f2b2000-05-05 19:34:50 +0000285
Wanlong Gao354ebb42012-12-07 10:10:04 +0800286 /*
287 * Determine if token is a valid string.
288 */
289 for (ind = 0; ind < sizeof(Lio_info1) / sizeof(struct lio_info_type);
290 ind++) {
291 if (strcmp(string, Lio_info1[ind].token) == 0) {
292 mask |= Lio_info1[ind].bits;
293 found = 1;
294 break;
295 }
296 }
whrb973f2b2000-05-05 19:34:50 +0000297
Wanlong Gao354ebb42012-12-07 10:10:04 +0800298 if (found == 0) {
299 return -1;
300 }
whrb973f2b2000-05-05 19:34:50 +0000301
Wanlong Gao354ebb42012-12-07 10:10:04 +0800302 return mask;
whrb973f2b2000-05-05 19:34:50 +0000303
304}
305
306/***********************************************************************
307 * This function will print a help message describing the characters
308 * that can be parsed by lio_parse_io_arg1().
309 * They will be printed one per line.
310 * (rrl 04/96)
311 ***********************************************************************/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800312void lio_help1(char *prefix)
whrb973f2b2000-05-05 19:34:50 +0000313{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800314 unsigned int ind;
whrb973f2b2000-05-05 19:34:50 +0000315
Wanlong Gao354ebb42012-12-07 10:10:04 +0800316 for (ind = 0; ind < sizeof(Lio_info1) / sizeof(struct lio_info_type);
317 ind++) {
318 printf("%s %s : %s\n", prefix, Lio_info1[ind].token,
319 Lio_info1[ind].desc);
320 }
whrb973f2b2000-05-05 19:34:50 +0000321
Wanlong Gao354ebb42012-12-07 10:10:04 +0800322 return;
whrb973f2b2000-05-05 19:34:50 +0000323}
324
325/***********************************************************************
326 * This function will parse a string and return the desired io-method.
327 * This function will take a comma separated list of io type and wait
328 * method tokens as defined in Lio_info2[]. If a token does not match
329 * any of the tokens in Lio_info2[], it will be coverted to a number.
330 * If it was a number, those bits are also set.
vapier45a8ba02009-07-20 10:59:32 +0000331 *
whrb973f2b2000-05-05 19:34:50 +0000332 * (rrl 04/96)
333 ***********************************************************************/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800334int lio_parse_io_arg2(char *string, char **badtoken)
whrb973f2b2000-05-05 19:34:50 +0000335{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800336 char *token = string;
337 char *cc = token;
338 char savecc;
339 int found;
340 int mask = 0;
whrb973f2b2000-05-05 19:34:50 +0000341
Wanlong Gao354ebb42012-12-07 10:10:04 +0800342 int tmp;
343 unsigned int ind;
344 char chr;
whrb973f2b2000-05-05 19:34:50 +0000345
Wanlong Gao354ebb42012-12-07 10:10:04 +0800346 if (token == NULL)
347 return -1;
whrb973f2b2000-05-05 19:34:50 +0000348
Wanlong Gao354ebb42012-12-07 10:10:04 +0800349 for (;;) {
350 for (; ((*cc != ',') && (*cc != '\0')); cc++) ;
351 savecc = *cc;
352 *cc = '\0';
whrb973f2b2000-05-05 19:34:50 +0000353
Wanlong Gao354ebb42012-12-07 10:10:04 +0800354 found = 0;
whrb973f2b2000-05-05 19:34:50 +0000355
Wanlong Gao354ebb42012-12-07 10:10:04 +0800356 /*
357 * Determine if token is a valid string or number and if
358 * so, add the bits to the mask.
359 */
360 for (ind = 0;
361 ind < sizeof(Lio_info2) / sizeof(struct lio_info_type);
362 ind++) {
363 if (strcmp(token, Lio_info2[ind].token) == 0) {
364 mask |= Lio_info2[ind].bits;
365 found = 1;
366 break;
367 }
368 }
whrb973f2b2000-05-05 19:34:50 +0000369
Wanlong Gao354ebb42012-12-07 10:10:04 +0800370 /*
371 * If token does not match one of the defined tokens, determine
372 * if it is a number, if so, add the bits.
373 */
374 if (!found) {
375 if (sscanf(token, "%i%c", &tmp, &chr) == 1) {
376 mask |= tmp;
377 found = 1;
378 }
379 }
whrb973f2b2000-05-05 19:34:50 +0000380
Wanlong Gao354ebb42012-12-07 10:10:04 +0800381 *cc = savecc;
whrb973f2b2000-05-05 19:34:50 +0000382
Wanlong Gao354ebb42012-12-07 10:10:04 +0800383 if (!found) { /* token is not valid */
384 if (badtoken != NULL)
385 *badtoken = token;
386 return (-1);
387 }
whrb973f2b2000-05-05 19:34:50 +0000388
Wanlong Gao354ebb42012-12-07 10:10:04 +0800389 if (savecc == '\0')
390 break;
whrb973f2b2000-05-05 19:34:50 +0000391
Wanlong Gao354ebb42012-12-07 10:10:04 +0800392 token = ++cc;
393 }
whrb973f2b2000-05-05 19:34:50 +0000394
Wanlong Gao354ebb42012-12-07 10:10:04 +0800395 return mask;
whrb973f2b2000-05-05 19:34:50 +0000396}
397
398/***********************************************************************
399 * This function will print a help message describing the tokens
400 * that can be parsed by lio_parse_io_arg2().
401 * It will print them one per line.
402 *
403 * (rrl 04/96)
404 ***********************************************************************/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800405void lio_help2(char *prefix)
whrb973f2b2000-05-05 19:34:50 +0000406{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800407 unsigned int ind;
whrb973f2b2000-05-05 19:34:50 +0000408
Wanlong Gao354ebb42012-12-07 10:10:04 +0800409 for (ind = 0; ind < sizeof(Lio_info2) / sizeof(struct lio_info_type);
410 ind++) {
411 printf("%s %s : %s\n", prefix, Lio_info2[ind].token,
412 Lio_info2[ind].desc);
413 }
414 return;
whrb973f2b2000-05-05 19:34:50 +0000415}
416
whrb973f2b2000-05-05 19:34:50 +0000417/***********************************************************************
418 * This is an internal signal handler.
419 * If the handler is called, it will increment the Received_signal
420 * global variable.
421 ***********************************************************************/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800422static void lio_async_signal_handler(int sig)
whrb973f2b2000-05-05 19:34:50 +0000423{
Garrett Cooper903910d2010-11-23 09:27:44 -0800424 if (Debug_level)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800425 printf
426 ("DEBUG %s/%d: received signal %d, a signal caught %d times\n",
427 __FILE__, __LINE__, sig, Received_signal + 1);
whrb973f2b2000-05-05 19:34:50 +0000428
429 Received_signal++;
430
431 return;
432}
whrb973f2b2000-05-05 19:34:50 +0000433
subrata_modak26e07d52009-02-26 06:33:39 +0000434#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
whrb973f2b2000-05-05 19:34:50 +0000435/***********************************************************************
436 * This is an internal callback handler.
437 * If the handler is called, it will increment the Received_callback
438 * global variable.
439 ***********************************************************************/
Khem Raj989bc412016-01-07 12:25:16 +0000440static void lio_async_callback_handler(union sigval sigval)
whrb973f2b2000-05-05 19:34:50 +0000441{
Garrett Cooper903910d2010-11-23 09:27:44 -0800442 if (Debug_level)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800443 printf
444 ("DEBUG %s/%d: received callback, nbytes=%ld, a callback called %d times\n",
445 __FILE__, __LINE__, (long)sigval.sival_int,
446 Received_callback + 1);
whrb973f2b2000-05-05 19:34:50 +0000447
448 Received_callback++;
449
450 return;
451}
452#endif /* sgi */
453
454/***********************************************************************
455 * lio_random_methods
456 * This function will randomly choose an io type and wait method
457 * from set of io types and wait methods. Since this information
458 * is stored in a bitmask, it randomly chooses an io type from
459 * the io type bits specified and does the same for wait methods.
460 *
461 * Return Value
462 * This function will return a value with all non choosen io type
vapier45a8ba02009-07-20 10:59:32 +0000463 * and wait method bits cleared. The LIO_RANDOM bit is also
whrb973f2b2000-05-05 19:34:50 +0000464 * cleared. All other bits are left unchanged.
465 *
466 * (rrl 04/96)
467 ***********************************************************************/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800468int lio_random_methods(long curr_mask)
whrb973f2b2000-05-05 19:34:50 +0000469{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800470 int mask = 0;
whrb973f2b2000-05-05 19:34:50 +0000471
Wanlong Gao354ebb42012-12-07 10:10:04 +0800472 /* remove random select, io type, and wait method bits from curr_mask */
473 mask = curr_mask & (~(LIO_IO_TYPES | LIO_WAIT_TYPES | LIO_RANDOM));
whrb973f2b2000-05-05 19:34:50 +0000474
Wanlong Gao354ebb42012-12-07 10:10:04 +0800475 /* randomly select io type from specified io types */
476 mask = mask | random_bit(curr_mask & LIO_IO_TYPES);
whrb973f2b2000-05-05 19:34:50 +0000477
Wanlong Gao354ebb42012-12-07 10:10:04 +0800478 /* randomly select wait methods from specified wait methods */
479 mask = mask | random_bit(curr_mask & LIO_WAIT_TYPES);
whrb973f2b2000-05-05 19:34:50 +0000480
Wanlong Gao354ebb42012-12-07 10:10:04 +0800481 return mask;
whrb973f2b2000-05-05 19:34:50 +0000482}
483
subrata_modakea37be82008-12-11 13:17:49 +0000484static void wait4sync_io(int fd, int read)
485{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800486 fd_set s;
487 FD_ZERO(&s);
488 FD_SET(fd, &s);
subrata_modakea37be82008-12-11 13:17:49 +0000489
Wanlong Gao354ebb42012-12-07 10:10:04 +0800490 select(fd + 1, read ? &s : NULL, read ? NULL : &s, NULL, NULL);
subrata_modakea37be82008-12-11 13:17:49 +0000491}
492
whrb973f2b2000-05-05 19:34:50 +0000493/***********************************************************************
vapier45a8ba02009-07-20 10:59:32 +0000494 * Generic write function
whrb973f2b2000-05-05 19:34:50 +0000495 * This function can be used to do a write using write(2), writea(2),
496 * aio_write(3), writev(2), pwrite(2),
497 * or single stride listio(2)/lio_listio(3).
498 * By setting the desired bits in the method
499 * bitmask, the caller can control the type of write and the wait method
500 * that will be used. If no io type bits are set, write will be used.
501 *
502 * If async io was attempted and no wait method bits are set then the
503 * wait method is: recall(2) for writea(2) and listio(2); aio_suspend(3) for
504 * aio_write(3) and lio_listio(3).
505 *
vapier45a8ba02009-07-20 10:59:32 +0000506 * If multiple wait methods are specified,
whrb973f2b2000-05-05 19:34:50 +0000507 * only one wait method will be used. The order is predetermined.
508 *
509 * If the call specifies a signal and one of the two signal wait methods,
510 * a signal handler for the signal is set. This will reset an already
vapier45a8ba02009-07-20 10:59:32 +0000511 * set handler for this signal.
whrb973f2b2000-05-05 19:34:50 +0000512 *
513 * If the LIO_RANDOM method bit is set, this function will randomly
514 * choose a io type and wait method from bits in the method argument.
515 *
516 * If an error is encountered, an error message will be generated
517 * in a internal static buffer. If errmsg is not NULL, it will
518 * be updated to point to the static buffer, allowing the caller
519 * to print the error message.
520 *
521 * Return Value
522 * If a system call fails, -errno is returned.
523 * If LIO_WAIT_NONE bit is set, the return value is the return value
524 * of the system call.
525 * If the io did not fail, the amount of data written is returned.
526 * If the size the system call say was written is different
527 * then what was asked to be written, errmsg is updated for
528 * this error condition. The return value is still the amount
vapier45a8ba02009-07-20 10:59:32 +0000529 * the system call says was written.
whrb973f2b2000-05-05 19:34:50 +0000530 *
531 * (rrl 04/96)
532 ***********************************************************************/
Stanislav Kholmanskikh87aa2dc2014-04-11 11:45:19 +0400533int lio_write_buffer(int fd, /* open file descriptor */
534 int method, /* contains io type and wait method bitmask */
535 char *buffer, /* pointer to buffer */
536 int size, /* the size of the io */
537 int sig, /* signal to use if async io */
538 char **errmsg, /* char pointer that will be updated to point to err message */
539 long wrd) /* to allow future features, use zero for now */
whrb973f2b2000-05-05 19:34:50 +0000540{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800541 int ret = 0; /* syscall return or used to get random method */
542 char *io_type; /* Holds string of type of io */
543 int omethod = method;
544 int listio_cmd; /* Holds the listio/lio_listio cmd */
whrb973f2b2000-05-05 19:34:50 +0000545#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +0800546 struct listreq request; /* Used when a listio is wanted */
547 struct iosw status, *statptr[1];
whrb973f2b2000-05-05 19:34:50 +0000548#else
Wanlong Gao354ebb42012-12-07 10:10:04 +0800549 /* for linux or sgi */
550 struct iovec iov; /* iovec for writev(2) */
whrb973f2b2000-05-05 19:34:50 +0000551#endif
subrata_modakea37be82008-12-11 13:17:49 +0000552#if defined (sgi)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800553 aiocb_t aiocbp; /* POSIX aio control block */
554 aiocb_t *aiolist[1]; /* list of aio control blocks for lio_listio */
555 off64_t poffset; /* pwrite(2) offset */
whrb973f2b2000-05-05 19:34:50 +0000556#endif
subrata_modak26e07d52009-02-26 06:33:39 +0000557#if defined(__linux__) && !defined(__UCLIBC__)
subrata_modakea37be82008-12-11 13:17:49 +0000558 struct aiocb aiocbp; /* POSIX aio control block */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800559 struct aiocb *aiolist[1]; /* list of aio control blocks for lio_listio */
subrata_modakea37be82008-12-11 13:17:49 +0000560 off64_t poffset; /* pwrite(2) offset */
561#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800562 /*
563 * If LIO_RANDOM bit specified, get new method randomly.
564 */
565 if (method & LIO_RANDOM) {
566 if (Debug_level > 3)
567 printf("DEBUG %s/%d: method mask to choose from: %#o\n",
568 __FILE__, __LINE__, method);
569 method = lio_random_methods(method);
570 if (Debug_level > 2)
571 printf("DEBUG %s/%d: random chosen method %#o\n",
572 __FILE__, __LINE__, method);
573 }
whrb973f2b2000-05-05 19:34:50 +0000574
Wanlong Gao354ebb42012-12-07 10:10:04 +0800575 if (errmsg != NULL)
576 *errmsg = Errormsg;
whrb973f2b2000-05-05 19:34:50 +0000577
Wanlong Gao354ebb42012-12-07 10:10:04 +0800578 Rec_signal = Received_signal; /* get the current number of signals received */
subrata_modak26e07d52009-02-26 06:33:39 +0000579#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +0800580 Rec_callback = Received_callback; /* get the current number of callbacks received */
whrb973f2b2000-05-05 19:34:50 +0000581#endif
582
583#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +0800584 memset(&status, 0x00, sizeof(struct iosw));
585 memset(&request, 0x00, sizeof(struct listreq));
586 statptr[0] = &status;
whrb973f2b2000-05-05 19:34:50 +0000587#else
Wanlong Gao354ebb42012-12-07 10:10:04 +0800588 /* for linux or sgi */
589 memset(&iov, 0x00, sizeof(struct iovec));
590 iov.iov_base = buffer;
591 iov.iov_len = size;
whrb973f2b2000-05-05 19:34:50 +0000592#endif
subrata_modak26e07d52009-02-26 06:33:39 +0000593#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
subrata_modakea37be82008-12-11 13:17:49 +0000594#if defined(sgi)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800595 memset(&aiocbp, 0x00, sizeof(aiocb_t));
subrata_modakea37be82008-12-11 13:17:49 +0000596#else
597 memset(&aiocbp, 0x00, sizeof(struct aiocb));
598#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800599 aiocbp.aio_fildes = fd;
600 aiocbp.aio_nbytes = size;
601 aiocbp.aio_buf = buffer;
whrb973f2b2000-05-05 19:34:50 +0000602/* aiocbp.aio_offset = lseek( fd, 0, SEEK_CUR ); -- set below */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800603 aiocbp.aio_sigevent.sigev_notify = SIGEV_NONE;
604 aiocbp.aio_sigevent.sigev_signo = 0;
subrata_modakea37be82008-12-11 13:17:49 +0000605#ifdef sgi
Wanlong Gao354ebb42012-12-07 10:10:04 +0800606 aiocbp.aio_sigevent.sigev_func = NULL;
607 aiocbp.aio_sigevent.sigev_value.sival_int = 0;
subrata_modak26e07d52009-02-26 06:33:39 +0000608#elif defined(__linux__) && !defined(__UCLIBC__)
subrata_modakea37be82008-12-11 13:17:49 +0000609 aiocbp.aio_sigevent.sigev_notify_function = NULL;
610 aiocbp.aio_sigevent.sigev_notify_attributes = 0;
611#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800612 aiolist[0] = &aiocbp;
whrb973f2b2000-05-05 19:34:50 +0000613
Wanlong Gao354ebb42012-12-07 10:10:04 +0800614 if ((ret = lseek(fd, 0, SEEK_CUR)) == -1) {
615 ret = 0;
616 /* If there is an error and it is not ESPIPE then kick out the error.
617 * If the fd is a fifo then we have to make sure that
618 * lio_random_methods() didn't select pwrite/pread; if it did then
619 * switch to write/read.
620 */
621 if (errno == ESPIPE) {
622 if (method & LIO_IO_SYNCP) {
623 if (omethod & LIO_RANDOM) {
624 method &= ~LIO_IO_SYNCP;
625 method |= LIO_IO_SYNC;
626 if (Debug_level > 2)
627 printf
628 ("DEBUG %s/%d: random chosen method switched to %#o for fifo\n",
629 __FILE__, __LINE__,
630 method);
631 } else if (Debug_level) {
632 printf
633 ("DEBUG %s/%d: pwrite will fail when it writes to a fifo\n",
634 __FILE__, __LINE__);
635 }
whrb973f2b2000-05-05 19:34:50 +0000636 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800637 /* else: let it ride */
638 } else {
639 sprintf(Errormsg,
640 "%s/%d lseek(fd=%d,0,SEEK_CUR) failed, errno=%d %s",
641 __FILE__, __LINE__, fd, errno, strerror(errno));
642 return -errno;
whrb973f2b2000-05-05 19:34:50 +0000643 }
whrb973f2b2000-05-05 19:34:50 +0000644 }
subrata_modak26e07d52009-02-26 06:33:39 +0000645#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +0800646 poffset = (off64_t) ret;
subrata_modakea37be82008-12-11 13:17:49 +0000647#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800648 aiocbp.aio_offset = ret;
whrb973f2b2000-05-05 19:34:50 +0000649
650#endif
651
Wanlong Gao354ebb42012-12-07 10:10:04 +0800652 /*
653 * If the LIO_USE_SIGNAL bit is not set, only use the signal
654 * if the LIO_WAIT_SIGPAUSE or the LIO_WAIT_SIGACTIVE bits are bit.
655 * Otherwise there is not necessary a signal handler to trap
656 * the signal.
whrb973f2b2000-05-05 19:34:50 +0000657 */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800658 if (sig && !(method & LIO_USE_SIGNAL) && !(method & LIO_WAIT_SIGTYPES)) {
659
660 sig = 0; /* ignore signal parameter */
661 }
662#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
663 if (sig && (method & LIO_WAIT_CBTYPES))
664 sig = 0; /* ignore signal parameter */
665#endif
666
667 /*
668 * only setup signal hander if sig was specified and
669 * a sig wait method was specified.
670 * Doing this will change the handler for this signal. The
671 * old signal handler will not be restored.
672 *** restoring the signal handler could be added ***
673 */
674
675 if (sig && (method & LIO_WAIT_SIGTYPES)) {
676#ifdef CRAY
677 sigctl(SCTL_REG, sig, lio_async_signal_handler);
678#endif
679#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
680 aiocbp.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
681 aiocbp.aio_sigevent.sigev_signo = sig;
682 sigset(sig, lio_async_signal_handler);
683#endif /* sgi */
684 }
685#if defined(sgi)
686 else if (method & LIO_WAIT_CBTYPES) {
687 /* sival_int just has to be something that I can use
688 * to identify the callback, and "size" happens to be handy...
689 */
690 aiocbp.aio_sigevent.sigev_notify = SIGEV_CALLBACK;
691 aiocbp.aio_sigevent.sigev_func = lio_async_callback_handler;
692 aiocbp.aio_sigevent.sigev_value.sival_int = size;
693 }
whrb973f2b2000-05-05 19:34:50 +0000694#endif
subrata_modak26e07d52009-02-26 06:33:39 +0000695#if defined(__linux__) && !defined(__UCLIBC__)
Garrett Cooper903910d2010-11-23 09:27:44 -0800696 else if (method & LIO_WAIT_CBTYPES) {
subrata_modakea37be82008-12-11 13:17:49 +0000697 /* sival_int just has to be something that I can use
698 * to identify the callback, and "size" happens to be handy...
699 */
700 aiocbp.aio_sigevent.sigev_notify = SIGEV_THREAD;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800701 aiocbp.aio_sigevent.sigev_notify_function =
702 lio_async_callback_handler;
703 aiocbp.aio_sigevent.sigev_notify_attributes =
704 (void *)(uintptr_t) size;
subrata_modakea37be82008-12-11 13:17:49 +0000705 }
706#endif
whrb973f2b2000-05-05 19:34:50 +0000707 /*
Wanlong Gao354ebb42012-12-07 10:10:04 +0800708 * Determine the system call that will be called and produce
709 * the string of the system call and place it in Lio_SysCall.
710 * Also update the io_type char pointer to give brief description
711 * of system call. Execute the system call and check for
712 * system call failure. If sync i/o, return the number of
713 * bytes written/read.
714 */
whrb973f2b2000-05-05 19:34:50 +0000715
Wanlong Gao354ebb42012-12-07 10:10:04 +0800716 if ((method & LIO_IO_SYNC)
717 || (method & (LIO_IO_TYPES | LIO_IO_ATYPES)) == 0) {
718 /*
719 * write(2) is used if LIO_IO_SYNC bit is set or not none
720 * of the LIO_IO_TYPES bits are set (default).
721 */
whrb973f2b2000-05-05 19:34:50 +0000722
Wanlong Gao354ebb42012-12-07 10:10:04 +0800723 sprintf(Lio_SysCall, "write(%d, buf, %d)", fd, size);
724 io_type = "write";
whrb973f2b2000-05-05 19:34:50 +0000725
Wanlong Gao354ebb42012-12-07 10:10:04 +0800726 if (Debug_level) {
727 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
728 Lio_SysCall);
729 }
730 while (1) {
731 if (((ret = write(fd, buffer, size)) == -1)
732 && errno != EAGAIN && errno != EINTR) {
733 sprintf(Errormsg,
734 "%s/%d write(%d, buf, %d) ret:-1, errno=%d %s",
735 __FILE__, __LINE__, fd, size, errno,
736 strerror(errno));
737 return -errno;
738 }
whrb973f2b2000-05-05 19:34:50 +0000739
Wanlong Gao354ebb42012-12-07 10:10:04 +0800740 if (ret != -1) {
741 if (ret != size) {
742 sprintf(Errormsg,
743 "%s/%d write(%d, buf, %d) returned=%d",
744 __FILE__, __LINE__,
745 fd, size, ret);
746 size -= ret;
747 buffer += ret;
748 } else {
749 if (Debug_level > 1)
750 printf
751 ("DEBUG %s/%d: write completed without error (ret %d)\n",
752 __FILE__, __LINE__, ret);
whrb973f2b2000-05-05 19:34:50 +0000753
Wanlong Gao354ebb42012-12-07 10:10:04 +0800754 return ret;
755 }
756 }
757 wait4sync_io(fd, 0);
758 }
whrb973f2b2000-05-05 19:34:50 +0000759
whrb973f2b2000-05-05 19:34:50 +0000760 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800761
762 else if (method & LIO_IO_ASYNC) {
763#ifdef CRAY
764 sprintf(Lio_SysCall,
765 "writea(%d, buf, %d, &status, %d)", fd, size, sig);
766 io_type = "writea";
767
768 if (Debug_level) {
769 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
770 Lio_SysCall);
771 }
772
773 sigoff();
774 if ((ret = writea(fd, buffer, size, &status, sig)) == -1) {
775 sprintf(Errormsg,
776 "%s/%d writea(%d, buf, %d, &stat, %d) ret:-1, errno=%d %s",
777 __FILE__, __LINE__,
778 fd, size, sig, errno, strerror(errno));
779 sigon();
780 return -errno;
781 }
whrb973f2b2000-05-05 19:34:50 +0000782#endif
subrata_modak26e07d52009-02-26 06:33:39 +0000783#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +0800784 sprintf(Lio_SysCall,
785 "aio_write(fildes=%d, buf, nbytes=%d, signo=%d)", fd,
786 size, sig);
787 io_type = "aio_write";
whrb973f2b2000-05-05 19:34:50 +0000788
Wanlong Gao354ebb42012-12-07 10:10:04 +0800789 if (Debug_level) {
790 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
791 Lio_SysCall);
792 }
whrb973f2b2000-05-05 19:34:50 +0000793
Wanlong Gao354ebb42012-12-07 10:10:04 +0800794 if (sig)
795 sighold(sig);
796 if ((ret = aio_write(&aiocbp)) == -1) {
797 sprintf(Errormsg,
798 "%s/%d aio_write(fildes=%d, buf, nbytes=%d, signo=%d) ret:-1, errno=%d %s",
799 __FILE__, __LINE__,
800 fd, size, sig, errno, strerror(errno));
801 if (sig)
802 sigrelse(sig);
803 return -errno;
804 }
whrb973f2b2000-05-05 19:34:50 +0000805#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800806 }
807 /* LIO_IO_ASYNC */
808 else if (method & LIO_IO_SLISTIO) {
whrb973f2b2000-05-05 19:34:50 +0000809#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +0800810 request.li_opcode = LO_WRITE;
811 request.li_fildes = fd;
812 request.li_buf = buffer;
813 request.li_nbyte = size;
814 request.li_status = &status;
815 request.li_signo = sig;
816 request.li_nstride = 0;
817 request.li_filstride = 0;
818 request.li_memstride = 0;
whrb973f2b2000-05-05 19:34:50 +0000819
Wanlong Gao354ebb42012-12-07 10:10:04 +0800820 listio_cmd = LC_WAIT;
821 io_type = "listio(2) sync write";
whrb973f2b2000-05-05 19:34:50 +0000822
Wanlong Gao354ebb42012-12-07 10:10:04 +0800823 sprintf(Lio_SysCall,
824 "listio(LC_WAIT, &req, 1) LO_WRITE, fd:%d, nbyte:%d",
825 fd, size);
whrb973f2b2000-05-05 19:34:50 +0000826
Wanlong Gao354ebb42012-12-07 10:10:04 +0800827 if (Debug_level) {
828 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
829 Lio_SysCall);
830 }
whrb973f2b2000-05-05 19:34:50 +0000831
Wanlong Gao354ebb42012-12-07 10:10:04 +0800832 sigoff();
833 if (listio(listio_cmd, &request, 1) == -1) {
834 sprintf(Errormsg,
835 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
836 __FILE__, __LINE__, Lio_SysCall, fd, size,
837 errno, strerror(errno));
838 sigon();
839 return -errno;
840 }
whrb973f2b2000-05-05 19:34:50 +0000841
Wanlong Gao354ebb42012-12-07 10:10:04 +0800842 if (Debug_level > 1)
843 printf("DEBUG %s/%d: %s did not return -1\n",
844 __FILE__, __LINE__, Lio_SysCall);
whrb973f2b2000-05-05 19:34:50 +0000845
Wanlong Gao354ebb42012-12-07 10:10:04 +0800846 ret = lio_check_asyncio(io_type, size, &status);
847 return ret;
whrb973f2b2000-05-05 19:34:50 +0000848
849#endif
subrata_modak26e07d52009-02-26 06:33:39 +0000850#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
whrb973f2b2000-05-05 19:34:50 +0000851
Wanlong Gao354ebb42012-12-07 10:10:04 +0800852 aiocbp.aio_lio_opcode = LIO_WRITE;
853 listio_cmd = LIO_WAIT;
854 io_type = "lio_listio(3) sync write";
whrb973f2b2000-05-05 19:34:50 +0000855
Wanlong Gao354ebb42012-12-07 10:10:04 +0800856 sprintf(Lio_SysCall,
857 "lio_listio(LIO_WAIT, aiolist, 1, NULL) LIO_WRITE, fd:%d, nbyte:%d, sig:%d",
858 fd, size, sig);
whrb973f2b2000-05-05 19:34:50 +0000859
Wanlong Gao354ebb42012-12-07 10:10:04 +0800860 if (Debug_level) {
861 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
862 Lio_SysCall);
863 }
whrb973f2b2000-05-05 19:34:50 +0000864
Wanlong Gao354ebb42012-12-07 10:10:04 +0800865 if (sig)
866 sighold(sig);
867 if (lio_listio(listio_cmd, aiolist, 1, NULL) == -1) {
868 sprintf(Errormsg,
869 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
870 __FILE__, __LINE__, Lio_SysCall, fd, size,
871 errno, strerror(errno));
872 if (sig)
873 sigrelse(sig);
874 return -errno;
875 }
whrb973f2b2000-05-05 19:34:50 +0000876
Wanlong Gao354ebb42012-12-07 10:10:04 +0800877 if (Debug_level > 1)
878 printf("DEBUG %s/%d: %s did not return -1\n",
879 __FILE__, __LINE__, Lio_SysCall);
whrb973f2b2000-05-05 19:34:50 +0000880
Wanlong Gao354ebb42012-12-07 10:10:04 +0800881 ret = lio_check_asyncio(io_type, size, &aiocbp, method);
882 return ret;
whrb973f2b2000-05-05 19:34:50 +0000883#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800884 }
885 /* LIO_IO_SLISTIO */
886 else if (method & LIO_IO_ALISTIO) {
whrb973f2b2000-05-05 19:34:50 +0000887#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +0800888 request.li_opcode = LO_WRITE;
889 request.li_fildes = fd;
890 request.li_buf = buffer;
891 request.li_nbyte = size;
892 request.li_status = &status;
893 request.li_signo = sig;
894 request.li_nstride = 0;
895 request.li_filstride = 0;
896 request.li_memstride = 0;
whrb973f2b2000-05-05 19:34:50 +0000897
Wanlong Gao354ebb42012-12-07 10:10:04 +0800898 listio_cmd = LC_START;
899 io_type = "listio(2) async write";
whrb973f2b2000-05-05 19:34:50 +0000900
Wanlong Gao354ebb42012-12-07 10:10:04 +0800901 sprintf(Lio_SysCall,
902 "listio(LC_START, &req, 1) LO_WRITE, fd:%d, nbyte:%d",
903 fd, size);
whrb973f2b2000-05-05 19:34:50 +0000904
Wanlong Gao354ebb42012-12-07 10:10:04 +0800905 if (Debug_level) {
906 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
907 Lio_SysCall);
908 }
whrb973f2b2000-05-05 19:34:50 +0000909
Wanlong Gao354ebb42012-12-07 10:10:04 +0800910 sigoff();
911 if (listio(listio_cmd, &request, 1) == -1) {
912 sprintf(Errormsg,
913 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
914 __FILE__, __LINE__, Lio_SysCall, fd, size,
915 errno, strerror(errno));
916 sigon();
917 return -errno;
918 }
whrb973f2b2000-05-05 19:34:50 +0000919#endif
subrata_modak26e07d52009-02-26 06:33:39 +0000920#if defined (sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +0800921 aiocbp.aio_lio_opcode = LIO_WRITE;
922 listio_cmd = LIO_NOWAIT;
923 io_type = "lio_listio(3) async write";
whrb973f2b2000-05-05 19:34:50 +0000924
Wanlong Gao354ebb42012-12-07 10:10:04 +0800925 sprintf(Lio_SysCall,
926 "lio_listio(LIO_NOWAIT, aiolist, 1, NULL) LIO_WRITE, fd:%d, nbyte:%d",
927 fd, size);
whrb973f2b2000-05-05 19:34:50 +0000928
Wanlong Gao354ebb42012-12-07 10:10:04 +0800929 if (Debug_level) {
930 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
931 Lio_SysCall);
932 }
whrb973f2b2000-05-05 19:34:50 +0000933
Wanlong Gao354ebb42012-12-07 10:10:04 +0800934 if (sig)
935 sighold(sig);
936 if (lio_listio(listio_cmd, aiolist, 1, NULL) == -1) {
937 sprintf(Errormsg,
938 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
939 __FILE__, __LINE__, Lio_SysCall, fd, size,
940 errno, strerror(errno));
941 if (sig)
942 sigrelse(sig);
943 return -errno;
944 }
whrb973f2b2000-05-05 19:34:50 +0000945#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800946 }
947 /* LIO_IO_ALISTIO */
whrb973f2b2000-05-05 19:34:50 +0000948#ifndef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +0800949 else if (method & LIO_IO_SYNCV) {
950 io_type = "writev(2)";
whrb973f2b2000-05-05 19:34:50 +0000951
Wanlong Gao354ebb42012-12-07 10:10:04 +0800952 sprintf(Lio_SysCall, "writev(%d, &iov, 1) nbyte:%d", fd, size);
whrb973f2b2000-05-05 19:34:50 +0000953
Wanlong Gao354ebb42012-12-07 10:10:04 +0800954 if (Debug_level) {
955 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
956 Lio_SysCall);
957 }
958 if ((ret = writev(fd, &iov, 1)) == -1) {
959 sprintf(Errormsg,
960 "%s/%d writev(%d, iov, 1) nbyte:%d ret:-1, errno=%d %s",
961 __FILE__, __LINE__, fd, size, errno,
962 strerror(errno));
963 return -errno;
964 }
whrb973f2b2000-05-05 19:34:50 +0000965
Wanlong Gao354ebb42012-12-07 10:10:04 +0800966 if (ret != size) {
967 sprintf(Errormsg,
968 "%s/%d writev(%d, iov, 1) nbyte:%d returned=%d",
969 __FILE__, __LINE__, fd, size, ret);
970 } else if (Debug_level > 1)
971 printf
972 ("DEBUG %s/%d: writev completed without error (ret %d)\n",
973 __FILE__, __LINE__, ret);
whrb973f2b2000-05-05 19:34:50 +0000974
Wanlong Gao354ebb42012-12-07 10:10:04 +0800975 return ret;
976 } /* LIO_IO_SYNCV */
whrb973f2b2000-05-05 19:34:50 +0000977#endif
978
subrata_modak26e07d52009-02-26 06:33:39 +0000979#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +0800980 else if (method & LIO_IO_SYNCP) {
981 io_type = "pwrite(2)";
whrb973f2b2000-05-05 19:34:50 +0000982
Wanlong Gao354ebb42012-12-07 10:10:04 +0800983 sprintf(Lio_SysCall,
984 "pwrite(%d, buf, %d, %lld)", fd, size,
985 (long long)poffset);
whrb973f2b2000-05-05 19:34:50 +0000986
Wanlong Gao354ebb42012-12-07 10:10:04 +0800987 if (Debug_level) {
988 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
989 Lio_SysCall);
990 }
991 if ((ret = pwrite(fd, buffer, size, poffset)) == -1) {
992 sprintf(Errormsg,
993 "%s/%d pwrite(%d, buf, %d, %lld) ret:-1, errno=%d %s",
994 __FILE__, __LINE__, fd, size,
995 (long long)poffset, errno, strerror(errno));
996 return -errno;
997 }
whrb973f2b2000-05-05 19:34:50 +0000998
Wanlong Gao354ebb42012-12-07 10:10:04 +0800999 if (ret != size) {
1000 sprintf(Errormsg,
1001 "%s/%d pwrite(%d, buf, %d, %lld) returned=%d",
1002 __FILE__, __LINE__,
1003 fd, size, (long long)poffset, ret);
1004 } else if (Debug_level > 1)
1005 printf
1006 ("DEBUG %s/%d: pwrite completed without error (ret %d)\n",
1007 __FILE__, __LINE__, ret);
whrb973f2b2000-05-05 19:34:50 +00001008
Wanlong Gao354ebb42012-12-07 10:10:04 +08001009 return ret;
1010 } /* LIO_IO_SYNCP */
whrb973f2b2000-05-05 19:34:50 +00001011#endif
1012
Wanlong Gao354ebb42012-12-07 10:10:04 +08001013 else {
1014 printf("DEBUG %s/%d: No I/O method chosen\n", __FILE__,
1015 __LINE__);
1016 return -1;
1017 }
whrb973f2b2000-05-05 19:34:50 +00001018
Wanlong Gao354ebb42012-12-07 10:10:04 +08001019 /*
1020 * wait for async io to complete.
1021 */
whrb973f2b2000-05-05 19:34:50 +00001022#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +08001023 ret = lio_wait4asyncio(method, fd, statptr);
whrb973f2b2000-05-05 19:34:50 +00001024#endif
subrata_modak26e07d52009-02-26 06:33:39 +00001025#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +08001026 ret = lio_wait4asyncio(method, fd, &aiocbp);
whrb973f2b2000-05-05 19:34:50 +00001027#endif
1028
Wanlong Gao354ebb42012-12-07 10:10:04 +08001029 /*
1030 * If there was an error waiting for async i/o to complete,
1031 * return the error value (errno) to the caller.
1032 * Note: Errormsg should already have been updated.
1033 */
1034 if (ret < 0) {
1035 return ret;
1036 }
1037
1038 /*
1039 * If i/o was not waited for (may not have been completed at this time),
1040 * return the size that was requested.
1041 */
1042 if (ret == 1)
1043 return size;
1044
1045 /*
1046 * check that async io was successful.
1047 * Note: if the there was an system call failure, -errno
1048 * was returned and Errormsg should already have been updated.
1049 * If amount i/o was different than size, Errormsg should already
1050 * have been updated but the actual i/o size if returned.
1051 */
1052
1053#ifdef CRAY
1054 ret = lio_check_asyncio(io_type, size, &status);
1055#endif
1056#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1057 ret = lio_check_asyncio(io_type, size, &aiocbp, method);
1058#endif
1059
whrb973f2b2000-05-05 19:34:50 +00001060 return ret;
Wanlong Gao354ebb42012-12-07 10:10:04 +08001061} /* end of lio_write_buffer */
whrb973f2b2000-05-05 19:34:50 +00001062
1063/***********************************************************************
vapier45a8ba02009-07-20 10:59:32 +00001064 * Generic read function
whrb973f2b2000-05-05 19:34:50 +00001065 * This function can be used to do a read using read(2), reada(2),
1066 * aio_read(3), readv(2), pread(2),
1067 * or single stride listio(2)/lio_listio(3).
1068 * By setting the desired bits in the method
1069 * bitmask, the caller can control the type of read and the wait method
1070 * that will be used. If no io type bits are set, read will be used.
1071 *
1072 * If async io was attempted and no wait method bits are set then the
1073 * wait method is: recall(2) for reada(2) and listio(2); aio_suspend(3) for
1074 * aio_read(3) and lio_listio(3).
1075 *
vapier45a8ba02009-07-20 10:59:32 +00001076 * If multiple wait methods are specified,
whrb973f2b2000-05-05 19:34:50 +00001077 * only one wait method will be used. The order is predetermined.
1078 *
1079 * If the call specifies a signal and one of the two signal wait methods,
1080 * a signal handler for the signal is set. This will reset an already
vapier45a8ba02009-07-20 10:59:32 +00001081 * set handler for this signal.
whrb973f2b2000-05-05 19:34:50 +00001082 *
1083 * If the LIO_RANDOM method bit is set, this function will randomly
1084 * choose a io type and wait method from bits in the method argument.
1085 *
1086 * If an error is encountered, an error message will be generated
1087 * in a internal static buffer. If errmsg is not NULL, it will
1088 * be updated to point to the static buffer, allowing the caller
1089 * to print the error message.
1090 *
1091 * Return Value
1092 * If a system call fails, -errno is returned.
1093 * If LIO_WAIT_NONE bit is set, the return value is the return value
1094 * of the system call.
1095 * If the io did not fail, the amount of data written is returned.
1096 * If the size the system call say was written is different
1097 * then what was asked to be written, errmsg is updated for
1098 * this error condition. The return value is still the amount
vapier45a8ba02009-07-20 10:59:32 +00001099 * the system call says was written.
whrb973f2b2000-05-05 19:34:50 +00001100 *
1101 * (rrl 04/96)
1102 ***********************************************************************/
Stanislav Kholmanskikh87aa2dc2014-04-11 11:45:19 +04001103int lio_read_buffer(int fd, /* open file descriptor */
1104 int method, /* contains io type and wait method bitmask*/
1105 char *buffer, /* pointer to buffer */
1106 int size, /* the size of the io */
1107 int sig, /* signal to use if async io */
1108 char **errmsg, /* char pointer that will be updated to point to err message */
1109 long wrd) /* to allow future features, use zero for now */
whrb973f2b2000-05-05 19:34:50 +00001110{
Wanlong Gao354ebb42012-12-07 10:10:04 +08001111 int ret = 0; /* syscall return or used to get random method */
1112 char *io_type; /* Holds string of type of io */
1113 int listio_cmd; /* Holds the listio/lio_listio cmd */
1114 int omethod = method;
whrb973f2b2000-05-05 19:34:50 +00001115#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +08001116 struct listreq request; /* Used when a listio is wanted */
1117 struct iosw status, *statptr[1];
whrb973f2b2000-05-05 19:34:50 +00001118#else
Wanlong Gao354ebb42012-12-07 10:10:04 +08001119 /* for linux or sgi */
1120 struct iovec iov; /* iovec for readv(2) */
whrb973f2b2000-05-05 19:34:50 +00001121#endif
1122#ifdef sgi
Wanlong Gao354ebb42012-12-07 10:10:04 +08001123 aiocb_t aiocbp; /* POSIX aio control block */
1124 aiocb_t *aiolist[1]; /* list of aio control blocks for lio_listio */
1125 off64_t poffset; /* pread(2) offset */
whrb973f2b2000-05-05 19:34:50 +00001126#endif
subrata_modak26e07d52009-02-26 06:33:39 +00001127#if defined (__linux__) && !defined(__UCLIBC__)
subrata_modakea37be82008-12-11 13:17:49 +00001128 struct aiocb aiocbp; /* POSIX aio control block */
Wanlong Gao354ebb42012-12-07 10:10:04 +08001129 struct aiocb *aiolist[1]; /* list of aio control blocks for lio_listio */
subrata_modakea37be82008-12-11 13:17:49 +00001130 off64_t poffset; /* pread(2) offset */
1131#endif
whrb973f2b2000-05-05 19:34:50 +00001132
Wanlong Gao354ebb42012-12-07 10:10:04 +08001133 /*
1134 * If LIO_RANDOM bit specified, get new method randomly.
1135 */
1136 if (method & LIO_RANDOM) {
1137 if (Debug_level > 3)
1138 printf("DEBUG %s/%d: method mask to choose from: %#o\n",
1139 __FILE__, __LINE__, method);
1140 method = lio_random_methods(method);
1141 if (Debug_level > 2)
1142 printf("DEBUG %s/%d: random chosen method %#o\n",
1143 __FILE__, __LINE__, method);
1144 }
whrb973f2b2000-05-05 19:34:50 +00001145
Wanlong Gao354ebb42012-12-07 10:10:04 +08001146 if (errmsg != NULL)
1147 *errmsg = Errormsg;
whrb973f2b2000-05-05 19:34:50 +00001148
Wanlong Gao354ebb42012-12-07 10:10:04 +08001149 Rec_signal = Received_signal; /* get the current number of signals received */
subrata_modak26e07d52009-02-26 06:33:39 +00001150#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +08001151 Rec_callback = Received_callback; /* get the current number of callbacks received */
whrb973f2b2000-05-05 19:34:50 +00001152#endif
1153
1154#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +08001155 memset(&status, 0x00, sizeof(struct iosw));
1156 memset(&request, 0x00, sizeof(struct listreq));
1157 statptr[0] = &status;
whrb973f2b2000-05-05 19:34:50 +00001158#else
Wanlong Gao354ebb42012-12-07 10:10:04 +08001159 /* for linux or sgi */
1160 memset(&iov, 0x00, sizeof(struct iovec));
1161 iov.iov_base = buffer;
1162 iov.iov_len = size;
whrb973f2b2000-05-05 19:34:50 +00001163#endif
subrata_modak26e07d52009-02-26 06:33:39 +00001164#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
subrata_modakea37be82008-12-11 13:17:49 +00001165#if defined(sgi)
Wanlong Gao354ebb42012-12-07 10:10:04 +08001166 memset(&aiocbp, 0x00, sizeof(aiocb_t));
subrata_modakea37be82008-12-11 13:17:49 +00001167#else
1168 memset(&aiocbp, 0x00, sizeof(struct aiocb));
1169#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +08001170 aiocbp.aio_fildes = fd;
1171 aiocbp.aio_nbytes = size;
1172 aiocbp.aio_buf = buffer;
whrb973f2b2000-05-05 19:34:50 +00001173/* aiocbp.aio_offset = lseek( fd, 0, SEEK_CUR ); -- set below */
Wanlong Gao354ebb42012-12-07 10:10:04 +08001174 aiocbp.aio_sigevent.sigev_notify = SIGEV_NONE;
1175 aiocbp.aio_sigevent.sigev_signo = 0;
subrata_modakea37be82008-12-11 13:17:49 +00001176#ifdef sgi
Wanlong Gao354ebb42012-12-07 10:10:04 +08001177 aiocbp.aio_sigevent.sigev_func = NULL;
1178 aiocbp.aio_sigevent.sigev_value.sival_int = 0;
subrata_modak26e07d52009-02-26 06:33:39 +00001179#elif defined(__linux__) && !defined(__UCLIBC__)
subrata_modakea37be82008-12-11 13:17:49 +00001180 aiocbp.aio_sigevent.sigev_notify_function = NULL;
1181 aiocbp.aio_sigevent.sigev_notify_attributes = 0;
1182#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +08001183 aiolist[0] = &aiocbp;
whrb973f2b2000-05-05 19:34:50 +00001184
Wanlong Gao354ebb42012-12-07 10:10:04 +08001185 if ((ret = lseek(fd, 0, SEEK_CUR)) == -1) {
1186 ret = 0;
1187 /* If there is an error and it is not ESPIPE then kick out the error.
1188 * If the fd is a fifo then we have to make sure that
1189 * lio_random_methods() didn't select pwrite/pread; if it did then
1190 * switch to write/read.
1191 */
1192 if (errno == ESPIPE) {
1193 if (method & LIO_IO_SYNCP) {
1194 if (omethod & LIO_RANDOM) {
1195 method &= ~LIO_IO_SYNCP;
1196 method |= LIO_IO_SYNC;
1197 if (Debug_level > 2)
1198 printf
1199 ("DEBUG %s/%d: random chosen method switched to %#o for fifo\n",
1200 __FILE__, __LINE__,
1201 method);
1202 } else if (Debug_level) {
1203 printf
1204 ("DEBUG %s/%d: pread will fail when it reads from a fifo\n",
1205 __FILE__, __LINE__);
1206 }
whrb973f2b2000-05-05 19:34:50 +00001207 }
Wanlong Gao354ebb42012-12-07 10:10:04 +08001208 /* else: let it ride */
1209 } else {
1210 sprintf(Errormsg,
1211 "%s/%d lseek(fd=%d,0,SEEK_CUR) failed, errno=%d %s",
1212 __FILE__, __LINE__, fd, errno, strerror(errno));
1213 return -errno;
whrb973f2b2000-05-05 19:34:50 +00001214 }
whrb973f2b2000-05-05 19:34:50 +00001215 }
subrata_modak26e07d52009-02-26 06:33:39 +00001216#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +08001217 poffset = (off64_t) ret;
subrata_modakea37be82008-12-11 13:17:49 +00001218#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +08001219 aiocbp.aio_offset = ret;
whrb973f2b2000-05-05 19:34:50 +00001220
1221#endif
1222
Wanlong Gao354ebb42012-12-07 10:10:04 +08001223 /*
1224 * If the LIO_USE_SIGNAL bit is not set, only use the signal
1225 * if the LIO_WAIT_SIGPAUSE or the LIO_WAIT_SIGACTIVE bits are set.
1226 * Otherwise there is not necessarily a signal handler to trap
1227 * the signal.
1228 */
1229 if (sig && !(method & LIO_USE_SIGNAL) && !(method & LIO_WAIT_SIGTYPES)) {
whrb973f2b2000-05-05 19:34:50 +00001230
Wanlong Gao354ebb42012-12-07 10:10:04 +08001231 sig = 0; /* ignore signal parameter */
1232 }
subrata_modak26e07d52009-02-26 06:33:39 +00001233#if defined(sgi) || (defined(__linux__)&& !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +08001234 if (sig && (method & LIO_WAIT_CBTYPES))
1235 sig = 0; /* ignore signal parameter */
whrb973f2b2000-05-05 19:34:50 +00001236#endif
1237
Wanlong Gao354ebb42012-12-07 10:10:04 +08001238 /*
1239 * only setup signal hander if sig was specified and
1240 * a sig wait method was specified.
1241 * Doing this will change the handler for this signal. The
1242 * old signal handler will not be restored.
1243 *** restoring the signal handler could be added ***
1244 */
whrb973f2b2000-05-05 19:34:50 +00001245
Wanlong Gao354ebb42012-12-07 10:10:04 +08001246 if (sig && (method & LIO_WAIT_SIGTYPES)) {
whrb973f2b2000-05-05 19:34:50 +00001247#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +08001248 sigctl(SCTL_REG, sig, lio_async_signal_handler);
whrb973f2b2000-05-05 19:34:50 +00001249#endif
subrata_modak26e07d52009-02-26 06:33:39 +00001250#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +08001251 aiocbp.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
1252 aiocbp.aio_sigevent.sigev_signo = sig;
1253 sigset(sig, lio_async_signal_handler);
whrb973f2b2000-05-05 19:34:50 +00001254#endif /* CRAY */
Wanlong Gao354ebb42012-12-07 10:10:04 +08001255 }
subrata_modakea37be82008-12-11 13:17:49 +00001256#if defined(sgi)
Wanlong Gao354ebb42012-12-07 10:10:04 +08001257 else if (method & LIO_WAIT_CBTYPES) {
1258 aiocbp.aio_sigevent.sigev_notify = SIGEV_CALLBACK;
1259 aiocbp.aio_sigevent.sigev_func = lio_async_callback_handler;
1260 /* sival_int just has to be something that I can use
1261 * to identify the callback, and "size" happens to be handy...
1262 */
1263 aiocbp.aio_sigevent.sigev_value.sival_int = size;
1264 }
whrb973f2b2000-05-05 19:34:50 +00001265#endif
subrata_modak26e07d52009-02-26 06:33:39 +00001266#if defined(__linux__) && !defined(__UCLIBC__)
Garrett Cooper903910d2010-11-23 09:27:44 -08001267 else if (method & LIO_WAIT_CBTYPES) {
subrata_modakea37be82008-12-11 13:17:49 +00001268 aiocbp.aio_sigevent.sigev_notify = SIGEV_THREAD;
Wanlong Gao354ebb42012-12-07 10:10:04 +08001269 aiocbp.aio_sigevent.sigev_notify_function =
1270 lio_async_callback_handler;
subrata_modakea37be82008-12-11 13:17:49 +00001271 /* sival_int just has to be something that I can use
1272 * to identify the callback, and "size" happens to be handy...
1273 */
Wanlong Gao354ebb42012-12-07 10:10:04 +08001274 aiocbp.aio_sigevent.sigev_notify_attributes =
1275 (void *)(uintptr_t) size;
subrata_modakea37be82008-12-11 13:17:49 +00001276 }
1277#endif
whrb973f2b2000-05-05 19:34:50 +00001278
whrb973f2b2000-05-05 19:34:50 +00001279 /*
Wanlong Gao354ebb42012-12-07 10:10:04 +08001280 * Determine the system call that will be called and produce
1281 * the string of the system call and place it in Lio_SysCall.
1282 * Also update the io_type char pointer to give brief description
1283 * of system call. Execute the system call and check for
1284 * system call failure. If sync i/o, return the number of
1285 * bytes written/read.
1286 */
whrb973f2b2000-05-05 19:34:50 +00001287
Wanlong Gao354ebb42012-12-07 10:10:04 +08001288 if ((method & LIO_IO_SYNC)
1289 || (method & (LIO_IO_TYPES | LIO_IO_ATYPES)) == 0) {
1290 /*
1291 * read(2) is used if LIO_IO_SYNC bit is set or not none
1292 * of the LIO_IO_TYPES bits are set (default).
1293 */
whrb973f2b2000-05-05 19:34:50 +00001294
Wanlong Gao354ebb42012-12-07 10:10:04 +08001295 sprintf(Lio_SysCall, "read(%d, buf, %d)", fd, size);
1296 io_type = "read";
whrb973f2b2000-05-05 19:34:50 +00001297
Wanlong Gao354ebb42012-12-07 10:10:04 +08001298 if (Debug_level) {
1299 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1300 Lio_SysCall);
1301 }
whrb973f2b2000-05-05 19:34:50 +00001302
Wanlong Gao354ebb42012-12-07 10:10:04 +08001303 while (1) {
1304 if (((ret = read(fd, buffer, size)) == -1)
1305 && errno != EINTR && errno != EAGAIN) {
1306 sprintf(Errormsg,
1307 "%s/%d read(%d, buf, %d) ret:-1, errno=%d %s",
1308 __FILE__, __LINE__, fd, size, errno,
1309 strerror(errno));
1310 return -errno;
1311 }
subrata_modakea37be82008-12-11 13:17:49 +00001312
Wanlong Gao354ebb42012-12-07 10:10:04 +08001313 if (ret == 0)
1314 return 0;
1315 if (ret != -1) {
1316 if (ret != size) {
1317 sprintf(Errormsg,
1318 "%s/%d read(%d, buf, %d) returned=%d",
1319 __FILE__, __LINE__,
1320 fd, size, ret);
1321 size -= ret;
1322 buffer += ret;
1323 } else {
1324 if (Debug_level > 1)
1325 printf
1326 ("DEBUG %s/%d: read completed without error (ret %d)\n",
1327 __FILE__, __LINE__, ret);
whrb973f2b2000-05-05 19:34:50 +00001328
Wanlong Gao354ebb42012-12-07 10:10:04 +08001329 return ret;
1330 }
1331 }
1332 wait4sync_io(fd, 1);
1333 }
whrb973f2b2000-05-05 19:34:50 +00001334
whrb973f2b2000-05-05 19:34:50 +00001335 }
Wanlong Gao354ebb42012-12-07 10:10:04 +08001336
1337 else if (method & LIO_IO_ASYNC) {
1338#ifdef CRAY
1339 sprintf(Lio_SysCall,
1340 "reada(%d, buf, %d, &status, %d)", fd, size, sig);
1341 io_type = "reada";
1342
1343 if (Debug_level) {
1344 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1345 Lio_SysCall);
1346 }
1347
1348 sigoff();
1349 if ((ret = reada(fd, buffer, size, &status, sig)) == -1) {
1350 sprintf(Errormsg,
1351 "%s/%d reada(%d, buf, %d, &stat, %d) ret:-1, errno=%d %s",
1352 __FILE__, __LINE__,
1353 fd, size, sig, errno, strerror(errno));
1354 sigon();
1355 return -errno;
1356 }
whrb973f2b2000-05-05 19:34:50 +00001357#endif
subrata_modak26e07d52009-02-26 06:33:39 +00001358#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +08001359 sprintf(Lio_SysCall,
1360 "aio_read(fildes=%d, buf, nbytes=%d, signo=%d)", fd,
1361 size, sig);
1362 io_type = "aio_read";
whrb973f2b2000-05-05 19:34:50 +00001363
Wanlong Gao354ebb42012-12-07 10:10:04 +08001364 if (Debug_level) {
1365 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1366 Lio_SysCall);
1367 }
whrb973f2b2000-05-05 19:34:50 +00001368
Wanlong Gao354ebb42012-12-07 10:10:04 +08001369 if (sig)
1370 sighold(sig);
1371 if ((ret = aio_read(&aiocbp)) == -1) {
1372 sprintf(Errormsg,
1373 "%s/%d aio_read(fildes=%d, buf, nbytes=%d, signo=%d) ret:-1, errno=%d %s",
1374 __FILE__, __LINE__,
1375 fd, size, sig, errno, strerror(errno));
1376 if (sig)
1377 sigrelse(sig);
1378 return -errno;
1379 }
1380#endif
whrb973f2b2000-05-05 19:34:50 +00001381 }
Wanlong Gao354ebb42012-12-07 10:10:04 +08001382 /* LIO_IO_ASYNC */
1383 else if (method & LIO_IO_SLISTIO) {
whrb973f2b2000-05-05 19:34:50 +00001384#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +08001385 request.li_opcode = LO_READ;
1386 request.li_fildes = fd;
1387 request.li_buf = buffer;
1388 request.li_nbyte = size;
1389 request.li_status = &status;
1390 request.li_signo = sig;
1391 request.li_nstride = 0;
1392 request.li_filstride = 0;
1393 request.li_memstride = 0;
whrb973f2b2000-05-05 19:34:50 +00001394
Wanlong Gao354ebb42012-12-07 10:10:04 +08001395 listio_cmd = LC_WAIT;
1396 io_type = "listio(2) sync read";
whrb973f2b2000-05-05 19:34:50 +00001397
Wanlong Gao354ebb42012-12-07 10:10:04 +08001398 sprintf(Lio_SysCall,
1399 "listio(LC_WAIT, &req, 1) LO_READ, fd:%d, nbyte:%d",
1400 fd, size);
whrb973f2b2000-05-05 19:34:50 +00001401
Wanlong Gao354ebb42012-12-07 10:10:04 +08001402 if (Debug_level) {
1403 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1404 Lio_SysCall);
1405 }
whrb973f2b2000-05-05 19:34:50 +00001406
Wanlong Gao354ebb42012-12-07 10:10:04 +08001407 sigoff();
1408 if (listio(listio_cmd, &request, 1) == -1) {
1409 sprintf(Errormsg,
1410 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1411 __FILE__, __LINE__, Lio_SysCall, fd, size,
1412 errno, strerror(errno));
1413 sigon();
1414 return -errno;
1415 }
whrb973f2b2000-05-05 19:34:50 +00001416
Wanlong Gao354ebb42012-12-07 10:10:04 +08001417 if (Debug_level > 1)
1418 printf("DEBUG %s/%d: %s did not return -1\n",
1419 __FILE__, __LINE__, Lio_SysCall);
whrb973f2b2000-05-05 19:34:50 +00001420
Wanlong Gao354ebb42012-12-07 10:10:04 +08001421 ret = lio_check_asyncio(io_type, size, &status);
1422 return ret;
whrb973f2b2000-05-05 19:34:50 +00001423#endif
subrata_modak26e07d52009-02-26 06:33:39 +00001424#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +08001425 aiocbp.aio_lio_opcode = LIO_READ;
1426 listio_cmd = LIO_WAIT;
1427 io_type = "lio_listio(3) sync read";
whrb973f2b2000-05-05 19:34:50 +00001428
Wanlong Gao354ebb42012-12-07 10:10:04 +08001429 sprintf(Lio_SysCall,
1430 "lio_listio(LIO_WAIT, aiolist, 1, NULL) LIO_READ, fd:%d, nbyte:%d",
1431 fd, size);
whrb973f2b2000-05-05 19:34:50 +00001432
Wanlong Gao354ebb42012-12-07 10:10:04 +08001433 if (Debug_level) {
1434 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1435 Lio_SysCall);
1436 }
whrb973f2b2000-05-05 19:34:50 +00001437
Wanlong Gao354ebb42012-12-07 10:10:04 +08001438 if (sig)
1439 sighold(sig);
1440 if (lio_listio(listio_cmd, aiolist, 1, NULL) == -1) {
1441 sprintf(Errormsg,
1442 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1443 __FILE__, __LINE__, Lio_SysCall, fd, size,
1444 errno, strerror(errno));
1445 if (sig)
1446 sigrelse(sig);
1447 return -errno;
1448 }
whrb973f2b2000-05-05 19:34:50 +00001449
Wanlong Gao354ebb42012-12-07 10:10:04 +08001450 if (Debug_level > 1)
1451 printf("DEBUG %s/%d: %s did not return -1\n",
1452 __FILE__, __LINE__, Lio_SysCall);
whrb973f2b2000-05-05 19:34:50 +00001453
Wanlong Gao354ebb42012-12-07 10:10:04 +08001454 ret = lio_check_asyncio(io_type, size, &aiocbp, method);
1455 return ret;
whrb973f2b2000-05-05 19:34:50 +00001456#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +08001457 }
1458 /* LIO_IO_SLISTIO */
1459 else if (method & LIO_IO_ALISTIO) {
whrb973f2b2000-05-05 19:34:50 +00001460#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +08001461 request.li_opcode = LO_READ;
1462 request.li_fildes = fd;
1463 request.li_buf = buffer;
1464 request.li_nbyte = size;
1465 request.li_status = &status;
1466 request.li_signo = sig;
1467 request.li_nstride = 0;
1468 request.li_filstride = 0;
1469 request.li_memstride = 0;
whrb973f2b2000-05-05 19:34:50 +00001470
Wanlong Gao354ebb42012-12-07 10:10:04 +08001471 listio_cmd = LC_START;
1472 io_type = "listio(2) async read";
whrb973f2b2000-05-05 19:34:50 +00001473
Wanlong Gao354ebb42012-12-07 10:10:04 +08001474 sprintf(Lio_SysCall,
1475 "listio(LC_START, &req, 1) LO_READ, fd:%d, nbyte:%d",
1476 fd, size);
whrb973f2b2000-05-05 19:34:50 +00001477
Wanlong Gao354ebb42012-12-07 10:10:04 +08001478 if (Debug_level) {
1479 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1480 Lio_SysCall);
1481 }
whrb973f2b2000-05-05 19:34:50 +00001482
Wanlong Gao354ebb42012-12-07 10:10:04 +08001483 sigoff();
1484 if (listio(listio_cmd, &request, 1) == -1) {
1485 sprintf(Errormsg,
1486 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1487 __FILE__, __LINE__, Lio_SysCall, fd, size,
1488 errno, strerror(errno));
1489 sigon();
1490 return -errno;
1491 }
whrb973f2b2000-05-05 19:34:50 +00001492#endif
subrata_modak26e07d52009-02-26 06:33:39 +00001493#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +08001494 aiocbp.aio_lio_opcode = LIO_READ;
1495 listio_cmd = LIO_NOWAIT;
1496 io_type = "lio_listio(3) async read";
whrb973f2b2000-05-05 19:34:50 +00001497
Wanlong Gao354ebb42012-12-07 10:10:04 +08001498 sprintf(Lio_SysCall,
1499 "lio_listio(LIO_NOWAIT, aiolist, 1, NULL) LIO_READ, fd:%d, nbyte:%d",
1500 fd, size);
whrb973f2b2000-05-05 19:34:50 +00001501
Wanlong Gao354ebb42012-12-07 10:10:04 +08001502 if (Debug_level) {
1503 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1504 Lio_SysCall);
1505 }
whrb973f2b2000-05-05 19:34:50 +00001506
Wanlong Gao354ebb42012-12-07 10:10:04 +08001507 if (sig)
1508 sighold(sig);
1509 if (lio_listio(listio_cmd, aiolist, 1, NULL) == -1) {
1510 sprintf(Errormsg,
1511 "%s/%d %s failed, fd:%d, nbyte:%d errno=%d %s",
1512 __FILE__, __LINE__, Lio_SysCall, fd, size,
1513 errno, strerror(errno));
1514 if (sig)
1515 sigrelse(sig);
1516 return -errno;
1517 }
whrb973f2b2000-05-05 19:34:50 +00001518#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +08001519 }
1520 /* LIO_IO_ALISTIO */
whrb973f2b2000-05-05 19:34:50 +00001521#ifndef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +08001522 else if (method & LIO_IO_SYNCV) {
1523 io_type = "readv(2)";
whrb973f2b2000-05-05 19:34:50 +00001524
Wanlong Gao354ebb42012-12-07 10:10:04 +08001525 sprintf(Lio_SysCall, "readv(%d, &iov, 1) nbyte:%d", fd, size);
whrb973f2b2000-05-05 19:34:50 +00001526
Wanlong Gao354ebb42012-12-07 10:10:04 +08001527 if (Debug_level) {
1528 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1529 Lio_SysCall);
1530 }
1531 if ((ret = readv(fd, &iov, 1)) == -1) {
1532 sprintf(Errormsg,
1533 "%s/%d readv(%d, iov, 1) nbyte:%d ret:-1, errno=%d %s",
1534 __FILE__, __LINE__, fd, size, errno,
1535 strerror(errno));
1536 return -errno;
1537 }
whrb973f2b2000-05-05 19:34:50 +00001538
Wanlong Gao354ebb42012-12-07 10:10:04 +08001539 if (ret != size) {
1540 sprintf(Errormsg,
1541 "%s/%d readv(%d, iov, 1) nbyte:%d returned=%d",
1542 __FILE__, __LINE__, fd, size, ret);
1543 } else if (Debug_level > 1)
1544 printf
1545 ("DEBUG %s/%d: readv completed without error (ret %d)\n",
1546 __FILE__, __LINE__, ret);
whrb973f2b2000-05-05 19:34:50 +00001547
Wanlong Gao354ebb42012-12-07 10:10:04 +08001548 return ret;
1549 } /* LIO_IO_SYNCV */
whrb973f2b2000-05-05 19:34:50 +00001550#endif
1551
subrata_modak26e07d52009-02-26 06:33:39 +00001552#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +08001553 else if (method & LIO_IO_SYNCP) {
1554 io_type = "pread(2)";
whrb973f2b2000-05-05 19:34:50 +00001555
Wanlong Gao354ebb42012-12-07 10:10:04 +08001556 sprintf(Lio_SysCall,
1557 "pread(%d, buf, %d, %lld)", fd, size,
1558 (long long)poffset);
whrb973f2b2000-05-05 19:34:50 +00001559
Wanlong Gao354ebb42012-12-07 10:10:04 +08001560 if (Debug_level) {
1561 printf("DEBUG %s/%d: %s\n", __FILE__, __LINE__,
1562 Lio_SysCall);
1563 }
1564 if ((ret = pread(fd, buffer, size, poffset)) == -1) {
1565 sprintf(Errormsg,
1566 "%s/%d pread(%d, buf, %d, %lld) ret:-1, errno=%d %s",
1567 __FILE__, __LINE__, fd, size,
1568 (long long)poffset, errno, strerror(errno));
1569 return -errno;
1570 }
whrb973f2b2000-05-05 19:34:50 +00001571
Wanlong Gao354ebb42012-12-07 10:10:04 +08001572 if (ret != size) {
1573 sprintf(Errormsg,
1574 "%s/%d pread(%d, buf, %d, %lld) returned=%d",
1575 __FILE__, __LINE__,
1576 fd, size, (long long)poffset, ret);
1577 } else if (Debug_level > 1)
1578 printf
1579 ("DEBUG %s/%d: pread completed without error (ret %d)\n",
1580 __FILE__, __LINE__, ret);
whrb973f2b2000-05-05 19:34:50 +00001581
Wanlong Gao354ebb42012-12-07 10:10:04 +08001582 return ret;
1583 } /* LIO_IO_SYNCP */
whrb973f2b2000-05-05 19:34:50 +00001584#endif
1585
Wanlong Gao354ebb42012-12-07 10:10:04 +08001586 else {
1587 printf("DEBUG %s/%d: No I/O method chosen\n", __FILE__,
1588 __LINE__);
1589 return -1;
1590 }
whrb973f2b2000-05-05 19:34:50 +00001591
Wanlong Gao354ebb42012-12-07 10:10:04 +08001592 /*
1593 * wait for async io to complete.
1594 * Note: Sync io should have returned prior to getting here.
1595 */
whrb973f2b2000-05-05 19:34:50 +00001596#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +08001597 ret = lio_wait4asyncio(method, fd, statptr);
whrb973f2b2000-05-05 19:34:50 +00001598#endif
subrata_modak26e07d52009-02-26 06:33:39 +00001599#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +08001600 ret = lio_wait4asyncio(method, fd, &aiocbp);
whrb973f2b2000-05-05 19:34:50 +00001601#endif
1602
Wanlong Gao354ebb42012-12-07 10:10:04 +08001603 /*
1604 * If there was an error waiting for async i/o to complete,
1605 * return the error value (errno) to the caller.
1606 * Note: Errormsg should already have been updated.
1607 */
1608 if (ret < 0) {
1609 return ret;
1610 }
1611
1612 /*
1613 * If i/o was not waited for (may not have been completed at this time),
1614 * return the size that was requested.
1615 */
1616 if (ret == 1)
1617 return size;
1618
1619 /*
1620 * check that async io was successful.
1621 * Note: if the there was an system call failure, -errno
1622 * was returned and Errormsg should already have been updated.
1623 * If amount i/o was different than size, Errormsg should already
1624 * have been updated but the actual i/o size if returned.
1625 */
1626
1627#ifdef CRAY
1628 ret = lio_check_asyncio(io_type, size, &status);
1629#endif
1630#if defined(sgi) || (defined(__linux__) && !defined(__UCLIBC__))
1631 ret = lio_check_asyncio(io_type, size, &aiocbp, method);
1632#endif
1633
whrb973f2b2000-05-05 19:34:50 +00001634 return ret;
Wanlong Gao354ebb42012-12-07 10:10:04 +08001635} /* end of lio_read_buffer */
whrb973f2b2000-05-05 19:34:50 +00001636
subrata_modakea37be82008-12-11 13:17:49 +00001637#if !defined(__sun) && !defined(__hpux) && !defined(_AIX)
whrb973f2b2000-05-05 19:34:50 +00001638/***********************************************************************
1639 * This function will check that async io was successful.
1640 * It can also be used to check sync listio since it uses the
1641 * same method.
1642 *
1643 * Return Values
1644 * If status.sw_error is set, -status.sw_error is returned.
1645 * Otherwise sw_count's field value is returned.
1646 *
1647 * (rrl 04/96)
1648 ***********************************************************************/
whrb973f2b2000-05-05 19:34:50 +00001649#ifdef CRAY
subrata_modak26e07d52009-02-26 06:33:39 +00001650int lio_check_asyncio(char *io_type, int size, struct iosw *status)
subrata_modakea37be82008-12-11 13:17:49 +00001651#elif defined(sgi)
Wanlong Gao354ebb42012-12-07 10:10:04 +08001652int lio_check_asyncio(char *io_type, int size, aiocb_t * aiocbp, int method)
subrata_modak26e07d52009-02-26 06:33:39 +00001653#elif defined(__linux__) && !defined(__UCLIBC__)
Wanlong Gao354ebb42012-12-07 10:10:04 +08001654int lio_check_asyncio(char *io_type, int size, struct aiocb *aiocbp, int method)
whrb973f2b2000-05-05 19:34:50 +00001655{
Wanlong Gao354ebb42012-12-07 10:10:04 +08001656 int ret;
whrb973f2b2000-05-05 19:34:50 +00001657
1658#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +08001659 if (status->sw_error) {
1660 sprintf(Errormsg,
1661 "%s/%d %s, sw_error set = %d %s, sw_count = %d",
1662 __FILE__, __LINE__, io_type,
1663 status->sw_error, strerror(status->sw_error),
1664 status->sw_count);
1665 return -status->sw_error;
1666 } else if (status->sw_count != size) {
1667 sprintf(Errormsg,
1668 "%s/%d %s, sw_count not as expected(%d), but actual:%d",
1669 __FILE__, __LINE__, io_type, size, status->sw_count);
1670 } else if (Debug_level > 1) {
1671 printf
1672 ("DEBUG %s/%d: %s completed without error (sw_error == 0, sw_count == %d)\n",
1673 __FILE__, __LINE__, io_type, status->sw_count);
1674 }
whrb973f2b2000-05-05 19:34:50 +00001675
Wanlong Gao354ebb42012-12-07 10:10:04 +08001676 return status->sw_count;
whrb973f2b2000-05-05 19:34:50 +00001677
1678#else
1679
Wanlong Gao354ebb42012-12-07 10:10:04 +08001680 int cnt = 1;
whrb973f2b2000-05-05 19:34:50 +00001681
Wanlong Gao354ebb42012-12-07 10:10:04 +08001682 /* The I/O may have been synchronous with signal completion. It doesn't
1683 * make sense, but the combination could be generated. Release the
1684 * completion signal here otherwise it'll hang around and bite us
1685 * later.
1686 */
1687 if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL)
1688 sigrelse(aiocbp->aio_sigevent.sigev_signo);
whrb973f2b2000-05-05 19:34:50 +00001689
Wanlong Gao354ebb42012-12-07 10:10:04 +08001690 ret = aio_error(aiocbp);
whrb973f2b2000-05-05 19:34:50 +00001691
Wanlong Gao354ebb42012-12-07 10:10:04 +08001692 while (ret == EINPROGRESS) {
1693 ret = aio_error(aiocbp);
1694 ++cnt;
1695 }
1696 if (cnt > 1) {
1697 sprintf(Errormsg,
1698 "%s/%d %s, aio_error had to loop on EINPROGRESS, cnt=%d; random method %#o; sigev_notify=%s",
1699 __FILE__, __LINE__, io_type, cnt, method,
1700 (aiocbp->aio_sigevent.sigev_notify ==
1701 SIGEV_SIGNAL ? "signal" : aiocbp->aio_sigevent.
1702 sigev_notify == SIGEV_NONE ? "none" :
mridgee6508f82005-01-04 21:00:17 +00001703#ifdef SIGEV_CALLBACK
Wanlong Gao354ebb42012-12-07 10:10:04 +08001704 aiocbp->aio_sigevent.sigev_notify ==
1705 SIGEV_CALLBACK ? "callback" :
mridgee6508f82005-01-04 21:00:17 +00001706#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +08001707 aiocbp->aio_sigevent.sigev_notify ==
1708 SIGEV_THREAD ? "thread" : "unknown"));
1709 return -ret;
1710 }
whrb973f2b2000-05-05 19:34:50 +00001711
Wanlong Gao354ebb42012-12-07 10:10:04 +08001712 if (ret != 0) {
1713 sprintf(Errormsg,
1714 "%s/%d %s, aio_error = %d %s; random method %#o",
1715 __FILE__, __LINE__, io_type,
1716 ret, strerror(ret), method);
1717 return -ret;
1718 }
1719 ret = aio_return(aiocbp);
1720 if (ret != size) {
1721 sprintf(Errormsg,
1722 "%s/%d %s, aio_return not as expected(%d), but actual:%d",
1723 __FILE__, __LINE__, io_type, size, ret);
whrb973f2b2000-05-05 19:34:50 +00001724
1725#ifdef BUG1_workaround
Wanlong Gao354ebb42012-12-07 10:10:04 +08001726 if (ret == 0) {
1727 ret = size;
1728 if (Debug_level > 1) {
1729 printf
1730 ("WARN %s/%d: %s completed with bug1_workaround (aio_error == 0, aio_return now == %d)\n",
1731 __FILE__, __LINE__, io_type, ret);
1732 }
whrb973f2b2000-05-05 19:34:50 +00001733 }
whrb973f2b2000-05-05 19:34:50 +00001734#endif /* BUG1_workaround */
1735
Wanlong Gao354ebb42012-12-07 10:10:04 +08001736 } else if (Debug_level > 1) {
1737 printf
1738 ("DEBUG %s/%d: %s completed without error (aio_error == 0, aio_return == %d)\n",
1739 __FILE__, __LINE__, io_type, ret);
1740 }
whrb973f2b2000-05-05 19:34:50 +00001741
Wanlong Gao354ebb42012-12-07 10:10:04 +08001742 return ret;
whrb973f2b2000-05-05 19:34:50 +00001743
1744#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +08001745} /* end of lio_check_asyncio */
subrata_modak26e07d52009-02-26 06:33:39 +00001746#endif
whrb973f2b2000-05-05 19:34:50 +00001747
1748/***********************************************************************
1749 *
1750 * This function will wait for async io to complete.
1751 * If multiple wait methods are specified, the order is predetermined
1752 * to LIO_WAIT_RECALL,
1753 * LIO_WAIT_ACTIVE, LIO_WAIT_SIGPAUSE, LIO_WAIT_SIGACTIVE,
1754 * then LIO_WAIT_NONE.
1755 *
1756 * If no wait method was specified the default wait method is: recall(2)
1757 * or aio_suspend(3), as appropriate.
1758 *
1759 * Return Values
1760 * <0: errno of failed recall
1761 * 0 : async io was completed
1762 * 1 : async was not waited for, io may not have completed.
1763 *
1764 * (rrl 04/96)
1765 ***********************************************************************/
whrb973f2b2000-05-05 19:34:50 +00001766#ifdef CRAY
subrata_modak26e07d52009-02-26 06:33:39 +00001767int lio_wait4asyncio(int method, int fd, struct iosw **statptr)
subrata_modakea37be82008-12-11 13:17:49 +00001768#elif defined(sgi)
Wanlong Gao354ebb42012-12-07 10:10:04 +08001769int lio_wait4asyncio(int method, int fd, aiocb_t * aiocbp)
subrata_modak26e07d52009-02-26 06:33:39 +00001770#elif defined(__linux__) && !defined(__UCLIBC__)
Wanlong Gao354ebb42012-12-07 10:10:04 +08001771int lio_wait4asyncio(int method, int fd, struct aiocb *aiocbp)
whrb973f2b2000-05-05 19:34:50 +00001772{
Wanlong Gao354ebb42012-12-07 10:10:04 +08001773 int cnt;
whrb973f2b2000-05-05 19:34:50 +00001774#ifdef sgi
Wanlong Gao354ebb42012-12-07 10:10:04 +08001775 int ret;
1776 const aiocb_t *aioary[1];
whrb973f2b2000-05-05 19:34:50 +00001777#endif
subrata_modak26e07d52009-02-26 06:33:39 +00001778#if defined(__linux__)&& !defined(__UCLIBC__)
subrata_modakea37be82008-12-11 13:17:49 +00001779 int ret;
1780 const struct aiocb *aioary[1];
1781#endif
whrb973f2b2000-05-05 19:34:50 +00001782
Wanlong Gao354ebb42012-12-07 10:10:04 +08001783 if ((method & LIO_WAIT_RECALL)
subrata_modak26e07d52009-02-26 06:33:39 +00001784#if defined(sgi) || (defined(__linux__)&& !defined(__UCLIBC__))
Wanlong Gao354ebb42012-12-07 10:10:04 +08001785 || (method & LIO_WAIT_CBSUSPEND)
1786 || (method & LIO_WAIT_SIGSUSPEND)
whrb973f2b2000-05-05 19:34:50 +00001787#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +08001788 || ((method & LIO_WAIT_TYPES) == 0)) {
1789 /*
1790 * If method has LIO_WAIT_RECALL bit set or method does
1791 * not have any wait method bits set (default), use recall/aio_suspend.
1792 */
whrb973f2b2000-05-05 19:34:50 +00001793#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +08001794 if (Debug_level > 2)
1795 printf("DEBUG %s/%d: wait method : recall\n", __FILE__,
1796 __LINE__);
1797 sigon();
1798 if (recall(fd, 1, statptr)) {
1799 sprintf(Errormsg,
1800 "%s/%d recall(%d, 1, stat) failed, errno:%d %s",
1801 __FILE__, __LINE__, fd, errno, strerror(errno));
whrb973f2b2000-05-05 19:34:50 +00001802 return -errno;
1803 }
whrb973f2b2000-05-05 19:34:50 +00001804#else
Wanlong Gao354ebb42012-12-07 10:10:04 +08001805 if (Debug_level > 2)
1806 printf
1807 ("DEBUG %s/%d: wait method : aio_suspend, sigev_notify=%s\n",
1808 __FILE__, __LINE__,
1809 (aiocbp->aio_sigevent.sigev_notify ==
1810 SIGEV_SIGNAL ? "signal" : aiocbp->aio_sigevent.
1811 sigev_notify == SIGEV_NONE ? "none" :
1812#ifdef SIGEV_CALLBACK
1813 aiocbp->aio_sigevent.sigev_notify ==
1814 SIGEV_CALLBACK ? "callback" :
1815#endif
1816 aiocbp->aio_sigevent.sigev_notify ==
1817 SIGEV_THREAD ? "thread" : "unknown"));
1818
1819 aioary[0] = aiocbp;
1820 ret = aio_suspend(aioary, 1, NULL);
1821 if ((ret == -1) && (errno == EINTR)) {
1822 if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL) {
1823 if (Debug_level > 2) {
1824 printf
1825 ("DEBUG %s/%d: aio_suspend received EINTR, sigev_notify=SIGEV_SIGNAL -- ok\n",
1826 __FILE__, __LINE__);
1827 }
1828 } else {
1829 sprintf(Errormsg,
1830 "%s/%d aio_suspend received EINTR, sigev_notify=%s, not ok\n",
1831 __FILE__, __LINE__,
1832 (aiocbp->aio_sigevent.sigev_notify ==
1833 SIGEV_SIGNAL ? "signal" : aiocbp->
1834 aio_sigevent.sigev_notify ==
1835 SIGEV_NONE ? "none" :
1836#ifdef SIGEV_CALLBACK
1837 aiocbp->aio_sigevent.sigev_notify ==
1838 SIGEV_CALLBACK ? "callback" :
1839#endif
1840 aiocbp->aio_sigevent.sigev_notify ==
1841 SIGEV_THREAD ? "thread" : "unknown"));
1842 return -errno;
1843 }
1844 } else if (ret) {
1845 sprintf(Errormsg,
1846 "%s/%d aio_suspend(fildes=%d, aioary, 1, NULL) failed, errno:%d %s",
1847 __FILE__, __LINE__, fd, errno, strerror(errno));
1848 return -errno;
whrb973f2b2000-05-05 19:34:50 +00001849 }
Wanlong Gao354ebb42012-12-07 10:10:04 +08001850#endif
1851
1852 } else if (method & LIO_WAIT_ACTIVE) {
1853 if (Debug_level > 2)
1854 printf("DEBUG %s/%d: wait method : active\n", __FILE__,
1855 __LINE__);
1856#ifdef CRAY
1857 sigon();
1858 /*
1859 * loop until sw_flag, sw_count or sw_error field elements
1860 * change to non-zero.
1861 */
1862 cnt = 0;
1863 while ((*statptr)->sw_flag == 0 &&
1864 (*statptr)->sw_count == 0 && (*statptr)->sw_error == 0) {
1865 cnt++;
1866 }
1867#else
1868 /* loop while aio_error() returns EINPROGRESS */
1869 cnt = 0;
1870 while (1) {
1871 ret = aio_error(aiocbp);
1872 if ((ret == 0) || (ret != EINPROGRESS)) {
1873 break;
1874 }
1875 ++cnt;
1876 }
whrb973f2b2000-05-05 19:34:50 +00001877
1878#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +08001879 if (Debug_level > 5 && cnt && (cnt % 50) == 0)
1880 printf("DEBUG %s/%d: wait active cnt = %d\n",
1881 __FILE__, __LINE__, cnt);
whrb973f2b2000-05-05 19:34:50 +00001882
Wanlong Gao354ebb42012-12-07 10:10:04 +08001883 } else if (method & LIO_WAIT_SIGPAUSE) {
1884 if (Debug_level > 2)
1885 printf("DEBUG %s/%d: wait method : sigpause\n",
1886 __FILE__, __LINE__);
whrb973f2b2000-05-05 19:34:50 +00001887#ifdef sgi
Wanlong Gao354ebb42012-12-07 10:10:04 +08001888 /* note: don't do the sigon() for CRAY in this case. why? -- roehrich 6/11/97 */
1889 if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL)
1890 sigrelse(aiocbp->aio_sigevent.sigev_signo);
1891 else {
1892 printf("DEBUG %s/%d: sigev_notify != SIGEV_SIGNAL\n",
1893 __FILE__, __LINE__);
1894 return -1;
1895 }
whrb973f2b2000-05-05 19:34:50 +00001896#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +08001897 pause();
whrb973f2b2000-05-05 19:34:50 +00001898
Wanlong Gao354ebb42012-12-07 10:10:04 +08001899 } else if (method & LIO_WAIT_SIGACTIVE) {
1900 if (Debug_level > 2)
1901 printf("DEBUG %s/%d: wait method : sigactive\n",
1902 __FILE__, __LINE__);
whrb973f2b2000-05-05 19:34:50 +00001903#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +08001904 sigon();
whrb973f2b2000-05-05 19:34:50 +00001905#else
Wanlong Gao354ebb42012-12-07 10:10:04 +08001906 if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL)
1907 sigrelse(aiocbp->aio_sigevent.sigev_signo);
1908 else {
1909 printf("DEBUG %s/%d: sigev_notify != SIGEV_SIGNAL\n",
1910 __FILE__, __LINE__);
1911 return -1;
1912 }
whrb973f2b2000-05-05 19:34:50 +00001913#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +08001914 /* loop waiting for signal */
1915 while (Received_signal == Rec_signal) {
whrb973f2b2000-05-05 19:34:50 +00001916#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +08001917 sigon();
whrb973f2b2000-05-05 19:34:50 +00001918#else
Wanlong Gao354ebb42012-12-07 10:10:04 +08001919 sigrelse(aiocbp->aio_sigevent.sigev_signo);
whrb973f2b2000-05-05 19:34:50 +00001920#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +08001921 }
whrb973f2b2000-05-05 19:34:50 +00001922
Wanlong Gao354ebb42012-12-07 10:10:04 +08001923 } else if (method & LIO_WAIT_NONE) {
1924 if (Debug_level > 2)
1925 printf("DEBUG %s/%d: wait method : none\n", __FILE__,
1926 __LINE__);
1927 /* It's broken because the aiocb/iosw is an automatic variable in
1928 * lio_{read,write}_buffer, so when the function returns and the
1929 * I/O completes there will be nowhere to write the I/O status.
1930 * It doesn't cause a problem on unicos--probably because of some
1931 * compiler quirk, or an accident. It causes POSIX async I/O
1932 * to core dump some threads. spr/pv 705909. 6/27/97 roehrich
1933 */
1934 sprintf(Errormsg,
1935 "%s/%d LIO_WAIT_NONE was selected (this is broken)\n",
1936 __FILE__, __LINE__);
whrb973f2b2000-05-05 19:34:50 +00001937#ifdef CRAY
Wanlong Gao354ebb42012-12-07 10:10:04 +08001938 sigon();
whrb973f2b2000-05-05 19:34:50 +00001939#endif
1940/* return 1;*/
Wanlong Gao354ebb42012-12-07 10:10:04 +08001941 return -1;
1942 } else {
1943 if (Debug_level > 2)
1944 printf("DEBUG %s/%d: no wait method was chosen\n",
1945 __FILE__, __LINE__);
1946 return -1;
1947 }
whrb973f2b2000-05-05 19:34:50 +00001948
Wanlong Gao354ebb42012-12-07 10:10:04 +08001949 return 0;
whrb973f2b2000-05-05 19:34:50 +00001950
Wanlong Gao354ebb42012-12-07 10:10:04 +08001951} /* end of lio_wait4asyncio */
whrb973f2b2000-05-05 19:34:50 +00001952
1953#endif /* ifndef linux */
subrata_modak26e07d52009-02-26 06:33:39 +00001954#endif
whrb973f2b2000-05-05 19:34:50 +00001955
1956#if UNIT_TEST
1957/***********************************************************************
1958 * The following code is provided as unit test.
1959 * Just define add "-DUNIT_TEST=1" to the cc line.
vapier45a8ba02009-07-20 10:59:32 +00001960 *
whrb973f2b2000-05-05 19:34:50 +00001961 * (rrl 04/96)
1962 ***********************************************************************/
1963struct unit_info_t {
Wanlong Gao354ebb42012-12-07 10:10:04 +08001964 int method;
1965 int sig;
1966 char *str;
1967} Unit_info[] = {
1968 {
1969 LIO_IO_SYNC, 0, "sync io"}, {
1970 LIO_IO_SYNCV, 0, "sync readv/writev"}, {
1971 LIO_IO_SYNCP, 0, "sync pread/pwrite"}, {
1972 LIO_IO_ASYNC, 0, "async io, def wait"}, {
1973 LIO_IO_SLISTIO, 0, "sync listio"}, {
1974 LIO_IO_ALISTIO, 0, "async listio, def wait"}, {
1975 LIO_IO_ASYNC | LIO_WAIT_ACTIVE, 0, "async active"}, {
1976 LIO_IO_ASYNC | LIO_WAIT_RECALL, 0, "async recall/suspend"}, {
1977 LIO_IO_ASYNC | LIO_WAIT_SIGPAUSE, SIGUSR1, "async sigpause"}, {
1978 LIO_IO_ASYNC | LIO_WAIT_SIGACTIVE, SIGUSR1, "async sigactive"}, {
1979 LIO_IO_ALISTIO | LIO_WAIT_ACTIVE, 0, "async listio active"}, {
1980 LIO_IO_ALISTIO | LIO_WAIT_RECALL, 0, "async listio recall"}, {
1981 LIO_IO_ALISTIO | LIO_WAIT_SIGACTIVE, SIGUSR1, "async listio sigactive"},
1982 {
1983 LIO_IO_ALISTIO | LIO_WAIT_SIGPAUSE, SIGUSR1, "async listio sigpause"},
1984 {
1985 LIO_IO_ASYNC, SIGUSR2, "async io, def wait, sigusr2"}, {
1986LIO_IO_ALISTIO, SIGUSR2, "async listio, def wait, sigusr2"},};
whrb973f2b2000-05-05 19:34:50 +00001987
Wanlong Gao354ebb42012-12-07 10:10:04 +08001988int main(argc, argv)
whrb973f2b2000-05-05 19:34:50 +00001989int argc;
1990char **argv;
1991{
Wanlong Gao354ebb42012-12-07 10:10:04 +08001992 extern char *optarg;
1993 extern int optind;
whrb973f2b2000-05-05 19:34:50 +00001994
Wanlong Gao354ebb42012-12-07 10:10:04 +08001995 int fd;
1996 char *err;
1997 char buffer[4096];
1998 int size = 4096;
1999 int ret;
2000 int ind;
2001 int iter = 3;
2002 int method;
2003 int exit_status = 0;
2004 int c;
2005 int i;
2006 char *symbols = NULL;
2007 int die_on_err = 0;
whrb973f2b2000-05-05 19:34:50 +00002008
Wanlong Gao354ebb42012-12-07 10:10:04 +08002009 while ((c = getopt(argc, argv, "s:di:")) != -1) {
2010 switch (c) {
2011 case 's':
2012 symbols = optarg;
2013 break;
2014 case 'd':
2015 ++die_on_err;
2016 break;
2017 case 'i':
2018 iter = atoi(optarg);
whrb973f2b2000-05-05 19:34:50 +00002019 break;
2020 }
whrb973f2b2000-05-05 19:34:50 +00002021 }
2022
Wanlong Gao354ebb42012-12-07 10:10:04 +08002023 if ((fd =
2024 open("unit_test_file", O_CREAT | O_RDWR | O_TRUNC, 0777)) == -1) {
2025 perror
2026 ("open(unit_test_file, O_CREAT|O_RDWR|O_TRUNC, 0777) failed");
2027 exit(1);
whrb973f2b2000-05-05 19:34:50 +00002028 }
2029
Wanlong Gao354ebb42012-12-07 10:10:04 +08002030 Debug_level = 9;
2031
2032 if (symbols != NULL) {
2033 if ((method = lio_parse_io_arg2(symbols, &err)) == -1) {
2034 printf
2035 ("lio_parse_io_arg2(%s, &err) failed, bad token starting at %s\n",
2036 symbols, err);
2037 if (die_on_err)
2038 exit(1);
2039 } else
2040 printf("lio_parse_io_arg2(%s, &err) returned %#o\n",
2041 symbols, method);
2042
2043 exit_status = 0;
2044 for (ind = 0; ind < iter; ind++) {
2045 memset(buffer, 'A', 4096);
2046 if (lseek(fd, 0, 0) == -1) {
2047 printf("lseek(fd,0,0), %d, failed, errno %d\n",
2048 __LINE__, errno);
2049 ++exit_status;
2050 }
2051 if ((ret = lio_write_buffer(fd, method, buffer,
2052 size, SIGUSR1, &err,
2053 0)) != size) {
2054 printf
2055 ("lio_write_buffer returned -1, err = %s\n",
2056 err);
2057 } else
2058 printf("lio_write_buffer returned %d\n", ret);
2059
2060 memset(buffer, 'B', 4096);
2061 if (lseek(fd, 0, 0) == -1) {
2062 printf("lseek(fd,0,0), %d, failed, errno %d\n",
2063 __LINE__, errno);
2064 ++exit_status;
2065 }
2066 if ((ret = lio_read_buffer(fd, method, buffer,
2067 size, SIGUSR2, &err,
2068 0)) != size) {
2069 printf
2070 ("lio_read_buffer returned -1, err = %s\n",
2071 err);
2072 } else
2073 printf("lio_read_buffer returned %d\n", ret);
2074
2075 for (i = 0; i < 4096; ++i) {
2076 if (buffer[i] != 'A') {
2077 printf(" buffer[%d] = %d\n", i,
2078 buffer[i]);
2079 ++exit_status;
2080 break;
2081 }
2082 }
2083
2084 if (exit_status)
2085 exit(exit_status);
2086
2087 }
2088
2089 unlink("unit_test_file");
2090 exit(0);
whrb973f2b2000-05-05 19:34:50 +00002091 }
2092
Wanlong Gao354ebb42012-12-07 10:10:04 +08002093 for (ind = 0; ind < sizeof(Unit_info) / sizeof(struct unit_info_t);
2094 ind++) {
whrb973f2b2000-05-05 19:34:50 +00002095
Wanlong Gao354ebb42012-12-07 10:10:04 +08002096 printf("\n********* write %s ***************\n",
2097 Unit_info[ind].str);
2098 if (lseek(fd, 0, 0) == -1) {
2099 printf("lseek(fd,0,0), %d, failed, errno %d\n",
2100 __LINE__, errno);
2101 ++exit_status;
2102 }
2103
2104 memset(buffer, 'A', 4096);
2105 if ((ret = lio_write_buffer(fd, Unit_info[ind].method, buffer,
2106 size, Unit_info[ind].sig, &err,
2107 0)) != size) {
2108 printf
2109 (">>>>> lio_write_buffer(fd,0%x,buffer,%d,%d,err,0) returned -1,\n err = %s\n",
2110 Unit_info[ind].method, size, Unit_info[ind].sig,
2111 err);
whrb973f2b2000-05-05 19:34:50 +00002112 ++exit_status;
Garrett Cooper903910d2010-11-23 09:27:44 -08002113 if (die_on_err)
whrb973f2b2000-05-05 19:34:50 +00002114 exit(exit_status);
Wanlong Gao354ebb42012-12-07 10:10:04 +08002115 } else {
2116 printf("lio_write_buffer returned %d\n", ret);
whrb973f2b2000-05-05 19:34:50 +00002117 }
whrb973f2b2000-05-05 19:34:50 +00002118
Wanlong Gao354ebb42012-12-07 10:10:04 +08002119 printf("\n********* read %s ***************\n",
2120 Unit_info[ind].str);
2121 if (lseek(fd, 0, 0) == -1) {
2122 printf("lseek(fd,0,0), %d, failed, errno %d\n",
2123 __LINE__, errno);
2124 ++exit_status;
2125 }
2126 memset(buffer, 'B', 4096);
2127 if ((ret = lio_read_buffer(fd, Unit_info[ind].method, buffer,
2128 size, Unit_info[ind].sig, &err,
2129 0)) != size) {
2130 printf
2131 (">>>>> lio_read_buffer(fd,0%x,buffer,%d,%d,err,0) returned -1,\n err = %s\n",
2132 Unit_info[ind].method, size, Unit_info[ind].sig,
2133 err);
2134 ++exit_status;
2135 if (die_on_err)
2136 exit(exit_status);
2137 } else {
2138 printf("lio_read_buffer returned %d\n", ret);
2139 }
whrb973f2b2000-05-05 19:34:50 +00002140
Wanlong Gao354ebb42012-12-07 10:10:04 +08002141 for (i = 0; i < 4096; ++i) {
2142 if (buffer[i] != 'A') {
2143 printf(" buffer[%d] = %d\n", i, buffer[i]);
2144 ++exit_status;
2145 if (die_on_err)
2146 exit(exit_status);
2147 break;
2148 }
2149 }
whrb973f2b2000-05-05 19:34:50 +00002150
Wanlong Gao354ebb42012-12-07 10:10:04 +08002151 fflush(stdout);
2152 fflush(stderr);
2153 sleep(1);
whrb973f2b2000-05-05 19:34:50 +00002154
Wanlong Gao354ebb42012-12-07 10:10:04 +08002155 }
2156
2157 unlink("unit_test_file");
2158
2159 exit(exit_status);
whrb973f2b2000-05-05 19:34:50 +00002160}
Garrett Cooper9ef7f2d2011-04-08 22:44:06 -07002161#endif