summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_aio.c
diff options
context:
space:
mode:
authorjasone <jasone@FreeBSD.org>2000-02-23 07:44:25 +0000
committerjasone <jasone@FreeBSD.org>2000-02-23 07:44:25 +0000
commit8fc7b7d84141f685dba69b0e9575d46e5109241e (patch)
treee4524ed9c647cf61f52ad7d4b08db4aac83ba69d /sys/kern/vfs_aio.c
parentb89752e40d987dc003c45e59addd1ad23e1f4921 (diff)
downloadFreeBSD-src-8fc7b7d84141f685dba69b0e9575d46e5109241e.zip
FreeBSD-src-8fc7b7d84141f685dba69b0e9575d46e5109241e.tar.gz
Add the VFS_AIO config option and leave it off by default. Unless the
VFS_AIO option is specified, all aio-related syscalls return ENOSYS. The aio code is very fragile right now, and is unsuitable for default inclusion in a production shell box. Approved by: jkh
Diffstat (limited to 'sys/kern/vfs_aio.c')
-rw-r--r--sys/kern/vfs_aio.c160
1 files changed, 153 insertions, 7 deletions
diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c
index 467df8e..9ef54a7 100644
--- a/sys/kern/vfs_aio.c
+++ b/sys/kern/vfs_aio.c
@@ -47,6 +47,7 @@
#include <sys/aio.h>
#include <machine/limits.h>
+#include "opt_vfs_aio.h"
static long jobrefid;
@@ -1389,6 +1390,9 @@ aio_aqueue(struct proc *p, struct aiocb *job, int type)
int
aio_return(struct proc *p, struct aio_return_args *uap)
{
+#ifndef VFS_AIO
+ return ENOSYS;
+#else
int s;
int jobref;
struct aiocblist *cb, *ncb;
@@ -1449,6 +1453,7 @@ aio_return(struct proc *p, struct aio_return_args *uap)
splx(s);
return (EINVAL);
+#endif /* VFS_AIO */
}
/*
@@ -1457,6 +1462,9 @@ aio_return(struct proc *p, struct aio_return_args *uap)
int
aio_suspend(struct proc *p, struct aio_suspend_args *uap)
{
+#ifndef VFS_AIO
+ return ENOSYS;
+#else
struct timeval atv;
struct timespec ts;
struct aiocb *const *cbptr, *cbp;
@@ -1561,16 +1569,130 @@ aio_suspend(struct proc *p, struct aio_suspend_args *uap)
/* NOTREACHED */
return EINVAL;
+#endif /* VFS_AIO */
}
/*
- * aio_cancel at the kernel level is a NOOP right now. It might be possible to
- * support it partially in user mode, or in kernel mode later on.
+ * aio_cancel cancels any non-physio aio operations not currently in
+ * progress.
*/
int
aio_cancel(struct proc *p, struct aio_cancel_args *uap)
{
- return ENOSYS;
+#ifndef VFS_AIO
+ return ENOSYS;
+#else
+ struct kaioinfo *ki;
+ struct aiocblist *cbe, *cbn;
+ struct file *fp;
+ struct filedesc *fdp;
+ struct socket *so;
+ struct proc *po;
+ int s,error;
+ int cancelled=0;
+ int notcancelled=0;
+ struct vnode *vp;
+
+ fdp = p->p_fd;
+
+ fp = fdp->fd_ofiles[uap->fd];
+
+ if (fp == NULL) {
+ return EBADF;
+ }
+
+ if (fp->f_type == DTYPE_VNODE) {
+ vp = (struct vnode *)fp->f_data;
+
+ if (vn_isdisk(vp,&error)) {
+ p->p_retval[0] = AIO_NOTCANCELED;
+ return 0;
+ }
+ } else if (fp->f_type == DTYPE_SOCKET) {
+ so = (struct socket *)fp->f_data;
+
+ s = splnet();
+
+ for (cbe = TAILQ_FIRST(&so->so_aiojobq); cbe; cbe = cbn) {
+ cbn = TAILQ_NEXT(cbe, list);
+ if ((uap->aiocbp == NULL) ||
+ (uap->aiocbp == cbe->uuaiocb) ) {
+ po = cbe->userproc;
+ ki = po->p_aioinfo;
+ TAILQ_REMOVE(&so->so_aiojobq, cbe, list);
+ TAILQ_REMOVE(&ki->kaio_sockqueue, cbe, plist);
+ TAILQ_INSERT_TAIL(&ki->kaio_jobdone, cbe, plist);
+ if (ki->kaio_flags & KAIO_WAKEUP) {
+ wakeup(po);
+ }
+ cbe->jobstate = JOBST_JOBFINISHED;
+ cbe->uaiocb._aiocb_private.status=-1;
+ cbe->uaiocb._aiocb_private.error=ECANCELED;
+ cancelled++;
+ if (cbe->uaiocb.aio_sigevent.sigev_notify ==
+ SIGEV_SIGNAL)
+ psignal(cbe->userproc, cbe->uaiocb.aio_sigevent.sigev_signo);
+ if (uap->aiocbp)
+ break;
+ }
+ }
+
+ splx(s);
+
+ if ((cancelled) && (uap->aiocbp)) {
+ p->p_retval[0] = AIO_CANCELED;
+ return 0;
+ }
+
+ }
+
+ ki=p->p_aioinfo;
+
+ s = splnet();
+
+ for (cbe = TAILQ_FIRST(&ki->kaio_jobqueue); cbe; cbe = cbn) {
+ cbn = TAILQ_NEXT(cbe, plist);
+
+ if ((uap->fd == cbe->uaiocb.aio_fildes) &&
+ ((uap->aiocbp == NULL ) ||
+ (uap->aiocbp == cbe->uuaiocb))) {
+
+ if (cbe->jobstate == JOBST_JOBQGLOBAL) {
+ TAILQ_REMOVE(&aio_jobs, cbe, list);
+ TAILQ_REMOVE(&ki->kaio_jobqueue, cbe, plist);
+ TAILQ_INSERT_TAIL(&ki->kaio_jobdone, cbe,
+ plist);
+ cancelled++;
+ ki->kaio_queue_finished_count++;
+ cbe->jobstate = JOBST_JOBFINISHED;
+ cbe->uaiocb._aiocb_private.status = -1;
+ cbe->uaiocb._aiocb_private.error = ECANCELED;
+ if (cbe->uaiocb.aio_sigevent.sigev_notify ==
+ SIGEV_SIGNAL)
+ psignal(cbe->userproc, cbe->uaiocb.aio_sigevent.sigev_signo);
+ } else {
+ notcancelled++;
+ }
+ }
+ }
+
+ splx(s);
+
+
+ if (notcancelled) {
+ p->p_retval[0] = AIO_NOTCANCELED;
+ return 0;
+ }
+
+ if (cancelled) {
+ p->p_retval[0] = AIO_CANCELED;
+ return 0;
+ }
+
+ p->p_retval[0] = AIO_ALLDONE;
+
+ return 0;
+#endif /* VFS_AIO */
}
/*
@@ -1581,6 +1703,9 @@ aio_cancel(struct proc *p, struct aio_cancel_args *uap)
int
aio_error(struct proc *p, struct aio_error_args *uap)
{
+#ifndef VFS_AIO
+ return ENOSYS;
+#else
int s;
struct aiocblist *cb;
struct kaioinfo *ki;
@@ -1657,11 +1782,15 @@ aio_error(struct proc *p, struct aio_error_args *uap)
return fuword(&uap->aiocbp->_aiocb_private.error);
#endif
return EINVAL;
+#endif /* VFS_AIO */
}
int
aio_read(struct proc *p, struct aio_read_args *uap)
{
+#ifndef VFS_AIO
+ return ENOSYS;
+#else
struct filedesc *fdp;
struct file *fp;
struct uio auio;
@@ -1723,11 +1852,15 @@ aio_read(struct proc *p, struct aio_read_args *uap)
cnt -= auio.uio_resid;
p->p_retval[0] = cnt;
return error;
+#endif /* VFS_AIO */
}
int
aio_write(struct proc *p, struct aio_write_args *uap)
{
+#ifndef VFS_AIO
+ return ENOSYS;
+#else
struct filedesc *fdp;
struct file *fp;
struct uio auio;
@@ -1792,11 +1925,15 @@ aio_write(struct proc *p, struct aio_write_args *uap)
cnt -= auio.uio_resid;
p->p_retval[0] = cnt;
return error;
+#endif /* VFS_AIO */
}
int
lio_listio(struct proc *p, struct lio_listio_args *uap)
{
+#ifndef VFS_AIO
+ return ENOSYS;
+#else
int nent, nentqueued;
struct aiocb *iocb, * const *cbptr;
struct aiocblist *cb;
@@ -1956,6 +2093,7 @@ lio_listio(struct proc *p, struct lio_listio_args *uap)
}
return runningcode;
+#endif /* VFS_AIO */
}
/*
@@ -2053,6 +2191,9 @@ aio_physwakeup(struct buf *bp)
int
aio_waitcomplete(struct proc *p, struct aio_waitcomplete_args *uap)
{
+#ifndef VFS_AIO
+ return ENOSYS;
+#else
struct timeval atv;
struct timespec ts;
struct aiocb **cbptr;
@@ -2060,6 +2201,8 @@ aio_waitcomplete(struct proc *p, struct aio_waitcomplete_args *uap)
struct aiocblist *cb = NULL;
int error, s, timo;
+ suword(uap->aiocbp, (int)NULL);
+
timo = 0;
if (uap->timeout) {
/* Get timespec struct. */
@@ -2097,7 +2240,7 @@ aio_waitcomplete(struct proc *p, struct aio_waitcomplete_args *uap)
cb->inputcharge = 0;
}
aio_free_entry(cb);
- return 0;
+ return cb->uaiocb._aiocb_private.error;
}
s = splbio();
@@ -2106,18 +2249,21 @@ aio_waitcomplete(struct proc *p, struct aio_waitcomplete_args *uap)
suword(uap->aiocbp, (int)cb->uuaiocb);
p->p_retval[0] = cb->uaiocb._aiocb_private.status;
aio_free_entry(cb);
- return 0;
+ return cb->uaiocb._aiocb_private.error;
}
- splx(s);
ki->kaio_flags |= KAIO_WAKEUP;
error = tsleep(p, PRIBIO | PCATCH, "aiowc", timo);
+ splx(s);
- if (error < 0)
+ if (error == ERESTART)
+ return EINTR;
+ else if (error < 0)
return error;
else if (error == EINTR)
return EINTR;
else if (error == EWOULDBLOCK)
return EAGAIN;
}
+#endif /* VFS_AIO */
}
OpenPOWER on IntegriCloud