File:  [ELWIX - Embedded LightWeight unIX -] / libaitio / src / aio.c
Revision 1.9: download - view: text, annotated - select for diffs - revision graph
Sat Feb 8 22:06:17 2014 UTC (10 years, 4 months ago) by misho
Branches: MAIN
CVS tags: io7_4, io7_3, io7_2, io7_1, io7_0, IO7_3, IO7_2, IO7_1, IO7_0, IO6_9, HEAD
version 6.9

    1: /*************************************************************************
    2: * (C) 2010 AITNET ltd - Sofia/Bulgaria - <misho@aitnet.org>
    3: *  by Michael Pounov <misho@elwix.org>
    4: *
    5: * $Author: misho $
    6: * $Id: aio.c,v 1.9 2014/02/08 22:06:17 misho Exp $
    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: 
   15: Copyright 2004 - 2014
   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: */
   46: #include "global.h"
   47: 
   48: 
   49: /* default AIO completion request timeout */
   50: struct timespec aiots = { 10, 0 };
   51: 
   52: 
   53: /*
   54:  * io_rread() - Raw VFS read function
   55:  *
   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: 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;
   69: 	struct aiocb acb, *racb;
   70: #endif
   71: 
   72: 	if (!buf) {
   73: 		io_SetErr(EINVAL, "Invalid arguments");
   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: 
  109: #if 0
  110: 	while (aio_error(&acb) == EINPROGRESS);
  111: 	ret = aio_return(&acb);
  112: #endif
  113: 	ret = aio_waitcomplete(&racb, &aiots);
  114: 	if (ret == -1) {
  115: 		LOGERR;
  116: 		return -1;
  117: 	}
  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: /*
  133:  * io_rwrite() - Raw VFS write function
  134:  *
  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
  140:  * return: -1 error or !=-1 written bytes
  141:  */
  142: 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
  147: 	struct aiocb acb, *racb;
  148: #endif
  149: 
  150: 	if (!buf) {
  151: 		io_SetErr(EINVAL, "Invalid arguments");
  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: 
  176: #if 0
  177: 	while (aio_error(&acb) == EINPROGRESS);
  178: 	ret = aio_return(&acb);
  179: #endif
  180: 	ret = aio_waitcomplete(&racb, &aiots);
  181: 	if (ret == -1) {
  182: 		LOGERR;
  183: 		return -1;
  184: 	}
  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: }
  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: 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 = e_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] = e_malloc(sizeof(struct aiocb));
  282: 		if (!acb[i]) {
  283: 			LOGERR;
  284: 			for (i = 0; i < nbufs; i++)
  285: 				if (acb[i])
  286: 					e_free(acb[i]);
  287: 			e_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: 				e_free(acb[i]);
  304: 		e_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: 			e_free(acb[i]);
  313: 	}
  314: 	e_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 = e_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] = e_malloc(sizeof(struct aiocb));
  373: 		if (!acb[i]) {
  374: 			LOGERR;
  375: 			for (i = 0; i < nbufs; i++)
  376: 				if (acb[i])
  377: 					e_free(acb[i]);
  378: 			e_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: 				e_free(acb[i]);
  395: 		e_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: 			e_free(acb[i]);
  404: 	}
  405: 	e_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>