aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStanislav Kinsbursky <skinsbursky@parallels.com>2012-09-18 05:37:23 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-10-01 18:27:43 -0400
commitcb7323fffa85df37161f4d3be45e1f787808309c (patch)
treee981d8fb5bc7d10a8118a9d2e0805a4c5fbd4545
parent303a7ce92064c285a04c870f2dc0192fdb2968cb (diff)
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>
-rw-r--r--fs/lockd/mon.c37
1 files changed, 20 insertions, 17 deletions
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index e0bc36e74ceb..e4fb3ba5a58a 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -7,7 +7,6 @@
7 */ 7 */
8 8
9#include <linux/types.h> 9#include <linux/types.h>
10#include <linux/utsname.h>
11#include <linux/kernel.h> 10#include <linux/kernel.h>
12#include <linux/ktime.h> 11#include <linux/ktime.h>
13#include <linux/slab.h> 12#include <linux/slab.h>
@@ -86,7 +85,7 @@ static struct rpc_clnt *nsm_create(struct net *net)
86 return rpc_create(&args); 85 return rpc_create(&args);
87} 86}
88 87
89__maybe_unused static struct rpc_clnt *nsm_client_get(struct net *net) 88static struct rpc_clnt *nsm_client_get(struct net *net)
90{ 89{
91 static DEFINE_MUTEX(nsm_create_mutex); 90 static DEFINE_MUTEX(nsm_create_mutex);
92 struct rpc_clnt *clnt; 91 struct rpc_clnt *clnt;
@@ -113,7 +112,7 @@ out:
113 return clnt; 112 return clnt;
114} 113}
115 114
116__maybe_unused static void nsm_client_put(struct net *net) 115static void nsm_client_put(struct net *net)
117{ 116{
118 struct lockd_net *ln = net_generic(net, lockd_net_id); 117 struct lockd_net *ln = net_generic(net, lockd_net_id);
119 struct rpc_clnt *clnt = ln->nsm_clnt; 118 struct rpc_clnt *clnt = ln->nsm_clnt;
@@ -132,9 +131,8 @@ __maybe_unused static void nsm_client_put(struct net *net)
132} 131}
133 132
134static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res, 133static 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 int status; 136 int status;
139 struct nsm_args args = { 137 struct nsm_args args = {
140 .priv = &nsm->sm_priv, 138 .priv = &nsm->sm_priv,
@@ -142,20 +140,14 @@ static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
142 .vers = 3, 140 .vers = 3,
143 .proc = NLMPROC_NSM_NOTIFY, 141 .proc = NLMPROC_NSM_NOTIFY,
144 .mon_name = nsm->sm_mon_name, 142 .mon_name = nsm->sm_mon_name,
145 .nodename = utsname()->nodename, 143 .nodename = clnt->cl_nodename,
146 }; 144 };
147 struct rpc_message msg = { 145 struct rpc_message msg = {
148 .rpc_argp = &args, 146 .rpc_argp = &args,
149 .rpc_resp = res, 147 .rpc_resp = res,
150 }; 148 };
151 149
152 clnt = nsm_create(net); 150 BUG_ON(clnt == NULL);
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 }
159 151
160 memset(res, 0, sizeof(*res)); 152 memset(res, 0, sizeof(*res));
161 153
@@ -166,8 +158,6 @@ static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
166 status); 158 status);
167 else 159 else
168 status = 0; 160 status = 0;
169 rpc_shutdown_client(clnt);
170 out:
171 return status; 161 return status;
172} 162}
173 163
@@ -187,6 +177,7 @@ int nsm_monitor(const struct nlm_host *host)
187 struct nsm_handle *nsm = host->h_nsmhandle; 177 struct nsm_handle *nsm = host->h_nsmhandle;
188 struct nsm_res res; 178 struct nsm_res res;
189 int status; 179 int status;
180 struct rpc_clnt *clnt;
190 181
191 dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name); 182 dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name);
192 183
@@ -199,7 +190,15 @@ int nsm_monitor(const struct nlm_host *host)
199 */ 190 */
200 nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf; 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 if (unlikely(res.status != 0)) 202 if (unlikely(res.status != 0))
204 status = -EIO; 203 status = -EIO;
205 if (unlikely(status < 0)) { 204 if (unlikely(status < 0)) {
@@ -231,9 +230,11 @@ void nsm_unmonitor(const struct nlm_host *host)
231 230
232 if (atomic_read(&nsm->sm_count) == 1 231 if (atomic_read(&nsm->sm_count) == 1
233 && nsm->sm_monitored && !nsm->sm_sticky) { 232 && nsm->sm_monitored && !nsm->sm_sticky) {
233 struct lockd_net *ln = net_generic(host->net, lockd_net_id);
234
234 dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name); 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 if (res.status != 0) 238 if (res.status != 0)
238 status = -EIO; 239 status = -EIO;
239 if (status < 0) 240 if (status < 0)
@@ -241,6 +242,8 @@ void nsm_unmonitor(const struct nlm_host *host)
241 nsm->sm_name); 242 nsm->sm_name);
242 else 243 else
243 nsm->sm_monitored = 0; 244 nsm->sm_monitored = 0;
245
246 nsm_client_put(host->net);
244 } 247 }
245} 248}
246 249