Annotation of libaitio/src/aio.c, revision 1.6
1.3 misho 1: /*************************************************************************
2: * (C) 2010 AITNET ltd - Sofia/Bulgaria - <misho@aitnet.org>
3: * by Michael Pounov <misho@elwix.org>
4: *
5: * $Author: misho $
1.6 ! misho 6: * $Id: aio.c,v 1.5.14.3 2012/08/02 00:38:24 misho Exp $
1.3 misho 7: *
8: **************************************************************************
9: The ELWIX and AITNET software is distributed under the following
10: terms:
11:
12: All of the documentation and software included in the ELWIX and AITNET
13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
14:
1.4 misho 15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
1.3 misho 16: by Michael Pounov <misho@elwix.org>. All rights reserved.
17:
18: Redistribution and use in source and binary forms, with or without
19: modification, are permitted provided that the following conditions
20: are met:
21: 1. Redistributions of source code must retain the above copyright
22: notice, this list of conditions and the following disclaimer.
23: 2. Redistributions in binary form must reproduce the above copyright
24: notice, this list of conditions and the following disclaimer in the
25: documentation and/or other materials provided with the distribution.
26: 3. All advertising materials mentioning features or use of this software
27: must display the following acknowledgement:
28: This product includes software developed by Michael Pounov <misho@elwix.org>
29: ELWIX - Embedded LightWeight unIX and its contributors.
30: 4. Neither the name of AITNET nor the names of its contributors
31: may be used to endorse or promote products derived from this software
32: without specific prior written permission.
33:
34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37: ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44: SUCH DAMAGE.
45: */
1.2 misho 46: #include "global.h"
47:
48:
1.6 ! misho 49: /* default AIO completion request timeout */
! 50: struct timespec aiots = { 10, 0 };
! 51:
! 52:
1.2 misho 53: /*
1.5 misho 54: * io_rread() - Raw VFS read function
1.4 misho 55: *
1.2 misho 56: * @fd = File handle
57: * @buf = Read buffer
58: * @nbytes = Read buffer size
59: * @offset = Read from position, if -1 read nbytes from current position
60: * @update = Update file handle position !0
61: * return: -1 error or !=-1 readed bytes
62: */
63: inline int
64: io_rread(int fd, void * __restrict buf, size_t nbytes, off_t offset, int update)
65: {
66: int ret;
67: #ifdef AIO_OPS
68: off_t old = 0;
1.6 ! misho 69: struct aiocb acb, *racb;
1.2 misho 70: #endif
71:
72: if (!buf) {
1.5 misho 73: io_SetErr(EINVAL, "Invalid arguments");
1.2 misho 74: return -1;
75: }
76: if (!nbytes)
77: return 0;
78: if (offset == -1) {
79: offset = lseek(fd, 0, SEEK_CUR);
80: if (offset == -1) {
81: LOGERR;
82: return -1;
83: }
84: }
85:
86: #ifdef AIO_OPS
87: /* This made for generate EOF for file */
88: if (!update && (old = lseek(fd, 0, SEEK_CUR)) == -1) {
89: LOGERR;
90: return -1;
91: }
92: if (offset >= lseek(fd, 0, SEEK_END))
93: return 0;
94: if (!update)
95: lseek(fd, old, SEEK_SET);
96:
97: memset(buf, 0, nbytes);
98: memset(&acb, 0, sizeof acb);
99: acb.aio_fildes = fd;
100: acb.aio_nbytes = nbytes;
101: acb.aio_buf = buf;
102: acb.aio_offset = offset;
103:
104: if (aio_read(&acb) == -1) {
105: LOGERR;
106: return -1;
107: }
108:
1.6 ! misho 109: #if 0
1.2 misho 110: while (aio_error(&acb) == EINPROGRESS);
111: ret = aio_return(&acb);
1.6 ! misho 112: #endif
! 113: ret = aio_waitcomplete(&racb, &aiots);
1.2 misho 114: if (ret == -1) {
115: LOGERR;
116: return -1;
1.6 ! misho 117: }
1.2 misho 118: #else
119: ret = pread(fd, buf, nbytes, offset);
120: if (ret == -1) {
121: LOGERR;
122: return -1;
123: }
124: #endif
125:
126: if (update)
127: lseek(fd, offset + ret, SEEK_SET);
128:
129: return ret;
130: }
131:
132: /*
1.5 misho 133: * io_rwrite() - Raw VFS write function
1.4 misho 134: *
1.2 misho 135: * @fd = File handle
136: * @buf = Write buffer
137: * @nbytes = Write bytes from buffer
138: * @offset = Write at position, if -1 write nbytes from current position
139: * @update = Update file handle position !0
1.6 ! misho 140: * return: -1 error or !=-1 written bytes
1.2 misho 141: */
142: inline int
143: io_rwrite(int fd, void * __restrict buf, size_t nbytes, off_t offset, int update)
144: {
145: int ret;
146: #ifdef AIO_OPS
1.6 ! misho 147: struct aiocb acb, *racb;
1.2 misho 148: #endif
149:
150: if (!buf) {
1.5 misho 151: io_SetErr(EINVAL, "Invalid arguments");
1.2 misho 152: return -1;
153: }
154: if (!nbytes)
155: return 0;
156: if (offset == -1) {
157: offset = lseek(fd, 0, SEEK_CUR);
158: if (offset == -1) {
159: LOGERR;
160: return -1;
161: }
162: }
163:
164: #ifdef AIO_OPS
165: memset(&acb, 0, sizeof acb);
166: acb.aio_fildes = fd;
167: acb.aio_nbytes = nbytes;
168: acb.aio_buf = buf;
169: acb.aio_offset = offset;
170:
171: if (aio_write(&acb) == -1) {
172: LOGERR;
173: return -1;
174: }
175:
1.6 ! misho 176: #if 0
1.2 misho 177: while (aio_error(&acb) == EINPROGRESS);
178: ret = aio_return(&acb);
1.6 ! misho 179: #endif
! 180: ret = aio_waitcomplete(&racb, &aiots);
1.2 misho 181: if (ret == -1) {
182: LOGERR;
183: return -1;
1.6 ! misho 184: }
1.2 misho 185: #else
186: ret = pwrite(fd, buf, nbytes, offset);
187: if (ret == -1) {
188: LOGERR;
189: return -1;
190: }
191: #endif
192:
193: if (update)
194: lseek(fd, offset + ret, SEEK_SET);
195:
196:
197: return ret;
198: }
1.6 ! misho 199:
! 200: #ifdef AIO_OPS
! 201: /*
! 202: * io_aiobulk() - AIO bulk R/W function
! 203: *
! 204: * @mode = Bulk wait mode
! 205: * @acbs = List of aiocb structures
! 206: * @nacb = Number of aiocb in list
! 207: * @sig = Event for completed operations, may be =NULL
! 208: * return: -1 error or 0 ok
! 209: */
! 210: inline int
! 211: io_aiobulk(int mode, struct aiocb ** __restrict acbs, int nacb, struct sigevent *sig)
! 212: {
! 213: int ret;
! 214:
! 215: if (!acbs) {
! 216: io_SetErr(EINVAL, "Invalid arguments");
! 217: return -1;
! 218: }
! 219: if (!nacb)
! 220: return 0;
! 221:
! 222: if ((ret = lio_listio(mode, acbs, nacb, sig)) == -1)
! 223: LOGERR;
! 224:
! 225: return ret;
! 226: }
! 227: #endif
! 228:
! 229: /*
! 230: * io_rreadv() - Raw VFS bulk read function
! 231: *
! 232: * @fd = File handle
! 233: * @bufs = Read buffers
! 234: * @nbufs = Number of read buffers
! 235: * @offset = Read from position, if -1 read nbytes from current position
! 236: * @update = Update file handle position !0
! 237: * return: -1 error or !=-1 readed bytes
! 238: */
! 239: int
! 240: io_rreadv(int fd, struct iovec * __restrict bufs, int nbufs, off_t offset, int update)
! 241: {
! 242: int ret;
! 243: #ifdef AIO_OPS
! 244: register int i;
! 245: off_t off, old = 0;
! 246: struct aiocb **acb;
! 247: #endif
! 248:
! 249: if (!bufs) {
! 250: io_SetErr(EINVAL, "Invalid arguments");
! 251: return -1;
! 252: }
! 253: if (!nbufs)
! 254: return 0;
! 255: if (offset == -1) {
! 256: offset = lseek(fd, 0, SEEK_CUR);
! 257: if (offset == -1) {
! 258: LOGERR;
! 259: return -1;
! 260: }
! 261: }
! 262:
! 263: #ifdef AIO_OPS
! 264: /* This made for generate EOF for file */
! 265: if (!update && (old = lseek(fd, 0, SEEK_CUR)) == -1) {
! 266: LOGERR;
! 267: return -1;
! 268: }
! 269: if (offset >= lseek(fd, 0, SEEK_END))
! 270: return 0;
! 271: if (!update)
! 272: lseek(fd, old, SEEK_SET);
! 273:
! 274: acb = io_calloc(sizeof(void*), nbufs);
! 275: if (!acb) {
! 276: LOGERR;
! 277: return -1;
! 278: }
! 279: memset(acb, 0, sizeof(void*) * nbufs);
! 280: for (i = 0, off = offset; i < nbufs; off += bufs[i++].iov_len) {
! 281: acb[i] = io_malloc(sizeof(struct aiocb));
! 282: if (!acb[i]) {
! 283: LOGERR;
! 284: for (i = 0; i < nbufs; i++)
! 285: if (acb[i])
! 286: io_free(acb[i]);
! 287: io_free(acb);
! 288: return -1;
! 289: } else
! 290: memset(acb[i], 0, sizeof(struct aiocb));
! 291: acb[i]->aio_fildes = fd;
! 292: acb[i]->aio_nbytes = bufs[i].iov_len;
! 293: acb[i]->aio_buf = bufs[i].iov_base;
! 294: acb[i]->aio_offset = off;
! 295: acb[i]->aio_lio_opcode = LIO_READ;
! 296: }
! 297:
! 298: ret = io_aiobulk(LIO_WAIT, acb, nbufs, NULL);
! 299: if (ret == -1) {
! 300: LOGERR;
! 301: for (i = 0; i < nbufs; i++)
! 302: if (acb[i])
! 303: io_free(acb[i]);
! 304: io_free(acb);
! 305: return -1;
! 306: }
! 307:
! 308: for (i = 0; i < nbufs; i++) {
! 309: bufs[i].iov_len = aio_return(acb[i]);
! 310: offset += bufs[i].iov_len;
! 311: if (acb[i])
! 312: io_free(acb[i]);
! 313: }
! 314: io_free(acb);
! 315: #else
! 316: ret = preadv(fd, bufs, nbufs, offset);
! 317: if (ret == -1) {
! 318: LOGERR;
! 319: return -1;
! 320: } else
! 321: offset += ret;
! 322: #endif
! 323:
! 324: if (update)
! 325: lseek(fd, offset, SEEK_SET);
! 326:
! 327: return ret;
! 328: }
! 329:
! 330: /*
! 331: * io_rwritev() - Raw VFS bulk write function
! 332: *
! 333: * @fd = File handle
! 334: * @bufs = Write buffers
! 335: * @nbufs = Number of write buffers
! 336: * @offset = Write to position, if -1 write nbytes to current position
! 337: * @update = Update file handle position !0
! 338: * return: -1 error or !=-1 written bytes
! 339: */
! 340: int
! 341: io_rwritev(int fd, struct iovec * __restrict bufs, int nbufs, off_t offset, int update)
! 342: {
! 343: int ret;
! 344: #ifdef AIO_OPS
! 345: register int i;
! 346: struct aiocb **acb;
! 347: off_t off;
! 348: #endif
! 349:
! 350: if (!bufs) {
! 351: io_SetErr(EINVAL, "Invalid arguments");
! 352: return -1;
! 353: }
! 354: if (!nbufs)
! 355: return 0;
! 356: if (offset == -1) {
! 357: offset = lseek(fd, 0, SEEK_CUR);
! 358: if (offset == -1) {
! 359: LOGERR;
! 360: return -1;
! 361: }
! 362: }
! 363:
! 364: #ifdef AIO_OPS
! 365: acb = io_calloc(sizeof(void*), nbufs);
! 366: if (!acb) {
! 367: LOGERR;
! 368: return -1;
! 369: } else
! 370: memset(acb, 0, sizeof(void*) * nbufs);
! 371: for (i = 0, off = offset; i < nbufs; off += bufs[i++].iov_len) {
! 372: acb[i] = io_malloc(sizeof(struct aiocb));
! 373: if (!acb[i]) {
! 374: LOGERR;
! 375: for (i = 0; i < nbufs; i++)
! 376: if (acb[i])
! 377: io_free(acb[i]);
! 378: io_free(acb);
! 379: return -1;
! 380: } else
! 381: memset(acb[i], 0, sizeof(struct aiocb));
! 382: acb[i]->aio_fildes = fd;
! 383: acb[i]->aio_nbytes = bufs[i].iov_len;
! 384: acb[i]->aio_buf = bufs[i].iov_base;
! 385: acb[i]->aio_offset = off;
! 386: acb[i]->aio_lio_opcode = LIO_WRITE;
! 387: }
! 388:
! 389: ret = io_aiobulk(LIO_WAIT, acb, nbufs, NULL);
! 390: if (ret == -1) {
! 391: LOGERR;
! 392: for (i = 0; i < nbufs; i++)
! 393: if (acb[i])
! 394: io_free(acb[i]);
! 395: io_free(acb);
! 396: return -1;
! 397: }
! 398:
! 399: for (i = 0; i < nbufs; i++) {
! 400: bufs[i].iov_len = aio_return(acb[i]);
! 401: offset += bufs[i].iov_len;
! 402: if (acb[i])
! 403: io_free(acb[i]);
! 404: }
! 405: io_free(acb);
! 406: #else
! 407: ret = pwritev(fd, bufs, nbufs, offset);
! 408: if (ret == -1) {
! 409: LOGERR;
! 410: return -1;
! 411: } else
! 412: offset += ret;
! 413: #endif
! 414:
! 415: if (update)
! 416: lseek(fd, offset, SEEK_SET);
! 417:
! 418: return ret;
! 419: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>