summaryrefslogtreecommitdiff
path: root/sys/nfs
diff options
context:
space:
mode:
Diffstat (limited to 'sys/nfs')
-rw-r--r--sys/nfs/nfs.h7
-rw-r--r--sys/nfs/nfs_aiod.c217
-rw-r--r--sys/nfs/nfs_bio.c75
-rw-r--r--sys/nfs/nfs_subs.c6
-rw-r--r--sys/nfs/nfs_syscalls.c136
-rw-r--r--sys/nfs/nfs_var.h10
-rw-r--r--sys/nfs/nfs_vfsops.c29
-rw-r--r--sys/nfs/nfs_vnops.c4
-rw-r--r--sys/nfs/nfsmount.h5
-rw-r--r--sys/nfs/nfsnode.h22
10 files changed, 327 insertions, 184 deletions
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_ */