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>