1 From 09497160e5a2af55cefe2a0903fff5ac803cc63a Mon Sep 17 00:00:00 2001
2 From: Sasha Levin <sashal@kernel.org>
3 Date: Mon, 29 Nov 2021 15:51:25 +1100
4 Subject: SUNRPC: always treat sv_nrpools==1 as "not pooled"
6 From: NeilBrown <neilb@suse.de>
8 [ Upstream commit 93aa619eb0b42eec2f3a9b4d9db41f5095390aec ]
10 Currently 'pooled' services hold a reference on the pool_map, and
11 'unpooled' services do not.
12 svc_destroy() uses the presence of ->svo_function (via
13 svc_serv_is_pooled()) to determine if the reference should be dropped.
14 There is no direct correlation between being pooled and the use of
15 svo_function, though in practice, lockd is the only non-pooled service,
16 and the only one not to use svo_function.
18 This is untidy and would cause problems if we changed lockd to use
19 svc_set_num_threads(), which requires the use of ->svo_function.
21 So change the test for "is the service pooled" to "is sv_nrpools > 1".
23 This means that when svc_pool_map_get() returns 1, it must NOT take a
24 reference to the pool.
26 We discard svc_serv_is_pooled(), and test sv_nrpools directly.
28 Signed-off-by: NeilBrown <neilb@suse.de>
29 Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
31 net/sunrpc/svc.c | 54 ++++++++++++++++++++++++++----------------------
32 1 file changed, 29 insertions(+), 25 deletions(-)
34 diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
35 index 8fbfea9f2a04c..fee7a22578b64 100644
36 --- a/net/sunrpc/svc.c
37 +++ b/net/sunrpc/svc.c
40 static void svc_unregister(const struct svc_serv *serv, struct net *net);
42 -#define svc_serv_is_pooled(serv) ((serv)->sv_ops->svo_function)
44 #define SVC_POOL_DEFAULT SVC_POOL_GLOBAL
47 @@ -240,8 +238,10 @@ svc_pool_map_init_pernode(struct svc_pool_map *m)
50 * Add a reference to the global map of cpus to pools (and
51 - * vice versa). Initialise the map if we're the first user.
52 - * Returns the number of pools.
53 + * vice versa) if pools are in use.
54 + * Initialise the map if we're the first user.
55 + * Returns the number of pools. If this is '1', no reference
59 svc_pool_map_get(void)
60 @@ -253,6 +253,7 @@ svc_pool_map_get(void)
63 mutex_unlock(&svc_pool_map_mutex);
64 + WARN_ON_ONCE(m->npools <= 1);
68 @@ -268,29 +269,36 @@ svc_pool_map_get(void)
74 /* default, or memory allocation failure */
76 m->mode = SVC_POOL_GLOBAL;
81 + /* service is unpooled, so doesn't hold a reference */
84 mutex_unlock(&svc_pool_map_mutex);
90 - * Drop a reference to the global map of cpus to pools.
91 + * Drop a reference to the global map of cpus to pools, if
92 + * pools were in use, i.e. if npools > 1.
93 * When the last reference is dropped, the map data is
94 * freed; this allows the sysadmin to change the pool
95 * mode using the pool_mode module option without
96 * rebooting or re-loading sunrpc.ko.
99 -svc_pool_map_put(void)
100 +svc_pool_map_put(int npools)
102 struct svc_pool_map *m = &svc_pool_map;
106 mutex_lock(&svc_pool_map_mutex);
109 @@ -359,21 +367,18 @@ svc_pool_for_cpu(struct svc_serv *serv, int cpu)
110 struct svc_pool_map *m = &svc_pool_map;
111 unsigned int pidx = 0;
114 - * An uninitialised map happens in a pure client when
115 - * lockd is brought up, so silently treat it the
116 - * same as SVC_POOL_GLOBAL.
118 - if (svc_serv_is_pooled(serv)) {
120 - case SVC_POOL_PERCPU:
121 - pidx = m->to_pool[cpu];
123 - case SVC_POOL_PERNODE:
124 - pidx = m->to_pool[cpu_to_node(cpu)];
127 + if (serv->sv_nrpools <= 1)
128 + return serv->sv_pools;
131 + case SVC_POOL_PERCPU:
132 + pidx = m->to_pool[cpu];
134 + case SVC_POOL_PERNODE:
135 + pidx = m->to_pool[cpu_to_node(cpu)];
139 return &serv->sv_pools[pidx % serv->sv_nrpools];
142 @@ -526,7 +531,7 @@ svc_create_pooled(struct svc_program *prog, unsigned int bufsize,
146 - svc_pool_map_put();
147 + svc_pool_map_put(npools);
150 EXPORT_SYMBOL_GPL(svc_create_pooled);
151 @@ -561,8 +566,7 @@ svc_destroy(struct kref *ref)
153 cache_clean_deferred(serv);
155 - if (svc_serv_is_pooled(serv))
156 - svc_pool_map_put();
157 + svc_pool_map_put(serv->sv_nrpools);
159 kfree(serv->sv_pools);