Skip to content

Commit 8e0c8d2

Browse files
jtlaytonchucklever
authored andcommitted
sunrpc: fix up the special handling of sv_nrpools == 1
Only pooled services take a reference to the svc_pool_map. The sunrpc code has always used the sv_nrpools value to detect whether the service is pooled. The problem there is that nfsd is a pooled service, but when it's running in "global" pool_mode, it doesn't take a reference to the pool map because it has a sv_nrpools value of 1. This means that we have two separate codepaths for starting the server, depending on whether it's pooled or not. Fix this by adding a new flag to the svc_serv, that indicates whether the serv is pooled. With this we can have the nfsd service unconditionally take a reference, regardless of pool_mode. Note that this is a behavior change for /sys/module/sunrpc/parameters/pool_mode. Usually this file does not allow you to change the pool-mode while there are nfsd threads running, but if the pool-mode is "global" it's allowed. My assumption is that this is a bug, since it probably should never have worked this way. This patch changes the behavior such that you get back EBUSY even when nfsd is running in global mode. I think this is more reasonable behavior, and given that most people set this today using the module parameter, it's doubtful anyone will notice. Signed-off-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
1 parent 3a6adfc commit 8e0c8d2

File tree

2 files changed

+8
-19
lines changed

2 files changed

+8
-19
lines changed

include/linux/sunrpc/svc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ struct svc_serv {
8585
char * sv_name; /* service name */
8686

8787
unsigned int sv_nrpools; /* number of thread pools */
88+
bool sv_is_pooled; /* is this a pooled service? */
8889
struct svc_pool * sv_pools; /* array of thread pools */
8990
int (*sv_threadfn)(void *data);
9091

net/sunrpc/svc.c

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -250,10 +250,8 @@ svc_pool_map_get(void)
250250
int npools = -1;
251251

252252
mutex_lock(&svc_pool_map_mutex);
253-
254253
if (m->count++) {
255254
mutex_unlock(&svc_pool_map_mutex);
256-
WARN_ON_ONCE(m->npools <= 1);
257255
return m->npools;
258256
}
259257

@@ -275,40 +273,28 @@ svc_pool_map_get(void)
275273
m->mode = SVC_POOL_GLOBAL;
276274
}
277275
m->npools = npools;
278-
279-
if (npools == 1)
280-
/* service is unpooled, so doesn't hold a reference */
281-
m->count--;
282-
283276
mutex_unlock(&svc_pool_map_mutex);
284277
return npools;
285278
}
286279

287280
/*
288-
* Drop a reference to the global map of cpus to pools, if
289-
* pools were in use, i.e. if npools > 1.
281+
* Drop a reference to the global map of cpus to pools.
290282
* When the last reference is dropped, the map data is
291-
* freed; this allows the sysadmin to change the pool
292-
* mode using the pool_mode module option without
293-
* rebooting or re-loading sunrpc.ko.
283+
* freed; this allows the sysadmin to change the pool.
294284
*/
295285
static void
296-
svc_pool_map_put(int npools)
286+
svc_pool_map_put(void)
297287
{
298288
struct svc_pool_map *m = &svc_pool_map;
299289

300-
if (npools <= 1)
301-
return;
302290
mutex_lock(&svc_pool_map_mutex);
303-
304291
if (!--m->count) {
305292
kfree(m->to_pool);
306293
m->to_pool = NULL;
307294
kfree(m->pool_to);
308295
m->pool_to = NULL;
309296
m->npools = 0;
310297
}
311-
312298
mutex_unlock(&svc_pool_map_mutex);
313299
}
314300

@@ -553,9 +539,10 @@ struct svc_serv *svc_create_pooled(struct svc_program *prog,
553539
serv = __svc_create(prog, stats, bufsize, npools, threadfn);
554540
if (!serv)
555541
goto out_err;
542+
serv->sv_is_pooled = true;
556543
return serv;
557544
out_err:
558-
svc_pool_map_put(npools);
545+
svc_pool_map_put();
559546
return NULL;
560547
}
561548
EXPORT_SYMBOL_GPL(svc_create_pooled);
@@ -585,7 +572,8 @@ svc_destroy(struct svc_serv **servp)
585572

586573
cache_clean_deferred(serv);
587574

588-
svc_pool_map_put(serv->sv_nrpools);
575+
if (serv->sv_is_pooled)
576+
svc_pool_map_put();
589577

590578
for (i = 0; i < serv->sv_nrpools; i++) {
591579
struct svc_pool *pool = &serv->sv_pools[i];

0 commit comments

Comments
 (0)