Revise the nfsiod auto tuning code. Now both the upper and lower limits

are specifyable by sysctl and are respected.

Submitted by:	Maxime Henrion <mux@sneakerz.org>
This commit is contained in:
Peter Wemm 2002-01-15 20:57:21 +00:00
parent 5d4be85d55
commit 1bde568682
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=89407
3 changed files with 87 additions and 22 deletions

View File

@ -76,7 +76,7 @@
#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 runnable */
#define NFS_MAXASYNCDAEMON 64 /* Max. number async_daemons runnable */
#define NFS_DIRBLKSIZ 4096 /* Must be a multiple of DIRBLKSIZ */
#ifdef _KERNEL
#define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */

View File

@ -1143,7 +1143,7 @@ nfs_asyncio(struct buf *bp, struct ucred *cred, struct thread *td)
/*
* Find a free iod to process this request.
*/
for (iod = 0; iod < NFS_MAXASYNCDAEMON; iod++)
for (iod = 0; iod < nfs_numasync; iod++)
if (nfs_iodwant[iod]) {
gotiod = TRUE;
break;
@ -1158,6 +1158,19 @@ nfs_asyncio(struct buf *bp, struct ucred *cred, struct thread *td)
gotiod = TRUE;
}
if (gotiod) {
/*
* Found one, so wake it up and tell it which
* mount to process.
*/
NFS_DPF(ASYNCIO, ("nfs_asyncio: waking iod %d for mount %p\n",
iod, nmp));
nfs_iodwant[iod] = (struct proc *)0;
nfs_iodmount[iod] = nmp;
nmp->nm_bufqiods++;
wakeup((caddr_t)&nfs_iodwant[iod]);
}
/*
* If none are free, we may already have an iod working on this mount
* point. If so, it will process our request.
@ -1176,17 +1189,6 @@ nfs_asyncio(struct buf *bp, struct ucred *cred, struct thread *td)
* the buffer.
*/
if (gotiod) {
/*
* Found one, so wake it up and tell it which
* mount to process.
*/
NFS_DPF(ASYNCIO, ("nfs_asyncio: waking iod %d for mount %p\n",
iod, nmp));
nfs_iodwant[iod] = (struct proc *)0;
nfs_iodmount[iod] = nmp;
nmp->nm_bufqiods++;
wakeup((caddr_t)&nfs_iodwant[iod]);
/*
* Ensure that the queue never grows too large. We still want
* to asynchronize so we block rather then return EIO.

View File

@ -83,13 +83,74 @@ static int nfs_asyncdaemon[NFS_MAXASYNCDAEMON];
SYSCTL_DECL(_vfs_nfs);
/* Maximum number of seconds a nfsiod kthread will sleep before exiting */
static unsigned int nfs_iodmaxidle = 120;
SYSCTL_UINT(_vfs_nfs, OID_AUTO, iodmaxidle, CTLFLAG_RW, &nfs_iodmaxidle, 0, "");
/* Maximum number of nfsiod kthreads */
static unsigned int nfs_iodmax = 20;
/* Minimum number of nfsiod kthreads to keep as spares */
static unsigned int nfs_iodmin = 4;
SYSCTL_INT(_vfs_nfs, OID_AUTO, iodmin, CTLFLAG_RW, &nfs_iodmin, 0, "");
/* Maximum number of seconds a nfsiod kthread will sleep before exiting */
static int nfs_iodmaxidle = 120;
SYSCTL_INT(_vfs_nfs, OID_AUTO, iodmaxidle, CTLFLAG_RW, &nfs_iodmaxidle, 0, "");
static int
sysctl_iodmin(SYSCTL_HANDLER_ARGS)
{
int error, i;
int newmin;
newmin = nfs_iodmin;
error = sysctl_handle_int(oidp, &newmin, 0, req);
if (error || (req->newptr == NULL))
return (error);
if (newmin > nfs_iodmax)
return (EINVAL);
nfs_iodmin = newmin;
if (nfs_numasync >= nfs_iodmin)
return (0);
/*
* If the current number of nfsiod is lower
* than the new minimum, create some more.
*/
for (i = nfs_iodmin - nfs_numasync; i > 0; i--)
nfs_nfsiodnew();
return (0);
}
SYSCTL_PROC(_vfs_nfs, OID_AUTO, iodmin, CTLTYPE_UINT | CTLFLAG_RW, 0,
sizeof (nfs_iodmin), sysctl_iodmin, "IU", "");
static int
sysctl_iodmax(SYSCTL_HANDLER_ARGS)
{
int error, i;
int iod, newmax;
newmax = nfs_iodmax;
error = sysctl_handle_int(oidp, &newmax, 0, req);
if (error || (req->newptr == NULL))
return (error);
if (newmax > NFS_MAXASYNCDAEMON)
return (EINVAL);
nfs_iodmax = newmax;
if (nfs_numasync <= nfs_iodmax)
return (0);
/*
* If there are some asleep nfsiods that should
* exit, wakeup() them so that they check nfs_iodmax
* and exit. Those who are active will exit as
* soon as they finish I/O.
*/
iod = nfs_numasync - 1;
for (i = 0; i < nfs_numasync - nfs_iodmax; i++) {
if (nfs_iodwant[iod])
wakeup((caddr_t)&nfs_iodwant[iod]);
iod--;
}
return (0);
}
SYSCTL_PROC(_vfs_nfs, OID_AUTO, iodmax, CTLTYPE_UINT | CTLFLAG_RW, 0,
sizeof (nfs_iodmax), sysctl_iodmax, "IU", "");
int
nfs_nfsiodnew(void)
@ -97,8 +158,10 @@ nfs_nfsiodnew(void)
int error, i;
int newiod;
if (nfs_numasync >= nfs_iodmax)
return (-1);
newiod = -1;
for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
for (i = 0; i < nfs_iodmax; i++)
if (nfs_asyncdaemon[i] == 0) {
nfs_asyncdaemon[i]++;
newiod = i;
@ -163,9 +226,6 @@ nfssvc_iod(void *instance)
int error = 0;
mtx_lock(&Giant);
/*
* Assign my position or return error if too many already running
*/
myiod = (int *)instance - nfs_asyncdaemon;
/*
* Main loop
@ -174,6 +234,8 @@ nfssvc_iod(void *instance)
while (((nmp = nfs_iodmount[myiod]) == NULL
|| !TAILQ_FIRST(&nmp->nm_bufq))
&& error == 0) {
if (myiod >= nfs_iodmax)
goto finish;
if (nmp)
nmp->nm_bufqiods--;
nfs_iodwant[myiod] = curthread->td_proc;
@ -213,13 +275,14 @@ nfssvc_iod(void *instance)
}
}
}
finish:
nfs_asyncdaemon[myiod] = 0;
if (nmp)
nmp->nm_bufqiods--;
nfs_iodwant[myiod] = NULL;
nfs_iodmount[myiod] = NULL;
nfs_numasync--;
if (error == EWOULDBLOCK)
if ((error == 0) || (error == EWOULDBLOCK))
kthread_exit(0);
/* Abnormal termination */
kthread_exit(1);