1 /* $NetBSD: autofs_linux.c,v 1.1.1.3 2015/01/17 16:34:16 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1999-2003 Ion Badulescu 5 * Copyright (c) 1997-2014 Erez Zadok 6 * Copyright (c) 1990 Jan-Simon Pendry 7 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine 8 * Copyright (c) 1990 The Regents of the University of California. 9 * All rights reserved. 10 * 11 * This code is derived from software contributed to Berkeley by 12 * Jan-Simon Pendry at Imperial College, London. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 3. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * 39 * File: am-utils/conf/autofs/autofs_linux.c 40 * 41 */ 42 43 /* 44 * Automounter filesystem for Linux 45 */ 46 47 #ifdef HAVE_CONFIG_H 48 # include <config.h> 49 #endif /* HAVE_CONFIG_H */ 50 #include <am_defs.h> 51 #include <amd.h> 52 53 #ifdef HAVE_FS_AUTOFS 54 55 /* 56 * MACROS: 57 */ 58 59 #define AUTOFS_MIN_VERSION 3 60 #if AUTOFS_MAX_PROTO_VERSION >= 5 61 /* 62 * Autofs version 5 support is experimental; change this to 5 you want 63 * to play with, it. There are reports it does not work. 64 */ 65 #define AUTOFS_MAX_VERSION 4 /* we only know up to version 5 */ 66 #else 67 #define AUTOFS_MAX_VERSION AUTOFS_MAX_PROTO_VERSION 68 #endif 69 70 /* 71 * STRUCTURES: 72 */ 73 74 /* 75 * VARIABLES: 76 */ 77 78 static int autofs_max_fds; 79 static am_node **hash; 80 static int *list; 81 static int numfds = 0; 82 static int bind_works = 1; 83 84 85 static void 86 hash_init(void) 87 { 88 int i; 89 struct rlimit rlim; 90 91 if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { 92 plog(XLOG_ERROR, "getrlimit failed, defaulting to 256 fd's"); 93 autofs_max_fds = 256; 94 } else { 95 autofs_max_fds = (rlim.rlim_cur > 1024) ? 1024 : rlim.rlim_cur; 96 plog(XLOG_INFO, "%d fd's available for autofs", autofs_max_fds); 97 } 98 99 list = malloc(autofs_max_fds * sizeof(*list)); 100 hash = malloc(autofs_max_fds * sizeof(*hash)); 101 102 for (i = 0 ; i < autofs_max_fds; i++) { 103 hash[i] = NULL; 104 list[i] = -1; 105 } 106 } 107 108 109 static void 110 hash_insert(int fd, am_node *mp) 111 { 112 if (hash[fd] != 0) 113 plog(XLOG_ERROR, "file descriptor %d already in the hash", fd); 114 115 hash[fd] = mp; 116 list[numfds] = fd; 117 numfds++; 118 } 119 120 121 static void 122 hash_delete(int fd) 123 { 124 int i; 125 126 if (hash[fd] == 0) 127 plog(XLOG_WARNING, "file descriptor %d not in the hash", fd); 128 129 hash[fd] = NULL; 130 numfds--; 131 for (i = 0; i < numfds; i++) 132 if (list[i] == fd) { 133 list[i] = list[numfds]; 134 break; 135 } 136 } 137 138 139 int 140 autofs_get_fh(am_node *mp) 141 { 142 int fds[2]; 143 autofs_fh_t *fh; 144 145 plog(XLOG_DEBUG, "autofs_get_fh for %s", mp->am_path); 146 if (pipe(fds) < 0) 147 return errno; 148 149 /* sanity check */ 150 if (fds[0] > autofs_max_fds) { 151 close(fds[0]); 152 close(fds[1]); 153 return EMFILE; 154 } 155 156 fh = ALLOC(autofs_fh_t); 157 fh->fd = fds[0]; 158 fh->kernelfd = fds[1]; 159 fh->ioctlfd = -1; 160 fh->pending_mounts = NULL; 161 fh->pending_umounts = NULL; 162 163 mp->am_autofs_fh = fh; 164 165 return 0; 166 } 167 168 169 void 170 autofs_mounted(am_node *mp) 171 { 172 autofs_fh_t *fh = mp->am_autofs_fh; 173 unsigned long timeout = gopt.am_timeo; 174 175 close(fh->kernelfd); 176 fh->kernelfd = -1; 177 178 autofs_get_mp(mp); 179 180 /* Get autofs protocol version */ 181 if (ioctl(fh->ioctlfd, AUTOFS_IOC_PROTOVER, &fh->version) < 0) { 182 plog(XLOG_ERROR, "AUTOFS_IOC_PROTOVER: %s", strerror(errno)); 183 fh->version = AUTOFS_MIN_VERSION; 184 plog(XLOG_ERROR, "autofs: assuming protocol version %d", fh->version); 185 } else 186 plog(XLOG_INFO, "autofs: using protocol version %d", fh->version); 187 188 /* set expiration timeout */ 189 if (ioctl(fh->ioctlfd, AUTOFS_IOC_SETTIMEOUT, &timeout) < 0) 190 plog(XLOG_ERROR, "AUTOFS_IOC_SETTIMEOUT: %s", strerror(errno)); 191 192 /* tell the daemon to call us for expirations */ 193 mp->am_autofs_ttl = clocktime(NULL) + gopt.am_timeo_w; 194 } 195 196 197 void 198 autofs_get_mp(am_node *mp) 199 { 200 autofs_fh_t *fh = mp->am_autofs_fh; 201 dlog("autofs: getting mount point"); 202 if (fh->ioctlfd < 0) 203 fh->ioctlfd = open(mp->am_path, O_RDONLY); 204 hash_insert(fh->fd, mp); 205 } 206 207 208 void 209 autofs_release_mp(am_node *mp) 210 { 211 autofs_fh_t *fh = mp->am_autofs_fh; 212 dlog("autofs: releasing mount point"); 213 if (fh->ioctlfd >= 0) { 214 close(fh->ioctlfd); 215 fh->ioctlfd = -1; 216 } 217 /* 218 * take the kernel fd out of the hash/fdset 219 * so select() doesn't go crazy if the umount succeeds 220 */ 221 if (fh->fd >= 0) 222 hash_delete(fh->fd); 223 } 224 225 226 void 227 autofs_release_fh(am_node *mp) 228 { 229 autofs_fh_t *fh = mp->am_autofs_fh; 230 struct autofs_pending_mount **pp, *p; 231 struct autofs_pending_umount **upp, *up; 232 233 dlog("autofs: releasing file handle"); 234 if (fh) { 235 /* 236 * if a mount succeeded, the kernel fd was closed on 237 * the amd side, so it might have been reused. 238 * we set it to -1 after closing it, to avoid the problem. 239 */ 240 if (fh->kernelfd >= 0) 241 close(fh->kernelfd); 242 243 if (fh->ioctlfd >= 0) 244 close(fh->ioctlfd); 245 246 if (fh->fd >= 0) 247 close(fh->fd); 248 249 pp = &fh->pending_mounts; 250 while (*pp) { 251 p = *pp; 252 XFREE(p->name); 253 *pp = p->next; 254 XFREE(p); 255 } 256 257 upp = &fh->pending_umounts; 258 while (*upp) { 259 up = *upp; 260 XFREE(up->name); 261 *upp = up->next; 262 XFREE(up); 263 } 264 265 XFREE(fh); 266 mp->am_autofs_fh = NULL; 267 } 268 } 269 270 271 void 272 autofs_add_fdset(fd_set *readfds) 273 { 274 int i; 275 for (i = 0; i < numfds; i++) 276 FD_SET(list[i], readfds); 277 } 278 279 280 static ssize_t 281 autofs_get_pkt(int fd, void *buf, size_t bytes) 282 { 283 ssize_t i; 284 285 do { 286 i = read(fd, buf, bytes); 287 288 if (i <= 0) 289 break; 290 291 buf = (char *)buf + i; 292 bytes -= i; 293 } while (bytes); 294 295 return bytes; 296 } 297 298 299 static void 300 send_fail(int fd, autofs_wqt_t token) 301 { 302 if (token == 0) 303 return; 304 if (ioctl(fd, AUTOFS_IOC_FAIL, token) < 0) 305 plog(XLOG_ERROR, "AUTOFS_IOC_FAIL: %s", strerror(errno)); 306 } 307 308 309 static void 310 send_ready(int fd, autofs_wqt_t token) 311 { 312 if (token == 0) 313 return; 314 if (ioctl(fd, AUTOFS_IOC_READY, token) < 0) 315 plog(XLOG_ERROR, "AUTOFS_IOC_READY: %s", strerror(errno)); 316 } 317 318 319 static void 320 autofs_lookup_failed(am_node *mp, char *name) 321 { 322 autofs_fh_t *fh = mp->am_autofs_fh; 323 struct autofs_pending_mount **pp, *p; 324 325 pp = &fh->pending_mounts; 326 while (*pp && !STREQ((*pp)->name, name)) 327 pp = &(*pp)->next; 328 329 /* sanity check */ 330 if (*pp == NULL) 331 return; 332 333 p = *pp; 334 plog(XLOG_INFO, "autofs: lookup of %s failed", name); 335 send_fail(fh->ioctlfd, p->wait_queue_token); 336 337 XFREE(p->name); 338 *pp = p->next; 339 XFREE(p); 340 } 341 342 343 static void 344 autofs_expire_one(am_node *mp, char *name, autofs_wqt_t token) 345 { 346 autofs_fh_t *fh; 347 am_node *ap; 348 struct autofs_pending_umount *p; 349 char *ap_path; 350 351 fh = mp->am_autofs_fh; 352 353 ap_path = str3cat(NULL, mp->am_path, "/", name); 354 if (amuDebug(D_TRACE)) 355 plog(XLOG_DEBUG, "\tumount(%s)", ap_path); 356 357 p = fh->pending_umounts; 358 while (p && p->wait_queue_token != token) 359 p = p->next; 360 361 if (p) { 362 /* already pending */ 363 dlog("Umounting of %s already pending", ap_path); 364 amd_stats.d_drops++; 365 goto out; 366 } 367 368 ap = find_ap(ap_path); 369 if (ap == NULL) { 370 /* not found??? not sure what to do here... */ 371 send_fail(fh->ioctlfd, token); 372 goto out; 373 } 374 375 p = ALLOC(struct autofs_pending_umount); 376 p->wait_queue_token = token; 377 p->name = xstrdup(name); 378 p->next = fh->pending_umounts; 379 fh->pending_umounts = p; 380 381 unmount_mp(ap); 382 383 out: 384 XFREE(ap_path); 385 } 386 387 388 static void 389 autofs_missing_one(am_node *mp, autofs_wqt_t wait_queue_token, char *name) 390 { 391 autofs_fh_t *fh; 392 mntfs *mf; 393 am_node *ap; 394 struct autofs_pending_mount *p; 395 int error; 396 397 mf = mp->am_al->al_mnt; 398 fh = mp->am_autofs_fh; 399 400 p = fh->pending_mounts; 401 while (p && p->wait_queue_token != wait_queue_token) 402 p = p->next; 403 404 if (p) { 405 /* already pending */ 406 dlog("Mounting of %s/%s already pending", 407 mp->am_path, name); 408 amd_stats.d_drops++; 409 return; 410 } 411 412 p = ALLOC(struct autofs_pending_mount); 413 p->wait_queue_token = wait_queue_token; 414 p->name = xstrdup(name); 415 p->next = fh->pending_mounts; 416 fh->pending_mounts = p; 417 418 if (amuDebug(D_TRACE)) 419 plog(XLOG_DEBUG, "\tlookup(%s, %s)", mp->am_path, name); 420 ap = mf->mf_ops->lookup_child(mp, name, &error, VLOOK_CREATE); 421 if (ap && error < 0) 422 ap = mf->mf_ops->mount_child(ap, &error); 423 424 /* some of the rest can be done in amfs_auto_cont */ 425 426 if (ap == 0) { 427 if (error < 0) { 428 dlog("Mount still pending, not sending autofs reply yet"); 429 return; 430 } 431 autofs_lookup_failed(mp, name); 432 } 433 mp->am_stats.s_lookup++; 434 } 435 436 437 static void 438 autofs_handle_expire(am_node *mp, struct autofs_packet_expire *pkt) 439 { 440 autofs_expire_one(mp, pkt->name, 0); 441 } 442 443 444 static void 445 autofs_handle_missing(am_node *mp, struct autofs_packet_missing *pkt) 446 { 447 autofs_missing_one(mp, pkt->wait_queue_token, pkt->name); 448 } 449 450 451 #if AUTOFS_MAX_PROTO_VERSION >= 4 452 static void 453 autofs_handle_expire_multi(am_node *mp, struct autofs_packet_expire_multi *pkt) 454 { 455 autofs_expire_one(mp, pkt->name, pkt->wait_queue_token); 456 } 457 #endif /* AUTOFS_MAX_PROTO_VERSION >= 4 */ 458 459 460 #if AUTOFS_MAX_PROTO_VERSION >= 5 461 static void 462 autofs_handle_expire_direct(am_node *mp, 463 autofs_packet_expire_direct_t *pkt) 464 { 465 autofs_expire_one(mp, pkt->name, 0); 466 } 467 468 static void 469 autofs_handle_expire_indirect(am_node *mp, 470 autofs_packet_expire_indirect_t *pkt) 471 { 472 autofs_expire_one(mp, pkt->name, 0); 473 } 474 475 476 static void 477 autofs_handle_missing_direct(am_node *mp, 478 autofs_packet_missing_direct_t *pkt) 479 { 480 autofs_missing_one(mp, pkt->wait_queue_token, pkt->name); 481 } 482 483 484 static void 485 autofs_handle_missing_indirect(am_node *mp, 486 autofs_packet_missing_indirect_t *pkt) 487 { 488 autofs_missing_one(mp, pkt->wait_queue_token, pkt->name); 489 } 490 #endif /* AUTOFS_MAX_PROTO_VERSION >= 5 */ 491 492 493 int 494 autofs_handle_fdset(fd_set *readfds, int nsel) 495 { 496 int i; 497 union { 498 #if AUTOFS_MAX_PROTO_VERSION >= 5 499 union autofs_v5_packet_union pkt5; 500 #endif 501 union autofs_packet_union pkt; 502 } p; 503 autofs_fh_t *fh; 504 am_node *mp; 505 size_t len; 506 507 for (i = 0; nsel && i < numfds; i++) { 508 if (!FD_ISSET(list[i], readfds)) 509 continue; 510 511 nsel--; 512 FD_CLR(list[i], readfds); 513 mp = hash[list[i]]; 514 fh = mp->am_autofs_fh; 515 516 #if AUTOFS_MAX_PROTO_VERSION >= 5 517 if (fh->version < 5) { 518 len = sizeof(p.pkt); 519 } else { 520 len = sizeof(p.pkt5); 521 } 522 #else 523 len = sizeof(p.pkt); 524 #endif /* AUTOFS_MAX_PROTO_VERSION >= 5 */ 525 526 if (autofs_get_pkt(fh->fd, &p, len)) 527 continue; 528 529 switch (p.pkt.hdr.type) { 530 case autofs_ptype_missing: 531 autofs_handle_missing(mp, &p.pkt.missing); 532 break; 533 case autofs_ptype_expire: 534 autofs_handle_expire(mp, &p.pkt.expire); 535 break; 536 #if AUTOFS_MAX_PROTO_VERSION >= 4 537 case autofs_ptype_expire_multi: 538 autofs_handle_expire_multi(mp, &p.pkt.expire_multi); 539 break; 540 #endif /* AUTOFS_MAX_PROTO_VERSION >= 4 */ 541 #if AUTOFS_MAX_PROTO_VERSION >= 5 542 case autofs_ptype_expire_indirect: 543 autofs_handle_expire_indirect(mp, &p.pkt5.expire_direct); 544 break; 545 case autofs_ptype_expire_direct: 546 autofs_handle_expire_direct(mp, &p.pkt5.expire_direct); 547 break; 548 case autofs_ptype_missing_indirect: 549 autofs_handle_missing_indirect(mp, &p.pkt5.missing_direct); 550 break; 551 case autofs_ptype_missing_direct: 552 autofs_handle_missing_direct(mp, &p.pkt5.missing_direct); 553 break; 554 #endif /* AUTOFS_MAX_PROTO_VERSION >= 5 */ 555 default: 556 plog(XLOG_ERROR, "Unknown autofs packet type %d", 557 p.pkt.hdr.type); 558 } 559 } 560 return nsel; 561 } 562 563 564 int 565 create_autofs_service(void) 566 { 567 hash_init(); 568 569 /* not the best place, but... */ 570 if (linux_version_code() < KERNEL_VERSION(2,4,0)) 571 bind_works = 0; 572 573 return 0; 574 } 575 576 577 int 578 destroy_autofs_service(void) 579 { 580 /* Nothing to do */ 581 return 0; 582 } 583 584 585 static int 586 autofs_bind_umount(char *mountpoint) 587 { 588 int err = 1; 589 #ifdef MNT2_GEN_OPT_BIND 590 if (bind_works && gopt.flags & CFM_AUTOFS_USE_LOFS) { 591 struct stat buf; 592 593 if ((err = lstat(mountpoint, &buf))) 594 return errno; 595 if (S_ISLNK(buf.st_mode)) 596 goto use_symlink; 597 598 plog(XLOG_INFO, "autofs: un-bind-mounting %s", mountpoint); 599 err = umount_fs(mountpoint, mnttab_file_name, 1); 600 if (err) 601 plog(XLOG_INFO, "autofs: unmounting %s failed: %m", mountpoint); 602 else 603 err = rmdir(mountpoint); 604 goto out; 605 } 606 #endif /* MNT2_GEN_OPT_BIND */ 607 use_symlink: 608 plog(XLOG_INFO, "autofs: deleting symlink %s", mountpoint); 609 err = unlink(mountpoint); 610 611 out: 612 if (err) 613 return errno; 614 return 0; 615 } 616 617 618 int 619 autofs_mount_fs(am_node *mp, mntfs *mf) 620 { 621 char *target, *target2 = NULL; 622 int err = 0; 623 624 if (mf->mf_flags & MFF_ON_AUTOFS) { 625 if ((err = mkdir(mp->am_path, 0555))) 626 return errno; 627 } 628 629 /* 630 * For sublinks, we could end up here with an already mounted f/s. 631 * Don't do anything in that case. 632 */ 633 if (!(mf->mf_flags & MFF_MOUNTED)) 634 err = mf->mf_ops->mount_fs(mp, mf); 635 636 if (err) { 637 if (mf->mf_flags & MFF_ON_AUTOFS) 638 rmdir(mp->am_path); 639 return err; 640 } 641 642 if (mf->mf_flags & MFF_ON_AUTOFS) 643 /* Nothing else to do */ 644 return 0; 645 646 if (mp->am_link) 647 target = mp->am_link; 648 else 649 target = mf->mf_fo->opt_fs; 650 651 #ifdef MNT2_GEN_OPT_BIND 652 if (bind_works && gopt.flags & CFM_AUTOFS_USE_LOFS) { 653 struct stat buf; 654 655 /* 656 * HACK ALERT! 657 * 658 * Since the bind mount mechanism doesn't allow mountpoint crossing, 659 * we _must_ use symlinks for the host mount case. Otherwise we end up 660 * with a bunch of empty mountpoints... 661 */ 662 if (mf->mf_ops == &amfs_host_ops) 663 goto use_symlink; 664 665 if (target[0] != '/') 666 target2 = str3cat(NULL, mp->am_parent->am_path, "/", target); 667 else 668 target2 = xstrdup(target); 669 670 /* 671 * We need to stat() the destination, because the bind mount does not 672 * follow symlinks and/or allow for non-existent destinations. 673 * We fall back to symlinks if there are problems. 674 * 675 * We also need to temporarily change pgrp, otherwise our stat() won't 676 * trigger whatever cascading mounts are needed. 677 * 678 * WARNING: we will deadlock if this function is called from the master 679 * amd process and it happens to trigger another auto mount. Therefore, 680 * this function should be called only from a child amd process, or 681 * at the very least it should not be called from the parent unless we 682 * know for sure that it won't cause a recursive mount. We refuse to 683 * cause the recursive mount anyway if called from the parent amd. 684 */ 685 if (!foreground) { 686 pid_t pgrp = getpgrp(); 687 setpgrp(); 688 err = stat(target2, &buf); 689 if ((err = setpgid(0, pgrp))) { 690 plog(XLOG_ERROR, "autofs: cannot restore pgrp: %s", strerror(errno)); 691 plog(XLOG_ERROR, "autofs: aborting the mount"); 692 goto out; 693 } 694 if (err) 695 goto use_symlink; 696 } 697 if ((err = lstat(target2, &buf))) 698 goto use_symlink; 699 if (S_ISLNK(buf.st_mode)) 700 goto use_symlink; 701 702 plog(XLOG_INFO, "autofs: bind-mounting %s -> %s", mp->am_path, target2); 703 mkdir(mp->am_path, 0555); 704 err = mount_lofs(mp->am_path, target2, mf->mf_mopts, 1); 705 if (err) { 706 rmdir(mp->am_path); 707 plog(XLOG_INFO, "autofs: bind-mounting %s -> %s failed", mp->am_path, target2); 708 goto use_symlink; 709 } 710 goto out; 711 } 712 #endif /* MNT2_GEN_OPT_BIND */ 713 use_symlink: 714 plog(XLOG_INFO, "autofs: symlinking %s -> %s", mp->am_path, target); 715 err = symlink(target, mp->am_path); 716 717 out: 718 if (target2) 719 XFREE(target2); 720 721 if (err) 722 return errno; 723 return 0; 724 } 725 726 727 int 728 autofs_umount_fs(am_node *mp, mntfs *mf) 729 { 730 int err = 0; 731 if (!(mf->mf_flags & MFF_ON_AUTOFS)) { 732 err = autofs_bind_umount(mp->am_path); 733 if (err) 734 return err; 735 } 736 737 /* 738 * Multiple sublinks could reference this f/s. 739 * Don't actually unmount it unless we're holding the last reference. 740 */ 741 if (mf->mf_refc == 1) { 742 err = mf->mf_ops->umount_fs(mp, mf); 743 if (err) 744 return err; 745 if (mf->mf_flags & MFF_ON_AUTOFS) 746 rmdir(mp->am_path); 747 } 748 return 0; 749 } 750 751 752 int 753 autofs_umount_succeeded(am_node *mp) 754 { 755 autofs_fh_t *fh = mp->am_parent->am_autofs_fh; 756 struct autofs_pending_umount **pp, *p; 757 758 /* Already gone? */ 759 if (fh == NULL) 760 return 0; 761 762 pp = &fh->pending_umounts; 763 while (*pp && !STREQ((*pp)->name, mp->am_name)) 764 pp = &(*pp)->next; 765 766 /* sanity check */ 767 if (*pp == NULL) 768 return -1; 769 770 p = *pp; 771 plog(XLOG_INFO, "autofs: unmounting %s succeeded", mp->am_path); 772 send_ready(fh->ioctlfd, p->wait_queue_token); 773 774 XFREE(p->name); 775 *pp = p->next; 776 XFREE(p); 777 return 0; 778 } 779 780 781 int 782 autofs_umount_failed(am_node *mp) 783 { 784 autofs_fh_t *fh = mp->am_parent->am_autofs_fh; 785 struct autofs_pending_umount **pp, *p; 786 787 pp = &fh->pending_umounts; 788 while (*pp && !STREQ((*pp)->name, mp->am_name)) 789 pp = &(*pp)->next; 790 791 /* sanity check */ 792 if (*pp == NULL) 793 return -1; 794 795 p = *pp; 796 plog(XLOG_INFO, "autofs: unmounting %s failed", mp->am_path); 797 send_fail(fh->ioctlfd, p->wait_queue_token); 798 799 XFREE(p->name); 800 *pp = p->next; 801 XFREE(p); 802 return 0; 803 } 804 805 806 void 807 autofs_mount_succeeded(am_node *mp) 808 { 809 autofs_fh_t *fh = mp->am_parent->am_autofs_fh; 810 struct autofs_pending_mount **pp, *p; 811 812 /* 813 * don't expire the entries -- the kernel will do it for us. 814 * 815 * but it won't do autofs filesystems, so we expire them the old 816 * fashioned way instead. 817 */ 818 if (!(mp->am_al->al_mnt->mf_flags & MFF_IS_AUTOFS)) 819 mp->am_flags |= AMF_NOTIMEOUT; 820 821 pp = &fh->pending_mounts; 822 while (*pp && !STREQ((*pp)->name, mp->am_name)) 823 pp = &(*pp)->next; 824 825 /* sanity check */ 826 if (*pp == NULL) 827 return; 828 829 p = *pp; 830 plog(XLOG_INFO, "autofs: mounting %s succeeded", mp->am_path); 831 send_ready(fh->ioctlfd, p->wait_queue_token); 832 833 XFREE(p->name); 834 *pp = p->next; 835 XFREE(p); 836 } 837 838 839 void 840 autofs_mount_failed(am_node *mp) 841 { 842 autofs_fh_t *fh = mp->am_parent->am_autofs_fh; 843 struct autofs_pending_mount **pp, *p; 844 845 pp = &fh->pending_mounts; 846 while (*pp && !STREQ((*pp)->name, mp->am_name)) 847 pp = &(*pp)->next; 848 849 /* sanity check */ 850 if (*pp == NULL) 851 return; 852 853 p = *pp; 854 plog(XLOG_INFO, "autofs: mounting %s failed", mp->am_path); 855 send_fail(fh->ioctlfd, p->wait_queue_token); 856 857 XFREE(p->name); 858 *pp = p->next; 859 XFREE(p); 860 } 861 862 863 void 864 autofs_get_opts(char *opts, size_t l, autofs_fh_t *fh) 865 { 866 xsnprintf(opts, l, "fd=%d,minproto=%d,maxproto=%d", 867 fh->kernelfd, AUTOFS_MIN_VERSION, AUTOFS_MAX_VERSION); 868 } 869 870 871 int 872 autofs_compute_mount_flags(mntent_t *mnt) 873 { 874 return 0; 875 } 876 877 878 #if AUTOFS_MAX_PROTO_VERSION >= 4 879 static int autofs_timeout_mp_task(void *arg) 880 { 881 am_node *mp = (am_node *)arg; 882 autofs_fh_t *fh = mp->am_autofs_fh; 883 int now = 0; 884 885 while (ioctl(fh->ioctlfd, AUTOFS_IOC_EXPIRE_MULTI, &now) == 0); 886 return 0; 887 } 888 #endif /* AUTOFS_MAX_PROTO_VERSION >= 4 */ 889 890 891 void autofs_timeout_mp(am_node *mp) 892 { 893 autofs_fh_t *fh = mp->am_autofs_fh; 894 time_t now = clocktime(NULL); 895 896 /* update the ttl */ 897 mp->am_autofs_ttl = now + gopt.am_timeo_w; 898 899 if (fh->version < 4) { 900 struct autofs_packet_expire pkt; 901 while (ioctl(fh->ioctlfd, AUTOFS_IOC_EXPIRE, &pkt) == 0) 902 autofs_handle_expire(mp, &pkt); 903 return; 904 } 905 906 #if AUTOFS_MAX_PROTO_VERSION >= 4 907 run_task(autofs_timeout_mp_task, mp, NULL, NULL); 908 #endif /* AUTOFS_MAX_PROTO_VERSION >= 4 */ 909 } 910 911 #endif /* HAVE_FS_AUTOFS */ 912