~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/lockd/mon.c

Version: ~ [ linux-5.16 ] ~ [ linux-5.15.13 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.90 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.170 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.224 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.261 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.296 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.298 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp