Commit cb7323fffa85df37161f4d3be45e1f787808309c

Authored by Stanislav Kinsbursky
Committed by Trond Myklebust
1 parent 303a7ce920

lockd: create and use per-net NSM RPC clients on MON/UNMON requests

NSM RPC client can be required on NFSv3 umount, when child reaper is dying
(and destroying it's mount namespace). It means, that current nsproxy is set
to NULL already, but creation of RPC client requires UTS namespace for gaining
hostname string.

This patch creates reference-counted per-net NSM client on first monitor
request and destroys it after last unmonitor request.

Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

Showing 1 changed file with 20 additions and 17 deletions Side-by-side Diff

... ... @@ -7,7 +7,6 @@
7 7 */
8 8  
9 9 #include <linux/types.h>
10   -#include <linux/utsname.h>
11 10 #include <linux/kernel.h>
12 11 #include <linux/ktime.h>
13 12 #include <linux/slab.h>
... ... @@ -86,7 +85,7 @@
86 85 return rpc_create(&args);
87 86 }
88 87  
89   -__maybe_unused static struct rpc_clnt *nsm_client_get(struct net *net)
  88 +static struct rpc_clnt *nsm_client_get(struct net *net)
90 89 {
91 90 static DEFINE_MUTEX(nsm_create_mutex);
92 91 struct rpc_clnt *clnt;
... ... @@ -113,7 +112,7 @@
113 112 return clnt;
114 113 }
115 114  
116   -__maybe_unused static void nsm_client_put(struct net *net)
  115 +static void nsm_client_put(struct net *net)
117 116 {
118 117 struct lockd_net *ln = net_generic(net, lockd_net_id);
119 118 struct rpc_clnt *clnt = ln->nsm_clnt;
120 119  
... ... @@ -132,9 +131,8 @@
132 131 }
133 132  
134 133 static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
135   - struct net *net)
  134 + struct rpc_clnt *clnt)
136 135 {
137   - struct rpc_clnt *clnt;
138 136 int status;
139 137 struct nsm_args args = {
140 138 .priv = &nsm->sm_priv,
141 139  
... ... @@ -142,20 +140,14 @@
142 140 .vers = 3,
143 141 .proc = NLMPROC_NSM_NOTIFY,
144 142 .mon_name = nsm->sm_mon_name,
145   - .nodename = utsname()->nodename,
  143 + .nodename = clnt->cl_nodename,
146 144 };
147 145 struct rpc_message msg = {
148 146 .rpc_argp = &args,
149 147 .rpc_resp = res,
150 148 };
151 149  
152   - clnt = nsm_create(net);
153   - if (IS_ERR(clnt)) {
154   - status = PTR_ERR(clnt);
155   - dprintk("lockd: failed to create NSM upcall transport, "
156   - "status=%d\n", status);
157   - goto out;
158   - }
  150 + BUG_ON(clnt == NULL);
159 151  
160 152 memset(res, 0, sizeof(*res));
161 153  
... ... @@ -166,8 +158,6 @@
166 158 status);
167 159 else
168 160 status = 0;
169   - rpc_shutdown_client(clnt);
170   - out:
171 161 return status;
172 162 }
173 163  
... ... @@ -187,6 +177,7 @@
187 177 struct nsm_handle *nsm = host->h_nsmhandle;
188 178 struct nsm_res res;
189 179 int status;
  180 + struct rpc_clnt *clnt;
190 181  
191 182 dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name);
192 183  
... ... @@ -199,7 +190,15 @@
199 190 */
200 191 nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf;
201 192  
202   - status = nsm_mon_unmon(nsm, NSMPROC_MON, &res, host->net);
  193 + clnt = nsm_client_get(host->net);
  194 + if (IS_ERR(clnt)) {
  195 + status = PTR_ERR(clnt);
  196 + dprintk("lockd: failed to create NSM upcall transport, "
  197 + "status=%d, net=%p\n", status, host->net);
  198 + return status;
  199 + }
  200 +
  201 + status = nsm_mon_unmon(nsm, NSMPROC_MON, &res, clnt);
203 202 if (unlikely(res.status != 0))
204 203 status = -EIO;
205 204 if (unlikely(status < 0)) {
206 205  
... ... @@ -231,9 +230,11 @@
231 230  
232 231 if (atomic_read(&nsm->sm_count) == 1
233 232 && nsm->sm_monitored && !nsm->sm_sticky) {
  233 + struct lockd_net *ln = net_generic(host->net, lockd_net_id);
  234 +
234 235 dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name);
235 236  
236   - status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res, host->net);
  237 + status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res, ln->nsm_clnt);
237 238 if (res.status != 0)
238 239 status = -EIO;
239 240 if (status < 0)
... ... @@ -241,6 +242,8 @@
241 242 nsm->sm_name);
242 243 else
243 244 nsm->sm_monitored = 0;
  245 +
  246 + nsm_client_put(host->net);
244 247 }
245 248 }
246 249