1 /*- 2 * Copyright (c) 2014 The FreeBSD Foundation 3 * 4 * This software was developed by Edward Tomasz Napierala under sponsorship 5 * from the FreeBSD Foundation. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 */ 29 /*- 30 * Copyright (c) 1989, 1991, 1993, 1995 31 * The Regents of the University of California. All rights reserved. 32 * 33 * This code is derived from software contributed to Berkeley by 34 * Rick Macklem at The University of Guelph. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. Neither the name of the University nor the names of its contributors 45 * may be used to endorse or promote products derived from this software 46 * without specific prior written permission. 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 * 60 */ 61 62 #include <sys/param.h> 63 #include <sys/systm.h> 64 #include <sys/buf.h> 65 #include <sys/conf.h> 66 #include <sys/dirent.h> 67 #include <sys/ioccom.h> 68 #include <sys/kernel.h> 69 #include <sys/module.h> 70 #include <sys/mount.h> 71 #include <sys/refcount.h> 72 #include <sys/sx.h> 73 #include <sys/sysctl.h> 74 #include <sys/syscallsubr.h> 75 #include <sys/taskqueue.h> 76 #include <sys/tree.h> 77 #include <sys/vnode.h> 78 #include <machine/atomic.h> 79 #include <vm/uma.h> 80 81 #include <fs/autofs/autofs.h> 82 #include <fs/autofs/autofs_ioctl.h> 83 84 MALLOC_DEFINE(M_AUTOFS, "autofs", "Automounter filesystem"); 85 86 uma_zone_t autofs_request_zone; 87 uma_zone_t autofs_node_zone; 88 89 static int autofs_open(struct cdev *dev, int flags, int fmt, 90 struct thread *td); 91 static int autofs_close(struct cdev *dev, int flag, int fmt, 92 struct thread *td); 93 static int autofs_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, 94 int mode, struct thread *td); 95 96 static struct cdevsw autofs_cdevsw = { 97 .d_version = D_VERSION, 98 .d_open = autofs_open, 99 .d_close = autofs_close, 100 .d_ioctl = autofs_ioctl, 101 .d_name = "autofs", 102 }; 103 104 /* 105 * List of signals that can interrupt an autofs trigger. Might be a good 106 * idea to keep it synchronised with list in sys/fs/nfs/nfs_commonkrpc.c. 107 */ 108 int autofs_sig_set[] = { 109 SIGINT, 110 SIGTERM, 111 SIGHUP, 112 SIGKILL, 113 SIGQUIT 114 }; 115 116 struct autofs_softc *autofs_softc; 117 118 SYSCTL_NODE(_vfs, OID_AUTO, autofs, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 119 "Automounter filesystem"); 120 int autofs_debug = 1; 121 TUNABLE_INT("vfs.autofs.debug", &autofs_debug); 122 SYSCTL_INT(_vfs_autofs, OID_AUTO, debug, CTLFLAG_RWTUN, 123 &autofs_debug, 1, "Enable debug messages"); 124 int autofs_mount_on_stat = 0; 125 TUNABLE_INT("vfs.autofs.mount_on_stat", &autofs_mount_on_stat); 126 SYSCTL_INT(_vfs_autofs, OID_AUTO, mount_on_stat, CTLFLAG_RWTUN, 127 &autofs_mount_on_stat, 0, "Trigger mount on stat(2) on mountpoint"); 128 int autofs_timeout = 30; 129 TUNABLE_INT("vfs.autofs.timeout", &autofs_timeout); 130 SYSCTL_INT(_vfs_autofs, OID_AUTO, timeout, CTLFLAG_RWTUN, 131 &autofs_timeout, 30, "Number of seconds to wait for automountd(8)"); 132 int autofs_cache = 600; 133 TUNABLE_INT("vfs.autofs.cache", &autofs_cache); 134 SYSCTL_INT(_vfs_autofs, OID_AUTO, cache, CTLFLAG_RWTUN, 135 &autofs_cache, 600, "Number of seconds to wait before reinvoking " 136 "automountd(8) for any given file or directory"); 137 int autofs_retry_attempts = 3; 138 TUNABLE_INT("vfs.autofs.retry_attempts", &autofs_retry_attempts); 139 SYSCTL_INT(_vfs_autofs, OID_AUTO, retry_attempts, CTLFLAG_RWTUN, 140 &autofs_retry_attempts, 3, "Number of attempts before failing mount"); 141 int autofs_retry_delay = 1; 142 TUNABLE_INT("vfs.autofs.retry_delay", &autofs_retry_delay); 143 SYSCTL_INT(_vfs_autofs, OID_AUTO, retry_delay, CTLFLAG_RWTUN, 144 &autofs_retry_delay, 1, "Number of seconds before retrying"); 145 int autofs_interruptible = 1; 146 TUNABLE_INT("vfs.autofs.interruptible", &autofs_interruptible); 147 SYSCTL_INT(_vfs_autofs, OID_AUTO, interruptible, CTLFLAG_RWTUN, 148 &autofs_interruptible, 1, "Allow requests to be interrupted by signal"); 149 150 static int 151 autofs_node_cmp(const struct autofs_node *a, const struct autofs_node *b) 152 { 153 154 return (strcmp(a->an_name, b->an_name)); 155 } 156 157 RB_GENERATE(autofs_node_tree, autofs_node, an_link, autofs_node_cmp); 158 159 int 160 autofs_init(struct vfsconf *vfsp) 161 { 162 int error; 163 164 KASSERT(autofs_softc == NULL, 165 ("softc %p, should be NULL", autofs_softc)); 166 167 autofs_softc = malloc(sizeof(*autofs_softc), M_AUTOFS, 168 M_WAITOK | M_ZERO); 169 170 autofs_request_zone = uma_zcreate("autofs_request", 171 sizeof(struct autofs_request), NULL, NULL, NULL, NULL, 172 UMA_ALIGN_PTR, 0); 173 autofs_node_zone = uma_zcreate("autofs_node", 174 sizeof(struct autofs_node), NULL, NULL, NULL, NULL, 175 UMA_ALIGN_PTR, 0); 176 177 TAILQ_INIT(&autofs_softc->sc_requests); 178 cv_init(&autofs_softc->sc_cv, "autofscv"); 179 sx_init(&autofs_softc->sc_lock, "autofslk"); 180 181 error = make_dev_p(MAKEDEV_CHECKNAME, &autofs_softc->sc_cdev, 182 &autofs_cdevsw, NULL, UID_ROOT, GID_WHEEL, 0600, "autofs"); 183 if (error != 0) { 184 AUTOFS_WARN("failed to create device node, error %d", error); 185 uma_zdestroy(autofs_request_zone); 186 uma_zdestroy(autofs_node_zone); 187 free(autofs_softc, M_AUTOFS); 188 189 return (error); 190 } 191 autofs_softc->sc_cdev->si_drv1 = autofs_softc; 192 193 return (0); 194 } 195 196 int 197 autofs_uninit(struct vfsconf *vfsp) 198 { 199 200 sx_xlock(&autofs_softc->sc_lock); 201 if (autofs_softc->sc_dev_opened) { 202 sx_xunlock(&autofs_softc->sc_lock); 203 return (EBUSY); 204 } 205 if (autofs_softc->sc_cdev != NULL) 206 destroy_dev(autofs_softc->sc_cdev); 207 208 uma_zdestroy(autofs_request_zone); 209 uma_zdestroy(autofs_node_zone); 210 211 sx_xunlock(&autofs_softc->sc_lock); 212 /* 213 * XXX: Race with open? 214 */ 215 free(autofs_softc, M_AUTOFS); 216 217 return (0); 218 } 219 220 bool 221 autofs_ignore_thread(const struct thread *td) 222 { 223 struct proc *p; 224 225 p = td->td_proc; 226 227 if (autofs_softc->sc_dev_opened == false) 228 return (false); 229 230 PROC_LOCK(p); 231 if (p->p_session->s_sid == autofs_softc->sc_dev_sid) { 232 PROC_UNLOCK(p); 233 return (true); 234 } 235 PROC_UNLOCK(p); 236 237 return (false); 238 } 239 240 static char * 241 autofs_path(struct autofs_node *anp) 242 { 243 struct autofs_mount *amp; 244 char *path, *tmp; 245 246 amp = anp->an_mount; 247 248 path = strdup("", M_AUTOFS); 249 for (; anp->an_parent != NULL; anp = anp->an_parent) { 250 tmp = malloc(strlen(anp->an_name) + strlen(path) + 2, 251 M_AUTOFS, M_WAITOK); 252 strcpy(tmp, anp->an_name); 253 strcat(tmp, "/"); 254 strcat(tmp, path); 255 free(path, M_AUTOFS); 256 path = tmp; 257 } 258 259 tmp = malloc(strlen(amp->am_mountpoint) + strlen(path) + 2, 260 M_AUTOFS, M_WAITOK); 261 strcpy(tmp, amp->am_mountpoint); 262 strcat(tmp, "/"); 263 strcat(tmp, path); 264 free(path, M_AUTOFS); 265 path = tmp; 266 267 return (path); 268 } 269 270 static void 271 autofs_task(void *context, int pending) 272 { 273 struct autofs_request *ar; 274 275 ar = context; 276 277 sx_xlock(&autofs_softc->sc_lock); 278 AUTOFS_WARN("request %d for %s timed out after %d seconds", 279 ar->ar_id, ar->ar_path, autofs_timeout); 280 /* 281 * XXX: EIO perhaps? 282 */ 283 ar->ar_error = ETIMEDOUT; 284 ar->ar_wildcards = true; 285 ar->ar_done = true; 286 ar->ar_in_progress = false; 287 cv_broadcast(&autofs_softc->sc_cv); 288 sx_xunlock(&autofs_softc->sc_lock); 289 } 290 291 bool 292 autofs_cached(struct autofs_node *anp, const char *component, int componentlen) 293 { 294 int error; 295 struct autofs_mount *amp; 296 297 amp = anp->an_mount; 298 299 AUTOFS_ASSERT_UNLOCKED(amp); 300 301 /* 302 * For root node we need to request automountd(8) assistance even 303 * if the node is marked as cached, but the requested top-level 304 * directory does not exist. This is necessary for wildcard indirect 305 * map keys to work. We don't do this if we know that there are 306 * no wildcards. 307 */ 308 if (anp->an_parent == NULL && componentlen != 0 && anp->an_wildcards) { 309 AUTOFS_SLOCK(amp); 310 error = autofs_node_find(anp, component, componentlen, NULL); 311 AUTOFS_SUNLOCK(amp); 312 if (error != 0) 313 return (false); 314 } 315 316 return (anp->an_cached); 317 } 318 319 static void 320 autofs_cache_callout(void *context) 321 { 322 struct autofs_node *anp; 323 324 anp = context; 325 anp->an_cached = false; 326 } 327 328 void 329 autofs_flush(struct autofs_mount *amp) 330 { 331 332 /* 333 * XXX: This will do for now, but ideally we should iterate 334 * over all the nodes. 335 */ 336 amp->am_root->an_cached = false; 337 AUTOFS_DEBUG("%s flushed", amp->am_mountpoint); 338 } 339 340 /* 341 * The set/restore sigmask functions are used to (temporarily) overwrite 342 * the thread td_sigmask during triggering. 343 */ 344 static void 345 autofs_set_sigmask(sigset_t *oldset) 346 { 347 sigset_t newset; 348 int i; 349 350 SIGFILLSET(newset); 351 /* Remove the autofs set of signals from newset */ 352 PROC_LOCK(curproc); 353 mtx_lock(&curproc->p_sigacts->ps_mtx); 354 for (i = 0 ; i < nitems(autofs_sig_set); i++) { 355 /* 356 * But make sure we leave the ones already masked 357 * by the process, i.e. remove the signal from the 358 * temporary signalmask only if it wasn't already 359 * in p_sigmask. 360 */ 361 if (!SIGISMEMBER(curthread->td_sigmask, autofs_sig_set[i]) && 362 !SIGISMEMBER(curproc->p_sigacts->ps_sigignore, 363 autofs_sig_set[i])) { 364 SIGDELSET(newset, autofs_sig_set[i]); 365 } 366 } 367 mtx_unlock(&curproc->p_sigacts->ps_mtx); 368 kern_sigprocmask(curthread, SIG_SETMASK, &newset, oldset, 369 SIGPROCMASK_PROC_LOCKED); 370 PROC_UNLOCK(curproc); 371 } 372 373 static void 374 autofs_restore_sigmask(sigset_t *set) 375 { 376 377 kern_sigprocmask(curthread, SIG_SETMASK, set, NULL, 0); 378 } 379 380 static int 381 autofs_trigger_one(struct autofs_node *anp, 382 const char *component, int componentlen) 383 { 384 sigset_t oldset; 385 struct autofs_mount *amp; 386 struct autofs_node *firstanp; 387 struct autofs_request *ar; 388 char *key, *path; 389 int error = 0, request_error, last; 390 bool wildcards; 391 392 amp = anp->an_mount; 393 394 sx_assert(&autofs_softc->sc_lock, SA_XLOCKED); 395 396 if (anp->an_parent == NULL) { 397 key = strndup(component, componentlen, M_AUTOFS); 398 } else { 399 for (firstanp = anp; firstanp->an_parent->an_parent != NULL; 400 firstanp = firstanp->an_parent) 401 continue; 402 key = strdup(firstanp->an_name, M_AUTOFS); 403 } 404 405 path = autofs_path(anp); 406 407 TAILQ_FOREACH(ar, &autofs_softc->sc_requests, ar_next) { 408 if (strcmp(ar->ar_path, path) != 0) 409 continue; 410 if (strcmp(ar->ar_key, key) != 0) 411 continue; 412 413 KASSERT(strcmp(ar->ar_from, amp->am_from) == 0, 414 ("from changed; %s != %s", ar->ar_from, amp->am_from)); 415 KASSERT(strcmp(ar->ar_prefix, amp->am_prefix) == 0, 416 ("prefix changed; %s != %s", 417 ar->ar_prefix, amp->am_prefix)); 418 KASSERT(strcmp(ar->ar_options, amp->am_options) == 0, 419 ("options changed; %s != %s", 420 ar->ar_options, amp->am_options)); 421 422 break; 423 } 424 425 if (ar != NULL) { 426 refcount_acquire(&ar->ar_refcount); 427 } else { 428 ar = uma_zalloc(autofs_request_zone, M_WAITOK | M_ZERO); 429 ar->ar_mount = amp; 430 431 ar->ar_id = 432 atomic_fetchadd_int(&autofs_softc->sc_last_request_id, 1); 433 strlcpy(ar->ar_from, amp->am_from, sizeof(ar->ar_from)); 434 strlcpy(ar->ar_path, path, sizeof(ar->ar_path)); 435 strlcpy(ar->ar_prefix, amp->am_prefix, sizeof(ar->ar_prefix)); 436 strlcpy(ar->ar_key, key, sizeof(ar->ar_key)); 437 strlcpy(ar->ar_options, 438 amp->am_options, sizeof(ar->ar_options)); 439 440 TIMEOUT_TASK_INIT(taskqueue_thread, &ar->ar_task, 0, 441 autofs_task, ar); 442 taskqueue_enqueue_timeout(taskqueue_thread, &ar->ar_task, 443 autofs_timeout * hz); 444 refcount_init(&ar->ar_refcount, 1); 445 TAILQ_INSERT_TAIL(&autofs_softc->sc_requests, ar, ar_next); 446 } 447 448 cv_broadcast(&autofs_softc->sc_cv); 449 while (ar->ar_done == false) { 450 if (autofs_interruptible != 0) { 451 autofs_set_sigmask(&oldset); 452 error = cv_wait_sig(&autofs_softc->sc_cv, 453 &autofs_softc->sc_lock); 454 autofs_restore_sigmask(&oldset); 455 if (error != 0) { 456 AUTOFS_WARN("cv_wait_sig for %s failed " 457 "with error %d", ar->ar_path, error); 458 break; 459 } 460 } else { 461 cv_wait(&autofs_softc->sc_cv, &autofs_softc->sc_lock); 462 } 463 } 464 465 request_error = ar->ar_error; 466 if (request_error != 0) { 467 AUTOFS_WARN("request for %s completed with error %d, " 468 "pid %d (%s)", ar->ar_path, request_error, 469 curproc->p_pid, curproc->p_comm); 470 } 471 472 wildcards = ar->ar_wildcards; 473 474 last = refcount_release(&ar->ar_refcount); 475 if (last) { 476 TAILQ_REMOVE(&autofs_softc->sc_requests, ar, ar_next); 477 /* 478 * Unlock the sc_lock, so that autofs_task() can complete. 479 */ 480 sx_xunlock(&autofs_softc->sc_lock); 481 taskqueue_cancel_timeout(taskqueue_thread, &ar->ar_task, NULL); 482 taskqueue_drain_timeout(taskqueue_thread, &ar->ar_task); 483 uma_zfree(autofs_request_zone, ar); 484 sx_xlock(&autofs_softc->sc_lock); 485 } 486 487 /* 488 * Note that we do not do negative caching on purpose. This 489 * way the user can retry access at any time, e.g. after fixing 490 * the failure reason, without waiting for cache timer to expire. 491 */ 492 if (error == 0 && request_error == 0 && autofs_cache > 0) { 493 anp->an_cached = true; 494 anp->an_wildcards = wildcards; 495 callout_reset(&anp->an_callout, autofs_cache * hz, 496 autofs_cache_callout, anp); 497 } 498 499 free(key, M_AUTOFS); 500 free(path, M_AUTOFS); 501 502 if (error != 0) 503 return (error); 504 return (request_error); 505 } 506 507 /* 508 * Send request to automountd(8) and wait for completion. 509 */ 510 int 511 autofs_trigger(struct autofs_node *anp, 512 const char *component, int componentlen) 513 { 514 int error; 515 516 for (;;) { 517 error = autofs_trigger_one(anp, component, componentlen); 518 if (error == 0) { 519 anp->an_retries = 0; 520 return (0); 521 } 522 if (error == EINTR || error == ERESTART) { 523 AUTOFS_DEBUG("trigger interrupted by signal, " 524 "not retrying"); 525 anp->an_retries = 0; 526 return (error); 527 } 528 anp->an_retries++; 529 if (anp->an_retries >= autofs_retry_attempts) { 530 AUTOFS_DEBUG("trigger failed %d times; returning " 531 "error %d", anp->an_retries, error); 532 anp->an_retries = 0; 533 return (error); 534 } 535 AUTOFS_DEBUG("trigger failed with error %d; will retry in " 536 "%d seconds, %d attempts left", error, autofs_retry_delay, 537 autofs_retry_attempts - anp->an_retries); 538 sx_xunlock(&autofs_softc->sc_lock); 539 pause("autofs_retry", autofs_retry_delay * hz); 540 sx_xlock(&autofs_softc->sc_lock); 541 } 542 } 543 544 static int 545 autofs_ioctl_request(struct autofs_daemon_request *adr) 546 { 547 struct autofs_request *ar; 548 int error; 549 550 sx_xlock(&autofs_softc->sc_lock); 551 for (;;) { 552 TAILQ_FOREACH(ar, &autofs_softc->sc_requests, ar_next) { 553 if (ar->ar_done) 554 continue; 555 if (ar->ar_in_progress) 556 continue; 557 558 break; 559 } 560 561 if (ar != NULL) 562 break; 563 564 error = cv_wait_sig(&autofs_softc->sc_cv, 565 &autofs_softc->sc_lock); 566 if (error != 0) { 567 sx_xunlock(&autofs_softc->sc_lock); 568 return (error); 569 } 570 } 571 572 ar->ar_in_progress = true; 573 sx_xunlock(&autofs_softc->sc_lock); 574 575 adr->adr_id = ar->ar_id; 576 strlcpy(adr->adr_from, ar->ar_from, sizeof(adr->adr_from)); 577 strlcpy(adr->adr_path, ar->ar_path, sizeof(adr->adr_path)); 578 strlcpy(adr->adr_prefix, ar->ar_prefix, sizeof(adr->adr_prefix)); 579 strlcpy(adr->adr_key, ar->ar_key, sizeof(adr->adr_key)); 580 strlcpy(adr->adr_options, ar->ar_options, sizeof(adr->adr_options)); 581 582 PROC_LOCK(curproc); 583 autofs_softc->sc_dev_sid = curproc->p_session->s_sid; 584 PROC_UNLOCK(curproc); 585 586 return (0); 587 } 588 589 static int 590 autofs_ioctl_done_101(struct autofs_daemon_done_101 *add) 591 { 592 struct autofs_request *ar; 593 594 sx_xlock(&autofs_softc->sc_lock); 595 TAILQ_FOREACH(ar, &autofs_softc->sc_requests, ar_next) { 596 if (ar->ar_id == add->add_id) 597 break; 598 } 599 600 if (ar == NULL) { 601 sx_xunlock(&autofs_softc->sc_lock); 602 AUTOFS_DEBUG("id %d not found", add->add_id); 603 return (ESRCH); 604 } 605 606 ar->ar_error = add->add_error; 607 ar->ar_wildcards = true; 608 ar->ar_done = true; 609 ar->ar_in_progress = false; 610 cv_broadcast(&autofs_softc->sc_cv); 611 612 sx_xunlock(&autofs_softc->sc_lock); 613 614 return (0); 615 } 616 617 static int 618 autofs_ioctl_done(struct autofs_daemon_done *add) 619 { 620 struct autofs_request *ar; 621 622 sx_xlock(&autofs_softc->sc_lock); 623 TAILQ_FOREACH(ar, &autofs_softc->sc_requests, ar_next) { 624 if (ar->ar_id == add->add_id) 625 break; 626 } 627 628 if (ar == NULL) { 629 sx_xunlock(&autofs_softc->sc_lock); 630 AUTOFS_DEBUG("id %d not found", add->add_id); 631 return (ESRCH); 632 } 633 634 ar->ar_error = add->add_error; 635 ar->ar_wildcards = add->add_wildcards; 636 ar->ar_done = true; 637 ar->ar_in_progress = false; 638 cv_broadcast(&autofs_softc->sc_cv); 639 640 sx_xunlock(&autofs_softc->sc_lock); 641 642 return (0); 643 } 644 645 static int 646 autofs_open(struct cdev *dev, int flags, int fmt, struct thread *td) 647 { 648 649 sx_xlock(&autofs_softc->sc_lock); 650 /* 651 * We must never block automountd(8) and its descendants, and we use 652 * session ID to determine that: we store session id of the process 653 * that opened the device, and then compare it with session ids 654 * of triggering processes. This means running a second automountd(8) 655 * instance would break the previous one. The check below prevents 656 * it from happening. 657 */ 658 if (autofs_softc->sc_dev_opened) { 659 sx_xunlock(&autofs_softc->sc_lock); 660 return (EBUSY); 661 } 662 663 autofs_softc->sc_dev_opened = true; 664 sx_xunlock(&autofs_softc->sc_lock); 665 666 return (0); 667 } 668 669 static int 670 autofs_close(struct cdev *dev, int flag, int fmt, struct thread *td) 671 { 672 673 sx_xlock(&autofs_softc->sc_lock); 674 KASSERT(autofs_softc->sc_dev_opened, ("not opened?")); 675 autofs_softc->sc_dev_opened = false; 676 sx_xunlock(&autofs_softc->sc_lock); 677 678 return (0); 679 } 680 681 static int 682 autofs_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int mode, 683 struct thread *td) 684 { 685 686 KASSERT(autofs_softc->sc_dev_opened, ("not opened?")); 687 688 switch (cmd) { 689 case AUTOFSREQUEST: 690 return (autofs_ioctl_request( 691 (struct autofs_daemon_request *)arg)); 692 case AUTOFSDONE101: 693 return (autofs_ioctl_done_101( 694 (struct autofs_daemon_done_101 *)arg)); 695 case AUTOFSDONE: 696 return (autofs_ioctl_done( 697 (struct autofs_daemon_done *)arg)); 698 default: 699 AUTOFS_DEBUG("invalid cmd %lx", cmd); 700 return (EINVAL); 701 } 702 } 703