From owner-freebsd-stable@FreeBSD.ORG Thu Nov 29 19:41:30 2007 Return-Path: Delivered-To: freebsd-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id A569316A468 for ; Thu, 29 Nov 2007 19:41:30 +0000 (UTC) (envelope-from julian@elischer.org) Received: from outJ.internet-mail-service.net (outJ.internet-mail-service.net [216.240.47.233]) by mx1.freebsd.org (Postfix) with ESMTP id 8419913C442 for ; Thu, 29 Nov 2007 19:41:30 +0000 (UTC) (envelope-from julian@elischer.org) Received: from mx0.idiom.com (HELO idiom.com) (216.240.32.160) by out.internet-mail-service.net (qpsmtpd/0.40) with ESMTP; Thu, 29 Nov 2007 11:41:29 -0800 X-Client-Authorized: MaGic Cook1e X-Client-Authorized: MaGic Cook1e X-Client-Authorized: MaGic Cook1e Received: from julian-mac.elischer.org (nat.ironport.com [63.251.108.100]) by idiom.com (Postfix) with ESMTP id 11281126B58; Thu, 29 Nov 2007 11:41:29 -0800 (PST) Message-ID: <474F15E8.1000704@elischer.org> Date: Thu, 29 Nov 2007 11:41:28 -0800 From: Julian Elischer User-Agent: Thunderbird 2.0.0.9 (Macintosh/20071031) MIME-Version: 1.0 To: David Xu , re@freebsd.org, FreeBSD Stable Content-Type: multipart/mixed; boundary="------------040402040806080201000404" Cc: Subject: MFC TO 6.X (6.3?) to fix aio_return() ? X-BeenThere: freebsd-stable@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Production branch of FreeBSD source code List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 29 Nov 2007 19:41:30 -0000 This is a multi-part message in MIME format. --------------040402040806080201000404 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit This diff is a partial MFC (picking parts out of -current) that makes aio_return() return the error return of a completed AIO request. (as it does on othe OS's and in 7.x). The man page for 6.x and other OS's indicate that aio_return shoud return all the same results as a returning read() or write() including setting errno on error. in 6.x this does not happen. on 7.0 it does. The included test program can show the result when using gnop() to simulate IO errors. BTW the test program could be used as a start to sample code as to how to use kqueue and aio together. If people agree this is worth fixing, it would be nice to get it in 6.3 --------------040402040806080201000404 Content-Type: text/plain; x-mac-type="0"; x-mac-creator="0"; name="aio_return-6.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="aio_return-6.diff" Index: vfs_aio.c =================================================================== RCS file: /home/ncvs/src/sys/kern/vfs_aio.c,v retrieving revision 1.195.2.4 diff -d -u -r1.195.2.4 vfs_aio.c --- vfs_aio.c 9 Sep 2006 01:30:11 -0000 1.195.2.4 +++ vfs_aio.c 29 Nov 2007 19:26:12 -0000 @@ -1529,6 +1529,7 @@ struct aiocblist *cb, *ncb; struct aiocb *ujob; struct kaioinfo *ki; + int status, error; ujob = uap->aiocbp; jobref = fuword(&ujob->_aiocb_private.kernelinfo); @@ -1542,14 +1543,6 @@ TAILQ_FOREACH(cb, &ki->kaio_jobdone, plist) { if (((intptr_t) cb->uaiocb._aiocb_private.kernelinfo) == jobref) { - if (cb->uaiocb.aio_lio_opcode == LIO_WRITE) { - p->p_stats->p_ru.ru_oublock += - cb->outputcharge; - cb->outputcharge = 0; - } else if (cb->uaiocb.aio_lio_opcode == LIO_READ) { - p->p_stats->p_ru.ru_inblock += cb->inputcharge; - cb->inputcharge = 0; - } goto done; } } @@ -1565,15 +1558,33 @@ done: PROC_UNLOCK(p); if (cb != NULL) { - if (ujob == cb->uuaiocb) { - td->td_retval[0] = - cb->uaiocb._aiocb_private.status; - } else - td->td_retval[0] = EFAULT; - aio_free_entry(cb); - return (0); + status = cb->uaiocb._aiocb_private.status; + error = cb->uaiocb._aiocb_private.error; + if (ujob != cb->uuaiocb) { + /* check for a mismatch. is it possible? */ + /* (It's not in 7.x) */ + error = EFAULT; + } else { + if (error == 0) { + td->td_retval[0] = status; + } + if (cb->uaiocb.aio_lio_opcode == LIO_WRITE) { + p->p_stats->p_ru.ru_oublock += + cb->outputcharge; + cb->outputcharge = 0; + } else if (cb->uaiocb.aio_lio_opcode == LIO_READ) { + p->p_stats->p_ru.ru_inblock += cb->inputcharge; + cb->inputcharge = 0; + } + suword(&ujob->_aiocb_private.error, error); + suword(&ujob->_aiocb_private.status, status); + aio_free_entry(cb); + } + } else { + /* no such aiocb known */ + error = EINVAL; } - return (EINVAL); + return (error); } /* --------------040402040806080201000404 Content-Type: text/plain; name="try2.c" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="try2.c" #include #include #include #include #include #include #include #include #include #include #include #include #define BUFSIZE 512 #define TMOUT_SEC 5 #define TMOUT_NSEC 0 main() { int fd; int ret; struct aiocb my_aiocb; int kq; if ((kq = kqueue()) == -1) err(1, "kqueue"); fd = open("/dev/mfid0s1d.nop", O_RDONLY); if (fd < 0) perror("open"); /* Zero out the aiocb structure (recommended) */ bzero((char *)&my_aiocb, sizeof(struct aiocb)); /* Allocate a data buffer for the aiocb request */ my_aiocb.aio_buf = malloc(BUFSIZE + 1); if (!my_aiocb.aio_buf) perror("malloc"); /* Initialize the necessary fields in the aiocb */ my_aiocb.aio_fildes = fd; my_aiocb.aio_nbytes = BUFSIZE; my_aiocb.aio_offset = (512 * (100LL + 10)); my_aiocb.aio_sigevent.sigev_notify = SIGEV_KEVENT; my_aiocb.aio_sigevent.sigev_notify_kqueue = kq; /* udata for the created kqueue */ #if __FreeBSD_version > 700000 my_aiocb.aio_sigevent.sigev_value.sival_ptr = NULL; #else my_aiocb.aio_sigevent.sigev_value.sigval_ptr = NULL; #endif ret = aio_read(&my_aiocb); if (ret < 0) perror("aio_read"); #define USE_KQUEUE 1 #if USE_KQUEUE while (1) { int i; int n; int nchanges = 0; int nevents = 1; struct kevent ch[4]; struct kevent ev[4]; struct timespec timeout = {TMOUT_SEC, TMOUT_NSEC}; n = kevent(kq, ch, nchanges, ev, nevents, &timeout); if (n <= 0) { perror("kevent"); exit(1); } printf("%d events\n", n); for (i = 0; i < n; i++) { printf("event = 0x%x, %hd, %hx, 0x%x, 0x%x, 0x%x\n", ev[i].ident, ev[i].filter, ev[i].flags, ev[i].fflags, ev[i].data, ev[i].udata); if (ev[i].flags & (EV_ERROR | EV_EOF)) { if (ev[i].flags & EV_EOF) { printf("EV_EOF set\n"); } if (ev[i].flags & EV_ERROR) { printf("EV_ERROR set\n"); } /* error */ printf("errno from ev_data is %d\n", (int)ev[i].data); break; } else { printf("kevent returned valid data ready\n"); #if 0 if (ev[i].filter == EVFILT_READ) readable_fd(evi.ident); if (ev[i].filter == EVFILT_WRITE) writeable_fd(evi.ident); #endif } } if ((ret = aio_error(&my_aiocb)) != EINPROGRESS) { printf("aio_error returned %d\n", ret); } if ((ret = aio_return(&my_aiocb)) > 0) { printf("aio_return returned %d\n", ret); printf("aio_return said we have got data\n"); /* got ret bytes on the read */ } else { /* read failed, consult errno */ printf("aio_return returned %d\n", ret); perror("aio_return"); } break; } #else /* ! USE_KQUEUE */ while (aio_error(&my_aiocb) == EINPROGRESS) { printf("aio_error returned %d\n", ret); sleep (1); { if ((ret = aio_return(&my_aiocb)) > 0) { printf("aio_return returned %d\n", ret); printf("got data\n"); /* got ret bytes on the read */ } else { /* read failed, consult errno */ printf("aio_return returned %d\n", ret); perror("aio_return"); } #endif } #if 0 struct kevent { uintptr_t ident; /* identifier for this event */ short filter; /* filter for event */ u_short flags; /* action flags for kqueue */ u_int fflags; /* filter flag value */ intptr_t data; /* filter data value */ void *udata; /* opaque user data identifier */ }; struct __aiocb_private { long status; long error; void *kernelinfo; }; typedef struct aiocb { int aio_fildes; /* File descriptor */ off_t aio_offset; /* File offset for I/O */ volatile void *aio_buf;/* I/O buffer in process space */ size_t aio_nbytes; /* Number of bytes for I/O */ char __spare__ [sizeof(int) * 2 + sizeof(void *)]; /* osigevent. */ int aio_lio_opcode; /* LIO opcode */ int aio_reqprio; /* Request priority -- ignored */ struct __aiocb_private _aiocb_private; struct sigevent aio_sigevent; /* Signal to deliver */ } aiocb_t; #endif --------------040402040806080201000404--