lockd: drop inappropriate svc_get() from locked_get()
[linux-2.6-block.git] / fs / lockd / svc.c
CommitLineData
09c434b8 1// SPDX-License-Identifier: GPL-2.0-only
1da177e4
LT
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
1da177e4
LT
16#include <linux/module.h>
17#include <linux/init.h>
18#include <linux/sysctl.h>
19#include <linux/moduleparam.h>
20
3f07c014 21#include <linux/sched/signal.h>
1da177e4
LT
22#include <linux/errno.h>
23#include <linux/in.h>
24#include <linux/uio.h>
1da177e4 25#include <linux/smp.h>
353ab6e9 26#include <linux/mutex.h>
d751a7cd 27#include <linux/kthread.h>
83144186 28#include <linux/freezer.h>
0751ddf7 29#include <linux/inetdevice.h>
1da177e4
LT
30
31#include <linux/sunrpc/types.h>
32#include <linux/sunrpc/stats.h>
33#include <linux/sunrpc/clnt.h>
34#include <linux/sunrpc/svc.h>
35#include <linux/sunrpc/svcsock.h>
0751ddf7 36#include <linux/sunrpc/svc_xprt.h>
24e36663 37#include <net/ip.h>
0751ddf7
SM
38#include <net/addrconf.h>
39#include <net/ipv6.h>
1da177e4
LT
40#include <linux/lockd/lockd.h>
41#include <linux/nfs.h>
42
a9c5d73a 43#include "netns.h"
d68e3c4a 44#include "procfs.h"
a9c5d73a 45
1da177e4
LT
46#define NLMDBG_FACILITY NLMDBG_SVC
47#define LOCKD_BUFSIZE (1024 + NLMSVC_XDRSIZE)
48#define ALLOWED_SIGS (sigmask(SIGKILL))
49
50static struct svc_program nlmsvc_program;
51
2a297450 52const struct nlmsvc_binding *nlmsvc_ops;
2de59872 53EXPORT_SYMBOL_GPL(nlmsvc_ops);
1da177e4 54
353ab6e9 55static DEFINE_MUTEX(nlmsvc_mutex);
1da177e4 56static unsigned int nlmsvc_users;
2840fe86 57static struct svc_serv *nlmsvc_serv;
1da177e4
LT
58unsigned long nlmsvc_timeout;
59
c7d03a00 60unsigned int lockd_net_id;
a9c5d73a 61
1da177e4
LT
62/*
63 * These can be set at insmod time (useful for NFS as root filesystem),
64 * and also changed through the sysctl interface. -- Jamie Lokier, Aug 2003
65 */
66static unsigned long nlm_grace_period;
67static unsigned long nlm_timeout = LOCKD_DFLT_TIMEO;
68static int nlm_udpport, nlm_tcpport;
69
c72a476b
JL
70/* RLIM_NOFILE defaults to 1024. That seems like a reasonable default here. */
71static unsigned int nlm_max_connections = 1024;
72
1da177e4
LT
73/*
74 * Constants needed for the sysctl interface.
75 */
76static const unsigned long nlm_grace_period_min = 0;
77static const unsigned long nlm_grace_period_max = 240;
78static const unsigned long nlm_timeout_min = 3;
79static const unsigned long nlm_timeout_max = 20;
1da177e4 80
90d5b180 81#ifdef CONFIG_SYSCTL
fc412a61 82static const int nlm_port_min = 0, nlm_port_max = 65535;
1da177e4 83static struct ctl_table_header * nlm_sysctl_table;
90d5b180 84#endif
1da177e4 85
9a8db97e 86static unsigned long get_lockd_grace_period(void)
1da177e4 87{
1da177e4
LT
88 /* Note: nlm_timeout should always be nonzero */
89 if (nlm_grace_period)
9a8db97e 90 return roundup(nlm_grace_period, nlm_timeout) * HZ;
1da177e4 91 else
9a8db97e
ME
92 return nlm_timeout * 5 * HZ;
93}
94
08d44a35 95static void grace_ender(struct work_struct *grace)
9a8db97e 96{
ea44463f 97 struct delayed_work *dwork = to_delayed_work(grace);
08d44a35
SK
98 struct lockd_net *ln = container_of(dwork, struct lockd_net,
99 grace_period_end);
100
101 locks_end_grace(&ln->lockd_manager);
1da177e4
LT
102}
103
5ccb0066 104static void set_grace_period(struct net *net)
1da177e4 105{
af558e33 106 unsigned long grace_period = get_lockd_grace_period();
5ccb0066 107 struct lockd_net *ln = net_generic(net, lockd_net_id);
c8ab5f2a 108
5ccb0066 109 locks_start_grace(net, &ln->lockd_manager);
66547b02
SK
110 cancel_delayed_work_sync(&ln->grace_period_end);
111 schedule_delayed_work(&ln->grace_period_end, grace_period);
1da177e4
LT
112}
113
89996df4
BF
114static void restart_grace(void)
115{
116 if (nlmsvc_ops) {
5ccb0066
SK
117 struct net *net = &init_net;
118 struct lockd_net *ln = net_generic(net, lockd_net_id);
66547b02
SK
119
120 cancel_delayed_work_sync(&ln->grace_period_end);
08d44a35 121 locks_end_grace(&ln->lockd_manager);
89996df4 122 nlmsvc_invalidate_all();
5ccb0066 123 set_grace_period(net);
89996df4
BF
124 }
125}
126
1da177e4
LT
127/*
128 * This is the lockd kernel thread
129 */
d751a7cd
JL
130static int
131lockd(void *vrqstp)
1da177e4 132{
5b444cc9 133 int err = 0;
d751a7cd 134 struct svc_rqst *rqstp = vrqstp;
efda760f
BF
135 struct net *net = &init_net;
136 struct lockd_net *ln = net_generic(net, lockd_net_id);
1da177e4 137
d751a7cd 138 /* try_to_freeze() is called from svc_recv() */
83144186 139 set_freezable();
1da177e4 140
d751a7cd 141 /* Allow SIGKILL to tell lockd to drop all of its locks */
1da177e4
LT
142 allow_signal(SIGKILL);
143
1da177e4
LT
144 dprintk("NFS locking service started (ver " LOCKD_VERSION ").\n");
145
1da177e4
LT
146 /*
147 * The main request loop. We don't terminate until the last
d751a7cd 148 * NFS mount or NFS daemon has gone away.
1da177e4 149 */
d751a7cd 150 while (!kthread_should_stop()) {
1da177e4 151 long timeout = MAX_SCHEDULE_TIMEOUT;
5216a8e7 152 RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
1da177e4 153
c72a476b
JL
154 /* update sv_maxconn if it has changed */
155 rqstp->rq_server->sv_maxconn = nlm_max_connections;
156
1da177e4
LT
157 if (signalled()) {
158 flush_signals(current);
89996df4 159 restart_grace();
d751a7cd 160 continue;
1da177e4
LT
161 }
162
8fafa900
BF
163 timeout = nlmsvc_retry_blocked();
164
1da177e4
LT
165 /*
166 * Find a socket with data available and call its
167 * recvfrom routine.
168 */
6fb2b47f 169 err = svc_recv(rqstp, timeout);
5b444cc9 170 if (err == -EAGAIN || err == -EINTR)
1da177e4 171 continue;
ad06e4bd
CL
172 dprintk("lockd: request from %s\n",
173 svc_print_addr(rqstp, buf, sizeof(buf)));
1da177e4 174
6fb2b47f 175 svc_process(rqstp);
1da177e4 176 }
2bd61579 177 flush_signals(current);
d751a7cd
JL
178 if (nlmsvc_ops)
179 nlmsvc_invalidate_all();
180 nlm_shutdown_hosts();
efda760f
BF
181 cancel_delayed_work_sync(&ln->grace_period_end);
182 locks_end_grace(&ln->lockd_manager);
6a4e2527
N
183
184 dprintk("lockd_down: service stopped\n");
185
186 svc_exit_thread(rqstp);
f49169c9 187 return 0;
1da177e4
LT
188}
189
eb16e907 190static int create_lockd_listener(struct svc_serv *serv, const char *name,
c228fa20 191 struct net *net, const int family,
40373b12
TM
192 const unsigned short port,
193 const struct cred *cred)
d3fe5ea7
CL
194{
195 struct svc_xprt *xprt;
196
c228fa20 197 xprt = svc_find_xprt(serv, name, net, family, 0);
d3fe5ea7 198 if (xprt == NULL)
352ad314
CL
199 return svc_xprt_create(serv, name, net, family, port,
200 SVC_SOCK_DEFAULTS, cred);
d3fe5ea7
CL
201 svc_xprt_put(xprt);
202 return 0;
203}
204
c228fa20 205static int create_lockd_family(struct svc_serv *serv, struct net *net,
40373b12 206 const int family, const struct cred *cred)
eb16e907
CL
207{
208 int err;
209
40373b12
TM
210 err = create_lockd_listener(serv, "udp", net, family, nlm_udpport,
211 cred);
eb16e907
CL
212 if (err < 0)
213 return err;
214
40373b12
TM
215 return create_lockd_listener(serv, "tcp", net, family, nlm_tcpport,
216 cred);
eb16e907
CL
217}
218
482fb94e 219/*
8c3916f4
CL
220 * Ensure there are active UDP and TCP listeners for lockd.
221 *
222 * Even if we have only TCP NFS mounts and/or TCP NFSDs, some
223 * local services (such as rpc.statd) still require UDP, and
224 * some NFS servers do not yet support NLM over TCP.
225 *
226 * Returns zero if all listeners are available; otherwise a
227 * negative errno value is returned.
482fb94e 228 */
40373b12
TM
229static int make_socks(struct svc_serv *serv, struct net *net,
230 const struct cred *cred)
24e36663 231{
482fb94e 232 static int warned;
0dba7c2a 233 int err;
482fb94e 234
40373b12 235 err = create_lockd_family(serv, net, PF_INET, cred);
0dba7c2a
CL
236 if (err < 0)
237 goto out_err;
238
40373b12 239 err = create_lockd_family(serv, net, PF_INET6, cred);
eb16e907 240 if (err < 0 && err != -EAFNOSUPPORT)
0dba7c2a
CL
241 goto out_err;
242
243 warned = 0;
244 return 0;
245
246out_err:
247 if (warned++ == 0)
7dcf91ec 248 printk(KERN_WARNING
0dba7c2a 249 "lockd_up: makesock failed, error=%d\n", err);
c7d7ec8f 250 svc_xprt_destroy_all(serv, net);
87cdd864 251 svc_rpcb_cleanup(serv, net);
24e36663
N
252 return err;
253}
254
40373b12
TM
255static int lockd_up_net(struct svc_serv *serv, struct net *net,
256 const struct cred *cred)
bb2224df
SK
257{
258 struct lockd_net *ln = net_generic(net, lockd_net_id);
bb2224df
SK
259 int error;
260
786185b5 261 if (ln->nlmsvc_users++)
bb2224df
SK
262 return 0;
263
dbf9b5d7 264 error = svc_bind(serv, net);
bb2224df 265 if (error)
dbf9b5d7 266 goto err_bind;
bb2224df 267
40373b12 268 error = make_socks(serv, net, cred);
bb2224df 269 if (error < 0)
7c17705e 270 goto err_bind;
5630f7fa 271 set_grace_period(net);
e919b076 272 dprintk("%s: per-net data created; net=%x\n", __func__, net->ns.inum);
bb2224df
SK
273 return 0;
274
dbf9b5d7 275err_bind:
786185b5 276 ln->nlmsvc_users--;
bb2224df
SK
277 return error;
278}
279
4db77695 280static void lockd_down_net(struct svc_serv *serv, struct net *net)
bb2224df
SK
281{
282 struct lockd_net *ln = net_generic(net, lockd_net_id);
bb2224df
SK
283
284 if (ln->nlmsvc_users) {
3b64739f
SK
285 if (--ln->nlmsvc_users == 0) {
286 nlm_shutdown_hosts_net(net);
3a2b19d1
VA
287 cancel_delayed_work_sync(&ln->grace_period_end);
288 locks_end_grace(&ln->lockd_manager);
c7d7ec8f 289 svc_xprt_destroy_all(serv, net);
87cdd864 290 svc_rpcb_cleanup(serv, net);
3b64739f 291 }
bb2224df 292 } else {
6b044fba
N
293 pr_err("%s: no users! net=%x\n",
294 __func__, net->ns.inum);
bb2224df
SK
295 BUG();
296 }
297}
298
0751ddf7
SM
299static int lockd_inetaddr_event(struct notifier_block *this,
300 unsigned long event, void *ptr)
301{
302 struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
303 struct sockaddr_in sin;
304
5a8a7ff5 305 if (event != NETDEV_DOWN)
0751ddf7
SM
306 goto out;
307
2840fe86 308 if (nlmsvc_serv) {
0751ddf7
SM
309 dprintk("lockd_inetaddr_event: removed %pI4\n",
310 &ifa->ifa_local);
311 sin.sin_family = AF_INET;
312 sin.sin_addr.s_addr = ifa->ifa_local;
2840fe86 313 svc_age_temp_xprts_now(nlmsvc_serv, (struct sockaddr *)&sin);
0751ddf7
SM
314 }
315
316out:
317 return NOTIFY_DONE;
318}
319
320static struct notifier_block lockd_inetaddr_notifier = {
321 .notifier_call = lockd_inetaddr_event,
322};
323
324#if IS_ENABLED(CONFIG_IPV6)
325static int lockd_inet6addr_event(struct notifier_block *this,
326 unsigned long event, void *ptr)
327{
328 struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
329 struct sockaddr_in6 sin6;
330
5a8a7ff5 331 if (event != NETDEV_DOWN)
0751ddf7
SM
332 goto out;
333
2840fe86 334 if (nlmsvc_serv) {
0751ddf7
SM
335 dprintk("lockd_inet6addr_event: removed %pI6\n", &ifa->addr);
336 sin6.sin6_family = AF_INET6;
337 sin6.sin6_addr = ifa->addr;
c01410f7
SM
338 if (ipv6_addr_type(&sin6.sin6_addr) & IPV6_ADDR_LINKLOCAL)
339 sin6.sin6_scope_id = ifa->idev->dev->ifindex;
2840fe86 340 svc_age_temp_xprts_now(nlmsvc_serv, (struct sockaddr *)&sin6);
0751ddf7
SM
341 }
342
343out:
344 return NOTIFY_DONE;
345}
346
347static struct notifier_block lockd_inet6addr_notifier = {
348 .notifier_call = lockd_inet6addr_event,
349};
350#endif
351
ecd3ad68 352static int lockd_get(void)
1da177e4 353{
d751a7cd 354 struct svc_serv *serv;
b73a2972 355 int error;
1da177e4 356
2840fe86 357 if (nlmsvc_serv) {
ecd3ad68 358 nlmsvc_users++;
2840fe86
N
359 return 0;
360 }
1da177e4
LT
361
362 /*
363 * Sanity check: if there's no pid,
364 * we should be the first user ...
365 */
4a3ae42d 366 if (nlmsvc_users)
1da177e4
LT
367 printk(KERN_WARNING
368 "lockd_up: no pid, %d users??\n", nlmsvc_users);
369
06bed7d1
TM
370 if (!nlm_timeout)
371 nlm_timeout = LOCKD_DFLT_TIMEO;
372 nlmsvc_timeout = nlm_timeout * HZ;
373
37902c63 374 serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, lockd);
1da177e4
LT
375 if (!serv) {
376 printk(KERN_WARNING "lockd_up: create service failed\n");
2840fe86 377 return -ENOMEM;
24452239 378 }
b73a2972 379
6b044fba
N
380 serv->sv_maxconn = nlm_max_connections;
381 error = svc_set_num_threads(serv, NULL, 1);
b73a2972
N
382 /* The thread now holds the only reference */
383 svc_put(serv);
384 if (error < 0)
385 return error;
386
2840fe86 387 nlmsvc_serv = serv;
0751ddf7
SM
388 register_inetaddr_notifier(&lockd_inetaddr_notifier);
389#if IS_ENABLED(CONFIG_IPV6)
390 register_inet6addr_notifier(&lockd_inet6addr_notifier);
391#endif
8dbf28e4 392 dprintk("lockd_up: service created\n");
ecd3ad68 393 nlmsvc_users++;
2840fe86 394 return 0;
24452239
SK
395}
396
865b6740
N
397static void lockd_put(void)
398{
399 if (WARN(nlmsvc_users <= 0, "lockd_down: no users!\n"))
400 return;
401 if (--nlmsvc_users)
402 return;
403
404 unregister_inetaddr_notifier(&lockd_inetaddr_notifier);
405#if IS_ENABLED(CONFIG_IPV6)
406 unregister_inet6addr_notifier(&lockd_inet6addr_notifier);
407#endif
408
6b044fba 409 svc_set_num_threads(nlmsvc_serv, NULL, 0);
865b6740
N
410 nlmsvc_serv = NULL;
411 dprintk("lockd_down: service destroyed\n");
412}
413
24452239
SK
414/*
415 * Bring up the lockd process if it's not already up.
416 */
40373b12 417int lockd_up(struct net *net, const struct cred *cred)
24452239 418{
7d13ec76 419 int error;
24452239
SK
420
421 mutex_lock(&nlmsvc_mutex);
422
ecd3ad68 423 error = lockd_get();
2840fe86 424 if (error)
865b6740 425 goto err;
1da177e4 426
b73a2972 427 error = lockd_up_net(nlmsvc_serv, net, cred);
dc3033e1 428 if (error < 0) {
865b6740
N
429 lockd_put();
430 goto err;
dc3033e1 431 }
1da177e4 432
865b6740 433err:
353ab6e9 434 mutex_unlock(&nlmsvc_mutex);
1da177e4
LT
435 return error;
436}
2de59872 437EXPORT_SYMBOL_GPL(lockd_up);
1da177e4
LT
438
439/*
440 * Decrement the user count and bring down lockd if we're the last.
441 */
442void
e3f70ead 443lockd_down(struct net *net)
1da177e4 444{
353ab6e9 445 mutex_lock(&nlmsvc_mutex);
2840fe86 446 lockd_down_net(nlmsvc_serv, net);
865b6740 447 lockd_put();
353ab6e9 448 mutex_unlock(&nlmsvc_mutex);
1da177e4 449}
2de59872 450EXPORT_SYMBOL_GPL(lockd_down);
1da177e4 451
90d5b180
CL
452#ifdef CONFIG_SYSCTL
453
1da177e4
LT
454/*
455 * Sysctl parameters (same as module parameters, different interface).
456 */
457
7ac9fe57 458static struct ctl_table nlm_sysctls[] = {
1da177e4 459 {
1da177e4
LT
460 .procname = "nlm_grace_period",
461 .data = &nlm_grace_period,
7ee91ec1 462 .maxlen = sizeof(unsigned long),
1da177e4 463 .mode = 0644,
6d456111 464 .proc_handler = proc_doulongvec_minmax,
1da177e4
LT
465 .extra1 = (unsigned long *) &nlm_grace_period_min,
466 .extra2 = (unsigned long *) &nlm_grace_period_max,
467 },
468 {
1da177e4
LT
469 .procname = "nlm_timeout",
470 .data = &nlm_timeout,
7ee91ec1 471 .maxlen = sizeof(unsigned long),
1da177e4 472 .mode = 0644,
6d456111 473 .proc_handler = proc_doulongvec_minmax,
1da177e4
LT
474 .extra1 = (unsigned long *) &nlm_timeout_min,
475 .extra2 = (unsigned long *) &nlm_timeout_max,
476 },
477 {
1da177e4
LT
478 .procname = "nlm_udpport",
479 .data = &nlm_udpport,
480 .maxlen = sizeof(int),
481 .mode = 0644,
6d456111 482 .proc_handler = proc_dointvec_minmax,
1da177e4
LT
483 .extra1 = (int *) &nlm_port_min,
484 .extra2 = (int *) &nlm_port_max,
485 },
486 {
1da177e4
LT
487 .procname = "nlm_tcpport",
488 .data = &nlm_tcpport,
489 .maxlen = sizeof(int),
490 .mode = 0644,
6d456111 491 .proc_handler = proc_dointvec_minmax,
1da177e4
LT
492 .extra1 = (int *) &nlm_port_min,
493 .extra2 = (int *) &nlm_port_max,
494 },
abd1f500 495 {
abd1f500
OK
496 .procname = "nsm_use_hostnames",
497 .data = &nsm_use_hostnames,
f1aa2eb5 498 .maxlen = sizeof(bool),
abd1f500 499 .mode = 0644,
d02a3a2c 500 .proc_handler = proc_dobool,
abd1f500 501 },
460f5cac 502 {
460f5cac
OK
503 .procname = "nsm_local_state",
504 .data = &nsm_local_state,
505 .maxlen = sizeof(int),
506 .mode = 0644,
6d456111 507 .proc_handler = proc_dointvec,
460f5cac 508 },
ab09203e 509 { }
1da177e4
LT
510};
511
90d5b180
CL
512#endif /* CONFIG_SYSCTL */
513
1da177e4 514/*
405ae7d3 515 * Module (and sysfs) parameters.
1da177e4
LT
516 */
517
518#define param_set_min_max(name, type, which_strtol, min, max) \
e4dca7b7 519static int param_set_##name(const char *val, const struct kernel_param *kp) \
1da177e4
LT
520{ \
521 char *endp; \
522 __typeof__(type) num = which_strtol(val, &endp, 0); \
523 if (endp == val || *endp || num < (min) || num > (max)) \
524 return -EINVAL; \
de5b8e8e 525 *((type *) kp->arg) = num; \
1da177e4
LT
526 return 0; \
527}
528
529static inline int is_callback(u32 proc)
530{
531 return proc == NLMPROC_GRANTED
532 || proc == NLMPROC_GRANTED_MSG
533 || proc == NLMPROC_TEST_RES
534 || proc == NLMPROC_LOCK_RES
535 || proc == NLMPROC_CANCEL_RES
536 || proc == NLMPROC_UNLOCK_RES
537 || proc == NLMPROC_NSM_NOTIFY;
538}
539
540
541static int lockd_authenticate(struct svc_rqst *rqstp)
542{
543 rqstp->rq_client = NULL;
544 switch (rqstp->rq_authop->flavour) {
545 case RPC_AUTH_NULL:
546 case RPC_AUTH_UNIX:
5c2465df 547 rqstp->rq_auth_stat = rpc_auth_ok;
1da177e4
LT
548 if (rqstp->rq_proc == 0)
549 return SVC_OK;
550 if (is_callback(rqstp->rq_proc)) {
551 /* Leave it to individual procedures to
552 * call nlmsvc_lookup_host(rqstp)
553 */
554 return SVC_OK;
555 }
556 return svc_set_client(rqstp);
557 }
5c2465df 558 rqstp->rq_auth_stat = rpc_autherr_badcred;
1da177e4
LT
559 return SVC_DENIED;
560}
561
562
563param_set_min_max(port, int, simple_strtol, 0, 65535)
564param_set_min_max(grace_period, unsigned long, simple_strtoul,
565 nlm_grace_period_min, nlm_grace_period_max)
566param_set_min_max(timeout, unsigned long, simple_strtoul,
567 nlm_timeout_min, nlm_timeout_max)
568
569MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
570MODULE_DESCRIPTION("NFS file locking service version " LOCKD_VERSION ".");
571MODULE_LICENSE("GPL");
572
573module_param_call(nlm_grace_period, param_set_grace_period, param_get_ulong,
574 &nlm_grace_period, 0644);
575module_param_call(nlm_timeout, param_set_timeout, param_get_ulong,
576 &nlm_timeout, 0644);
577module_param_call(nlm_udpport, param_set_port, param_get_int,
578 &nlm_udpport, 0644);
579module_param_call(nlm_tcpport, param_set_port, param_get_int,
580 &nlm_tcpport, 0644);
abd1f500 581module_param(nsm_use_hostnames, bool, 0644);
c72a476b 582module_param(nlm_max_connections, uint, 0644);
1da177e4 583
a9c5d73a
SK
584static int lockd_init_net(struct net *net)
585{
66547b02
SK
586 struct lockd_net *ln = net_generic(net, lockd_net_id);
587
588 INIT_DELAYED_WORK(&ln->grace_period_end, grace_ender);
f7790029 589 INIT_LIST_HEAD(&ln->lockd_manager.list);
c87fb4a3 590 ln->lockd_manager.block_opens = false;
0ad95472 591 INIT_LIST_HEAD(&ln->nsm_handles);
a9c5d73a
SK
592 return 0;
593}
594
595static void lockd_exit_net(struct net *net)
596{
a3152f14
VA
597 struct lockd_net *ln = net_generic(net, lockd_net_id);
598
599 WARN_ONCE(!list_empty(&ln->lockd_manager.list),
600 "net %x %s: lockd_manager.list is not empty\n",
601 net->ns.inum, __func__);
602 WARN_ONCE(!list_empty(&ln->nsm_handles),
603 "net %x %s: nsm_handles list is not empty\n",
604 net->ns.inum, __func__);
605 WARN_ONCE(delayed_work_pending(&ln->grace_period_end),
606 "net %x %s: grace_period_end was not cancelled\n",
607 net->ns.inum, __func__);
a9c5d73a
SK
608}
609
610static struct pernet_operations lockd_net_ops = {
611 .init = lockd_init_net,
612 .exit = lockd_exit_net,
613 .id = &lockd_net_id,
614 .size = sizeof(struct lockd_net),
615};
616
617
1da177e4
LT
618/*
619 * Initialising and terminating the module.
620 */
621
622static int __init init_nlm(void)
623{
a9c5d73a
SK
624 int err;
625
90d5b180 626#ifdef CONFIG_SYSCTL
a9c5d73a 627 err = -ENOMEM;
37b768ce 628 nlm_sysctl_table = register_sysctl("fs/nfs", nlm_sysctls);
a9c5d73a
SK
629 if (nlm_sysctl_table == NULL)
630 goto err_sysctl;
631#endif
632 err = register_pernet_subsys(&lockd_net_ops);
633 if (err)
634 goto err_pernet;
d68e3c4a
JL
635
636 err = lockd_create_procfs();
637 if (err)
638 goto err_procfs;
639
90d5b180 640 return 0;
a9c5d73a 641
d68e3c4a
JL
642err_procfs:
643 unregister_pernet_subsys(&lockd_net_ops);
a9c5d73a
SK
644err_pernet:
645#ifdef CONFIG_SYSCTL
646 unregister_sysctl_table(nlm_sysctl_table);
a9c5d73a 647err_sysctl:
12dd7ecf 648#endif
a9c5d73a 649 return err;
1da177e4
LT
650}
651
652static void __exit exit_nlm(void)
653{
654 /* FIXME: delete all NLM clients */
655 nlm_shutdown_hosts();
d68e3c4a 656 lockd_remove_procfs();
a9c5d73a 657 unregister_pernet_subsys(&lockd_net_ops);
90d5b180 658#ifdef CONFIG_SYSCTL
1da177e4 659 unregister_sysctl_table(nlm_sysctl_table);
90d5b180 660#endif
1da177e4
LT
661}
662
663module_init(init_nlm);
664module_exit(exit_nlm);
665
a9ad1a80
CL
666/**
667 * nlmsvc_dispatch - Process an NLM Request
668 * @rqstp: incoming request
a9ad1a80
CL
669 *
670 * Return values:
671 * %0: Processing complete; do not send a Reply
672 * %1: Processing complete; send Reply in rqstp->rq_res
673 */
cee4db19 674static int nlmsvc_dispatch(struct svc_rqst *rqstp)
a9ad1a80
CL
675{
676 const struct svc_procedure *procp = rqstp->rq_procinfo;
cee4db19 677 __be32 *statp = rqstp->rq_accept_statp;
a9ad1a80 678
16c66364 679 if (!procp->pc_decode(rqstp, &rqstp->rq_arg_stream))
a9ad1a80
CL
680 goto out_decode_err;
681
682 *statp = procp->pc_func(rqstp);
683 if (*statp == rpc_drop_reply)
684 return 0;
685 if (*statp != rpc_success)
686 return 1;
687
fda49441 688 if (!procp->pc_encode(rqstp, &rqstp->rq_res_stream))
a9ad1a80
CL
689 goto out_encode_err;
690
691 return 1;
692
693out_decode_err:
694 *statp = rpc_garbage_args;
695 return 1;
696
697out_encode_err:
698 *statp = rpc_system_err;
699 return 1;
700}
701
1da177e4
LT
702/*
703 * Define NLM program and procedures
704 */
65ba3d24 705static DEFINE_PER_CPU_ALIGNED(unsigned long, nlmsvc_version1_count[17]);
e9679189
CH
706static const struct svc_version nlmsvc_version1 = {
707 .vs_vers = 1,
708 .vs_nproc = 17,
709 .vs_proc = nlmsvc_procedures,
710 .vs_count = nlmsvc_version1_count,
a9ad1a80 711 .vs_dispatch = nlmsvc_dispatch,
e9679189 712 .vs_xdrsize = NLMSVC_XDRSIZE,
1da177e4 713};
65ba3d24
CL
714
715static DEFINE_PER_CPU_ALIGNED(unsigned long,
716 nlmsvc_version3_count[ARRAY_SIZE(nlmsvc_procedures)]);
e9679189
CH
717static const struct svc_version nlmsvc_version3 = {
718 .vs_vers = 3,
65ba3d24 719 .vs_nproc = ARRAY_SIZE(nlmsvc_procedures),
e9679189
CH
720 .vs_proc = nlmsvc_procedures,
721 .vs_count = nlmsvc_version3_count,
a9ad1a80 722 .vs_dispatch = nlmsvc_dispatch,
e9679189 723 .vs_xdrsize = NLMSVC_XDRSIZE,
1da177e4 724};
65ba3d24 725
1da177e4 726#ifdef CONFIG_LOCKD_V4
65ba3d24
CL
727static DEFINE_PER_CPU_ALIGNED(unsigned long,
728 nlmsvc_version4_count[ARRAY_SIZE(nlmsvc_procedures4)]);
e9679189
CH
729static const struct svc_version nlmsvc_version4 = {
730 .vs_vers = 4,
65ba3d24 731 .vs_nproc = ARRAY_SIZE(nlmsvc_procedures4),
e9679189
CH
732 .vs_proc = nlmsvc_procedures4,
733 .vs_count = nlmsvc_version4_count,
a9ad1a80 734 .vs_dispatch = nlmsvc_dispatch,
e9679189 735 .vs_xdrsize = NLMSVC_XDRSIZE,
1da177e4
LT
736};
737#endif
65ba3d24 738
e9679189 739static const struct svc_version *nlmsvc_version[] = {
1da177e4
LT
740 [1] = &nlmsvc_version1,
741 [3] = &nlmsvc_version3,
742#ifdef CONFIG_LOCKD_V4
743 [4] = &nlmsvc_version4,
744#endif
745};
746
747static struct svc_stat nlmsvc_stats;
748
e8c96f8c 749#define NLM_NRVERS ARRAY_SIZE(nlmsvc_version)
1da177e4
LT
750static struct svc_program nlmsvc_program = {
751 .pg_prog = NLM_PROGRAM, /* program number */
752 .pg_nvers = NLM_NRVERS, /* number of entries in nlmsvc_version */
753 .pg_vers = nlmsvc_version, /* version table */
754 .pg_name = "lockd", /* service name */
755 .pg_class = "nfsd", /* share authentication with nfsd */
756 .pg_stats = &nlmsvc_stats, /* stats table */
8e5b6773
TM
757 .pg_authenticate = &lockd_authenticate, /* export authentication */
758 .pg_init_request = svc_generic_init_request,
642ee6b2 759 .pg_rpcbind_set = svc_generic_rpcbind_set,
1da177e4 760};