lockd: per-net NSM client creation and destruction helpers introduced
[pandora-kernel.git] / fs / lockd / mon.c
1 /*
2  * linux/fs/lockd/mon.c
3  *
4  * The kernel statd client.
5  *
6  * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
7  */
8
9 #include <linux/types.h>
10 #include <linux/utsname.h>
11 #include <linux/kernel.h>
12 #include <linux/ktime.h>
13 #include <linux/slab.h>
14
15 #include <linux/sunrpc/clnt.h>
16 #include <linux/sunrpc/xprtsock.h>
17 #include <linux/sunrpc/svc.h>
18 #include <linux/lockd/lockd.h>
19
20 #include <asm/unaligned.h>
21
22 #include "netns.h"
23
24 #define NLMDBG_FACILITY         NLMDBG_MONITOR
25 #define NSM_PROGRAM             100024
26 #define NSM_VERSION             1
27
28 enum {
29         NSMPROC_NULL,
30         NSMPROC_STAT,
31         NSMPROC_MON,
32         NSMPROC_UNMON,
33         NSMPROC_UNMON_ALL,
34         NSMPROC_SIMU_CRASH,
35         NSMPROC_NOTIFY,
36 };
37
38 struct nsm_args {
39         struct nsm_private      *priv;
40         u32                     prog;           /* RPC callback info */
41         u32                     vers;
42         u32                     proc;
43
44         char                    *mon_name;
45 };
46
47 struct nsm_res {
48         u32                     status;
49         u32                     state;
50 };
51
52 static const struct rpc_program nsm_program;
53 static                          LIST_HEAD(nsm_handles);
54 static                          DEFINE_SPINLOCK(nsm_lock);
55
56 /*
57  * Local NSM state
58  */
59 u32     __read_mostly           nsm_local_state;
60 bool    __read_mostly           nsm_use_hostnames;
61
62 static inline struct sockaddr *nsm_addr(const struct nsm_handle *nsm)
63 {
64         return (struct sockaddr *)&nsm->sm_addr;
65 }
66
67 static struct rpc_clnt *nsm_create(struct net *net)
68 {
69         struct sockaddr_in sin = {
70                 .sin_family             = AF_INET,
71                 .sin_addr.s_addr        = htonl(INADDR_LOOPBACK),
72         };
73         struct rpc_create_args args = {
74                 .net                    = net,
75                 .protocol               = XPRT_TRANSPORT_TCP,
76                 .address                = (struct sockaddr *)&sin,
77                 .addrsize               = sizeof(sin),
78                 .servername             = "rpc.statd",
79                 .program                = &nsm_program,
80                 .version                = NSM_VERSION,
81                 .authflavor             = RPC_AUTH_NULL,
82                 .flags                  = RPC_CLNT_CREATE_NOPING,
83         };
84
85         return rpc_create(&args);
86 }
87
88 __maybe_unused static struct rpc_clnt *nsm_client_get(struct net *net)
89 {
90         static DEFINE_MUTEX(nsm_create_mutex);
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);
111 out:
112         return clnt;
113 }
114
115 __maybe_unused static 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
133 static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res,
134                          struct net *net)
135 {
136         struct rpc_clnt *clnt;
137         int             status;
138         struct nsm_args args = {
139                 .priv           = &nsm->sm_priv,
140                 .prog           = NLM_PROGRAM,
141                 .vers           = 3,
142                 .proc           = NLMPROC_NSM_NOTIFY,
143                 .mon_name       = nsm->sm_mon_name,
144         };
145         struct rpc_message msg = {
146                 .rpc_argp       = &args,
147                 .rpc_resp       = res,
148         };
149
150         clnt = nsm_create(net);
151         if (IS_ERR(clnt)) {
152                 status = PTR_ERR(clnt);
153                 dprintk("lockd: failed to create NSM upcall transport, "
154                                 "status=%d\n", status);
155                 goto out;
156         }
157
158         memset(res, 0, sizeof(*res));
159
160         msg.rpc_proc = &clnt->cl_procinfo[proc];
161         status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFTCONN);
162         if (status < 0)
163                 dprintk("lockd: NSM upcall RPC failed, status=%d\n",
164                                 status);
165         else
166                 status = 0;
167         rpc_shutdown_client(clnt);
168  out:
169         return status;
170 }
171
172 /**
173  * nsm_monitor - Notify a peer in case we reboot
174  * @host: pointer to nlm_host of peer to notify
175  *
176  * If this peer is not already monitored, this function sends an
177  * upcall to the local rpc.statd to record the name/address of
178  * the peer to notify in case we reboot.
179  *
180  * Returns zero if the peer is monitored by the local rpc.statd;
181  * otherwise a negative errno value is returned.
182  */
183 int nsm_monitor(const struct nlm_host *host)
184 {
185         struct nsm_handle *nsm = host->h_nsmhandle;
186         struct nsm_res  res;
187         int             status;
188
189         dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name);
190
191         if (nsm->sm_monitored)
192                 return 0;
193
194         /*
195          * Choose whether to record the caller_name or IP address of
196          * this peer in the local rpc.statd's database.
197          */
198         nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf;
199
200         status = nsm_mon_unmon(nsm, NSMPROC_MON, &res, host->net);
201         if (unlikely(res.status != 0))
202                 status = -EIO;
203         if (unlikely(status < 0)) {
204                 printk(KERN_NOTICE "lockd: cannot monitor %s\n", nsm->sm_name);
205                 return status;
206         }
207
208         nsm->sm_monitored = 1;
209         if (unlikely(nsm_local_state != res.state)) {
210                 nsm_local_state = res.state;
211                 dprintk("lockd: NSM state changed to %d\n", nsm_local_state);
212         }
213         return 0;
214 }
215
216 /**
217  * nsm_unmonitor - Unregister peer notification
218  * @host: pointer to nlm_host of peer to stop monitoring
219  *
220  * If this peer is monitored, this function sends an upcall to
221  * tell the local rpc.statd not to send this peer a notification
222  * when we reboot.
223  */
224 void nsm_unmonitor(const struct nlm_host *host)
225 {
226         struct nsm_handle *nsm = host->h_nsmhandle;
227         struct nsm_res  res;
228         int status;
229
230         if (atomic_read(&nsm->sm_count) == 1
231          && nsm->sm_monitored && !nsm->sm_sticky) {
232                 dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name);
233
234                 status = nsm_mon_unmon(nsm, NSMPROC_UNMON, &res, host->net);
235                 if (res.status != 0)
236                         status = -EIO;
237                 if (status < 0)
238                         printk(KERN_NOTICE "lockd: cannot unmonitor %s\n",
239                                         nsm->sm_name);
240                 else
241                         nsm->sm_monitored = 0;
242         }
243 }
244
245 static struct nsm_handle *nsm_lookup_hostname(const char *hostname,
246                                               const size_t len)
247 {
248         struct nsm_handle *nsm;
249
250         list_for_each_entry(nsm, &nsm_handles, sm_link)
251                 if (strlen(nsm->sm_name) == len &&
252                     memcmp(nsm->sm_name, hostname, len) == 0)
253                         return nsm;
254         return NULL;
255 }
256
257 static struct nsm_handle *nsm_lookup_addr(const struct sockaddr *sap)
258 {
259         struct nsm_handle *nsm;
260
261         list_for_each_entry(nsm, &nsm_handles, sm_link)
262                 if (rpc_cmp_addr(nsm_addr(nsm), sap))
263                         return nsm;
264         return NULL;
265 }
266
267 static struct nsm_handle *nsm_lookup_priv(const struct nsm_private *priv)
268 {
269         struct nsm_handle *nsm;
270
271         list_for_each_entry(nsm, &nsm_handles, sm_link)
272                 if (memcmp(nsm->sm_priv.data, priv->data,
273                                         sizeof(priv->data)) == 0)
274                         return nsm;
275         return NULL;
276 }
277
278 /*
279  * Construct a unique cookie to match this nsm_handle to this monitored
280  * host.  It is passed to the local rpc.statd via NSMPROC_MON, and
281  * returned via NLMPROC_SM_NOTIFY, in the "priv" field of these
282  * requests.
283  *
284  * The NSM protocol requires that these cookies be unique while the
285  * system is running.  We prefer a stronger requirement of making them
286  * unique across reboots.  If user space bugs cause a stale cookie to
287  * be sent to the kernel, it could cause the wrong host to lose its
288  * lock state if cookies were not unique across reboots.
289  *
290  * The cookies are exposed only to local user space via loopback.  They
291  * do not appear on the physical network.  If we want greater security
292  * for some reason, nsm_init_private() could perform a one-way hash to
293  * obscure the contents of the cookie.
294  */
295 static void nsm_init_private(struct nsm_handle *nsm)
296 {
297         u64 *p = (u64 *)&nsm->sm_priv.data;
298         struct timespec ts;
299         s64 ns;
300
301         ktime_get_ts(&ts);
302         ns = timespec_to_ns(&ts);
303         put_unaligned(ns, p);
304         put_unaligned((unsigned long)nsm, p + 1);
305 }
306
307 static struct nsm_handle *nsm_create_handle(const struct sockaddr *sap,
308                                             const size_t salen,
309                                             const char *hostname,
310                                             const size_t hostname_len)
311 {
312         struct nsm_handle *new;
313
314         new = kzalloc(sizeof(*new) + hostname_len + 1, GFP_KERNEL);
315         if (unlikely(new == NULL))
316                 return NULL;
317
318         atomic_set(&new->sm_count, 1);
319         new->sm_name = (char *)(new + 1);
320         memcpy(nsm_addr(new), sap, salen);
321         new->sm_addrlen = salen;
322         nsm_init_private(new);
323
324         if (rpc_ntop(nsm_addr(new), new->sm_addrbuf,
325                                         sizeof(new->sm_addrbuf)) == 0)
326                 (void)snprintf(new->sm_addrbuf, sizeof(new->sm_addrbuf),
327                                 "unsupported address family");
328         memcpy(new->sm_name, hostname, hostname_len);
329         new->sm_name[hostname_len] = '\0';
330
331         return new;
332 }
333
334 /**
335  * nsm_get_handle - Find or create a cached nsm_handle
336  * @sap: pointer to socket address of handle to find
337  * @salen: length of socket address
338  * @hostname: pointer to C string containing hostname to find
339  * @hostname_len: length of C string
340  *
341  * Behavior is modulated by the global nsm_use_hostnames variable.
342  *
343  * Returns a cached nsm_handle after bumping its ref count, or
344  * returns a fresh nsm_handle if a handle that matches @sap and/or
345  * @hostname cannot be found in the handle cache.  Returns NULL if
346  * an error occurs.
347  */
348 struct nsm_handle *nsm_get_handle(const struct sockaddr *sap,
349                                   const size_t salen, const char *hostname,
350                                   const size_t hostname_len)
351 {
352         struct nsm_handle *cached, *new = NULL;
353
354         if (hostname && memchr(hostname, '/', hostname_len) != NULL) {
355                 if (printk_ratelimit()) {
356                         printk(KERN_WARNING "Invalid hostname \"%.*s\" "
357                                             "in NFS lock request\n",
358                                 (int)hostname_len, hostname);
359                 }
360                 return NULL;
361         }
362
363 retry:
364         spin_lock(&nsm_lock);
365
366         if (nsm_use_hostnames && hostname != NULL)
367                 cached = nsm_lookup_hostname(hostname, hostname_len);
368         else
369                 cached = nsm_lookup_addr(sap);
370
371         if (cached != NULL) {
372                 atomic_inc(&cached->sm_count);
373                 spin_unlock(&nsm_lock);
374                 kfree(new);
375                 dprintk("lockd: found nsm_handle for %s (%s), "
376                                 "cnt %d\n", cached->sm_name,
377                                 cached->sm_addrbuf,
378                                 atomic_read(&cached->sm_count));
379                 return cached;
380         }
381
382         if (new != NULL) {
383                 list_add(&new->sm_link, &nsm_handles);
384                 spin_unlock(&nsm_lock);
385                 dprintk("lockd: created nsm_handle for %s (%s)\n",
386                                 new->sm_name, new->sm_addrbuf);
387                 return new;
388         }
389
390         spin_unlock(&nsm_lock);
391
392         new = nsm_create_handle(sap, salen, hostname, hostname_len);
393         if (unlikely(new == NULL))
394                 return NULL;
395         goto retry;
396 }
397
398 /**
399  * nsm_reboot_lookup - match NLMPROC_SM_NOTIFY arguments to an nsm_handle
400  * @info: pointer to NLMPROC_SM_NOTIFY arguments
401  *
402  * Returns a matching nsm_handle if found in the nsm cache. The returned
403  * nsm_handle's reference count is bumped. Otherwise returns NULL if some
404  * error occurred.
405  */
406 struct nsm_handle *nsm_reboot_lookup(const struct nlm_reboot *info)
407 {
408         struct nsm_handle *cached;
409
410         spin_lock(&nsm_lock);
411
412         cached = nsm_lookup_priv(&info->priv);
413         if (unlikely(cached == NULL)) {
414                 spin_unlock(&nsm_lock);
415                 dprintk("lockd: never saw rebooted peer '%.*s' before\n",
416                                 info->len, info->mon);
417                 return cached;
418         }
419
420         atomic_inc(&cached->sm_count);
421         spin_unlock(&nsm_lock);
422
423         dprintk("lockd: host %s (%s) rebooted, cnt %d\n",
424                         cached->sm_name, cached->sm_addrbuf,
425                         atomic_read(&cached->sm_count));
426         return cached;
427 }
428
429 /**
430  * nsm_release - Release an NSM handle
431  * @nsm: pointer to handle to be released
432  *
433  */
434 void nsm_release(struct nsm_handle *nsm)
435 {
436         if (atomic_dec_and_lock(&nsm->sm_count, &nsm_lock)) {
437                 list_del(&nsm->sm_link);
438                 spin_unlock(&nsm_lock);
439                 dprintk("lockd: destroyed nsm_handle for %s (%s)\n",
440                                 nsm->sm_name, nsm->sm_addrbuf);
441                 kfree(nsm);
442         }
443 }
444
445 /*
446  * XDR functions for NSM.
447  *
448  * See http://www.opengroup.org/ for details on the Network
449  * Status Monitor wire protocol.
450  */
451
452 static void encode_nsm_string(struct xdr_stream *xdr, const char *string)
453 {
454         const u32 len = strlen(string);
455         __be32 *p;
456
457         BUG_ON(len > SM_MAXSTRLEN);
458         p = xdr_reserve_space(xdr, 4 + len);
459         xdr_encode_opaque(p, string, len);
460 }
461
462 /*
463  * "mon_name" specifies the host to be monitored.
464  */
465 static void encode_mon_name(struct xdr_stream *xdr, const struct nsm_args *argp)
466 {
467         encode_nsm_string(xdr, argp->mon_name);
468 }
469
470 /*
471  * The "my_id" argument specifies the hostname and RPC procedure
472  * to be called when the status manager receives notification
473  * (via the NLMPROC_SM_NOTIFY call) that the state of host "mon_name"
474  * has changed.
475  */
476 static void encode_my_id(struct xdr_stream *xdr, const struct nsm_args *argp)
477 {
478         __be32 *p;
479
480         encode_nsm_string(xdr, utsname()->nodename);
481         p = xdr_reserve_space(xdr, 4 + 4 + 4);
482         *p++ = cpu_to_be32(argp->prog);
483         *p++ = cpu_to_be32(argp->vers);
484         *p = cpu_to_be32(argp->proc);
485 }
486
487 /*
488  * The "mon_id" argument specifies the non-private arguments
489  * of an NSMPROC_MON or NSMPROC_UNMON call.
490  */
491 static void encode_mon_id(struct xdr_stream *xdr, const struct nsm_args *argp)
492 {
493         encode_mon_name(xdr, argp);
494         encode_my_id(xdr, argp);
495 }
496
497 /*
498  * The "priv" argument may contain private information required
499  * by the NSMPROC_MON call. This information will be supplied in the
500  * NLMPROC_SM_NOTIFY call.
501  */
502 static void encode_priv(struct xdr_stream *xdr, const struct nsm_args *argp)
503 {
504         __be32 *p;
505
506         p = xdr_reserve_space(xdr, SM_PRIV_SIZE);
507         xdr_encode_opaque_fixed(p, argp->priv->data, SM_PRIV_SIZE);
508 }
509
510 static void nsm_xdr_enc_mon(struct rpc_rqst *req, struct xdr_stream *xdr,
511                             const struct nsm_args *argp)
512 {
513         encode_mon_id(xdr, argp);
514         encode_priv(xdr, argp);
515 }
516
517 static void nsm_xdr_enc_unmon(struct rpc_rqst *req, struct xdr_stream *xdr,
518                               const struct nsm_args *argp)
519 {
520         encode_mon_id(xdr, argp);
521 }
522
523 static int nsm_xdr_dec_stat_res(struct rpc_rqst *rqstp,
524                                 struct xdr_stream *xdr,
525                                 struct nsm_res *resp)
526 {
527         __be32 *p;
528
529         p = xdr_inline_decode(xdr, 4 + 4);
530         if (unlikely(p == NULL))
531                 return -EIO;
532         resp->status = be32_to_cpup(p++);
533         resp->state = be32_to_cpup(p);
534
535         dprintk("lockd: %s status %d state %d\n",
536                 __func__, resp->status, resp->state);
537         return 0;
538 }
539
540 static int nsm_xdr_dec_stat(struct rpc_rqst *rqstp,
541                             struct xdr_stream *xdr,
542                             struct nsm_res *resp)
543 {
544         __be32 *p;
545
546         p = xdr_inline_decode(xdr, 4);
547         if (unlikely(p == NULL))
548                 return -EIO;
549         resp->state = be32_to_cpup(p);
550
551         dprintk("lockd: %s state %d\n", __func__, resp->state);
552         return 0;
553 }
554
555 #define SM_my_name_sz   (1+XDR_QUADLEN(SM_MAXSTRLEN))
556 #define SM_my_id_sz     (SM_my_name_sz+3)
557 #define SM_mon_name_sz  (1+XDR_QUADLEN(SM_MAXSTRLEN))
558 #define SM_mon_id_sz    (SM_mon_name_sz+SM_my_id_sz)
559 #define SM_priv_sz      (XDR_QUADLEN(SM_PRIV_SIZE))
560 #define SM_mon_sz       (SM_mon_id_sz+SM_priv_sz)
561 #define SM_monres_sz    2
562 #define SM_unmonres_sz  1
563
564 static struct rpc_procinfo      nsm_procedures[] = {
565 [NSMPROC_MON] = {
566                 .p_proc         = NSMPROC_MON,
567                 .p_encode       = (kxdreproc_t)nsm_xdr_enc_mon,
568                 .p_decode       = (kxdrdproc_t)nsm_xdr_dec_stat_res,
569                 .p_arglen       = SM_mon_sz,
570                 .p_replen       = SM_monres_sz,
571                 .p_statidx      = NSMPROC_MON,
572                 .p_name         = "MONITOR",
573         },
574 [NSMPROC_UNMON] = {
575                 .p_proc         = NSMPROC_UNMON,
576                 .p_encode       = (kxdreproc_t)nsm_xdr_enc_unmon,
577                 .p_decode       = (kxdrdproc_t)nsm_xdr_dec_stat,
578                 .p_arglen       = SM_mon_id_sz,
579                 .p_replen       = SM_unmonres_sz,
580                 .p_statidx      = NSMPROC_UNMON,
581                 .p_name         = "UNMONITOR",
582         },
583 };
584
585 static const struct rpc_version nsm_version1 = {
586                 .number         = 1,
587                 .nrprocs        = ARRAY_SIZE(nsm_procedures),
588                 .procs          = nsm_procedures
589 };
590
591 static const struct rpc_version *nsm_version[] = {
592         [1] = &nsm_version1,
593 };
594
595 static struct rpc_stat          nsm_stats;
596
597 static const struct rpc_program nsm_program = {
598                 .name           = "statd",
599                 .number         = NSM_PROGRAM,
600                 .nrvers         = ARRAY_SIZE(nsm_version),
601                 .version        = nsm_version,
602                 .stats          = &nsm_stats
603 };