aboutsummaryrefslogtreecommitdiffstats
path: root/fs/lockd/mon.c
diff options
context:
space:
mode:
authorAndrey Ryabinin <aryabinin@virtuozzo.com>2015-10-07 07:39:55 -0400
committerJ. Bruce Fields <bfields@redhat.com>2015-10-23 15:57:27 -0400
commit0d0f4aab4e4d290138a4ae7f2ef8469e48c9a669 (patch)
tree7efb5dbfc6769b16a2f3415b5654efd83fd6d4db /fs/lockd/mon.c
parent226453d8cfbd5f3bbdcef0d71e67186715bb811d (diff)
lockd: get rid of reference-counted NSM RPC clients
Currently we have reference-counted per-net NSM RPC client which created on the first monitor request and destroyed after the last unmonitor request. It's needed because RPC client need to know 'utsname()->nodename', but utsname() might be NULL when nsm_unmonitor() called. So instead of holding the rpc client we could just save nodename in struct nlm_host and pass it to the rpc_create(). Thus ther is no need in keeping rpc client until last unmonitor request. We could create separate RPC clients for each monitor/unmonitor requests. Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/lockd/mon.c')
-rw-r--r--fs/lockd/mon.c89
1 files changed, 15 insertions, 74 deletions
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 6c05cd17e520..19166d4a8d31 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -42,7 +42,7 @@ struct nsm_args {
42 u32 proc; 42 u32 proc;
43 43
44 char *mon_name; 44 char *mon_name;
45 char *nodename; 45 const char *nodename;
46}; 46};
47 47
48struct nsm_res { 48struct nsm_res {
@@ -86,69 +86,18 @@ static struct rpc_clnt *nsm_create(struct net *net, const char *nodename)
86 return rpc_create(&args); 86 return rpc_create(&args);
87} 87}
88 88
89static struct rpc_clnt *nsm_client_set(struct lockd_net *ln,
90 struct rpc_clnt *clnt)
91{
92 spin_lock(&ln->nsm_clnt_lock);
93 if (ln->nsm_users == 0) {
94 if (clnt == NULL)
95 goto out;
96 ln->nsm_clnt = clnt;
97 }
98 clnt = ln->nsm_clnt;
99 ln->nsm_users++;
100out:
101 spin_unlock(&ln->nsm_clnt_lock);
102 return clnt;
103}
104
105static struct rpc_clnt *nsm_client_get(struct net *net, const char *nodename)
106{
107 struct rpc_clnt *clnt, *new;
108 struct lockd_net *ln = net_generic(net, lockd_net_id);
109
110 clnt = nsm_client_set(ln, NULL);
111 if (clnt != NULL)
112 goto out;
113
114 clnt = new = nsm_create(net, nodename);
115 if (IS_ERR(clnt))
116 goto out;
117
118 clnt = nsm_client_set(ln, new);
119 if (clnt != new)
120 rpc_shutdown_client(new);
121out:
122 return clnt;
123}
124
125static void nsm_client_put(struct net *net)
126{
127 struct lockd_net *ln = net_generic(net, lockd_net_id);
128 struct rpc_clnt *clnt = NULL;
129
130 spin_lock(&ln->nsm_clnt_lock);
131 ln->nsm_users--;
132 if (ln->nsm_users == 0) {
133 clnt = ln->nsm_clnt;
134 ln->nsm_clnt = NULL;
135 }
136 spin_unlock(&ln->nsm_clnt_lock);
137 if (clnt != NULL)
138 rpc_shutdown_client(clnt);
139}
140
141static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res, 89static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
142 struct rpc_clnt *clnt) 90 const struct nlm_host *host)
143{ 91{
144 int status; 92 int status;
93 struct rpc_clnt *clnt;
145 struct nsm_args args = { 94 struct nsm_args args = {
146 .priv = &nsm->sm_priv, 95 .priv = &nsm->sm_priv,
147 .prog = NLM_PROGRAM, 96 .prog = NLM_PROGRAM,
148 .vers = 3, 97 .vers = 3,
149 .proc = NLMPROC_NSM_NOTIFY, 98 .proc = NLMPROC_NSM_NOTIFY,
150 .mon_name = nsm->sm_mon_name, 99 .mon_name = nsm->sm_mon_name,
151 .nodename = clnt->cl_nodename, 100 .nodename = host->nodename,
152 }; 101 };
153 struct rpc_message msg = { 102 struct rpc_message msg = {
154 .rpc_argp = &args, 103 .rpc_argp = &args,
@@ -157,6 +106,13 @@ static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
157 106
158 memset(res, 0, sizeof(*res)); 107 memset(res, 0, sizeof(*res));
159 108
109 clnt = nsm_create(host->net, host->nodename);
110 if (IS_ERR(clnt)) {
111 dprintk("lockd: failed to create NSM upcall transport, "
112 "status=%ld, net=%p\n", PTR_ERR(clnt), host->net);
113 return PTR_ERR(clnt);
114 }
115
160 msg.rpc_proc = &clnt->cl_procinfo[proc]; 116 msg.rpc_proc = &clnt->cl_procinfo[proc];
161 status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFTCONN); 117 status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFTCONN);
162 if (status == -ECONNREFUSED) { 118 if (status == -ECONNREFUSED) {
@@ -170,6 +126,8 @@ static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
170 status); 126 status);
171 else 127 else
172 status = 0; 128 status = 0;
129
130 rpc_shutdown_client(clnt);
173 return status; 131 return status;
174} 132}
175 133
@@ -189,32 +147,19 @@ int nsm_monitor(const struct nlm_host *host)
189 struct nsm_handle *nsm = host->h_nsmhandle; 147 struct nsm_handle *nsm = host->h_nsmhandle;
190 struct nsm_res res; 148 struct nsm_res res;
191 int status; 149 int status;
192 struct rpc_clnt *clnt;
193 const char *nodename = NULL;
194 150
195 dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name); 151 dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name);
196 152
197 if (nsm->sm_monitored) 153 if (nsm->sm_monitored)
198 return 0; 154 return 0;
199 155
200 if (host->h_rpcclnt)
201 nodename = host->h_rpcclnt->cl_nodename;
202
203 /* 156 /*
204 * Choose whether to record the caller_name or IP address of 157 * Choose whether to record the caller_name or IP address of
205 * this peer in the local rpc.statd's database. 158 * this peer in the local rpc.statd's database.
206 */ 159 */
207 nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf; 160 nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf;
208 161
209 clnt = nsm_client_get(host->net, nodename); 162 status = nsm_mon_unmon(nsm, NSMPROC_MON, &res, host);
210 if (IS_ERR(clnt)) {
211 status = PTR_ERR(clnt);
212 dprintk("lockd: failed to create NSM upcall transport, "
213 "status=%d, net=%p\n", status, host->net);
214 return status;
215 }
216
217 status = nsm_mon_unmon(nsm, NSMPROC_MON, &res, clnt);
218 if (unlikely(res.status != 0)) 163 if (unlikely(res.status != 0))
219 status = -EIO; 164 status = -EIO;
220 if (unlikely(status < 0)) { 165 if (unlikely(status < 0)) {
@@ -246,11 +191,9 @@ void nsm_unmonitor(const struct nlm_host *host)
246 191
247 if (atomic_read(&nsm->sm_count) == 1 192 if (atomic_read(&nsm->sm_count) == 1
248 && nsm->sm_monitored && !nsm->sm_sticky) { 193 && nsm->sm_monitored && !nsm->sm_sticky) {
249 struct lockd_net *ln = net_generic(host->net, lockd_net_id);
250
251 dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name); 194 dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name);
252 195
253 status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res, ln->nsm_clnt); 196 status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res, host);
254 if (res.status != 0) 197 if (res.status != 0)
255 status = -EIO; 198 status = -EIO;
256 if (status < 0) 199 if (status < 0)
@@ -258,8 +201,6 @@ void nsm_unmonitor(const struct nlm_host *host)
258 nsm->sm_name); 201 nsm->sm_name);
259 else 202 else
260 nsm->sm_monitored = 0; 203 nsm->sm_monitored = 0;
261
262 nsm_client_put(host->net);
263 } 204 }
264} 205}
265 206