diff options
author | Thordur I. Bjornsson <thib@cvs.openbsd.org> | 2009-08-20 15:04:25 +0000 |
---|---|---|
committer | Thordur I. Bjornsson <thib@cvs.openbsd.org> | 2009-08-20 15:04:25 +0000 |
commit | c426e8990305c5a67004e693537df185276fa1f1 (patch) | |
tree | ec31fc944fe3e08fd4af4ef6c7ffb9e74e7e8076 | |
parent | f4720dcab9e25893c45de1617edcd35a8da7377b (diff) |
Rework the way we do async I/O in nfs. Introduce separate buf queues for
each mount, and when work is "found", peg an aiod to that mount todo the
I/O. Make nfs_asyncio() a bit smarter when deciding when to do asyncio
and when to force it sync, this is done by keeping the aiod's one two lists,
an "idle" and an "all" list, so asyncio is only done when there are aiods
hanging around todo it for us or are already pegged to the mount.
Idea liked by at least beck@ (and I think art@).
Extensive testing done by myself and jasper and a few others on various
arch's.
Ideas/Code from Net/Free.
OK blambert@.
-rw-r--r-- | sys/conf/files | 3 | ||||
-rw-r--r-- | sys/nfs/nfs.h | 7 | ||||
-rw-r--r-- | sys/nfs/nfs_aiod.c | 217 | ||||
-rw-r--r-- | sys/nfs/nfs_bio.c | 75 | ||||
-rw-r--r-- | sys/nfs/nfs_subs.c | 6 | ||||
-rw-r--r-- | sys/nfs/nfs_syscalls.c | 136 | ||||
-rw-r--r-- | sys/nfs/nfs_var.h | 10 | ||||
-rw-r--r-- | sys/nfs/nfs_vfsops.c | 29 | ||||
-rw-r--r-- | sys/nfs/nfs_vnops.c | 4 | ||||
-rw-r--r-- | sys/nfs/nfsmount.h | 5 | ||||
-rw-r--r-- | sys/nfs/nfsnode.h | 22 |
11 files changed, 329 insertions, 185 deletions
diff --git a/sys/conf/files b/sys/conf/files index bbfedc902bd..a6aa0dcb07e 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,4 +1,4 @@ -# $OpenBSD: files,v 1.470 2009/08/09 23:04:49 miod Exp $ +# $OpenBSD: files,v 1.471 2009/08/20 15:04:24 thib Exp $ # $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 @@ -906,6 +906,7 @@ file netnatm/natm_pcb.c natm file netnatm/natm_proto.c natm file netnatm/natm.c natm file nfs/krpc_subr.c nfsclient +file nfs/nfs_aiod.c nfsclient file nfs/nfs_bio.c nfsclient file nfs/nfs_boot.c nfsclient file nfs/nfs_debug.c nfsclient & ddb diff --git a/sys/nfs/nfs.h b/sys/nfs/nfs.h index 8e092f5cafc..1e801af776d 100644 --- a/sys/nfs/nfs.h +++ b/sys/nfs/nfs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs.h,v 1.48 2009/08/14 21:16:13 thib Exp $ */ +/* $OpenBSD: nfs.h,v 1.49 2009/08/20 15:04:24 thib Exp $ */ /* $NetBSD: nfs.h,v 1.10.4.1 1996/05/27 11:23:56 fvdl Exp $ */ /* @@ -55,7 +55,8 @@ #define NFS_READDIRSIZE 8192 /* Def. readdir size */ #define NFS_DEFRAHEAD 1 /* Def. read ahead # blocks */ #define NFS_MAXRAHEAD 4 /* Max. read ahead # blocks */ -#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */ +#define NFS_MAXASYNCDAEMON 64 /* Max. # of aiods runnable. */ +#define NFS_DEFASYNCDAEMON 4 /* Def. # of aiods runnable. */ /* * Ideally, NFS_DIRBLKSIZ should be bigger, but I've seen servers with @@ -189,8 +190,6 @@ struct nfsstats { * by them and break. */ #ifdef _KERNEL -extern int nfs_niothreads; - struct uio; struct buf; struct vattr; struct nameidata; /* XXX */ #define NFSINT_SIGMASK (sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGKILL)| \ diff --git a/sys/nfs/nfs_aiod.c b/sys/nfs/nfs_aiod.c new file mode 100644 index 00000000000..a3425163ee0 --- /dev/null +++ b/sys/nfs/nfs_aiod.c @@ -0,0 +1,217 @@ +/* $OpenBSD: nfs_aiod.c,v 1.1 2009/08/20 15:04:24 thib Exp $ */ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/proc.h> +#include <sys/malloc.h> +#include <sys/mount.h> +#include <sys/vnode.h> +#include <sys/kthread.h> +#include <sys/rwlock.h> +#include <sys/signalvar.h> +#include <sys/queue.h> +#include <sys/mutex.h> + +#include <nfs/rpcv2.h> +#include <nfs/nfsproto.h> +#include <nfs/nfs.h> +#include <nfs/nfsnode.h> +#include <nfs/nfs_var.h> +#include <nfs/nfsmount.h> + +/* The nfs_aiodl_mtx mutex protects the two lists. */ +struct mutex nfs_aiodl_mtx; +struct nfs_aiodhead nfs_aiods_all; +struct nfs_aiodhead nfs_aiods_idle; + +/* Current number of "running" aiods. Defaults to NFS_DEFASYNCDAEMON (4). */ +int nfs_numaiods = -1; + +/* Maximum # of buf to queue on an aiod. */ +int nfs_aiodbufqmax; + +/* + * Asynchronous I/O threads for client nfs. + * They do read-ahead and write-behind operations on the block I/O cache. + * Never returns unless it fails or gets killed. + */ +void +nfs_aiod(void *arg) +{ + struct nfs_aiod *aiod; + struct nfsmount *nmp; + struct proc *p; + struct buf *bp; + int error; + + p = (struct proc *)arg; + error = 0; + + aiod = malloc(sizeof(*aiod), M_TEMP, M_WAITOK|M_ZERO); + mtx_enter(&nfs_aiodl_mtx); + LIST_INSERT_HEAD(&nfs_aiods_all, aiod, nad_all); + mtx_leave(&nfs_aiodl_mtx); + nfs_numaiods++; + + /* + * Enforce an upper limit on how many bufs we'll queue up for + * a given aiod. This is arbitrarily chosen to be a quarter of + * the number of bufs in the system, divided evenly between + * the running aiods. + * + * Since the number of bufs in the system is dynamic, and the + * aiods are usually started up very early (during boot), the + * number of buffers available is pretty low, so the limit we + * enforce is way to low: So, always allow a minimum of 64 bufs. + * XXX: Footshooting. + */ + nfs_aiodbufqmax = max((bcstats.numbufs / 4) / nfs_numaiods, 64); + + +loop: /* Loop around until SIGKILL */ + mtx_enter(&nfs_aiodl_mtx); + LIST_INSERT_HEAD(&nfs_aiods_idle, aiod, nad_idle); + mtx_leave(&nfs_aiodl_mtx); + + while (1) { + nmp = aiod->nad_mnt; + if (nmp) { + aiod->nad_mnt = NULL; + break; + } + + error = tsleep(aiod, PWAIT, "nioidle", 0); + if (error) + goto out; + + /* + * Wakeup for this aiod happens in one of the following + * situations: + * - The thread is being asked to exit by nfs_set_naiod(), or + * - nfs_asyncio() has found work for this thread on a mount. + * + * In the former case, check to see if nfs_asyncio() has just + * found some work for this thread, and if so, ignore it until + * later. + */ + if (aiod->nad_exiting) { + if (aiod->nad_mnt == NULL) + goto out1; + else + break; + } + } + + while ((bp = TAILQ_FIRST(&nmp->nm_bufq)) != NULL) { + /* Take one off the front of the list */ + TAILQ_REMOVE(&nmp->nm_bufq, bp, b_freelist); + nmp->nm_bufqlen--; + nfs_doio(bp, NULL); + } + + KASSERT(nmp->nm_naiods > 0); + nmp->nm_naiods--; + if (aiod->nad_exiting) + goto out1; + + goto loop; + +out: + mtx_enter(&nfs_aiodl_mtx); + LIST_REMOVE(aiod, nad_idle); + mtx_leave(&nfs_aiodl_mtx); +out1: + free(aiod, M_TEMP); + nfs_numaiods--; + /* Rejust the limit of bufs to queue. See comment above. */ + nfs_aiodbufqmax = max((bcstats.numbufs / 4) / nfs_numaiods, 64); + kthread_exit(error); +} + +int +nfs_set_naiod(int howmany) +{ + struct nfs_aiod *aiod; + struct proc *p; + int want, error, dolock; + + KASSERT(howmany >= 0); + + error = 0; + dolock = 1; + + if (nfs_numaiods == -1) + nfs_numaiods = 0; + + want = howmany - nfs_numaiods; + + if (want > 0) { + /* Add more. */ + want = min(want, NFS_MAXASYNCDAEMON); + while (want > 0) { + error = kthread_create(nfs_aiod, p, &p, "nfsaio"); + if (error) + return (error); + want--; + } + } else if (want < 0) { + /* Get rid of some. */ + want = -want; + want = min(want, nfs_numaiods); + + /* Favour idle aiod's. */ + mtx_enter(&nfs_aiodl_mtx); + while (!LIST_EMPTY(&nfs_aiods_idle) && want > 0) { + aiod = LIST_FIRST(&nfs_aiods_idle); + LIST_REMOVE(aiod, nad_idle); + LIST_REMOVE(aiod, nad_all); /* Yuck. */ + aiod->nad_exiting = 1; + wakeup(aiod); + want--; + } + + while (!LIST_EMPTY(&nfs_aiods_all) && want > 0) { + aiod = LIST_FIRST(&nfs_aiods_all); + LIST_REMOVE(aiod, nad_all); + aiod->nad_exiting = 1; + wakeup(aiod); + want--; + } + mtx_leave(&nfs_aiodl_mtx); + } + /* ignore the want == nfs_numaiods case, since it means no work */ + + return (error); +} diff --git a/sys/nfs/nfs_bio.c b/sys/nfs/nfs_bio.c index 215470b5da9..6b17f779e6d 100644 --- a/sys/nfs/nfs_bio.c +++ b/sys/nfs/nfs_bio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs_bio.c,v 1.62 2009/07/28 11:19:43 art Exp $ */ +/* $OpenBSD: nfs_bio.c,v 1.63 2009/08/20 15:04:24 thib Exp $ */ /* $NetBSD: nfs_bio.c,v 1.25.4.2 1996/07/08 20:47:04 jtc Exp $ */ /* @@ -57,10 +57,7 @@ #include <nfs/nfsnode.h> #include <nfs/nfs_var.h> -extern int nfs_numasync; extern struct nfsstats nfsstats; -struct nfs_bufqhead nfs_bufq; -uint32_t nfs_bufqmax, nfs_bufqlen; /* * Vnode op for read using bio @@ -150,7 +147,7 @@ nfs_bioread(vp, uio, ioflag, cred) /* * Start the read ahead(s), as required. */ - if (nfs_numasync > 0 && nmp->nm_readahead > 0) { + if (nfs_numaiods > 0 && nmp->nm_readahead > 0) { for (nra = 0; nra < nmp->nm_readahead && (lbn + 1 + nra) * biosize < np->n_size; nra++) { rabn = (lbn + 1 + nra) * (biosize / DEV_BSIZE); @@ -506,25 +503,71 @@ nfs_vinvalbuf(struct vnode *vp, int flags, struct ucred *cred, struct proc *p) * are all hung on a dead server. */ int -nfs_asyncio(bp) - struct buf *bp; +nfs_asyncio(struct buf *bp) { - if (nfs_numasync == 0) + struct nfs_aiod *aiod; + struct nfsmount *nmp; + int gotone, error; + + aiod = NULL; + nmp = VFSTONFS(bp->b_vp->v_mount); + gotone = error = 0; + + mtx_enter(&nfs_aiodl_mtx); + aiod = LIST_FIRST(&nfs_aiods_idle); + if (aiod) { + /* + * Found an avilable aiod, wake it up and send + * it to work on this mount. + */ + LIST_REMOVE(aiod, nad_idle); + mtx_leave(&nfs_aiodl_mtx); + gotone = 1; + KASSERT(aiod->nad_mnt == NULL); + aiod->nad_mnt = nmp; + nmp->nm_naiods++; + wakeup(aiod); + } else { + mtx_leave(&nfs_aiodl_mtx); + } + + /* + * If no aiod's are available, check if theres already an + * aiod assoicated with this mount, if so it will process + * this buf. + */ + if (!gotone && nmp->nm_naiods > 0) + gotone = 1; + + /* + * If we still don't have an aiod to process this buffer, + * force it sync. + */ + if (!gotone) goto out; - if (nfs_bufqlen > nfs_bufqmax) - goto out; /* too many bufs in use, force sync */ - if ((bp->b_flags & B_READ) == 0) { - bp->b_flags |= B_WRITEINPROG; + /* + * Make sure we don't queue up to much. + * TODO: Look into implementing migration for aiods. + */ + if (nmp->nm_bufqlen >= nfs_aiodbufqmax) { + if (aiod != NULL) { + mtx_enter(&nfs_aiodl_mtx); + LIST_INSERT_HEAD(&nfs_aiods_idle, aiod, nad_idle); + mtx_leave(&nfs_aiodl_mtx); + } + goto out; } - TAILQ_INSERT_TAIL(&nfs_bufq, bp, b_freelist); - nfs_bufqlen++; + /* Finally, queue the buffer and return. */ - wakeup_one(&nfs_bufq); - return (0); + if ((bp->b_flags & B_READ) == 0) + bp->b_flags |= B_WRITEINPROG; + TAILQ_INSERT_TAIL(&nmp->nm_bufq, bp, b_freelist); + nmp->nm_bufqlen++; + return (0); out: nfsstats.forcedsync++; return (EIO); diff --git a/sys/nfs/nfs_subs.c b/sys/nfs/nfs_subs.c index 1f301d5c36b..bc845e93895 100644 --- a/sys/nfs/nfs_subs.c +++ b/sys/nfs/nfs_subs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs_subs.c,v 1.103 2009/08/13 15:18:16 blambert Exp $ */ +/* $OpenBSD: nfs_subs.c,v 1.104 2009/08/20 15:04:24 thib Exp $ */ /* $NetBSD: nfs_subs.c,v 1.27.4.3 1996/07/08 20:34:24 jtc Exp $ */ /* @@ -935,7 +935,9 @@ nfs_vfs_init(struct vfsconf *vfsp) { extern struct pool nfs_node_pool; - TAILQ_INIT(&nfs_bufq); + LIST_INIT(&nfs_aiods_all); + LIST_INIT(&nfs_aiods_idle); + mtx_init(&nfs_aiodl_mtx, IPL_BIO); pool_init(&nfs_node_pool, sizeof(struct nfsnode), 0, 0, 0, "nfsnodepl", NULL); diff --git a/sys/nfs/nfs_syscalls.c b/sys/nfs/nfs_syscalls.c index dc0835a1876..2820038399c 100644 --- a/sys/nfs/nfs_syscalls.c +++ b/sys/nfs/nfs_syscalls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs_syscalls.c,v 1.85 2009/08/10 09:38:44 thib Exp $ */ +/* $OpenBSD: nfs_syscalls.c,v 1.86 2009/08/20 15:04:24 thib Exp $ */ /* $NetBSD: nfs_syscalls.c,v 1.19 1996/02/18 11:53:52 fvdl Exp $ */ /* @@ -73,7 +73,6 @@ #include <nfs/nfs_var.h> /* Global defs. */ -extern int nfs_numasync; extern struct nfsstats nfsstats; struct nfssvc_sock *nfs_udpsock; int nfsd_waiting = 0; @@ -118,11 +117,6 @@ struct nfsdhead nfsd_head; int nfssvc_sockhead_flag; int nfsd_head_flag; -#ifdef NFSCLIENT -struct proc *nfs_asyncdaemon[NFS_MAXASYNCDAEMON]; -int nfs_niothreads = -1; -#endif - /* * NFS server pseudo system call for the nfsd's * Based on the flag value it either: @@ -556,135 +550,7 @@ nfsrv_init(terminating) pool_init(&nfsrv_descript_pl, sizeof(struct nfsrv_descript), 0, 0, 0, "ndscpl", &pool_allocator_nointr); } -#endif /* NFSSERVER */ - -#ifdef NFSCLIENT -/* - * Asynchronous I/O threads for client nfs. - * They do read-ahead and write-behind operations on the block I/O cache. - * Never returns unless it fails or gets killed. - */ -void -nfssvc_iod(void *arg) -{ - struct proc *p = (struct proc *)arg; - struct buf *bp, *nbp; - int i, myiod; - struct vnode *vp; - int error = 0, s, bufcount; - - bufcount = 256; /* XXX: Big enough? sysctl, constant ? */ - - /* Assign my position or return error if too many already running. */ - myiod = -1; - for (i = 0; i < NFS_MAXASYNCDAEMON; i++) { - if (nfs_asyncdaemon[i] == NULL) { - myiod = i; - break; - } - } - if (myiod == -1) - kthread_exit(EBUSY); - - nfs_asyncdaemon[myiod] = p; - nfs_numasync++; - - /* Upper limit on how many bufs we'll queue up for this iod. */ - if (nfs_bufqmax > bcstats.numbufs / 4) { - nfs_bufqmax = bcstats.numbufs / 4; /* limit to 1/4 of bufs */ - bufcount = 0; - } - - nfs_bufqmax += bufcount; - - /* Just loop around doin our stuff until SIGKILL. */ - for (;;) { - while (TAILQ_FIRST(&nfs_bufq) == NULL && error == 0) { - error = tsleep(&nfs_bufq, - PWAIT | PCATCH, "nfsidl", 0); - } - while ((bp = TAILQ_FIRST(&nfs_bufq)) != NULL) { - /* Take one off the front of the list */ - TAILQ_REMOVE(&nfs_bufq, bp, b_freelist); - nfs_bufqlen--; - if (bp->b_flags & B_READ) - (void) nfs_doio(bp, NULL); - else do { - /* - * Look for a delayed write for the same vnode, so I can do - * it now. We must grab it before calling nfs_doio() to - * avoid any risk of the vnode getting vclean()'d while - * we are doing the write rpc. - */ - vp = bp->b_vp; - s = splbio(); - LIST_FOREACH(nbp, &vp->v_dirtyblkhd, b_vnbufs) { - if ((nbp->b_flags & - (B_BUSY|B_DELWRI|B_NEEDCOMMIT|B_NOCACHE))!=B_DELWRI) - continue; - nbp->b_flags |= B_ASYNC; - bremfree(nbp); - buf_acquire(nbp); - break; - } - /* - * For the delayed write, do the first part of nfs_bwrite() - * up to, but not including nfs_strategy(). - */ - if (nbp) { - nbp->b_flags &= ~(B_READ|B_DONE|B_ERROR); - buf_undirty(nbp); - nbp->b_vp->v_numoutput++; - } - splx(s); - - (void) nfs_doio(bp, NULL); - } while ((bp = nbp) != NULL); - } - if (error) { - nfs_asyncdaemon[myiod] = NULL; - nfs_numasync--; - nfs_bufqmax -= bufcount; - kthread_exit(error); - } - } -} - -void -nfs_getset_niothreads(set) - int set; -{ - struct proc *p; - int i, have, start; - - for (have = 0, i = 0; i < NFS_MAXASYNCDAEMON; i++) - if (nfs_asyncdaemon[i] != NULL) - have++; - - if (set) { - /* clamp to sane range */ - nfs_niothreads = max(0, min(nfs_niothreads, NFS_MAXASYNCDAEMON)); - - start = nfs_niothreads - have; - - while (start > 0) { - kthread_create(nfssvc_iod, p, &p, "nfsio"); - start--; - } - - for (i = 0; (start < 0) && (i < NFS_MAXASYNCDAEMON); i++) - if (nfs_asyncdaemon[i] != NULL) { - psignal(nfs_asyncdaemon[i], SIGKILL); - start++; - } - } else { - if (nfs_niothreads >= 0) - nfs_niothreads = have; - } -} -#endif /* NFSCLIENT */ -#ifdef NFSSERVER /* * Find an nfssrv_sock for nfsd, sleeping if needed. */ diff --git a/sys/nfs/nfs_var.h b/sys/nfs/nfs_var.h index b96c942d709..adaf5e2772f 100644 --- a/sys/nfs/nfs_var.h +++ b/sys/nfs/nfs_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs_var.h,v 1.56 2009/08/13 15:18:16 blambert Exp $ */ +/* $OpenBSD: nfs_var.h,v 1.57 2009/08/20 15:04:24 thib Exp $ */ /* $NetBSD: nfs_var.h,v 1.3 1996/02/18 11:53:54 fvdl Exp $ */ /* @@ -44,6 +44,11 @@ struct componentname; struct nfs_diskless; struct nfsm_info; +/* nfs_aiod.c */ +void nfs_aiod(void *); +int nfs_set_naiod(int); +void nfs_init_aiod(void); + /* nfs_bio.c */ int nfs_bioread(struct vnode *, struct uio *, int, struct ucred *); int nfs_write(void *); @@ -256,9 +261,6 @@ int nfssvc_nfsd(struct nfsd *); void nfsrv_zapsock(struct nfssvc_sock *); void nfsrv_slpderef(struct nfssvc_sock *); void nfsrv_init(int); -void nfssvc_iod(void *); -void start_nfsio(void *); -void nfs_getset_niothreads(int); /* nfs_kq.c */ int nfs_kqfilter(void *); diff --git a/sys/nfs/nfs_vfsops.c b/sys/nfs/nfs_vfsops.c index 993320599ef..b39688be830 100644 --- a/sys/nfs/nfs_vfsops.c +++ b/sys/nfs/nfs_vfsops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs_vfsops.c,v 1.88 2009/08/13 15:18:16 blambert Exp $ */ +/* $OpenBSD: nfs_vfsops.c,v 1.89 2009/08/20 15:04:24 thib Exp $ */ /* $NetBSD: nfs_vfsops.c,v 1.46.4.1 1996/05/25 22:40:35 fvdl Exp $ */ /* @@ -611,9 +611,10 @@ nfs_mount(mp, path, data, ndp, p) if ((args.flags & (NFSMNT_NFSV3|NFSMNT_RDIRPLUS)) == NFSMNT_RDIRPLUS) return (EINVAL); - if (nfs_niothreads < 0) { - nfs_niothreads = 4; - nfs_getset_niothreads(1); + if (nfs_numaiods == -1) { + error = nfs_set_naiod(NFS_DEFASYNCDAEMON); + if (error) + return (error); } if (mp->mnt_flag & MNT_UPDATE) { @@ -671,9 +672,9 @@ mountnfs(argp, mp, nam, pth, hst) m_freem(nam); return (0); } else { - nmp = malloc(sizeof(struct nfsmount), M_NFSMNT, - M_WAITOK|M_ZERO); - mp->mnt_data = (qaddr_t)nmp; + nmp = malloc(sizeof(*nmp), M_NFSMNT, M_WAITOK|M_ZERO); + mp->mnt_data = nmp; + TAILQ_INIT(&nmp->nm_bufq); } vfs_getnewfsid(mp); @@ -836,7 +837,7 @@ int nfs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p) { - int rv; + int rv, naiods; /* * All names at this level are terminal. @@ -868,11 +869,13 @@ nfs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, return 0; case NFS_NIOTHREADS: - nfs_getset_niothreads(0); - - rv = sysctl_int(oldp, oldlenp, newp, newlen, &nfs_niothreads); - if (newp) - nfs_getset_niothreads(1); + naiods = nfs_numaiods; + rv = sysctl_int(oldp, oldlenp, newp, newlen, &naiods); + if (newp && rv == 0) { + if (naiods < 0) + return (EINVAL); + rv = nfs_set_naiod(naiods); + } return rv; diff --git a/sys/nfs/nfs_vnops.c b/sys/nfs/nfs_vnops.c index 9b70728edd1..47eeda6a711 100644 --- a/sys/nfs/nfs_vnops.c +++ b/sys/nfs/nfs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs_vnops.c,v 1.122 2009/08/13 15:18:16 blambert Exp $ */ +/* $OpenBSD: nfs_vnops.c,v 1.123 2009/08/20 15:04:24 thib Exp $ */ /* $NetBSD: nfs_vnops.c,v 1.62.4.1 1996/07/08 20:26:52 jtc Exp $ */ /* @@ -184,8 +184,6 @@ extern u_int32_t nfs_true, nfs_false; extern u_int32_t nfs_xdrneg1; extern struct nfsstats nfsstats; extern nfstype nfsv3_type[9]; -int nfs_numasync = 0; - void nfs_cache_enter(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) diff --git a/sys/nfs/nfsmount.h b/sys/nfs/nfsmount.h index f080e810bc3..9ba488834d8 100644 --- a/sys/nfs/nfsmount.h +++ b/sys/nfs/nfsmount.h @@ -1,4 +1,4 @@ -/* $OpenBSD: nfsmount.h,v 1.21 2009/08/10 10:59:12 thib Exp $ */ +/* $OpenBSD: nfsmount.h,v 1.22 2009/08/20 15:04:24 thib Exp $ */ /* $NetBSD: nfsmount.h,v 1.10 1996/02/18 11:54:03 fvdl Exp $ */ /* @@ -68,6 +68,9 @@ struct nfsmount { int nm_wsize; /* Max size of write rpc */ int nm_readdirsize; /* Size of a readdir rpc */ int nm_readahead; /* Num. of blocks to readahead */ + TAILQ_HEAD(, buf) nm_bufq; /* async io buffer queue. */ + int nm_bufqlen; /* number of buffers in nm_bufq */ + int nm_naiods; /* # of aiods processing this mount */ u_char nm_verf[NFSX_V3WRITEVERF]; /* V3 write verifier */ u_short nm_acregmin; /* Attr cache file recently modified */ u_short nm_acregmax; /* ac file not recently modified */ diff --git a/sys/nfs/nfsnode.h b/sys/nfs/nfsnode.h index ce8edebb97c..6f95d808bb0 100644 --- a/sys/nfs/nfsnode.h +++ b/sys/nfs/nfsnode.h @@ -1,4 +1,4 @@ -/* $OpenBSD: nfsnode.h,v 1.34 2009/08/10 10:59:12 thib Exp $ */ +/* $OpenBSD: nfsnode.h,v 1.35 2009/08/20 15:04:24 thib Exp $ */ /* $NetBSD: nfsnode.h,v 1.16 1996/02/18 11:54:04 fvdl Exp $ */ /* @@ -137,10 +137,20 @@ struct nfsnode { #define VTONFS(vp) ((struct nfsnode *)(vp)->v_data) #define NFSTOV(np) ((np)->n_vnode) -/* - * Queue head for nfsiod's - */ -extern TAILQ_HEAD(nfs_bufqhead, buf) nfs_bufq; -extern uint32_t nfs_bufqlen, nfs_bufqmax; +/* nfs aiod datas. */ +struct nfs_aiod { + LIST_ENTRY(nfs_aiod) nad_all; + LIST_ENTRY(nfs_aiod) nad_idle; + struct nfsmount *nad_mnt; + int nad_exiting; +}; + +LIST_HEAD(nfs_aiodhead, nfs_aiod); + +extern struct mutex nfs_aiodl_mtx; +extern struct nfs_aiodhead nfs_aiods_all; +extern struct nfs_aiodhead nfs_aiods_idle; +extern int nfs_numaiods; +extern int nfs_aiodbufqmax; #endif /* _NFS_NFSNODE_H_ */ |