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
hash_init(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
hash_insert(int fd,am_node * mp)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
hash_delete(int fd)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
autofs_get_fh(am_node * mp)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
autofs_mounted(am_node * mp)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
autofs_get_mp(am_node * mp)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
autofs_release_mp(am_node * mp)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
autofs_release_fh(am_node * mp)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
autofs_add_fdset(fd_set * readfds)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
autofs_get_pkt(int fd,void * buf,size_t bytes)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
send_fail(int fd,autofs_wqt_t token)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
send_ready(int fd,autofs_wqt_t token)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
autofs_lookup_failed(am_node * mp,char * name)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
autofs_expire_one(am_node * mp,char * name,autofs_wqt_t token)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
autofs_missing_one(am_node * mp,autofs_wqt_t wait_queue_token,char * name)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
autofs_handle_expire(am_node * mp,struct autofs_packet_expire * pkt)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
autofs_handle_missing(am_node * mp,struct autofs_packet_missing * pkt)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
autofs_handle_expire_multi(am_node * mp,struct autofs_packet_expire_multi * pkt)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
autofs_handle_expire_direct(am_node * mp,autofs_packet_expire_direct_t * pkt)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
autofs_handle_expire_indirect(am_node * mp,autofs_packet_expire_indirect_t * pkt)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
autofs_handle_missing_direct(am_node * mp,autofs_packet_missing_direct_t * pkt)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
autofs_handle_missing_indirect(am_node * mp,autofs_packet_missing_indirect_t * pkt)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
autofs_handle_fdset(fd_set * readfds,int nsel)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
create_autofs_service(void)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
destroy_autofs_service(void)578 destroy_autofs_service(void)
579 {
580 /* Nothing to do */
581 return 0;
582 }
583
584
585 static int
autofs_bind_umount(char * mountpoint)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
autofs_mount_fs(am_node * mp,mntfs * mf)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
autofs_umount_fs(am_node * mp,mntfs * mf)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
autofs_umount_succeeded(am_node * mp)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
autofs_umount_failed(am_node * mp)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
autofs_mount_succeeded(am_node * mp)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
autofs_mount_failed(am_node * mp)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
autofs_get_opts(char * opts,size_t l,autofs_fh_t * fh)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
autofs_compute_mount_flags(mntent_t * mnt)872 autofs_compute_mount_flags(mntent_t *mnt)
873 {
874 return 0;
875 }
876
877
878 #if AUTOFS_MAX_PROTO_VERSION >= 4
autofs_timeout_mp_task(void * arg)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
autofs_timeout_mp(am_node * mp)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