Annotation of libaitio/src/aio.c, revision 1.7
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.7 ! misho 6: * $Id: aio.c,v 1.6.14.1 2013/01/17 12:59:37 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.7 ! misho 15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
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:
1.7 ! misho 274: acb = e_calloc(sizeof(void*), nbufs);
1.6 misho 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) {
1.7 ! misho 281: acb[i] = e_malloc(sizeof(struct aiocb));
1.6 misho 282: if (!acb[i]) {
283: LOGERR;
284: for (i = 0; i < nbufs; i++)
285: if (acb[i])
1.7 ! misho 286: e_free(acb[i]);
! 287: e_free(acb);
1.6 misho 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])
1.7 ! misho 303: e_free(acb[i]);
! 304: e_free(acb);
1.6 misho 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])
1.7 ! misho 312: e_free(acb[i]);
1.6 misho 313: }
1.7 ! misho 314: e_free(acb);
1.6 misho 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
1.7 ! misho 365: acb = e_calloc(sizeof(void*), nbufs);
1.6 misho 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) {
1.7 ! misho 372: acb[i] = e_malloc(sizeof(struct aiocb));
1.6 misho 373: if (!acb[i]) {
374: LOGERR;
375: for (i = 0; i < nbufs; i++)
376: if (acb[i])
1.7 ! misho 377: e_free(acb[i]);
! 378: e_free(acb);
1.6 misho 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])
1.7 ! misho 394: e_free(acb[i]);
! 395: e_free(acb);
1.6 misho 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])
1.7 ! misho 403: e_free(acb[i]);
1.6 misho 404: }
1.7 ! misho 405: e_free(acb);
1.6 misho 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>