Commit e344f872 authored by Jeff Layton's avatar Jeff Layton Committed by Chuck Lever
Browse files

sunrpc: split svc_set_num_threads() into two functions



svc_set_num_threads() will set the number of running threads for a given
pool. If the pool argument is set to NULL however, it will distribute
the threads among all of the pools evenly.

These divergent codepaths complicate the move to dynamic threading.
Simplify the API by splitting these two cases into different helpers:

Add a new svc_set_pool_threads() function that sets the number of
threads in a single, given pool. Modify svc_set_num_threads() to
distribute the threads evenly between all of the pools and then call
svc_set_pool_threads() for each.

Signed-off-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent 5288993c
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -340,7 +340,7 @@ static int lockd_get(void)
		return -ENOMEM;
	}

	error = svc_set_num_threads(serv, NULL, 1);
	error = svc_set_num_threads(serv, 1);
	if (error < 0) {
		svc_destroy(&serv);
		return error;
@@ -368,7 +368,7 @@ static void lockd_put(void)
	unregister_inet6addr_notifier(&lockd_inet6addr_notifier);
#endif

	svc_set_num_threads(nlmsvc_serv, NULL, 0);
	svc_set_num_threads(nlmsvc_serv, 0);
	timer_delete_sync(&nlmsvc_retry);
	svc_destroy(&nlmsvc_serv);
	dprintk("lockd_down: service destroyed\n");
+4 −4
Original line number Diff line number Diff line
@@ -119,9 +119,9 @@ static int nfs_callback_start_svc(int minorversion, struct rpc_xprt *xprt,
	if (serv->sv_nrthreads == nrservs)
		return 0;

	ret = svc_set_num_threads(serv, NULL, nrservs);
	ret = svc_set_num_threads(serv, nrservs);
	if (ret) {
		svc_set_num_threads(serv, NULL, 0);
		svc_set_num_threads(serv, 0);
		return ret;
	}
	dprintk("nfs_callback_up: service started\n");
@@ -242,7 +242,7 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt)
	cb_info->users++;
err_net:
	if (!cb_info->users) {
		svc_set_num_threads(cb_info->serv, NULL, 0);
		svc_set_num_threads(cb_info->serv, 0);
		svc_destroy(&cb_info->serv);
	}
err_create:
@@ -268,7 +268,7 @@ void nfs_callback_down(int minorversion, struct net *net, struct rpc_xprt *xprt)
	nfs_callback_down_net(minorversion, serv, net);
	cb_info->users--;
	if (cb_info->users == 0) {
		svc_set_num_threads(serv, NULL, 0);
		svc_set_num_threads(serv, 0);
		dprintk("nfs_callback_down: service destroyed\n");
		xprt_svc_destroy_nullify_bc(xprt, &cb_info->serv);
	}
+9 −12
Original line number Diff line number Diff line
@@ -580,7 +580,7 @@ void nfsd_shutdown_threads(struct net *net)
	}

	/* Kill outstanding nfsd threads */
	svc_set_num_threads(serv, NULL, 0);
	svc_set_num_threads(serv, 0);
	nfsd_destroy_serv(net);
	mutex_unlock(&nfsd_mutex);
}
@@ -688,12 +688,9 @@ int nfsd_set_nrthreads(int n, int *nthreads, struct net *net)
	if (nn->nfsd_serv == NULL || n <= 0)
		return 0;

	/*
	 * Special case: When n == 1, pass in NULL for the pool, so that the
	 * change is distributed equally among them.
	 */
	/* Special case: When n == 1, distribute threads equally among pools. */
	if (n == 1)
		return svc_set_num_threads(nn->nfsd_serv, NULL, nthreads[0]);
		return svc_set_num_threads(nn->nfsd_serv, nthreads[0]);

	if (n > nn->nfsd_serv->sv_nrpools)
		n = nn->nfsd_serv->sv_nrpools;
@@ -719,7 +716,7 @@ int nfsd_set_nrthreads(int n, int *nthreads, struct net *net)

	/* apply the new numbers */
	for (i = 0; i < n; i++) {
		err = svc_set_num_threads(nn->nfsd_serv,
		err = svc_set_pool_threads(nn->nfsd_serv,
					   &nn->nfsd_serv->sv_pools[i],
					   nthreads[i]);
		if (err)
@@ -728,7 +725,7 @@ int nfsd_set_nrthreads(int n, int *nthreads, struct net *net)

	/* Anything undefined in array is considered to be 0 */
	for (i = n; i < nn->nfsd_serv->sv_nrpools; ++i) {
		err = svc_set_num_threads(nn->nfsd_serv,
		err = svc_set_pool_threads(nn->nfsd_serv,
					   &nn->nfsd_serv->sv_pools[i],
					   0);
		if (err)
+3 −1
Original line number Diff line number Diff line
@@ -446,7 +446,9 @@ struct svc_serv * svc_create_pooled(struct svc_program *prog,
				     struct svc_stat *stats,
				     unsigned int bufsize,
				     int (*threadfn)(void *data));
int		   svc_set_num_threads(struct svc_serv *, struct svc_pool *, int);
int		   svc_set_pool_threads(struct svc_serv *serv, struct svc_pool *pool,
					unsigned int nrservs);
int		   svc_set_num_threads(struct svc_serv *serv, unsigned int nrservs);
int		   svc_pool_stats_open(struct svc_info *si, struct file *file);
void		   svc_process(struct svc_rqst *rqstp);
void		   svc_process_bc(struct rpc_rqst *req, struct svc_rqst *rqstp);
+53 −15
Original line number Diff line number Diff line
@@ -856,15 +856,12 @@ svc_stop_kthreads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
}

/**
 * svc_set_num_threads - adjust number of threads per RPC service
 * svc_set_pool_threads - adjust number of threads per pool
 * @serv: RPC service to adjust
 * @pool: Specific pool from which to choose threads, or NULL
 * @nrservs: New number of threads for @serv (0 or less means kill all threads)
 * @pool: Specific pool from which to choose threads
 * @nrservs: New number of threads for @serv (0 means kill all threads)
 *
 * Create or destroy threads to make the number of threads for @serv the
 * given number. If @pool is non-NULL, change only threads in that pool;
 * otherwise, round-robin between all pools for @serv. @serv's
 * sv_nrthreads is adjusted for each thread created or destroyed.
 * Create or destroy threads in @pool to bring it to @nrservs.
 *
 * Caller must ensure mutual exclusion between this and server startup or
 * shutdown.
@@ -873,19 +870,60 @@ svc_stop_kthreads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
 * starting a thread.
 */
int
svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
svc_set_pool_threads(struct svc_serv *serv, struct svc_pool *pool,
		     unsigned int nrservs)
{
	int delta = nrservs;

	if (!pool)
		nrservs -= serv->sv_nrthreads;
	else
		nrservs -= pool->sp_nrthreads;
		return -EINVAL;

	if (nrservs > 0)
		return svc_start_kthreads(serv, pool, nrservs);
	if (nrservs < 0)
		return svc_stop_kthreads(serv, pool, nrservs);
	delta -= pool->sp_nrthreads;

	if (delta > 0)
		return svc_start_kthreads(serv, pool, delta);
	if (delta < 0)
		return svc_stop_kthreads(serv, pool, delta);
	return 0;
}
EXPORT_SYMBOL_GPL(svc_set_pool_threads);

/**
 * svc_set_num_threads - adjust number of threads in serv
 * @serv: RPC service to adjust
 * @nrservs: New number of threads for @serv (0 means kill all threads)
 *
 * Create or destroy threads in @serv to bring it to @nrservs. If there
 * are multiple pools then the new threads or victims will be distributed
 * evenly among them.
 *
 * Caller must ensure mutual exclusion between this and server startup or
 * shutdown.
 *
 * Returns zero on success or a negative errno if an error occurred while
 * starting a thread. On failure, some pools may have already been
 * adjusted; the caller is responsible for recovery.
 */
int
svc_set_num_threads(struct svc_serv *serv, unsigned int nrservs)
{
	unsigned int base = nrservs / serv->sv_nrpools;
	unsigned int remain = nrservs % serv->sv_nrpools;
	int i, err = 0;

	for (i = 0; i < serv->sv_nrpools; ++i) {
		int threads = base;

		if (remain) {
			++threads;
			--remain;
		}
		err = svc_set_pool_threads(serv, &serv->sv_pools[i], threads);
		if (err)
			break;
	}
	return err;
}
EXPORT_SYMBOL_GPL(svc_set_num_threads);

/**