mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-14 10:09:48 +00:00
Major cleanup and debugging of the new AIO/LIO code. The LIO code is
now corrected. New tunables/instrumentation added. The code is now likely "good enough to use." I will add the userland support soon. The "high performance" mode for raw devices is still missing, and will be added next. POSIX system calls that now appear to work: aio_cancel, aio_error, aio_read, aio_return, aio_suspend, aio_write, lio_listio. Missing, but to be added soon: aio_fsync.
This commit is contained in:
parent
31ef058922
commit
a624e84fff
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=30240
@ -13,7 +13,7 @@
|
||||
* bad that happens because of using this software isn't the responsibility
|
||||
* of the author. This software is distributed AS-IS.
|
||||
*
|
||||
* $Id: vfs_aio.c,v 1.3 1997/07/17 04:49:31 dyson Exp $
|
||||
* $Id: vfs_aio.c,v 1.4 1997/09/02 20:06:00 bde Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -42,6 +42,7 @@
|
||||
#include <sys/uio.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/signalvar.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
@ -63,6 +64,8 @@
|
||||
#define DIAGNOSTIC
|
||||
#endif
|
||||
|
||||
#define DEBUGAIO 1
|
||||
|
||||
static int jobrefid;
|
||||
|
||||
#define JOBST_NULL 0x0
|
||||
@ -77,6 +80,44 @@ static int jobrefid;
|
||||
#define MAX_AIO_QUEUE 1024 /* Bigger than AIO_LISTIO_MAX */
|
||||
#define TARGET_AIO_PROCS 64
|
||||
|
||||
int max_aio_procs = MAX_AIO_PROCS;
|
||||
int num_aio_procs = 0;
|
||||
int target_aio_procs = TARGET_AIO_PROCS;
|
||||
int max_queue_count = MAX_AIO_QUEUE;
|
||||
int num_queue_count = 0;
|
||||
|
||||
int max_aio_per_proc = MAX_AIO_PER_PROC,
|
||||
max_aio_queue_per_proc=MAX_AIO_QUEUE_PER_PROC;
|
||||
|
||||
|
||||
SYSCTL_NODE(_vfs, OID_AUTO, aio, CTLFLAG_RW, 0, "AIO mgmt");
|
||||
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_per_proc,
|
||||
CTLFLAG_RW, &max_aio_per_proc, 0, "");
|
||||
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_queue_per_proc,
|
||||
CTLFLAG_RW, &max_aio_queue_per_proc, 0, "");
|
||||
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_procs,
|
||||
CTLFLAG_RW, &max_aio_procs, 0, "");
|
||||
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, num_aio_procs,
|
||||
CTLFLAG_RD, &num_aio_procs, 0, "");
|
||||
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, num_queue_count,
|
||||
CTLFLAG_RD, &num_queue_count, 0, "");
|
||||
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, max_aio_queue,
|
||||
CTLFLAG_RW, &max_queue_count, 0, "");
|
||||
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, target_aio_procs,
|
||||
CTLFLAG_RW, &target_aio_procs, 0, "");
|
||||
|
||||
#if DEBUGAIO > 0
|
||||
static int debugaio;
|
||||
SYSCTL_INT(_vfs_aio, OID_AUTO, debugaio, CTLFLAG_RW, &debugaio, 0, "");
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Job queue item
|
||||
*/
|
||||
@ -114,12 +155,6 @@ TAILQ_HEAD (,aioproclist) aio_freeproc, aio_activeproc;
|
||||
TAILQ_HEAD(,aiocblist) aio_jobs; /* Async job list */
|
||||
TAILQ_HEAD(,aiocblist) aio_freejobs;
|
||||
|
||||
int max_aio_procs = MAX_AIO_PROCS;
|
||||
int num_aio_procs = 0;
|
||||
int target_aio_procs = TARGET_AIO_PROCS;
|
||||
|
||||
int max_queue_count = MAX_AIO_QUEUE;
|
||||
int num_queue_count = 0;
|
||||
|
||||
void aio_init_aioinfo(struct proc *p) ;
|
||||
void aio_onceonly(void *) ;
|
||||
@ -133,6 +168,7 @@ static void aio_marksuspend(struct proc *p, int njobs, int *joblist, int set) ;
|
||||
|
||||
SYSINIT(aio, SI_SUB_VFS, SI_ORDER_ANY, aio_onceonly, NULL);
|
||||
|
||||
|
||||
/*
|
||||
* Startup initialization
|
||||
*/
|
||||
@ -153,9 +189,9 @@ aio_init_aioinfo(struct proc *p) {
|
||||
if (p->p_aioinfo == NULL) {
|
||||
ki = malloc(sizeof (struct kaioinfo), M_AIO, M_WAITOK);
|
||||
p->p_aioinfo = ki;
|
||||
ki->kaio_maxactive_count = MAX_AIO_PER_PROC;
|
||||
ki->kaio_maxactive_count = max_aio_per_proc;
|
||||
ki->kaio_active_count = 0;
|
||||
ki->kaio_qallowed_count = MAX_AIO_QUEUE_PER_PROC;
|
||||
ki->kaio_qallowed_count = max_aio_queue_per_proc;
|
||||
ki->kaio_queue_count = 0;
|
||||
TAILQ_INIT(&ki->kaio_jobdone);
|
||||
TAILQ_INIT(&ki->kaio_jobqueue);
|
||||
@ -185,12 +221,15 @@ aio_free_entry(struct aiocblist *aiocbe) {
|
||||
if (aiocbe->jobflags & AIOCBLIST_ASYNCFREE)
|
||||
return 0;
|
||||
aiocbe->jobflags |= AIOCBLIST_RUNDOWN;
|
||||
tsleep(aiocbe, PRIBIO|PCATCH, "jobwai", 0);
|
||||
/*
|
||||
if (tsleep(aiocbe, PRIBIO|PCATCH, "jobwai", hz*5)) {
|
||||
aiocbe->jobflags |= AIOCBLIST_ASYNCFREE;
|
||||
aiocbe->jobflags &= ~AIOCBLIST_RUNDOWN;
|
||||
return 1;
|
||||
}
|
||||
aiocbe->jobflags &= ~AIOCBLIST_RUNDOWN;
|
||||
*/
|
||||
}
|
||||
aiocbe->jobflags &= ~AIOCBLIST_ASYNCFREE;
|
||||
|
||||
@ -201,6 +240,11 @@ aio_free_entry(struct aiocblist *aiocbe) {
|
||||
|
||||
--ki->kaio_queue_count;
|
||||
--num_queue_count;
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 0)
|
||||
printf("freeing entry: %d, %d\n",
|
||||
ki->kaio_queue_count, num_queue_count);
|
||||
#endif
|
||||
|
||||
if ( aiocbe->jobstate == JOBST_JOBQPROC) {
|
||||
aiop = aiocbe->jobaioproc;
|
||||
@ -228,6 +272,17 @@ aio_proc_rundown(struct proc *p) {
|
||||
if (ki == NULL)
|
||||
return;
|
||||
|
||||
while (ki->kaio_active_count > 0) {
|
||||
if (tsleep(ki, PRIBIO, "kaiowt", 60 * hz))
|
||||
break;
|
||||
}
|
||||
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 0)
|
||||
printf("Proc rundown: %d %d\n",
|
||||
num_queue_count, ki->kaio_queue_count);
|
||||
#endif
|
||||
|
||||
restart1:
|
||||
for ( aiocbe = TAILQ_FIRST(&ki->kaio_jobdone);
|
||||
aiocbe;
|
||||
@ -246,6 +301,7 @@ aio_proc_rundown(struct proc *p) {
|
||||
goto restart2;
|
||||
}
|
||||
free(ki, M_AIO);
|
||||
p->p_aioinfo = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -294,14 +350,19 @@ aio_process(struct aiocblist *aiocbe) {
|
||||
unsigned int fd;
|
||||
int cnt;
|
||||
int error;
|
||||
off_t offset;
|
||||
|
||||
userp = aiocbe->userproc;
|
||||
cb = &aiocbe->uaiocb;
|
||||
|
||||
#ifdef DEBUGAIO
|
||||
printf("fd: %d, offset: 0x%x, address: 0x%x, size: %d\n",
|
||||
cb->aio_fildes, (int) cb->aio_offset,
|
||||
cb->aio_buf, cb->aio_nbytes);
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 1)
|
||||
printf("AIO %s, fd: %d, offset: 0x%x, address: 0x%x, size: %d\n",
|
||||
cb->aio_lio_opcode == LIO_READ?"Read":"Write",
|
||||
cb->aio_fildes, (int) cb->aio_offset,
|
||||
cb->aio_buf, cb->aio_nbytes);
|
||||
#endif
|
||||
#if SLOW
|
||||
tsleep(curproc, PVM, "aioprc", hz);
|
||||
#endif
|
||||
fdp = curproc->p_fd;
|
||||
@ -316,7 +377,7 @@ aio_process(struct aiocblist *aiocbe) {
|
||||
|
||||
auio.uio_iov = &aiov;
|
||||
auio.uio_iovcnt = 1;
|
||||
auio.uio_offset = cb->aio_offset;
|
||||
auio.uio_offset = offset = cb->aio_offset;
|
||||
auio.uio_resid = cb->aio_nbytes;
|
||||
cnt = cb->aio_nbytes;
|
||||
auio.uio_segflg = UIO_USERSPACE;
|
||||
@ -338,6 +399,12 @@ aio_process(struct aiocblist *aiocbe) {
|
||||
psignal(userp, SIGPIPE);
|
||||
}
|
||||
}
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 1)
|
||||
printf("%s complete: error: %d, status: %d, nio: %d, resid: %d, offset: %d\n",
|
||||
cb->aio_lio_opcode == LIO_READ?"Read":"Write",
|
||||
error, cnt, cnt - auio.uio_resid, auio.uio_resid, (int) offset & 0xffffffff);
|
||||
#endif
|
||||
|
||||
cnt -= auio.uio_resid;
|
||||
cb->_aiocb_private.error = error;
|
||||
@ -391,10 +458,11 @@ aio_startproc(void *uproc)
|
||||
curproc->p_ucred->cr_groups[0] = 1;
|
||||
curproc->p_flag |= P_SYSTEM;
|
||||
|
||||
#ifdef DEBUGAIO
|
||||
printf("Started new process: %d\n", curproc->p_pid);
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 2)
|
||||
printf("Started new process: %d\n", curproc->p_pid);
|
||||
#endif
|
||||
wakeup(uproc);
|
||||
wakeup(&aio_freeproc);
|
||||
|
||||
while(1) {
|
||||
struct vmspace *myvm, *tmpvm;
|
||||
@ -406,7 +474,7 @@ aio_startproc(void *uproc)
|
||||
TAILQ_INSERT_HEAD(&aio_freeproc, aiop, list);
|
||||
aiop->aioprocflags |= AIOP_FREE;
|
||||
}
|
||||
tsleep(curproc, PZERO, "aiordy", 0);
|
||||
tsleep(cp, PRIBIO, "aiordy", 0);
|
||||
if (aiop->aioprocflags & AIOP_FREE) {
|
||||
TAILQ_REMOVE(&aio_freeproc, aiop, list);
|
||||
TAILQ_INSERT_TAIL(&aio_activeproc, aiop, list);
|
||||
@ -440,9 +508,23 @@ aio_startproc(void *uproc)
|
||||
}
|
||||
|
||||
ki->kaio_active_count++;
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 0)
|
||||
printf("process: pid: %d(%d), active: %d, queue: %d\n",
|
||||
cb->_aiocb_private.kernelinfo,
|
||||
userp->p_pid, ki->kaio_active_count, ki->kaio_queue_count);
|
||||
#endif
|
||||
aiocbe->jobaioproc = aiop;
|
||||
aio_process(aiocbe);
|
||||
--ki->kaio_active_count;
|
||||
if (ki->kaio_active_count == 0)
|
||||
wakeup(ki);
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 0)
|
||||
printf("DONE process: pid: %d(%d), active: %d, queue: %d\n",
|
||||
cb->_aiocb_private.kernelinfo,
|
||||
userp->p_pid, ki->kaio_active_count, ki->kaio_queue_count);
|
||||
#endif
|
||||
|
||||
aiocbe->jobstate = JOBST_JOBFINISHED;
|
||||
|
||||
@ -501,12 +583,13 @@ aio_newproc() {
|
||||
|
||||
cpu_set_fork_handler(p = pfind(rval[0]), aio_startproc, curproc);
|
||||
|
||||
#ifdef DEBUGAIO
|
||||
printf("Waiting for new process: %d, count: %d\n",
|
||||
curproc->p_pid, num_aio_procs);
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 2)
|
||||
printf("Waiting for new process: %d, count: %d\n",
|
||||
curproc->p_pid, num_aio_procs);
|
||||
#endif
|
||||
|
||||
error = tsleep(curproc, PZERO, "aiosta", 5*hz);
|
||||
error = tsleep(&aio_freeproc, PZERO, "aiosta", 5*hz);
|
||||
++num_aio_procs;
|
||||
|
||||
return error;
|
||||
@ -537,10 +620,21 @@ _aio_aqueue(struct proc *p, struct aiocb *job, int type) {
|
||||
error = copyin((caddr_t)job,
|
||||
(caddr_t) &aiocbe->uaiocb, sizeof aiocbe->uaiocb);
|
||||
if (error) {
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 0)
|
||||
printf("aio_aqueue: Copyin error: %d\n", error);
|
||||
#endif
|
||||
TAILQ_INSERT_HEAD(&aio_freejobs, aiocbe, list);
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the opcode
|
||||
*/
|
||||
if (type != LIO_NOP) {
|
||||
aiocbe->uaiocb.aio_lio_opcode = type;
|
||||
}
|
||||
opcode = aiocbe->uaiocb.aio_lio_opcode;
|
||||
|
||||
/*
|
||||
* Get the fd info for process
|
||||
@ -554,6 +648,10 @@ _aio_aqueue(struct proc *p, struct aiocb *job, int type) {
|
||||
if (fd >= fdp->fd_nfiles) {
|
||||
TAILQ_INSERT_HEAD(&aio_freejobs, aiocbe, list);
|
||||
if (type == 0) {
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 0)
|
||||
printf("aio_aqueue: Null type\n");
|
||||
#endif
|
||||
suword(&job->_aiocb_private.status, -1);
|
||||
suword(&job->_aiocb_private.error, EBADF);
|
||||
}
|
||||
@ -561,12 +659,17 @@ _aio_aqueue(struct proc *p, struct aiocb *job, int type) {
|
||||
}
|
||||
|
||||
fp = fdp->fd_ofiles[fd];
|
||||
if ((fp == NULL) || ((fp->f_flag & FWRITE) == 0)) {
|
||||
if ((fp == NULL) ||
|
||||
((opcode == LIO_WRITE) && ((fp->f_flag & FWRITE) == 0))) {
|
||||
TAILQ_INSERT_HEAD(&aio_freejobs, aiocbe, list);
|
||||
if (type == 0) {
|
||||
suword(&job->_aiocb_private.status, -1);
|
||||
suword(&job->_aiocb_private.error, EBADF);
|
||||
}
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 0)
|
||||
printf("aio_aqueue: Bad file descriptor\n");
|
||||
#endif
|
||||
return EBADF;
|
||||
}
|
||||
|
||||
@ -576,11 +679,16 @@ _aio_aqueue(struct proc *p, struct aiocb *job, int type) {
|
||||
suword(&job->_aiocb_private.status, -1);
|
||||
suword(&job->_aiocb_private.error, EINVAL);
|
||||
}
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 0)
|
||||
printf("aio_aqueue: bad offset\n");
|
||||
#endif
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
#ifdef DEBUGAIO
|
||||
printf("job addr: 0x%x, 0x%x, %d\n", job, &job->_aiocb_private.kernelinfo, jobrefid);
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 2)
|
||||
printf("job addr: 0x%x, 0x%x, %d\n", job, &job->_aiocb_private.kernelinfo, jobrefid);
|
||||
#endif
|
||||
|
||||
error = suword(&job->_aiocb_private.kernelinfo, jobrefid);
|
||||
@ -590,20 +698,20 @@ _aio_aqueue(struct proc *p, struct aiocb *job, int type) {
|
||||
suword(&job->_aiocb_private.status, -1);
|
||||
suword(&job->_aiocb_private.error, EINVAL);
|
||||
}
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 0)
|
||||
printf("aio_aqueue: fetch of kernelinfo from user space\n");
|
||||
#endif
|
||||
return error;
|
||||
}
|
||||
|
||||
aiocbe->uaiocb._aiocb_private.kernelinfo = (void *)jobrefid;
|
||||
#ifdef DEBUGAIO
|
||||
printf("aio_aqueue: New job: %d... ", jobrefid);
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 2)
|
||||
printf("aio_aqueue: New job: %d... ", jobrefid);
|
||||
#endif
|
||||
++jobrefid;
|
||||
|
||||
if (type != LIO_NOP) {
|
||||
aiocbe->uaiocb.aio_lio_opcode = type;
|
||||
}
|
||||
|
||||
opcode = aiocbe->uaiocb.aio_lio_opcode;
|
||||
if (opcode == LIO_NOP) {
|
||||
TAILQ_INSERT_HEAD(&aio_freejobs, aiocbe, list);
|
||||
if (type == 0) {
|
||||
@ -620,6 +728,10 @@ _aio_aqueue(struct proc *p, struct aiocb *job, int type) {
|
||||
suword(&job->_aiocb_private.status, -1);
|
||||
suword(&job->_aiocb_private.error, EINVAL);
|
||||
}
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 0)
|
||||
printf("aio_aqueue: invalid LIO op: %d\n", opcode);
|
||||
#endif
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
@ -633,8 +745,9 @@ _aio_aqueue(struct proc *p, struct aiocb *job, int type) {
|
||||
|
||||
retryproc:
|
||||
if (aiop = TAILQ_FIRST(&aio_freeproc)) {
|
||||
#ifdef DEBUGAIO
|
||||
printf("found a free AIO process\n");
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 0)
|
||||
printf("found a free AIO process\n");
|
||||
#endif
|
||||
TAILQ_REMOVE(&aio_freeproc, aiop, list);
|
||||
TAILQ_INSERT_TAIL(&aio_activeproc, aiop, list);
|
||||
@ -642,20 +755,29 @@ _aio_aqueue(struct proc *p, struct aiocb *job, int type) {
|
||||
TAILQ_INSERT_TAIL(&aiop->jobtorun, aiocbe, list);
|
||||
TAILQ_INSERT_TAIL(&ki->kaio_jobqueue, aiocbe, plist);
|
||||
aiocbe->jobstate = JOBST_JOBQPROC;
|
||||
|
||||
aiocbe->jobaioproc = aiop;
|
||||
wakeup(aiop->aioproc);
|
||||
} else if ((num_aio_procs < max_aio_procs) &&
|
||||
(ki->kaio_active_count < ki->kaio_maxactive_count)) {
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 1) {
|
||||
printf("aio_aqueue: starting new proc: num_aio_procs(%d), max_aio_procs(%d)\n", num_aio_procs, max_aio_procs);
|
||||
printf(" ki->kaio_active_count(%d), ki->kaio_maxactive_count(%d)\n", ki->kaio_active_count, ki->kaio_maxactive_count);
|
||||
}
|
||||
#endif
|
||||
if (error = aio_newproc()) {
|
||||
#ifdef DEBUGAIO
|
||||
printf("aio_aqueue: problem sleeping for starting proc: %d\n",
|
||||
error);
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 0)
|
||||
printf("aio_aqueue: problem sleeping for starting proc: %d\n",
|
||||
error);
|
||||
#endif
|
||||
}
|
||||
goto retryproc;
|
||||
} else {
|
||||
#ifdef DEBUGAIO
|
||||
printf("queuing to global queue\n");
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 0)
|
||||
printf("queuing to global queue\n");
|
||||
#endif
|
||||
TAILQ_INSERT_TAIL(&aio_jobs, aiocbe, list);
|
||||
TAILQ_INSERT_TAIL(&ki->kaio_jobqueue, aiocbe, plist);
|
||||
@ -702,6 +824,11 @@ aio_return(struct proc *p, struct aio_return_args *uap, int *retval) {
|
||||
if (jobref == -1)
|
||||
return EINVAL;
|
||||
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 0)
|
||||
printf("aio_return: jobref: %d\n", jobref);
|
||||
#endif
|
||||
|
||||
|
||||
for (cb = TAILQ_FIRST(&ki->kaio_jobdone);
|
||||
cb;
|
||||
@ -808,19 +935,14 @@ aio_suspend(struct proc *p, struct aio_suspend_args *uap, int *retval) {
|
||||
|
||||
for(i=0;i<uap->nent;i++) {
|
||||
cbp = (struct aiocb *) fuword((caddr_t) &cbptr[i]);
|
||||
#ifdef DEBUGAIO
|
||||
printf("cbp: %x\n", cbp);
|
||||
#if DEBUGAIO > 1
|
||||
if (debugaio > 2)
|
||||
printf("cbp: %x\n", cbp);
|
||||
#endif
|
||||
joblist[i] = fuword(&cbp->_aiocb_private.kernelinfo);
|
||||
cbptr++;
|
||||
}
|
||||
|
||||
#ifdef DEBUGAIO
|
||||
printf("Suspend, timeout: %d clocks, jobs:", timo);
|
||||
for(i=0;i<uap->nent;i++)
|
||||
printf(" %d", joblist[i]);
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
while (1) {
|
||||
for (cb = TAILQ_FIRST(&ki->kaio_jobdone);
|
||||
@ -834,31 +956,45 @@ aio_suspend(struct proc *p, struct aio_suspend_args *uap, int *retval) {
|
||||
}
|
||||
}
|
||||
|
||||
aio_marksuspend(p, uap->nent, joblist, 1);
|
||||
#ifdef DEBUGAIO
|
||||
printf("Suspending -- waiting for all I/O's to complete: ");
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 0) {
|
||||
printf("Suspend, timeout: %d clocks, jobs:", timo);
|
||||
for(i=0;i<uap->nent;i++)
|
||||
printf(" %d", joblist[i]);
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
aio_marksuspend(p, uap->nent, joblist, 1);
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 2) {
|
||||
printf("Suspending -- waiting for all I/O's to complete: ");
|
||||
for(i=0;i<uap->nent;i++)
|
||||
printf(" %d", joblist[i]);
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
error = tsleep(p, PRIBIO|PCATCH, "aiospn", timo);
|
||||
aio_marksuspend(p, uap->nent, joblist, 0);
|
||||
|
||||
if (error == EINTR) {
|
||||
#ifdef DEBUGAIO
|
||||
printf(" signal\n");
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 2)
|
||||
printf(" signal\n");
|
||||
#endif
|
||||
free(joblist, M_TEMP);
|
||||
return EINTR;
|
||||
} else if (error == EWOULDBLOCK) {
|
||||
#ifdef DEBUGAIO
|
||||
printf(" timeout\n");
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 2)
|
||||
printf(" timeout\n");
|
||||
#endif
|
||||
free(joblist, M_TEMP);
|
||||
return EAGAIN;
|
||||
}
|
||||
#ifdef DEBUGAIO
|
||||
printf("\n");
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 2)
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -940,6 +1076,10 @@ aio_read(struct proc *p, struct aio_read_args *uap, int *retval) {
|
||||
|
||||
pmodes = fuword(&uap->aiocbp->_aiocb_private.privatemodes);
|
||||
if ((pmodes & AIO_PMODE_SYNC) == 0) {
|
||||
#if DEBUGAIO > 1
|
||||
if (debugaio > 2)
|
||||
printf("queueing aio_read\n");
|
||||
#endif
|
||||
return aio_aqueue(p, (struct aiocb *) uap->aiocbp, LIO_READ);
|
||||
}
|
||||
|
||||
@ -1015,6 +1155,10 @@ aio_write(struct proc *p, struct aio_write_args *uap, int *retval) {
|
||||
*/
|
||||
pmodes = fuword(&uap->aiocbp->_aiocb_private.privatemodes);
|
||||
if ((pmodes & AIO_PMODE_SYNC) == 0) {
|
||||
#if DEBUGAIO > 1
|
||||
if (debugaio > 2)
|
||||
printf("queing aio_write\n");
|
||||
#endif
|
||||
return aio_aqueue(p, (struct aiocb *) uap->aiocbp, LIO_WRITE);
|
||||
}
|
||||
|
||||
@ -1076,29 +1220,48 @@ lio_listio(struct proc *p, struct lio_listio_args *uap, int *retval) {
|
||||
int error, runningcode;
|
||||
int i;
|
||||
|
||||
if ((uap->mode != LIO_NOWAIT) && (uap->mode != LIO_WAIT))
|
||||
if ((uap->mode != LIO_NOWAIT) && (uap->mode != LIO_WAIT)) {
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 0)
|
||||
printf("lio_listio: bad mode: %d\n", uap->mode);
|
||||
#endif
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
nent = uap->nent;
|
||||
if (nent > AIO_LISTIO_MAX)
|
||||
if (nent > AIO_LISTIO_MAX) {
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 0)
|
||||
printf("lio_listio: nent > AIO_LISTIO_MAX: %d > %d\n", nent, AIO_LISTIO_MAX);
|
||||
#endif
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (p->p_aioinfo == NULL) {
|
||||
aio_init_aioinfo(p);
|
||||
}
|
||||
|
||||
if ((nent + num_queue_count) > max_queue_count)
|
||||
if ((nent + num_queue_count) > max_queue_count) {
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 0)
|
||||
printf("lio_listio: (nent(%d) + num_queue_count(%d)) > max_queue_count(%d)\n", nent, num_queue_count, max_queue_count);
|
||||
#endif
|
||||
return EAGAIN;
|
||||
}
|
||||
|
||||
ki = p->p_aioinfo;
|
||||
if ((nent + ki->kaio_queue_count) > ki->kaio_qallowed_count)
|
||||
if ((nent + ki->kaio_queue_count) > ki->kaio_qallowed_count) {
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 0)
|
||||
printf("lio_listio: (nent(%d) + ki->kaio_queue_count(%d)) > ki->kaio_qallowed_count(%d)\n", nent, ki->kaio_queue_count, ki->kaio_qallowed_count);
|
||||
#endif
|
||||
return EAGAIN;
|
||||
}
|
||||
|
||||
/*
|
||||
* reserve resources, remember that we have to unwind part of them sometimes
|
||||
*/
|
||||
num_queue_count += nent;
|
||||
ki->kaio_queue_count += nent;
|
||||
*/
|
||||
nentqueued = 0;
|
||||
|
||||
/*
|
||||
@ -1109,14 +1272,30 @@ lio_listio(struct proc *p, struct lio_listio_args *uap, int *retval) {
|
||||
cbptr = uap->acb_list;
|
||||
for(i = 0; i < uap->nent; i++) {
|
||||
iocb = (struct aiocb *) fuword((caddr_t) &cbptr[i]);
|
||||
error = aio_aqueue(p, iocb, 0);
|
||||
error = _aio_aqueue(p, iocb, 0);
|
||||
if (error == 0)
|
||||
nentqueued++;
|
||||
}
|
||||
|
||||
if (nentqueued == 0)
|
||||
/*
|
||||
* If we haven't queued any, then just return error
|
||||
*/
|
||||
if (nentqueued == 0) {
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 0)
|
||||
printf("lio_listio: none queued\n");
|
||||
#endif
|
||||
return EIO;
|
||||
}
|
||||
|
||||
#if DEBUGAIO > 0
|
||||
if (debugaio > 0)
|
||||
printf("lio_listio: %d queued\n", nentqueued);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Calculate the appropriate error return
|
||||
*/
|
||||
runningcode = 0;
|
||||
if (nentqueued != nent)
|
||||
runningcode = EIO;
|
||||
@ -1127,14 +1306,25 @@ lio_listio(struct proc *p, struct lio_listio_args *uap, int *retval) {
|
||||
int found;
|
||||
int jobref, command, status;
|
||||
|
||||
/*
|
||||
* Fetch address of the control buf pointer in user space
|
||||
*/
|
||||
iocb = (struct aiocb *) fuword((caddr_t) &cbptr[i]);
|
||||
|
||||
/*
|
||||
* Fetch the associated command from user space
|
||||
*/
|
||||
command = fuword(&iocb->aio_lio_opcode);
|
||||
if (command == LIO_NOP)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If the status shows error or complete, then skip this entry.
|
||||
*/
|
||||
status = fuword(&iocb->_aiocb_private.status);
|
||||
if (status == -1)
|
||||
if (status != 0)
|
||||
continue;
|
||||
|
||||
jobref = fuword(&iocb->_aiocb_private.kernelinfo);
|
||||
|
||||
found = 0;
|
||||
@ -1150,6 +1340,9 @@ lio_listio(struct proc *p, struct lio_listio_args *uap, int *retval) {
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If all I/Os have been disposed of, then we can return
|
||||
*/
|
||||
if (i == uap->nent) {
|
||||
return runningcode;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user