aboutsummaryrefslogtreecommitdiffstats
path: root/fs/lockd/mon.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/lockd/mon.c')
-rw-r--r--fs/lockd/mon.c86
1 files changed, 69 insertions, 17 deletions
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 7ef14b3c5bee..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>
@@ -19,6 +18,8 @@
19 18
20#include <asm/unaligned.h> 19#include <asm/unaligned.h>
21 20
21#include "netns.h"
22
22#define NLMDBG_FACILITY NLMDBG_MONITOR 23#define NLMDBG_FACILITY NLMDBG_MONITOR
23#define NSM_PROGRAM 100024 24#define NSM_PROGRAM 100024
24#define NSM_VERSION 1 25#define NSM_VERSION 1
@@ -40,6 +41,7 @@ struct nsm_args {
40 u32 proc; 41 u32 proc;
41 42
42 char *mon_name; 43 char *mon_name;
44 char *nodename;
43}; 45};
44 46
45struct nsm_res { 47struct nsm_res {
@@ -70,7 +72,7 @@ static struct rpc_clnt *nsm_create(struct net *net)
70 }; 72 };
71 struct rpc_create_args args = { 73 struct rpc_create_args args = {
72 .net = net, 74 .net = net,
73 .protocol = XPRT_TRANSPORT_UDP, 75 .protocol = XPRT_TRANSPORT_TCP,
74 .address = (struct sockaddr *)&sin, 76 .address = (struct sockaddr *)&sin,
75 .addrsize = sizeof(sin), 77 .addrsize = sizeof(sin),
76 .servername = "rpc.statd", 78 .servername = "rpc.statd",
@@ -83,10 +85,54 @@ static struct rpc_clnt *nsm_create(struct net *net)
83 return rpc_create(&args); 85 return rpc_create(&args);
84} 86}
85 87
86static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res, 88static struct rpc_clnt *nsm_client_get(struct net *net)
87 struct net *net)
88{ 89{
90 static DEFINE_MUTEX(nsm_create_mutex);
89 struct rpc_clnt *clnt; 91 struct rpc_clnt *clnt;
92 struct lockd_net *ln = net_generic(net, lockd_net_id);
93
94 spin_lock(&ln->nsm_clnt_lock);
95 if (ln->nsm_users) {
96 ln->nsm_users++;
97 clnt = ln->nsm_clnt;
98 spin_unlock(&ln->nsm_clnt_lock);
99 goto out;
100 }
101 spin_unlock(&ln->nsm_clnt_lock);
102
103 mutex_lock(&nsm_create_mutex);
104 clnt = nsm_create(net);
105 if (!IS_ERR(clnt)) {
106 ln->nsm_clnt = clnt;
107 smp_wmb();
108 ln->nsm_users = 1;
109 }
110 mutex_unlock(&nsm_create_mutex);
111out:
112 return clnt;
113}
114
115static void nsm_client_put(struct net *net)
116{
117 struct lockd_net *ln = net_generic(net, lockd_net_id);
118 struct rpc_clnt *clnt = ln->nsm_clnt;
119 int shutdown = 0;
120
121 spin_lock(&ln->nsm_clnt_lock);
122 if (ln->nsm_users) {
123 if (--ln->nsm_users)
124 ln->nsm_clnt = NULL;
125 shutdown = !ln->nsm_users;
126 }
127 spin_unlock(&ln->nsm_clnt_lock);
128
129 if (shutdown)
130 rpc_shutdown_client(clnt);
131}
132
133static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
134 struct rpc_clnt *clnt)
135{
90 int status; 136 int status;
91 struct nsm_args args = { 137 struct nsm_args args = {
92 .priv = &nsm->sm_priv, 138 .priv = &nsm->sm_priv,
@@ -94,31 +140,24 @@ static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
94 .vers = 3, 140 .vers = 3,
95 .proc = NLMPROC_NSM_NOTIFY, 141 .proc = NLMPROC_NSM_NOTIFY,
96 .mon_name = nsm->sm_mon_name, 142 .mon_name = nsm->sm_mon_name,
143 .nodename = clnt->cl_nodename,
97 }; 144 };
98 struct rpc_message msg = { 145 struct rpc_message msg = {
99 .rpc_argp = &args, 146 .rpc_argp = &args,
100 .rpc_resp = res, 147 .rpc_resp = res,
101 }; 148 };
102 149
103 clnt = nsm_create(net); 150 BUG_ON(clnt == NULL);
104 if (IS_ERR(clnt)) {
105 status = PTR_ERR(clnt);
106 dprintk("lockd: failed to create NSM upcall transport, "
107 "status=%d\n", status);
108 goto out;
109 }
110 151
111 memset(res, 0, sizeof(*res)); 152 memset(res, 0, sizeof(*res));
112 153
113 msg.rpc_proc = &clnt->cl_procinfo[proc]; 154 msg.rpc_proc = &clnt->cl_procinfo[proc];
114 status = rpc_call_sync(clnt, &msg, 0); 155 status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFTCONN);
115 if (status < 0) 156 if (status < 0)
116 dprintk("lockd: NSM upcall RPC failed, status=%d\n", 157 dprintk("lockd: NSM upcall RPC failed, status=%d\n",
117 status); 158 status);
118 else 159 else
119 status = 0; 160 status = 0;
120 rpc_shutdown_client(clnt);
121 out:
122 return status; 161 return status;
123} 162}
124 163
@@ -138,6 +177,7 @@ int nsm_monitor(const struct nlm_host *host)
138 struct nsm_handle *nsm = host->h_nsmhandle; 177 struct nsm_handle *nsm = host->h_nsmhandle;
139 struct nsm_res res; 178 struct nsm_res res;
140 int status; 179 int status;
180 struct rpc_clnt *clnt;
141 181
142 dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name); 182 dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name);
143 183
@@ -150,7 +190,15 @@ int nsm_monitor(const struct nlm_host *host)
150 */ 190 */
151 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;
152 192
153 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);
154 if (unlikely(res.status != 0)) 202 if (unlikely(res.status != 0))
155 status = -EIO; 203 status = -EIO;
156 if (unlikely(status < 0)) { 204 if (unlikely(status < 0)) {
@@ -182,9 +230,11 @@ void nsm_unmonitor(const struct nlm_host *host)
182 230
183 if (atomic_read(&nsm->sm_count) == 1 231 if (atomic_read(&nsm->sm_count) == 1
184 && 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
185 dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name); 235 dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name);
186 236
187 status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res, host->net); 237 status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res, ln->nsm_clnt);
188 if (res.status != 0) 238 if (res.status != 0)
189 status = -EIO; 239 status = -EIO;
190 if (status < 0) 240 if (status < 0)
@@ -192,6 +242,8 @@ void nsm_unmonitor(const struct nlm_host *host)
192 nsm->sm_name); 242 nsm->sm_name);
193 else 243 else
194 nsm->sm_monitored = 0; 244 nsm->sm_monitored = 0;
245
246 nsm_client_put(host->net);
195 } 247 }
196} 248}
197 249
@@ -430,7 +482,7 @@ static void encode_my_id(struct xdr_stream *xdr, const struct nsm_args *argp)
430{ 482{
431 __be32 *p; 483 __be32 *p;
432 484
433 encode_nsm_string(xdr, utsname()->nodename); 485 encode_nsm_string(xdr, argp->nodename);
434 p = xdr_reserve_space(xdr, 4 + 4 + 4); 486 p = xdr_reserve_space(xdr, 4 + 4 + 4);
435 *p++ = cpu_to_be32(argp->prog); 487 *p++ = cpu_to_be32(argp->prog);
436 *p++ = cpu_to_be32(argp->vers); 488 *p++ = cpu_to_be32(argp->vers);