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