xref: /openbmc/linux/fs/lockd/svc.c (revision 606d099c)
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 
145 		if (signalled()) {
146 			flush_signals(current);
147 			if (nlmsvc_ops) {
148 				nlmsvc_invalidate_all();
149 				grace_period_expire = set_grace_period();
150 			}
151 		}
152 
153 		/*
154 		 * Retry any blocked locks that have been notified by
155 		 * the VFS. Don't do this during grace period.
156 		 * (Theoretically, there shouldn't even be blocked locks
157 		 * during grace period).
158 		 */
159 		if (!nlmsvc_grace_period) {
160 			timeout = nlmsvc_retry_blocked();
161 		} else if (time_before(grace_period_expire, jiffies))
162 			clear_grace_period();
163 
164 		/*
165 		 * Find a socket with data available and call its
166 		 * recvfrom routine.
167 		 */
168 		err = svc_recv(rqstp, timeout);
169 		if (err == -EAGAIN || err == -EINTR)
170 			continue;
171 		if (err < 0) {
172 			printk(KERN_WARNING
173 			       "lockd: terminating on error %d\n",
174 			       -err);
175 			break;
176 		}
177 
178 		dprintk("lockd: request from %08x\n",
179 			(unsigned)ntohl(rqstp->rq_addr.sin_addr.s_addr));
180 
181 		svc_process(rqstp);
182 
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 static int make_socks(struct svc_serv *serv, int proto)
227 {
228 	/* Make any sockets that are needed but not present.
229 	 * If nlm_udpport or nlm_tcpport were set as module
230 	 * options, make those sockets unconditionally
231 	 */
232 	static int		warned;
233 	int err = 0;
234 	if (proto == IPPROTO_UDP || nlm_udpport)
235 		if (!find_socket(serv, IPPROTO_UDP))
236 			err = svc_makesock(serv, IPPROTO_UDP, nlm_udpport);
237 	if (err == 0 && (proto == IPPROTO_TCP || nlm_tcpport))
238 		if (!find_socket(serv, IPPROTO_TCP))
239 			err= svc_makesock(serv, IPPROTO_TCP, nlm_tcpport);
240 	if (!err)
241 		warned = 0;
242 	else if (warned++ == 0)
243 		printk(KERN_WARNING
244 		       "lockd_up: makesock failed, error=%d\n", err);
245 	return err;
246 }
247 
248 /*
249  * Bring up the lockd process if it's not already up.
250  */
251 int
252 lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
253 {
254 	struct svc_serv *	serv;
255 	int			error = 0;
256 
257 	mutex_lock(&nlmsvc_mutex);
258 	/*
259 	 * Check whether we're already up and running.
260 	 */
261 	if (nlmsvc_pid) {
262 		if (proto)
263 			error = make_socks(nlmsvc_serv, proto);
264 		goto out;
265 	}
266 
267 	/*
268 	 * Sanity check: if there's no pid,
269 	 * we should be the first user ...
270 	 */
271 	if (nlmsvc_users)
272 		printk(KERN_WARNING
273 			"lockd_up: no pid, %d users??\n", nlmsvc_users);
274 
275 	error = -ENOMEM;
276 	serv = svc_create(&nlmsvc_program, LOCKD_BUFSIZE, NULL);
277 	if (!serv) {
278 		printk(KERN_WARNING "lockd_up: create service failed\n");
279 		goto out;
280 	}
281 
282 	if ((error = make_socks(serv, proto)) < 0)
283 		goto destroy_and_out;
284 
285 	/*
286 	 * Create the kernel thread and wait for it to start.
287 	 */
288 	error = svc_create_thread(lockd, serv);
289 	if (error) {
290 		printk(KERN_WARNING
291 			"lockd_up: create thread failed, error=%d\n", error);
292 		goto destroy_and_out;
293 	}
294 	wait_for_completion(&lockd_start_done);
295 
296 	/*
297 	 * Note: svc_serv structures have an initial use count of 1,
298 	 * so we exit through here on both success and failure.
299 	 */
300 destroy_and_out:
301 	svc_destroy(serv);
302 out:
303 	if (!error)
304 		nlmsvc_users++;
305 	mutex_unlock(&nlmsvc_mutex);
306 	return error;
307 }
308 EXPORT_SYMBOL(lockd_up);
309 
310 /*
311  * Decrement the user count and bring down lockd if we're the last.
312  */
313 void
314 lockd_down(void)
315 {
316 	static int warned;
317 
318 	mutex_lock(&nlmsvc_mutex);
319 	if (nlmsvc_users) {
320 		if (--nlmsvc_users)
321 			goto out;
322 	} else
323 		printk(KERN_WARNING "lockd_down: no users! pid=%d\n", nlmsvc_pid);
324 
325 	if (!nlmsvc_pid) {
326 		if (warned++ == 0)
327 			printk(KERN_WARNING "lockd_down: no lockd running.\n");
328 		goto out;
329 	}
330 	warned = 0;
331 
332 	kill_proc(nlmsvc_pid, SIGKILL, 1);
333 	/*
334 	 * Wait for the lockd process to exit, but since we're holding
335 	 * the lockd semaphore, we can't wait around forever ...
336 	 */
337 	clear_thread_flag(TIF_SIGPENDING);
338 	interruptible_sleep_on_timeout(&lockd_exit, HZ);
339 	if (nlmsvc_pid) {
340 		printk(KERN_WARNING
341 			"lockd_down: lockd failed to exit, clearing pid\n");
342 		nlmsvc_pid = 0;
343 	}
344 	spin_lock_irq(&current->sighand->siglock);
345 	recalc_sigpending();
346 	spin_unlock_irq(&current->sighand->siglock);
347 out:
348 	mutex_unlock(&nlmsvc_mutex);
349 }
350 EXPORT_SYMBOL(lockd_down);
351 
352 /*
353  * Sysctl parameters (same as module parameters, different interface).
354  */
355 
356 static ctl_table nlm_sysctls[] = {
357 	{
358 		.ctl_name	= CTL_UNNUMBERED,
359 		.procname	= "nlm_grace_period",
360 		.data		= &nlm_grace_period,
361 		.maxlen		= sizeof(unsigned long),
362 		.mode		= 0644,
363 		.proc_handler	= &proc_doulongvec_minmax,
364 		.extra1		= (unsigned long *) &nlm_grace_period_min,
365 		.extra2		= (unsigned long *) &nlm_grace_period_max,
366 	},
367 	{
368 		.ctl_name	= CTL_UNNUMBERED,
369 		.procname	= "nlm_timeout",
370 		.data		= &nlm_timeout,
371 		.maxlen		= sizeof(unsigned long),
372 		.mode		= 0644,
373 		.proc_handler	= &proc_doulongvec_minmax,
374 		.extra1		= (unsigned long *) &nlm_timeout_min,
375 		.extra2		= (unsigned long *) &nlm_timeout_max,
376 	},
377 	{
378 		.ctl_name	= CTL_UNNUMBERED,
379 		.procname	= "nlm_udpport",
380 		.data		= &nlm_udpport,
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 		.ctl_name	= CTL_UNNUMBERED,
389 		.procname	= "nlm_tcpport",
390 		.data		= &nlm_tcpport,
391 		.maxlen		= sizeof(int),
392 		.mode		= 0644,
393 		.proc_handler	= &proc_dointvec_minmax,
394 		.extra1		= (int *) &nlm_port_min,
395 		.extra2		= (int *) &nlm_port_max,
396 	},
397 	{
398 		.ctl_name	= CTL_UNNUMBERED,
399 		.procname	= "nsm_use_hostnames",
400 		.data		= &nsm_use_hostnames,
401 		.maxlen		= sizeof(int),
402 		.mode		= 0644,
403 		.proc_handler	= &proc_dointvec,
404 	},
405 	{
406 		.ctl_name	= CTL_UNNUMBERED,
407 		.procname	= "nsm_local_state",
408 		.data		= &nsm_local_state,
409 		.maxlen		= sizeof(int),
410 		.mode		= 0644,
411 		.proc_handler	= &proc_dointvec,
412 	},
413 	{ .ctl_name = 0 }
414 };
415 
416 static ctl_table nlm_sysctl_dir[] = {
417 	{
418 		.ctl_name	= CTL_UNNUMBERED,
419 		.procname	= "nfs",
420 		.mode		= 0555,
421 		.child		= nlm_sysctls,
422 	},
423 	{ .ctl_name = 0 }
424 };
425 
426 static ctl_table nlm_sysctl_root[] = {
427 	{
428 		.ctl_name	= CTL_FS,
429 		.procname	= "fs",
430 		.mode		= 0555,
431 		.child		= nlm_sysctl_dir,
432 	},
433 	{ .ctl_name = 0 }
434 };
435 
436 /*
437  * Module (and driverfs) parameters.
438  */
439 
440 #define param_set_min_max(name, type, which_strtol, min, max)		\
441 static int param_set_##name(const char *val, struct kernel_param *kp)	\
442 {									\
443 	char *endp;							\
444 	__typeof__(type) num = which_strtol(val, &endp, 0);		\
445 	if (endp == val || *endp || num < (min) || num > (max))		\
446 		return -EINVAL;						\
447 	*((int *) kp->arg) = num;					\
448 	return 0;							\
449 }
450 
451 static inline int is_callback(u32 proc)
452 {
453 	return proc == NLMPROC_GRANTED
454 		|| proc == NLMPROC_GRANTED_MSG
455 		|| proc == NLMPROC_TEST_RES
456 		|| proc == NLMPROC_LOCK_RES
457 		|| proc == NLMPROC_CANCEL_RES
458 		|| proc == NLMPROC_UNLOCK_RES
459 		|| proc == NLMPROC_NSM_NOTIFY;
460 }
461 
462 
463 static int lockd_authenticate(struct svc_rqst *rqstp)
464 {
465 	rqstp->rq_client = NULL;
466 	switch (rqstp->rq_authop->flavour) {
467 		case RPC_AUTH_NULL:
468 		case RPC_AUTH_UNIX:
469 			if (rqstp->rq_proc == 0)
470 				return SVC_OK;
471 			if (is_callback(rqstp->rq_proc)) {
472 				/* Leave it to individual procedures to
473 				 * call nlmsvc_lookup_host(rqstp)
474 				 */
475 				return SVC_OK;
476 			}
477 			return svc_set_client(rqstp);
478 	}
479 	return SVC_DENIED;
480 }
481 
482 
483 param_set_min_max(port, int, simple_strtol, 0, 65535)
484 param_set_min_max(grace_period, unsigned long, simple_strtoul,
485 		  nlm_grace_period_min, nlm_grace_period_max)
486 param_set_min_max(timeout, unsigned long, simple_strtoul,
487 		  nlm_timeout_min, nlm_timeout_max)
488 
489 MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
490 MODULE_DESCRIPTION("NFS file locking service version " LOCKD_VERSION ".");
491 MODULE_LICENSE("GPL");
492 
493 module_param_call(nlm_grace_period, param_set_grace_period, param_get_ulong,
494 		  &nlm_grace_period, 0644);
495 module_param_call(nlm_timeout, param_set_timeout, param_get_ulong,
496 		  &nlm_timeout, 0644);
497 module_param_call(nlm_udpport, param_set_port, param_get_int,
498 		  &nlm_udpport, 0644);
499 module_param_call(nlm_tcpport, param_set_port, param_get_int,
500 		  &nlm_tcpport, 0644);
501 module_param(nsm_use_hostnames, bool, 0644);
502 
503 /*
504  * Initialising and terminating the module.
505  */
506 
507 static int __init init_nlm(void)
508 {
509 	nlm_sysctl_table = register_sysctl_table(nlm_sysctl_root, 0);
510 	return nlm_sysctl_table ? 0 : -ENOMEM;
511 }
512 
513 static void __exit exit_nlm(void)
514 {
515 	/* FIXME: delete all NLM clients */
516 	nlm_shutdown_hosts();
517 	unregister_sysctl_table(nlm_sysctl_table);
518 }
519 
520 module_init(init_nlm);
521 module_exit(exit_nlm);
522 
523 /*
524  * Define NLM program and procedures
525  */
526 static struct svc_version	nlmsvc_version1 = {
527 		.vs_vers	= 1,
528 		.vs_nproc	= 17,
529 		.vs_proc	= nlmsvc_procedures,
530 		.vs_xdrsize	= NLMSVC_XDRSIZE,
531 };
532 static struct svc_version	nlmsvc_version3 = {
533 		.vs_vers	= 3,
534 		.vs_nproc	= 24,
535 		.vs_proc	= nlmsvc_procedures,
536 		.vs_xdrsize	= NLMSVC_XDRSIZE,
537 };
538 #ifdef CONFIG_LOCKD_V4
539 static struct svc_version	nlmsvc_version4 = {
540 		.vs_vers	= 4,
541 		.vs_nproc	= 24,
542 		.vs_proc	= nlmsvc_procedures4,
543 		.vs_xdrsize	= NLMSVC_XDRSIZE,
544 };
545 #endif
546 static struct svc_version *	nlmsvc_version[] = {
547 	[1] = &nlmsvc_version1,
548 	[3] = &nlmsvc_version3,
549 #ifdef CONFIG_LOCKD_V4
550 	[4] = &nlmsvc_version4,
551 #endif
552 };
553 
554 static struct svc_stat		nlmsvc_stats;
555 
556 #define NLM_NRVERS	ARRAY_SIZE(nlmsvc_version)
557 static struct svc_program	nlmsvc_program = {
558 	.pg_prog		= NLM_PROGRAM,		/* program number */
559 	.pg_nvers		= NLM_NRVERS,		/* number of entries in nlmsvc_version */
560 	.pg_vers		= nlmsvc_version,	/* version table */
561 	.pg_name		= "lockd",		/* service name */
562 	.pg_class		= "nfsd",		/* share authentication with nfsd */
563 	.pg_stats		= &nlmsvc_stats,	/* stats table */
564 	.pg_authenticate = &lockd_authenticate	/* export authentication */
565 };
566