diff options
author | davidxu <davidxu@FreeBSD.org> | 2006-03-24 00:50:06 +0000 |
---|---|---|
committer | davidxu <davidxu@FreeBSD.org> | 2006-03-24 00:50:06 +0000 |
commit | 60f31ebe10822843d8445ecdc53d4f4b28f61d90 (patch) | |
tree | 257324f6dcb7c14a1bf789e5f41d8ec70a267b1c /sys/kern | |
parent | c5cf5122a1e3f22157d6f17431f244e0d307ee4b (diff) | |
download | FreeBSD-src-60f31ebe10822843d8445ecdc53d4f4b28f61d90.zip FreeBSD-src-60f31ebe10822843d8445ecdc53d4f4b28f61d90.tar.gz |
1. Move code for scanning pending I/O from aio_fsync to aio_aqueue,
it has less overhead.
2. Avoid scheduling task if maximum number of I/O threads is reached.
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/vfs_aio.c | 128 |
1 files changed, 51 insertions, 77 deletions
diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c index 8097744..46d3630 100644 --- a/sys/kern/vfs_aio.c +++ b/sys/kern/vfs_aio.c @@ -313,7 +313,7 @@ static int aio_free_entry(struct aiocblist *aiocbe); static void aio_process(struct aiocblist *aiocbe); static int aio_newproc(int *); static int aio_aqueue(struct thread *td, struct aiocb *job, - struct aioliojob *lio, int type, int osigev, uint64_t *jseqno); + struct aioliojob *lio, int type, int osigev); static void aio_physwakeup(struct buf *bp); static void aio_proc_rundown(void *arg, struct proc *p); static int aio_qphysio(struct proc *p, struct aiocblist *iocb); @@ -325,7 +325,7 @@ static void aio_bio_done_notify(struct proc *userp, struct aiocblist *aiocbe, in #define DONE_BUF 1 #define DONE_QUEUE 2 static int do_lio_listio(struct thread *td, struct lio_listio_args *uap, int oldsigev); -static void aio_kick(struct proc *userp); +static int aio_kick(struct proc *userp); static void aio_kick_nowait(struct proc *userp); static void aio_kick_helper(void *context, int pending); static int filt_aioattach(struct knote *kn); @@ -904,8 +904,7 @@ aio_bio_done_notify(struct proc *userp, struct aiocblist *aiocbe, int type) notification_done: if (aiocbe->jobflags & AIOCBLIST_CHECKSYNC) { TAILQ_FOREACH_SAFE(scb, &ki->kaio_syncqueue, list, scbn) { - if (scb->pending != -1 && - aiocbe->fd_file == scb->fd_file && + if (aiocbe->fd_file == scb->fd_file && aiocbe->seqno < scb->seqno) { if (--scb->pending == 0) { mtx_lock(&aio_job_mtx); @@ -1308,12 +1307,12 @@ aio_swake_cb(struct socket *so, struct sockbuf *sb) */ static int aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj, - int type, int oldsigev, uint64_t *jseqno) + int type, int oldsigev) { struct proc *p = td->td_proc; struct file *fp; struct socket *so; - struct aiocblist *aiocbe; + struct aiocblist *aiocbe, *cb; struct kaioinfo *ki; struct kevent kev; struct kqueue *kq; @@ -1342,7 +1341,6 @@ aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj, aiocbe = uma_zalloc(aiocb_zone, M_WAITOK | M_ZERO); aiocbe->inputcharge = 0; aiocbe->outputcharge = 0; - aiocbe->pending = -1; knlist_init(&aiocbe->klist, &p->p_mtx, NULL, NULL, NULL); if (oldsigev) { @@ -1408,7 +1406,7 @@ aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj, goto aqueue_fail; } - if (aiocbe->uaiocb.aio_offset == -1LL) { + if (opcode != LIO_SYNC && aiocbe->uaiocb.aio_offset == -1LL) { error = EINVAL; goto aqueue_fail; } @@ -1418,8 +1416,6 @@ aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj, mtx_lock(&aio_job_mtx); jid = jobrefid++; aiocbe->seqno = jobseqno++; - if (jseqno) - *jseqno = aiocbe->seqno; mtx_unlock(&aio_job_mtx); error = suword(&job->_aiocb_private.kernelinfo, jid); if (error) { @@ -1540,15 +1536,34 @@ queueit: TAILQ_INSERT_TAIL(&ki->kaio_jobqueue, aiocbe, plist); TAILQ_INSERT_TAIL(&ki->kaio_all, aiocbe, allist); if (opcode == LIO_SYNC) { - TAILQ_INSERT_TAIL(&ki->kaio_syncqueue, aiocbe, list); - aiocbe->jobstate = JOBST_JOBQSYNC; - } else { - mtx_lock(&aio_job_mtx); - TAILQ_INSERT_TAIL(&aio_jobs, aiocbe, list); - aiocbe->jobstate = JOBST_JOBQGLOBAL; - aio_kick_nowait(p); - mtx_unlock(&aio_job_mtx); + TAILQ_FOREACH(cb, &ki->kaio_jobqueue, plist) { + if (cb->fd_file == aiocbe->fd_file && + cb->uaiocb.aio_lio_opcode != LIO_SYNC && + cb->seqno < aiocbe->seqno) { + cb->jobflags |= AIOCBLIST_CHECKSYNC; + aiocbe->pending++; + } + } + TAILQ_FOREACH(cb, &ki->kaio_bufqueue, plist) { + if (cb->fd_file == aiocbe->fd_file && + cb->uaiocb.aio_lio_opcode != LIO_SYNC && + cb->seqno < aiocbe->seqno) { + cb->jobflags |= AIOCBLIST_CHECKSYNC; + aiocbe->pending++; + } + } + if (aiocbe->pending != 0) { + TAILQ_INSERT_TAIL(&ki->kaio_syncqueue, aiocbe, list); + aiocbe->jobstate = JOBST_JOBQSYNC; + PROC_UNLOCK(p); + goto done; + } } + mtx_lock(&aio_job_mtx); + TAILQ_INSERT_TAIL(&aio_jobs, aiocbe, list); + aiocbe->jobstate = JOBST_JOBQGLOBAL; + aio_kick_nowait(p); + mtx_unlock(&aio_job_mtx); PROC_UNLOCK(p); error = 0; done: @@ -1566,17 +1581,19 @@ aio_kick_nowait(struct proc *userp) TAILQ_REMOVE(&aio_freeproc, aiop, list); aiop->aiothreadflags &= ~AIOP_FREE; wakeup(aiop->aiothread); - } else { + } else if (((num_aio_resv_start + num_aio_procs) < max_aio_procs) && + ((ki->kaio_active_count + num_aio_resv_start) < + ki->kaio_maxactive_count)) { taskqueue_enqueue(taskqueue_aiod_bio, &ki->kaio_task); } } -static void +static int aio_kick(struct proc *userp) { struct kaioinfo *ki = userp->p_aioinfo; struct aiothreadlist *aiop; - int error; + int error, ret = 0; mtx_assert(&aio_job_mtx, MA_OWNED); retryproc: @@ -1595,7 +1612,10 @@ retryproc: num_aio_resv_start--; goto retryproc; } + } else { + ret = -1; } + return (ret); } static void @@ -1604,8 +1624,10 @@ aio_kick_helper(void *context, int pending) struct proc *userp = context; mtx_lock(&aio_job_mtx); - while (--pending >= 0) - aio_kick(userp); + while (--pending >= 0) { + if (aio_kick(userp)) + break; + } mtx_unlock(&aio_job_mtx); } @@ -1893,14 +1915,14 @@ int oaio_read(struct thread *td, struct oaio_read_args *uap) { - return aio_aqueue(td, (struct aiocb *)uap->aiocbp, NULL, LIO_READ, 1, NULL); + return aio_aqueue(td, (struct aiocb *)uap->aiocbp, NULL, LIO_READ, 1); } int aio_read(struct thread *td, struct aio_read_args *uap) { - return aio_aqueue(td, uap->aiocbp, NULL, LIO_READ, 0, NULL); + return aio_aqueue(td, uap->aiocbp, NULL, LIO_READ, 0); } /* syscall - asynchronous write to a file (REALTIME) */ @@ -1908,14 +1930,14 @@ int oaio_write(struct thread *td, struct oaio_write_args *uap) { - return aio_aqueue(td, (struct aiocb *)uap->aiocbp, NULL, LIO_WRITE, 1, NULL); + return aio_aqueue(td, (struct aiocb *)uap->aiocbp, NULL, LIO_WRITE, 1); } int aio_write(struct thread *td, struct aio_write_args *uap) { - return aio_aqueue(td, uap->aiocbp, NULL, LIO_WRITE, 0, NULL); + return aio_aqueue(td, uap->aiocbp, NULL, LIO_WRITE, 0); } /* syscall - list directed I/O (REALTIME) */ @@ -2039,7 +2061,7 @@ do_lio_listio(struct thread *td, struct lio_listio_args *uap, int oldsigev) for (i = 0; i < uap->nent; i++) { iocb = (struct aiocb *)(intptr_t)fuword(&cbptr[i]); if (((intptr_t)iocb != -1) && ((intptr_t)iocb != 0)) { - error = aio_aqueue(td, iocb, lj, LIO_NOP, oldsigev, NULL); + error = aio_aqueue(td, iocb, lj, LIO_NOP, oldsigev); if (error != 0) nerror++; } @@ -2213,62 +2235,14 @@ int aio_fsync(struct thread *td, struct aio_fsync_args *uap) { struct proc *p = td->td_proc; - struct aiocblist *cb, *scb; struct kaioinfo *ki; - struct aiocb uaiocb; - int error; - uint64_t jseqno; if (uap->op != O_SYNC) /* XXX lack of O_DSYNC */ return (EINVAL); - error = copyin(uap->aiocbp, &uaiocb, sizeof(struct aiocb)); - if (error) - return (error); ki = p->p_aioinfo; if (ki == NULL) aio_init_aioinfo(p); - ki = p->p_aioinfo; - error = aio_aqueue(td, uap->aiocbp, NULL, LIO_SYNC, 0, &jseqno); - if (error) - return (error); - PROC_LOCK(p); - TAILQ_FOREACH(scb, &ki->kaio_syncqueue, plist) { - if (scb->seqno == jseqno) - break; - } - if (scb == NULL) { - PROC_UNLOCK(p); - return (0); - } - scb->pending = 0; - TAILQ_FOREACH(cb, &ki->kaio_jobqueue, plist) { - if (cb->fd_file == scb->fd_file && - cb->uaiocb.aio_lio_opcode != LIO_SYNC && - cb->seqno < scb->seqno) { - cb->jobflags |= AIOCBLIST_CHECKSYNC; - scb->pending++; - } - } - TAILQ_FOREACH(cb, &ki->kaio_bufqueue, plist) { - if (cb->fd_file == scb->fd_file && - cb->uaiocb.aio_lio_opcode != LIO_SYNC && - cb->seqno < scb->seqno) { - cb->jobflags |= AIOCBLIST_CHECKSYNC; - scb->pending++; - } - } - if (scb->pending == 0) { - mtx_lock(&aio_job_mtx); - if (scb->jobstate == JOBST_JOBQSYNC) { - scb->jobstate = JOBST_JOBQGLOBAL; - TAILQ_REMOVE(&ki->kaio_syncqueue, scb, list); - TAILQ_INSERT_TAIL(&aio_jobs, scb, list); - aio_kick_nowait(p); - } - mtx_unlock(&aio_job_mtx); - } - PROC_UNLOCK(p); - return (0); + return aio_aqueue(td, uap->aiocbp, NULL, LIO_SYNC, 0); } /* kqueue attach function */ |