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