]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/5.15.154/sunrpc-always-treat-sv_nrpools-1-as-not-pooled.patch
Linux 5.15.154
[thirdparty/kernel/stable-queue.git] / releases / 5.15.154 / sunrpc-always-treat-sv_nrpools-1-as-not-pooled.patch
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"
5
6 From: NeilBrown <neilb@suse.de>
7
8 [ Upstream commit 93aa619eb0b42eec2f3a9b4d9db41f5095390aec ]
9
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.
17
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.
20
21 So change the test for "is the service pooled" to "is sv_nrpools > 1".
22
23 This means that when svc_pool_map_get() returns 1, it must NOT take a
24 reference to the pool.
25
26 We discard svc_serv_is_pooled(), and test sv_nrpools directly.
27
28 Signed-off-by: NeilBrown <neilb@suse.de>
29 Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
30 ---
31 net/sunrpc/svc.c | 54 ++++++++++++++++++++++++++----------------------
32 1 file changed, 29 insertions(+), 25 deletions(-)
33
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
38 @@ -37,8 +37,6 @@
39
40 static void svc_unregister(const struct svc_serv *serv, struct net *net);
41
42 -#define svc_serv_is_pooled(serv) ((serv)->sv_ops->svo_function)
43 -
44 #define SVC_POOL_DEFAULT SVC_POOL_GLOBAL
45
46 /*
47 @@ -240,8 +238,10 @@ svc_pool_map_init_pernode(struct svc_pool_map *m)
48
49 /*
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
56 + * was taken.
57 */
58 static unsigned int
59 svc_pool_map_get(void)
60 @@ -253,6 +253,7 @@ svc_pool_map_get(void)
61
62 if (m->count++) {
63 mutex_unlock(&svc_pool_map_mutex);
64 + WARN_ON_ONCE(m->npools <= 1);
65 return m->npools;
66 }
67
68 @@ -268,29 +269,36 @@ svc_pool_map_get(void)
69 break;
70 }
71
72 - if (npools < 0) {
73 + if (npools <= 0) {
74 /* default, or memory allocation failure */
75 npools = 1;
76 m->mode = SVC_POOL_GLOBAL;
77 }
78 m->npools = npools;
79
80 + if (npools == 1)
81 + /* service is unpooled, so doesn't hold a reference */
82 + m->count--;
83 +
84 mutex_unlock(&svc_pool_map_mutex);
85 - return m->npools;
86 + return npools;
87 }
88
89 /*
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.
97 */
98 static void
99 -svc_pool_map_put(void)
100 +svc_pool_map_put(int npools)
101 {
102 struct svc_pool_map *m = &svc_pool_map;
103
104 + if (npools <= 1)
105 + return;
106 mutex_lock(&svc_pool_map_mutex);
107
108 if (!--m->count) {
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;
112
113 - /*
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.
117 - */
118 - if (svc_serv_is_pooled(serv)) {
119 - switch (m->mode) {
120 - case SVC_POOL_PERCPU:
121 - pidx = m->to_pool[cpu];
122 - break;
123 - case SVC_POOL_PERNODE:
124 - pidx = m->to_pool[cpu_to_node(cpu)];
125 - break;
126 - }
127 + if (serv->sv_nrpools <= 1)
128 + return serv->sv_pools;
129 +
130 + switch (m->mode) {
131 + case SVC_POOL_PERCPU:
132 + pidx = m->to_pool[cpu];
133 + break;
134 + case SVC_POOL_PERNODE:
135 + pidx = m->to_pool[cpu_to_node(cpu)];
136 + break;
137 }
138 +
139 return &serv->sv_pools[pidx % serv->sv_nrpools];
140 }
141
142 @@ -526,7 +531,7 @@ svc_create_pooled(struct svc_program *prog, unsigned int bufsize,
143 goto out_err;
144 return serv;
145 out_err:
146 - svc_pool_map_put();
147 + svc_pool_map_put(npools);
148 return NULL;
149 }
150 EXPORT_SYMBOL_GPL(svc_create_pooled);
151 @@ -561,8 +566,7 @@ svc_destroy(struct kref *ref)
152
153 cache_clean_deferred(serv);
154
155 - if (svc_serv_is_pooled(serv))
156 - svc_pool_map_put();
157 + svc_pool_map_put(serv->sv_nrpools);
158
159 kfree(serv->sv_pools);
160 kfree(serv);
161 --
162 2.43.0
163