svc.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * linux/fs/lockd/svc.c
  4. *
  5. * This is the central lockd service.
  6. *
  7. * FIXME: Separate the lockd NFS server functionality from the lockd NFS
  8. * client functionality. Oh why didn't Sun create two separate
  9. * services in the first place?
  10. *
  11. * Authors: Olaf Kirch (okir@monad.swb.de)
  12. *
  13. * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
  14. */
  15. #include <linux/module.h>
  16. #include <linux/init.h>
  17. #include <linux/sysctl.h>
  18. #include <linux/moduleparam.h>
  19. #include <linux/sched/signal.h>
  20. #include <linux/errno.h>
  21. #include <linux/in.h>
  22. #include <linux/uio.h>
  23. #include <linux/smp.h>
  24. #include <linux/mutex.h>
  25. #include <linux/freezer.h>
  26. #include <linux/inetdevice.h>
  27. #include <linux/sunrpc/types.h>
  28. #include <linux/sunrpc/stats.h>
  29. #include <linux/sunrpc/clnt.h>
  30. #include <linux/sunrpc/svc.h>
  31. #include <linux/sunrpc/svcsock.h>
  32. #include <linux/sunrpc/svc_xprt.h>
  33. #include <net/ip.h>
  34. #include <net/addrconf.h>
  35. #include <net/ipv6.h>
  36. #include <linux/lockd/lockd.h>
  37. #include <linux/nfs.h>
  38. #include "netns.h"
  39. #include "procfs.h"
  40. #define NLMDBG_FACILITY NLMDBG_SVC
  41. #define LOCKD_BUFSIZE (1024 + NLMSVC_XDRSIZE)
  42. static struct svc_program nlmsvc_program;
  43. const struct nlmsvc_binding *nlmsvc_ops;
  44. EXPORT_SYMBOL_GPL(nlmsvc_ops);
  45. static DEFINE_MUTEX(nlmsvc_mutex);
  46. static unsigned int nlmsvc_users;
  47. static struct svc_serv *nlmsvc_serv;
  48. static void nlmsvc_request_retry(struct timer_list *tl)
  49. {
  50. svc_wake_up(nlmsvc_serv);
  51. }
  52. DEFINE_TIMER(nlmsvc_retry, nlmsvc_request_retry);
  53. unsigned int lockd_net_id;
  54. /*
  55. * These can be set at insmod time (useful for NFS as root filesystem),
  56. * and also changed through the sysctl interface. -- Jamie Lokier, Aug 2003
  57. */
  58. static unsigned long nlm_grace_period;
  59. unsigned long nlm_timeout = LOCKD_DFLT_TIMEO;
  60. static int nlm_udpport, nlm_tcpport;
  61. /* RLIM_NOFILE defaults to 1024. That seems like a reasonable default here. */
  62. static unsigned int nlm_max_connections = 1024;
  63. /*
  64. * Constants needed for the sysctl interface.
  65. */
  66. static const unsigned long nlm_grace_period_min = 0;
  67. static const unsigned long nlm_grace_period_max = 240;
  68. static const unsigned long nlm_timeout_min = 3;
  69. static const unsigned long nlm_timeout_max = 20;
  70. #ifdef CONFIG_SYSCTL
  71. static const int nlm_port_min = 0, nlm_port_max = 65535;
  72. static struct ctl_table_header * nlm_sysctl_table;
  73. #endif
  74. static unsigned long get_lockd_grace_period(void)
  75. {
  76. /* Note: nlm_timeout should always be nonzero */
  77. if (nlm_grace_period)
  78. return roundup(nlm_grace_period, nlm_timeout) * HZ;
  79. else
  80. return nlm_timeout * 5 * HZ;
  81. }
  82. static void grace_ender(struct work_struct *grace)
  83. {
  84. struct delayed_work *dwork = to_delayed_work(grace);
  85. struct lockd_net *ln = container_of(dwork, struct lockd_net,
  86. grace_period_end);
  87. locks_end_grace(&ln->lockd_manager);
  88. }
  89. static void set_grace_period(struct net *net)
  90. {
  91. unsigned long grace_period = get_lockd_grace_period();
  92. struct lockd_net *ln = net_generic(net, lockd_net_id);
  93. locks_start_grace(net, &ln->lockd_manager);
  94. cancel_delayed_work_sync(&ln->grace_period_end);
  95. schedule_delayed_work(&ln->grace_period_end, grace_period);
  96. }
  97. /*
  98. * This is the lockd kernel thread
  99. */
  100. static int
  101. lockd(void *vrqstp)
  102. {
  103. struct svc_rqst *rqstp = vrqstp;
  104. struct net *net = &init_net;
  105. struct lockd_net *ln = net_generic(net, lockd_net_id);
  106. svc_thread_init_status(rqstp, 0);
  107. /* try_to_freeze() is called from svc_recv() */
  108. set_freezable();
  109. dprintk("NFS locking service started (ver " LOCKD_VERSION ").\n");
  110. /*
  111. * The main request loop. We don't terminate until the last
  112. * NFS mount or NFS daemon has gone away.
  113. */
  114. while (!svc_thread_should_stop(rqstp)) {
  115. /* update sv_maxconn if it has changed */
  116. rqstp->rq_server->sv_maxconn = nlm_max_connections;
  117. nlmsvc_retry_blocked(rqstp);
  118. svc_recv(rqstp);
  119. }
  120. if (nlmsvc_ops)
  121. nlmsvc_invalidate_all();
  122. nlm_shutdown_hosts();
  123. cancel_delayed_work_sync(&ln->grace_period_end);
  124. locks_end_grace(&ln->lockd_manager);
  125. dprintk("lockd_down: service stopped\n");
  126. svc_exit_thread(rqstp);
  127. return 0;
  128. }
  129. static int create_lockd_listener(struct svc_serv *serv, const char *name,
  130. struct net *net, const int family,
  131. const unsigned short port,
  132. const struct cred *cred)
  133. {
  134. struct svc_xprt *xprt;
  135. xprt = svc_find_xprt(serv, name, net, family, 0);
  136. if (xprt == NULL)
  137. return svc_xprt_create(serv, name, net, family, port,
  138. SVC_SOCK_DEFAULTS, cred);
  139. svc_xprt_put(xprt);
  140. return 0;
  141. }
  142. static int create_lockd_family(struct svc_serv *serv, struct net *net,
  143. const int family, const struct cred *cred)
  144. {
  145. int err;
  146. err = create_lockd_listener(serv, "udp", net, family, nlm_udpport,
  147. cred);
  148. if (err < 0)
  149. return err;
  150. return create_lockd_listener(serv, "tcp", net, family, nlm_tcpport,
  151. cred);
  152. }
  153. /*
  154. * Ensure there are active UDP and TCP listeners for lockd.
  155. *
  156. * Even if we have only TCP NFS mounts and/or TCP NFSDs, some
  157. * local services (such as rpc.statd) still require UDP, and
  158. * some NFS servers do not yet support NLM over TCP.
  159. *
  160. * Returns zero if all listeners are available; otherwise a
  161. * negative errno value is returned.
  162. */
  163. static int make_socks(struct svc_serv *serv, struct net *net,
  164. const struct cred *cred)
  165. {
  166. static int warned;
  167. int err;
  168. err = create_lockd_family(serv, net, PF_INET, cred);
  169. if (err < 0)
  170. goto out_err;
  171. err = create_lockd_family(serv, net, PF_INET6, cred);
  172. if (err < 0 && err != -EAFNOSUPPORT)
  173. goto out_err;
  174. warned = 0;
  175. return 0;
  176. out_err:
  177. if (warned++ == 0)
  178. printk(KERN_WARNING
  179. "lockd_up: makesock failed, error=%d\n", err);
  180. svc_xprt_destroy_all(serv, net);
  181. svc_rpcb_cleanup(serv, net);
  182. return err;
  183. }
  184. static int lockd_up_net(struct svc_serv *serv, struct net *net,
  185. const struct cred *cred)
  186. {
  187. struct lockd_net *ln = net_generic(net, lockd_net_id);
  188. int error;
  189. if (ln->nlmsvc_users++)
  190. return 0;
  191. error = svc_bind(serv, net);
  192. if (error)
  193. goto err_bind;
  194. error = make_socks(serv, net, cred);
  195. if (error < 0)
  196. goto err_bind;
  197. set_grace_period(net);
  198. dprintk("%s: per-net data created; net=%x\n", __func__, net->ns.inum);
  199. return 0;
  200. err_bind:
  201. ln->nlmsvc_users--;
  202. return error;
  203. }
  204. static void lockd_down_net(struct svc_serv *serv, struct net *net)
  205. {
  206. struct lockd_net *ln = net_generic(net, lockd_net_id);
  207. if (ln->nlmsvc_users) {
  208. if (--ln->nlmsvc_users == 0) {
  209. nlm_shutdown_hosts_net(net);
  210. cancel_delayed_work_sync(&ln->grace_period_end);
  211. locks_end_grace(&ln->lockd_manager);
  212. svc_xprt_destroy_all(serv, net);
  213. svc_rpcb_cleanup(serv, net);
  214. }
  215. } else {
  216. pr_err("%s: no users! net=%x\n",
  217. __func__, net->ns.inum);
  218. BUG();
  219. }
  220. }
  221. static int lockd_inetaddr_event(struct notifier_block *this,
  222. unsigned long event, void *ptr)
  223. {
  224. struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
  225. struct sockaddr_in sin;
  226. if (event != NETDEV_DOWN)
  227. goto out;
  228. if (nlmsvc_serv) {
  229. dprintk("lockd_inetaddr_event: removed %pI4\n",
  230. &ifa->ifa_local);
  231. sin.sin_family = AF_INET;
  232. sin.sin_addr.s_addr = ifa->ifa_local;
  233. svc_age_temp_xprts_now(nlmsvc_serv, (struct sockaddr *)&sin);
  234. }
  235. out:
  236. return NOTIFY_DONE;
  237. }
  238. static struct notifier_block lockd_inetaddr_notifier = {
  239. .notifier_call = lockd_inetaddr_event,
  240. };
  241. #if IS_ENABLED(CONFIG_IPV6)
  242. static int lockd_inet6addr_event(struct notifier_block *this,
  243. unsigned long event, void *ptr)
  244. {
  245. struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
  246. struct sockaddr_in6 sin6;
  247. if (event != NETDEV_DOWN)
  248. goto out;
  249. if (nlmsvc_serv) {
  250. dprintk("lockd_inet6addr_event: removed %pI6\n", &ifa->addr);
  251. sin6.sin6_family = AF_INET6;
  252. sin6.sin6_addr = ifa->addr;
  253. if (ipv6_addr_type(&sin6.sin6_addr) & IPV6_ADDR_LINKLOCAL)
  254. sin6.sin6_scope_id = ifa->idev->dev->ifindex;
  255. svc_age_temp_xprts_now(nlmsvc_serv, (struct sockaddr *)&sin6);
  256. }
  257. out:
  258. return NOTIFY_DONE;
  259. }
  260. static struct notifier_block lockd_inet6addr_notifier = {
  261. .notifier_call = lockd_inet6addr_event,
  262. };
  263. #endif
  264. static int lockd_get(void)
  265. {
  266. struct svc_serv *serv;
  267. int error;
  268. if (nlmsvc_serv) {
  269. nlmsvc_users++;
  270. return 0;
  271. }
  272. /*
  273. * Sanity check: if there's no pid,
  274. * we should be the first user ...
  275. */
  276. if (nlmsvc_users)
  277. printk(KERN_WARNING
  278. "lockd_up: no pid, %d users??\n", nlmsvc_users);
  279. serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, lockd);
  280. if (!serv) {
  281. printk(KERN_WARNING "lockd_up: create service failed\n");
  282. return -ENOMEM;
  283. }
  284. serv->sv_maxconn = nlm_max_connections;
  285. error = svc_set_num_threads(serv, NULL, 1);
  286. if (error < 0) {
  287. svc_destroy(&serv);
  288. return error;
  289. }
  290. nlmsvc_serv = serv;
  291. register_inetaddr_notifier(&lockd_inetaddr_notifier);
  292. #if IS_ENABLED(CONFIG_IPV6)
  293. register_inet6addr_notifier(&lockd_inet6addr_notifier);
  294. #endif
  295. dprintk("lockd_up: service created\n");
  296. nlmsvc_users++;
  297. return 0;
  298. }
  299. static void lockd_put(void)
  300. {
  301. if (WARN(nlmsvc_users <= 0, "lockd_down: no users!\n"))
  302. return;
  303. if (--nlmsvc_users)
  304. return;
  305. unregister_inetaddr_notifier(&lockd_inetaddr_notifier);
  306. #if IS_ENABLED(CONFIG_IPV6)
  307. unregister_inet6addr_notifier(&lockd_inet6addr_notifier);
  308. #endif
  309. svc_set_num_threads(nlmsvc_serv, NULL, 0);
  310. timer_delete_sync(&nlmsvc_retry);
  311. svc_destroy(&nlmsvc_serv);
  312. dprintk("lockd_down: service destroyed\n");
  313. }
  314. /*
  315. * Bring up the lockd process if it's not already up.
  316. */
  317. int lockd_up(struct net *net, const struct cred *cred)
  318. {
  319. int error;
  320. mutex_lock(&nlmsvc_mutex);
  321. error = lockd_get();
  322. if (error)
  323. goto err;
  324. error = lockd_up_net(nlmsvc_serv, net, cred);
  325. if (error < 0) {
  326. lockd_put();
  327. goto err;
  328. }
  329. err:
  330. mutex_unlock(&nlmsvc_mutex);
  331. return error;
  332. }
  333. EXPORT_SYMBOL_GPL(lockd_up);
  334. /*
  335. * Decrement the user count and bring down lockd if we're the last.
  336. */
  337. void
  338. lockd_down(struct net *net)
  339. {
  340. mutex_lock(&nlmsvc_mutex);
  341. lockd_down_net(nlmsvc_serv, net);
  342. lockd_put();
  343. mutex_unlock(&nlmsvc_mutex);
  344. }
  345. EXPORT_SYMBOL_GPL(lockd_down);
  346. #ifdef CONFIG_SYSCTL
  347. /*
  348. * Sysctl parameters (same as module parameters, different interface).
  349. */
  350. static struct ctl_table nlm_sysctls[] = {
  351. {
  352. .procname = "nlm_grace_period",
  353. .data = &nlm_grace_period,
  354. .maxlen = sizeof(unsigned long),
  355. .mode = 0644,
  356. .proc_handler = proc_doulongvec_minmax,
  357. .extra1 = (unsigned long *) &nlm_grace_period_min,
  358. .extra2 = (unsigned long *) &nlm_grace_period_max,
  359. },
  360. {
  361. .procname = "nlm_timeout",
  362. .data = &nlm_timeout,
  363. .maxlen = sizeof(unsigned long),
  364. .mode = 0644,
  365. .proc_handler = proc_doulongvec_minmax,
  366. .extra1 = (unsigned long *) &nlm_timeout_min,
  367. .extra2 = (unsigned long *) &nlm_timeout_max,
  368. },
  369. {
  370. .procname = "nlm_udpport",
  371. .data = &nlm_udpport,
  372. .maxlen = sizeof(int),
  373. .mode = 0644,
  374. .proc_handler = proc_dointvec_minmax,
  375. .extra1 = (int *) &nlm_port_min,
  376. .extra2 = (int *) &nlm_port_max,
  377. },
  378. {
  379. .procname = "nlm_tcpport",
  380. .data = &nlm_tcpport,
  381. .maxlen = sizeof(int),
  382. .mode = 0644,
  383. .proc_handler = proc_dointvec_minmax,
  384. .extra1 = (int *) &nlm_port_min,
  385. .extra2 = (int *) &nlm_port_max,
  386. },
  387. {
  388. .procname = "nsm_use_hostnames",
  389. .data = &nsm_use_hostnames,
  390. .maxlen = sizeof(bool),
  391. .mode = 0644,
  392. .proc_handler = proc_dobool,
  393. },
  394. {
  395. .procname = "nsm_local_state",
  396. .data = &nsm_local_state,
  397. .maxlen = sizeof(int),
  398. .mode = 0644,
  399. .proc_handler = proc_dointvec,
  400. },
  401. };
  402. #endif /* CONFIG_SYSCTL */
  403. /*
  404. * Module (and sysfs) parameters.
  405. */
  406. #define param_set_min_max(name, type, which_strtol, min, max) \
  407. static int param_set_##name(const char *val, const struct kernel_param *kp) \
  408. { \
  409. char *endp; \
  410. __typeof__(type) num = which_strtol(val, &endp, 0); \
  411. if (endp == val || *endp || num < (min) || num > (max)) \
  412. return -EINVAL; \
  413. *((type *) kp->arg) = num; \
  414. return 0; \
  415. }
  416. static inline int is_callback(u32 proc)
  417. {
  418. return proc == NLMPROC_GRANTED
  419. || proc == NLMPROC_GRANTED_MSG
  420. || proc == NLMPROC_TEST_RES
  421. || proc == NLMPROC_LOCK_RES
  422. || proc == NLMPROC_CANCEL_RES
  423. || proc == NLMPROC_UNLOCK_RES
  424. || proc == NLMPROC_NSM_NOTIFY;
  425. }
  426. static enum svc_auth_status lockd_authenticate(struct svc_rqst *rqstp)
  427. {
  428. rqstp->rq_client = NULL;
  429. switch (rqstp->rq_authop->flavour) {
  430. case RPC_AUTH_NULL:
  431. case RPC_AUTH_UNIX:
  432. rqstp->rq_auth_stat = rpc_auth_ok;
  433. if (rqstp->rq_proc == 0)
  434. return SVC_OK;
  435. if (is_callback(rqstp->rq_proc)) {
  436. /* Leave it to individual procedures to
  437. * call nlmsvc_lookup_host(rqstp)
  438. */
  439. return SVC_OK;
  440. }
  441. return svc_set_client(rqstp);
  442. }
  443. rqstp->rq_auth_stat = rpc_autherr_badcred;
  444. return SVC_DENIED;
  445. }
  446. param_set_min_max(port, int, simple_strtol, 0, 65535)
  447. param_set_min_max(grace_period, unsigned long, simple_strtoul,
  448. nlm_grace_period_min, nlm_grace_period_max)
  449. param_set_min_max(timeout, unsigned long, simple_strtoul,
  450. nlm_timeout_min, nlm_timeout_max)
  451. MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
  452. MODULE_DESCRIPTION("NFS file locking service version " LOCKD_VERSION ".");
  453. MODULE_LICENSE("GPL");
  454. module_param_call(nlm_grace_period, param_set_grace_period, param_get_ulong,
  455. &nlm_grace_period, 0644);
  456. module_param_call(nlm_timeout, param_set_timeout, param_get_ulong,
  457. &nlm_timeout, 0644);
  458. module_param_call(nlm_udpport, param_set_port, param_get_int,
  459. &nlm_udpport, 0644);
  460. module_param_call(nlm_tcpport, param_set_port, param_get_int,
  461. &nlm_tcpport, 0644);
  462. module_param(nsm_use_hostnames, bool, 0644);
  463. module_param(nlm_max_connections, uint, 0644);
  464. static int lockd_init_net(struct net *net)
  465. {
  466. struct lockd_net *ln = net_generic(net, lockd_net_id);
  467. INIT_DELAYED_WORK(&ln->grace_period_end, grace_ender);
  468. INIT_LIST_HEAD(&ln->lockd_manager.list);
  469. ln->lockd_manager.block_opens = false;
  470. INIT_LIST_HEAD(&ln->nsm_handles);
  471. return 0;
  472. }
  473. static void lockd_exit_net(struct net *net)
  474. {
  475. struct lockd_net *ln = net_generic(net, lockd_net_id);
  476. WARN_ONCE(!list_empty(&ln->lockd_manager.list),
  477. "net %x %s: lockd_manager.list is not empty\n",
  478. net->ns.inum, __func__);
  479. WARN_ONCE(!list_empty(&ln->nsm_handles),
  480. "net %x %s: nsm_handles list is not empty\n",
  481. net->ns.inum, __func__);
  482. WARN_ONCE(delayed_work_pending(&ln->grace_period_end),
  483. "net %x %s: grace_period_end was not cancelled\n",
  484. net->ns.inum, __func__);
  485. }
  486. static struct pernet_operations lockd_net_ops = {
  487. .init = lockd_init_net,
  488. .exit = lockd_exit_net,
  489. .id = &lockd_net_id,
  490. .size = sizeof(struct lockd_net),
  491. };
  492. /*
  493. * Initialising and terminating the module.
  494. */
  495. static int __init init_nlm(void)
  496. {
  497. int err;
  498. #ifdef CONFIG_SYSCTL
  499. err = -ENOMEM;
  500. nlm_sysctl_table = register_sysctl("fs/nfs", nlm_sysctls);
  501. if (nlm_sysctl_table == NULL)
  502. goto err_sysctl;
  503. #endif
  504. err = register_pernet_subsys(&lockd_net_ops);
  505. if (err)
  506. goto err_pernet;
  507. err = lockd_create_procfs();
  508. if (err)
  509. goto err_procfs;
  510. return 0;
  511. err_procfs:
  512. unregister_pernet_subsys(&lockd_net_ops);
  513. err_pernet:
  514. #ifdef CONFIG_SYSCTL
  515. unregister_sysctl_table(nlm_sysctl_table);
  516. err_sysctl:
  517. #endif
  518. return err;
  519. }
  520. static void __exit exit_nlm(void)
  521. {
  522. /* FIXME: delete all NLM clients */
  523. nlm_shutdown_hosts();
  524. lockd_remove_procfs();
  525. unregister_pernet_subsys(&lockd_net_ops);
  526. #ifdef CONFIG_SYSCTL
  527. unregister_sysctl_table(nlm_sysctl_table);
  528. #endif
  529. }
  530. module_init(init_nlm);
  531. module_exit(exit_nlm);
  532. /**
  533. * nlmsvc_dispatch - Process an NLM Request
  534. * @rqstp: incoming request
  535. *
  536. * Return values:
  537. * %0: Processing complete; do not send a Reply
  538. * %1: Processing complete; send Reply in rqstp->rq_res
  539. */
  540. static int nlmsvc_dispatch(struct svc_rqst *rqstp)
  541. {
  542. const struct svc_procedure *procp = rqstp->rq_procinfo;
  543. __be32 *statp = rqstp->rq_accept_statp;
  544. if (!procp->pc_decode(rqstp, &rqstp->rq_arg_stream))
  545. goto out_decode_err;
  546. *statp = procp->pc_func(rqstp);
  547. if (*statp == rpc_drop_reply)
  548. return 0;
  549. if (*statp != rpc_success)
  550. return 1;
  551. if (!procp->pc_encode(rqstp, &rqstp->rq_res_stream))
  552. goto out_encode_err;
  553. return 1;
  554. out_decode_err:
  555. *statp = rpc_garbage_args;
  556. return 1;
  557. out_encode_err:
  558. *statp = rpc_system_err;
  559. return 1;
  560. }
  561. /*
  562. * Define NLM program and procedures
  563. */
  564. static DEFINE_PER_CPU_ALIGNED(unsigned long, nlmsvc_version1_count[17]);
  565. static const struct svc_version nlmsvc_version1 = {
  566. .vs_vers = 1,
  567. .vs_nproc = 17,
  568. .vs_proc = nlmsvc_procedures,
  569. .vs_count = nlmsvc_version1_count,
  570. .vs_dispatch = nlmsvc_dispatch,
  571. .vs_xdrsize = NLMSVC_XDRSIZE,
  572. };
  573. static DEFINE_PER_CPU_ALIGNED(unsigned long,
  574. nlmsvc_version3_count[ARRAY_SIZE(nlmsvc_procedures)]);
  575. static const struct svc_version nlmsvc_version3 = {
  576. .vs_vers = 3,
  577. .vs_nproc = ARRAY_SIZE(nlmsvc_procedures),
  578. .vs_proc = nlmsvc_procedures,
  579. .vs_count = nlmsvc_version3_count,
  580. .vs_dispatch = nlmsvc_dispatch,
  581. .vs_xdrsize = NLMSVC_XDRSIZE,
  582. };
  583. #ifdef CONFIG_LOCKD_V4
  584. static DEFINE_PER_CPU_ALIGNED(unsigned long,
  585. nlmsvc_version4_count[ARRAY_SIZE(nlmsvc_procedures4)]);
  586. static const struct svc_version nlmsvc_version4 = {
  587. .vs_vers = 4,
  588. .vs_nproc = ARRAY_SIZE(nlmsvc_procedures4),
  589. .vs_proc = nlmsvc_procedures4,
  590. .vs_count = nlmsvc_version4_count,
  591. .vs_dispatch = nlmsvc_dispatch,
  592. .vs_xdrsize = NLMSVC_XDRSIZE,
  593. };
  594. #endif
  595. static const struct svc_version *nlmsvc_version[] = {
  596. [1] = &nlmsvc_version1,
  597. [3] = &nlmsvc_version3,
  598. #ifdef CONFIG_LOCKD_V4
  599. [4] = &nlmsvc_version4,
  600. #endif
  601. };
  602. #define NLM_NRVERS ARRAY_SIZE(nlmsvc_version)
  603. static struct svc_program nlmsvc_program = {
  604. .pg_prog = NLM_PROGRAM, /* program number */
  605. .pg_nvers = NLM_NRVERS, /* number of entries in nlmsvc_version */
  606. .pg_vers = nlmsvc_version, /* version table */
  607. .pg_name = "lockd", /* service name */
  608. .pg_class = "nfsd", /* share authentication with nfsd */
  609. .pg_authenticate = &lockd_authenticate, /* export authentication */
  610. .pg_init_request = svc_generic_init_request,
  611. .pg_rpcbind_set = svc_generic_rpcbind_set,
  612. };