xref: /openbmc/linux/fs/lockd/svc.c (revision e868d61272caa648214046a096e5a6bfc068dc8c)
1 /*
2  * linux/fs/lockd/svc.c
3  *
4  * This is the central lockd service.
5  *
6  * FIXME: Separate the lockd NFS server functionality from the lockd NFS
7  * 	  client functionality. Oh why didn't Sun create two separate
8  *	  services in the first place?
9  *
10  * Authors:	Olaf Kirch (okir@monad.swb.de)
11  *
12  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
13  */
14 
15 #include <linux/module.h>
16 #include <linux/init.h>
17 #include <linux/sysctl.h>
18 #include <linux/moduleparam.h>
19 
20 #include <linux/sched.h>
21 #include <linux/errno.h>
22 #include <linux/in.h>
23 #include <linux/uio.h>
24 #include <linux/slab.h>
25 #include <linux/smp.h>
26 #include <linux/smp_lock.h>
27 #include <linux/mutex.h>
28 
29 #include <linux/sunrpc/types.h>
30 #include <linux/sunrpc/stats.h>
31 #include <linux/sunrpc/clnt.h>
32 #include <linux/sunrpc/svc.h>
33 #include <linux/sunrpc/svcsock.h>
34 #include <net/ip.h>
35 #include <linux/lockd/lockd.h>
36 #include <linux/lockd/sm_inter.h>
37 #include <linux/nfs.h>
38 
39 #define NLMDBG_FACILITY		NLMDBG_SVC
40 #define LOCKD_BUFSIZE		(1024 + NLMSVC_XDRSIZE)
41 #define ALLOWED_SIGS		(sigmask(SIGKILL))
42 
43 static struct svc_program	nlmsvc_program;
44 
45 struct nlmsvc_binding *		nlmsvc_ops;
46 EXPORT_SYMBOL(nlmsvc_ops);
47 
48 static DEFINE_MUTEX(nlmsvc_mutex);
49 static unsigned int		nlmsvc_users;
50 static pid_t			nlmsvc_pid;
51 static struct svc_serv		*nlmsvc_serv;
52 int				nlmsvc_grace_period;
53 unsigned long			nlmsvc_timeout;
54 
55 static DECLARE_COMPLETION(lockd_start_done);
56 static DECLARE_WAIT_QUEUE_HEAD(lockd_exit);
57 
58 /*
59  * These can be set at insmod time (useful for NFS as root filesystem),
60  * and also changed through the sysctl interface.  -- Jamie Lokier, Aug 2003
61  */
62 static unsigned long		nlm_grace_period;
63 static unsigned long		nlm_timeout = LOCKD_DFLT_TIMEO;
64 static int			nlm_udpport, nlm_tcpport;
65 int				nsm_use_hostnames = 0;
66 
67 /*
68  * Constants needed for the sysctl interface.
69  */
70 static const unsigned long	nlm_grace_period_min = 0;
71 static const unsigned long	nlm_grace_period_max = 240;
72 static const unsigned long	nlm_timeout_min = 3;
73 static const unsigned long	nlm_timeout_max = 20;
74 static const int		nlm_port_min = 0, nlm_port_max = 65535;
75 
76 static struct ctl_table_header * nlm_sysctl_table;
77 
78 static unsigned long set_grace_period(void)
79 {
80 	unsigned long grace_period;
81 
82 	/* Note: nlm_timeout should always be nonzero */
83 	if (nlm_grace_period)
84 		grace_period = ((nlm_grace_period + nlm_timeout - 1)
85 				/ nlm_timeout) * nlm_timeout * HZ;
86 	else
87 		grace_period = nlm_timeout * 5 * HZ;
88 	nlmsvc_grace_period = 1;
89 	return grace_period + jiffies;
90 }
91 
92 static inline void clear_grace_period(void)
93 {
94 	nlmsvc_grace_period = 0;
95 }
96 
97 /*
98  * This is the lockd kernel thread
99  */
100 static void
101 lockd(struct svc_rqst *rqstp)
102 {
103 	int		err = 0;
104 	unsigned long grace_period_expire;
105 
106 	/* Lock module and set up kernel thread */
107 	/* lockd_up is waiting for us to startup, so will
108 	 * be holding a reference to this module, so it
109 	 * is safe to just claim another reference
110 	 */
111 	__module_get(THIS_MODULE);
112 	lock_kernel();
113 
114 	/*
115 	 * Let our maker know we're running.
116 	 */
117 	nlmsvc_pid = current->pid;
118 	nlmsvc_serv = rqstp->rq_server;
119 	complete(&lockd_start_done);
120 
121 	daemonize("lockd");
122 
123 	/* Process request with signals blocked, but allow SIGKILL.  */
124 	allow_signal(SIGKILL);
125 
126 	/* kick rpciod */
127 	rpciod_up();
128 
129 	dprintk("NFS locking service started (ver " LOCKD_VERSION ").\n");
130 
131 	if (!nlm_timeout)
132 		nlm_timeout = LOCKD_DFLT_TIMEO;
133 	nlmsvc_timeout = nlm_timeout * HZ;
134 
135 	grace_period_expire = set_grace_period();
136 
137 	/*
138 	 * The main request loop. We don't terminate until the last
139 	 * NFS mount or NFS daemon has gone away, and we've been sent a
140 	 * signal, or else another process has taken over our job.
141 	 */
142 	while ((nlmsvc_users || !signalled()) && nlmsvc_pid == current->pid) {
143 		long timeout = MAX_SCHEDULE_TIMEOUT;
144 		char buf[RPC_MAX_ADDRBUFLEN];
145 
146 		if (signalled()) {
147 			flush_signals(current);
148 			if (nlmsvc_ops) {
149 				nlmsvc_invalidate_all();
150 				grace_period_expire = set_grace_period();
151 			}
152 		}
153 
154 		/*
155 		 * Retry any blocked locks that have been notified by
156 		 * the VFS. Don't do this during grace period.
157 		 * (Theoretically, there shouldn't even be blocked locks
158 		 * during grace period).
159 		 */
160 		if (!nlmsvc_grace_period) {
161 			timeout = nlmsvc_retry_blocked();
162 		} else if (time_before(grace_period_expire, jiffies))
163 			clear_grace_period();
164 
165 		/*
166 		 * Find a socket with data available and call its
167 		 * recvfrom routine.
168 		 */
169 		err = svc_recv(rqstp, timeout);
170 		if (err == -EAGAIN || err == -EINTR)
171 			continue;
172 		if (err < 0) {
173 			printk(KERN_WARNING
174 			       "lockd: terminating on error %d\n",
175 			       -err);
176 			break;
177 		}
178 
179 		dprintk("lockd: request from %s\n",
180 				svc_print_addr(rqstp, buf, sizeof(buf)));
181 
182 		svc_process(rqstp);
183 	}
184 
185 	flush_signals(current);
186 
187 	/*
188 	 * Check whether there's a new lockd process before
189 	 * shutting down the hosts and clearing the slot.
190 	 */
191 	if (!nlmsvc_pid || current->pid == nlmsvc_pid) {
192 		if (nlmsvc_ops)
193 			nlmsvc_invalidate_all();
194 		nlm_shutdown_hosts();
195 		nlmsvc_pid = 0;
196 		nlmsvc_serv = NULL;
197 	} else
198 		printk(KERN_DEBUG
199 			"lockd: new process, skipping host shutdown\n");
200 	wake_up(&lockd_exit);
201 
202 	/* Exit the RPC thread */
203 	svc_exit_thread(rqstp);
204 
205 	/* release rpciod */
206 	rpciod_down();
207 
208 	/* Release module */
209 	unlock_kernel();
210 	module_put_and_exit(0);
211 }
212 
213 
214 static int find_socket(struct svc_serv *serv, int proto)
215 {
216 	struct svc_sock *svsk;
217 	int found = 0;
218 	list_for_each_entry(svsk, &serv->sv_permsocks, sk_list)
219 		if (svsk->sk_sk->sk_protocol == proto) {
220 			found = 1;
221 			break;
222 		}
223 	return found;
224 }
225 
226 /*
227  * Make any sockets that are needed but not present.
228  * If nlm_udpport or nlm_tcpport were set as module
229  * options, make those sockets unconditionally
230  */
231 static int make_socks(struct svc_serv *serv, int proto)
232 {
233 	static int warned;
234 	int err = 0;
235 
236 	if (proto == IPPROTO_UDP || nlm_udpport)
237 		if (!find_socket(serv, IPPROTO_UDP))
238 			err = svc_makesock(serv, IPPROTO_UDP, nlm_udpport,
239 						SVC_SOCK_DEFAULTS);
240 	if (err >= 0 && (proto == IPPROTO_TCP || nlm_tcpport))
241 		if (!find_socket(serv, IPPROTO_TCP))
242 			err = svc_makesock(serv, IPPROTO_TCP, nlm_tcpport,
243 						SVC_SOCK_DEFAULTS);
244 
245 	if (err >= 0) {
246 		warned = 0;
247 		err = 0;
248 	} else if (warned++ == 0)
249 		printk(KERN_WARNING
250 		       "lockd_up: makesock failed, error=%d\n", err);
251 	return err;
252 }
253 
254 /*
255  * Bring up the lockd process if it's not already up.
256  */
257 int
258 lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
259 {
260 	struct svc_serv *	serv;
261 	int			error = 0;
262 
263 	mutex_lock(&nlmsvc_mutex);
264 	/*
265 	 * Check whether we're already up and running.
266 	 */
267 	if (nlmsvc_pid) {
268 		if (proto)
269 			error = make_socks(nlmsvc_serv, proto);
270 		goto out;
271 	}
272 
273 	/*
274 	 * Sanity check: if there's no pid,
275 	 * we should be the first user ...
276 	 */
277 	if (nlmsvc_users)
278 		printk(KERN_WARNING
279 			"lockd_up: no pid, %d users??\n", nlmsvc_users);
280 
281 	error = -ENOMEM;
282 	serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, NULL);
283 	if (!serv) {
284 		printk(KERN_WARNING "lockd_up: create service failed\n");
285 		goto out;
286 	}
287 
288 	if ((error = make_socks(serv, proto)) < 0)
289 		goto destroy_and_out;
290 
291 	/*
292 	 * Create the kernel thread and wait for it to start.
293 	 */
294 	error = svc_create_thread(lockd, serv);
295 	if (error) {
296 		printk(KERN_WARNING
297 			"lockd_up: create thread failed, error=%d\n", error);
298 		goto destroy_and_out;
299 	}
300 	wait_for_completion(&lockd_start_done);
301 
302 	/*
303 	 * Note: svc_serv structures have an initial use count of 1,
304 	 * so we exit through here on both success and failure.
305 	 */
306 destroy_and_out:
307 	svc_destroy(serv);
308 out:
309 	if (!error)
310 		nlmsvc_users++;
311 	mutex_unlock(&nlmsvc_mutex);
312 	return error;
313 }
314 EXPORT_SYMBOL(lockd_up);
315 
316 /*
317  * Decrement the user count and bring down lockd if we're the last.
318  */
319 void
320 lockd_down(void)
321 {
322 	static int warned;
323 
324 	mutex_lock(&nlmsvc_mutex);
325 	if (nlmsvc_users) {
326 		if (--nlmsvc_users)
327 			goto out;
328 	} else
329 		printk(KERN_WARNING "lockd_down: no users! pid=%d\n", nlmsvc_pid);
330 
331 	if (!nlmsvc_pid) {
332 		if (warned++ == 0)
333 			printk(KERN_WARNING "lockd_down: no lockd running.\n");
334 		goto out;
335 	}
336 	warned = 0;
337 
338 	kill_proc(nlmsvc_pid, SIGKILL, 1);
339 	/*
340 	 * Wait for the lockd process to exit, but since we're holding
341 	 * the lockd semaphore, we can't wait around forever ...
342 	 */
343 	clear_thread_flag(TIF_SIGPENDING);
344 	interruptible_sleep_on_timeout(&lockd_exit, HZ);
345 	if (nlmsvc_pid) {
346 		printk(KERN_WARNING
347 			"lockd_down: lockd failed to exit, clearing pid\n");
348 		nlmsvc_pid = 0;
349 	}
350 	spin_lock_irq(&current->sighand->siglock);
351 	recalc_sigpending();
352 	spin_unlock_irq(&current->sighand->siglock);
353 out:
354 	mutex_unlock(&nlmsvc_mutex);
355 }
356 EXPORT_SYMBOL(lockd_down);
357 
358 /*
359  * Sysctl parameters (same as module parameters, different interface).
360  */
361 
362 static ctl_table nlm_sysctls[] = {
363 	{
364 		.ctl_name	= CTL_UNNUMBERED,
365 		.procname	= "nlm_grace_period",
366 		.data		= &nlm_grace_period,
367 		.maxlen		= sizeof(unsigned long),
368 		.mode		= 0644,
369 		.proc_handler	= &proc_doulongvec_minmax,
370 		.extra1		= (unsigned long *) &nlm_grace_period_min,
371 		.extra2		= (unsigned long *) &nlm_grace_period_max,
372 	},
373 	{
374 		.ctl_name	= CTL_UNNUMBERED,
375 		.procname	= "nlm_timeout",
376 		.data		= &nlm_timeout,
377 		.maxlen		= sizeof(unsigned long),
378 		.mode		= 0644,
379 		.proc_handler	= &proc_doulongvec_minmax,
380 		.extra1		= (unsigned long *) &nlm_timeout_min,
381 		.extra2		= (unsigned long *) &nlm_timeout_max,
382 	},
383 	{
384 		.ctl_name	= CTL_UNNUMBERED,
385 		.procname	= "nlm_udpport",
386 		.data		= &nlm_udpport,
387 		.maxlen		= sizeof(int),
388 		.mode		= 0644,
389 		.proc_handler	= &proc_dointvec_minmax,
390 		.extra1		= (int *) &nlm_port_min,
391 		.extra2		= (int *) &nlm_port_max,
392 	},
393 	{
394 		.ctl_name	= CTL_UNNUMBERED,
395 		.procname	= "nlm_tcpport",
396 		.data		= &nlm_tcpport,
397 		.maxlen		= sizeof(int),
398 		.mode		= 0644,
399 		.proc_handler	= &proc_dointvec_minmax,
400 		.extra1		= (int *) &nlm_port_min,
401 		.extra2		= (int *) &nlm_port_max,
402 	},
403 	{
404 		.ctl_name	= CTL_UNNUMBERED,
405 		.procname	= "nsm_use_hostnames",
406 		.data		= &nsm_use_hostnames,
407 		.maxlen		= sizeof(int),
408 		.mode		= 0644,
409 		.proc_handler	= &proc_dointvec,
410 	},
411 	{
412 		.ctl_name	= CTL_UNNUMBERED,
413 		.procname	= "nsm_local_state",
414 		.data		= &nsm_local_state,
415 		.maxlen		= sizeof(int),
416 		.mode		= 0644,
417 		.proc_handler	= &proc_dointvec,
418 	},
419 	{ .ctl_name = 0 }
420 };
421 
422 static ctl_table nlm_sysctl_dir[] = {
423 	{
424 		.ctl_name	= CTL_UNNUMBERED,
425 		.procname	= "nfs",
426 		.mode		= 0555,
427 		.child		= nlm_sysctls,
428 	},
429 	{ .ctl_name = 0 }
430 };
431 
432 static ctl_table nlm_sysctl_root[] = {
433 	{
434 		.ctl_name	= CTL_FS,
435 		.procname	= "fs",
436 		.mode		= 0555,
437 		.child		= nlm_sysctl_dir,
438 	},
439 	{ .ctl_name = 0 }
440 };
441 
442 /*
443  * Module (and sysfs) parameters.
444  */
445 
446 #define param_set_min_max(name, type, which_strtol, min, max)		\
447 static int param_set_##name(const char *val, struct kernel_param *kp)	\
448 {									\
449 	char *endp;							\
450 	__typeof__(type) num = which_strtol(val, &endp, 0);		\
451 	if (endp == val || *endp || num < (min) || num > (max))		\
452 		return -EINVAL;						\
453 	*((int *) kp->arg) = num;					\
454 	return 0;							\
455 }
456 
457 static inline int is_callback(u32 proc)
458 {
459 	return proc == NLMPROC_GRANTED
460 		|| proc == NLMPROC_GRANTED_MSG
461 		|| proc == NLMPROC_TEST_RES
462 		|| proc == NLMPROC_LOCK_RES
463 		|| proc == NLMPROC_CANCEL_RES
464 		|| proc == NLMPROC_UNLOCK_RES
465 		|| proc == NLMPROC_NSM_NOTIFY;
466 }
467 
468 
469 static int lockd_authenticate(struct svc_rqst *rqstp)
470 {
471 	rqstp->rq_client = NULL;
472 	switch (rqstp->rq_authop->flavour) {
473 		case RPC_AUTH_NULL:
474 		case RPC_AUTH_UNIX:
475 			if (rqstp->rq_proc == 0)
476 				return SVC_OK;
477 			if (is_callback(rqstp->rq_proc)) {
478 				/* Leave it to individual procedures to
479 				 * call nlmsvc_lookup_host(rqstp)
480 				 */
481 				return SVC_OK;
482 			}
483 			return svc_set_client(rqstp);
484 	}
485 	return SVC_DENIED;
486 }
487 
488 
489 param_set_min_max(port, int, simple_strtol, 0, 65535)
490 param_set_min_max(grace_period, unsigned long, simple_strtoul,
491 		  nlm_grace_period_min, nlm_grace_period_max)
492 param_set_min_max(timeout, unsigned long, simple_strtoul,
493 		  nlm_timeout_min, nlm_timeout_max)
494 
495 MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
496 MODULE_DESCRIPTION("NFS file locking service version " LOCKD_VERSION ".");
497 MODULE_LICENSE("GPL");
498 
499 module_param_call(nlm_grace_period, param_set_grace_period, param_get_ulong,
500 		  &nlm_grace_period, 0644);
501 module_param_call(nlm_timeout, param_set_timeout, param_get_ulong,
502 		  &nlm_timeout, 0644);
503 module_param_call(nlm_udpport, param_set_port, param_get_int,
504 		  &nlm_udpport, 0644);
505 module_param_call(nlm_tcpport, param_set_port, param_get_int,
506 		  &nlm_tcpport, 0644);
507 module_param(nsm_use_hostnames, bool, 0644);
508 
509 /*
510  * Initialising and terminating the module.
511  */
512 
513 static int __init init_nlm(void)
514 {
515 	nlm_sysctl_table = register_sysctl_table(nlm_sysctl_root);
516 	return nlm_sysctl_table ? 0 : -ENOMEM;
517 }
518 
519 static void __exit exit_nlm(void)
520 {
521 	/* FIXME: delete all NLM clients */
522 	nlm_shutdown_hosts();
523 	unregister_sysctl_table(nlm_sysctl_table);
524 }
525 
526 module_init(init_nlm);
527 module_exit(exit_nlm);
528 
529 /*
530  * Define NLM program and procedures
531  */
532 static struct svc_version	nlmsvc_version1 = {
533 		.vs_vers	= 1,
534 		.vs_nproc	= 17,
535 		.vs_proc	= nlmsvc_procedures,
536 		.vs_xdrsize	= NLMSVC_XDRSIZE,
537 };
538 static struct svc_version	nlmsvc_version3 = {
539 		.vs_vers	= 3,
540 		.vs_nproc	= 24,
541 		.vs_proc	= nlmsvc_procedures,
542 		.vs_xdrsize	= NLMSVC_XDRSIZE,
543 };
544 #ifdef CONFIG_LOCKD_V4
545 static struct svc_version	nlmsvc_version4 = {
546 		.vs_vers	= 4,
547 		.vs_nproc	= 24,
548 		.vs_proc	= nlmsvc_procedures4,
549 		.vs_xdrsize	= NLMSVC_XDRSIZE,
550 };
551 #endif
552 static struct svc_version *	nlmsvc_version[] = {
553 	[1] = &nlmsvc_version1,
554 	[3] = &nlmsvc_version3,
555 #ifdef CONFIG_LOCKD_V4
556 	[4] = &nlmsvc_version4,
557 #endif
558 };
559 
560 static struct svc_stat		nlmsvc_stats;
561 
562 #define NLM_NRVERS	ARRAY_SIZE(nlmsvc_version)
563 static struct svc_program	nlmsvc_program = {
564 	.pg_prog		= NLM_PROGRAM,		/* program number */
565 	.pg_nvers		= NLM_NRVERS,		/* number of entries in nlmsvc_version */
566 	.pg_vers		= nlmsvc_version,	/* version table */
567 	.pg_name		= "lockd",		/* service name */
568 	.pg_class		= "nfsd",		/* share authentication with nfsd */
569 	.pg_stats		= &nlmsvc_stats,	/* stats table */
570 	.pg_authenticate = &lockd_authenticate	/* export authentication */
571 };
572