Annotation of libaitio/src/aio.c, revision 1.9

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.9     ! misho       6: * $Id: aio.c,v 1.8.34.1 2014/02/05 02:24:28 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.9     ! misho      15: Copyright 2004 - 2014
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:  */
1.8       misho      63: int
1.2       misho      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:  */
1.8       misho     142: int
1.2       misho     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:  */
1.8       misho     210: int
1.6       misho     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>