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