Skip to content

Commit

Permalink
nfsd: don't take nfsd_mutex twice when setting number of threads.
Browse files Browse the repository at this point in the history
Currently when we write a number to 'threads' in nfsdfs,
we take the nfsd_mutex, update the number of threads, then take the
mutex again to read the number of threads.

Mostly this isn't a big deal.  However if we are write '0', and
portmap happens to be dead, then we can get unpredictable behaviour.
If the nfsd threads all got killed quickly and the last thread is
waiting for portmap to respond, then the second time we take the mutex
we will block waiting for the last thread.
However if the nfsd threads didn't die quite that fast, then there
will be no contention when we try to take the mutex again.

Unpredictability isn't fun, and waiting for the last thread to exit is
pointless, so avoid taking the lock twice.
To achieve this, get nfsd_svc return a non-negative number of active
threads when not returning a negative error.

Signed-off-by: NeilBrown <neilb@suse.de>
  • Loading branch information
NeilBrown authored and J. Bruce Fields committed Jun 18, 2009
1 parent 5d77ddf commit 82e12fe
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 5 deletions.
14 changes: 9 additions & 5 deletions fs/nfsd/nfsctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,10 +207,14 @@ static struct file_operations pool_stats_operations = {
static ssize_t write_svc(struct file *file, char *buf, size_t size)
{
struct nfsctl_svc *data;
int err;
if (size < sizeof(*data))
return -EINVAL;
data = (struct nfsctl_svc*) buf;
return nfsd_svc(data->svc_port, data->svc_nthreads);
err = nfsd_svc(data->svc_port, data->svc_nthreads);
if (err < 0)
return err;
return 0;
}

/**
Expand Down Expand Up @@ -692,12 +696,12 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
if (newthreads < 0)
return -EINVAL;
rv = nfsd_svc(NFS_PORT, newthreads);
if (rv)
if (rv < 0)
return rv;
}
} else
rv = nfsd_nrthreads();

return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n",
nfsd_nrthreads());
return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%d\n", rv);
}

/**
Expand Down
6 changes: 6 additions & 0 deletions fs/nfsd/nfssvc.c
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,12 @@ nfsd_svc(unsigned short port, int nrservs)
goto failure;

error = svc_set_num_threads(nfsd_serv, NULL, nrservs);
if (error == 0)
/* We are holding a reference to nfsd_serv which
* we don't want to count in the return value,
* so subtract 1
*/
error = nfsd_serv->sv_nrthreads - 1;
failure:
svc_destroy(nfsd_serv); /* Release server */
out:
Expand Down

0 comments on commit 82e12fe

Please sign in to comment.