]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/automount.c
automount: don't try to umount if it already happened
[thirdparty/systemd.git] / src / core / automount.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
5cb5a6ff 2
a7334b09
LP
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
a7334b09
LP
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 16 Lesser General Public License for more details.
a7334b09 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
a7334b09
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
5cb5a6ff 22#include <errno.h>
8d567588
LP
23#include <limits.h>
24#include <sys/mount.h>
25#include <unistd.h>
26#include <fcntl.h>
27#include <sys/epoll.h>
28#include <sys/stat.h>
29#include <linux/auto_fs4.h>
30#include <linux/auto_dev-ioctl.h>
5cb5a6ff 31
87f0e418 32#include "unit.h"
5cb5a6ff 33#include "automount.h"
20ad4cfd 34#include "mount.h"
8d567588 35#include "unit-name.h"
4e67ddd6 36#include "special.h"
e51bc1a2 37#include "label.h"
49e942b2 38#include "mkdir.h"
9eb977db 39#include "path-util.h"
718db961
LP
40#include "dbus-automount.h"
41#include "bus-util.h"
42#include "bus-error.h"
6482f626 43#include "formats-util.h"
0b452006 44#include "process-util.h"
deb0a77c 45#include "async.h"
5cb5a6ff 46
e537352b
LP
47static const UnitActiveState state_translation_table[_AUTOMOUNT_STATE_MAX] = {
48 [AUTOMOUNT_DEAD] = UNIT_INACTIVE,
49 [AUTOMOUNT_WAITING] = UNIT_ACTIVE,
50 [AUTOMOUNT_RUNNING] = UNIT_ACTIVE,
74ac3cbd 51 [AUTOMOUNT_FAILED] = UNIT_FAILED
e537352b 52};
5cb5a6ff 53
deb0a77c
MO
54struct expire_data {
55 int dev_autofs_fd;
56 int ioctl_fd;
57};
58
59static inline void expire_data_free(struct expire_data *data) {
60 if (!data)
61 return;
62
63 safe_close(data->dev_autofs_fd);
64 safe_close(data->ioctl_fd);
65 free(data);
66}
67
68DEFINE_TRIVIAL_CLEANUP_FUNC(struct expire_data*, expire_data_free);
69
a16e1123 70static int open_dev_autofs(Manager *m);
718db961 71static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata);
8d567588 72
e537352b
LP
73static void automount_init(Unit *u) {
74 Automount *a = AUTOMOUNT(u);
5cb5a6ff 75
8d567588 76 assert(u);
ac155bb8 77 assert(u->load_state == UNIT_STUB);
8d567588 78
718db961 79 a->pipe_fd = -1;
1cf18f27 80 a->directory_mode = 0755;
1124fe6f 81 UNIT(a)->ignore_on_isolate = true;
8d567588
LP
82}
83
a5e41bdb 84static void repeat_unmount(const char *path) {
8d567588
LP
85 assert(path);
86
87 for (;;) {
1b560190
LP
88 /* If there are multiple mounts on a mount point, this
89 * removes them all */
8d567588
LP
90
91 if (umount2(path, MNT_DETACH) >= 0)
92 continue;
93
94 if (errno != EINVAL)
56f64d95 95 log_error_errno(errno, "Failed to unmount: %m");
8d567588
LP
96
97 break;
98 }
99}
100
deb0a77c
MO
101static int automount_send_ready(Automount *a, Set *tokens, int status);
102
8d567588
LP
103static void unmount_autofs(Automount *a) {
104 assert(a);
105
106 if (a->pipe_fd < 0)
107 return;
108
deb0a77c
MO
109 automount_send_ready(a, a->tokens, -EHOSTDOWN);
110 automount_send_ready(a, a->expire_tokens, -EHOSTDOWN);
8d567588 111
718db961 112 a->pipe_event_source = sd_event_source_unref(a->pipe_event_source);
03e334a1 113 a->pipe_fd = safe_close(a->pipe_fd);
8d567588 114
a16e1123
LP
115 /* If we reload/reexecute things we keep the mount point
116 * around */
117 if (a->where &&
1124fe6f
MS
118 (UNIT(a)->manager->exit_code != MANAGER_RELOAD &&
119 UNIT(a)->manager->exit_code != MANAGER_REEXECUTE))
a5e41bdb 120 repeat_unmount(a->where);
8d567588
LP
121}
122
123static void automount_done(Unit *u) {
124 Automount *a = AUTOMOUNT(u);
125
126 assert(a);
127
128 unmount_autofs(a);
8d567588 129
a16e1123
LP
130 free(a->where);
131 a->where = NULL;
132
133 set_free(a->tokens);
134 a->tokens = NULL;
deb0a77c
MO
135 set_free(a->expire_tokens);
136 a->expire_tokens = NULL;
137
138 a->expire_event_source = sd_event_source_unref(a->expire_event_source);
8d567588
LP
139}
140
a57f7e2c
LP
141static int automount_add_mount_links(Automount *a) {
142 _cleanup_free_ char *parent = NULL;
6e2ef85b
LP
143 int r;
144
145 assert(a);
1b560190 146
a57f7e2c 147 r = path_get_parent(a->where, &parent);
0b2665c3 148 if (r < 0)
6e2ef85b
LP
149 return r;
150
a57f7e2c 151 return unit_require_mounts_for(UNIT(a), parent);
6e2ef85b
LP
152}
153
2edd4434
LP
154static int automount_add_default_dependencies(Automount *a) {
155 int r;
156
157 assert(a);
158
b2c23da8 159 if (UNIT(a)->manager->running_as != MANAGER_SYSTEM)
6b1dc2bd 160 return 0;
2a77d31d 161
6b1dc2bd
LP
162 r = unit_add_two_dependencies_by_name(UNIT(a), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
163 if (r < 0)
164 return r;
2edd4434
LP
165
166 return 0;
167}
168
8d567588 169static int automount_verify(Automount *a) {
e1d75803 170 _cleanup_free_ char *e = NULL;
7410616c
LP
171 int r;
172
8d567588
LP
173 assert(a);
174
1124fe6f 175 if (UNIT(a)->load_state != UNIT_LOADED)
8d567588
LP
176 return 0;
177
41e45059 178 if (path_equal(a->where, "/")) {
f2341e0a 179 log_unit_error(UNIT(a), "Cannot have an automount unit for the root directory. Refusing.");
41e45059
LP
180 return -EINVAL;
181 }
182
7410616c
LP
183 r = unit_name_from_path(a->where, ".automount", &e);
184 if (r < 0)
f2341e0a 185 return log_unit_error(UNIT(a), "Failed to generate unit name from path: %m");
8d567588 186
7410616c 187 if (!unit_has_name(UNIT(a), e)) {
f2341e0a 188 log_unit_error(UNIT(a), "Where= setting doesn't match unit name. Refusing.");
8d567588
LP
189 return -EINVAL;
190 }
191
192 return 0;
e537352b 193}
5cb5a6ff 194
e537352b 195static int automount_load(Unit *u) {
e537352b 196 Automount *a = AUTOMOUNT(u);
3ecaa09b 197 int r;
23a177ef 198
e537352b 199 assert(u);
ac155bb8 200 assert(u->load_state == UNIT_STUB);
5cb5a6ff 201
e537352b 202 /* Load a .automount file */
0b2665c3
LP
203 r = unit_load_fragment_and_dropin_optional(u);
204 if (r < 0)
e537352b 205 return r;
23a177ef 206
ac155bb8 207 if (u->load_state == UNIT_LOADED) {
57020a3a 208 Unit *x;
23a177ef 209
0b2665c3 210 if (!a->where) {
7410616c
LP
211 r = unit_name_to_path(u->id, &a->where);
212 if (r < 0)
213 return r;
0b2665c3 214 }
a16e1123
LP
215
216 path_kill_slashes(a->where);
217
3ecaa09b 218 r = unit_load_related_unit(u, ".mount", &x);
0b2665c3 219 if (r < 0)
6e2ef85b
LP
220 return r;
221
3ecaa09b 222 r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, x, true);
57020a3a 223 if (r < 0)
23a177ef
LP
224 return r;
225
3ecaa09b 226 r = automount_add_mount_links(a);
57020a3a 227 if (r < 0)
23a177ef 228 return r;
4e67ddd6 229
0b2665c3
LP
230 if (UNIT(a)->default_dependencies) {
231 r = automount_add_default_dependencies(a);
232 if (r < 0)
4e67ddd6 233 return r;
0b2665c3 234 }
23a177ef
LP
235 }
236
8d567588 237 return automount_verify(a);
5cb5a6ff
LP
238}
239
8d567588
LP
240static void automount_set_state(Automount *a, AutomountState state) {
241 AutomountState old_state;
e537352b 242 assert(a);
034c6ed7 243
8d567588
LP
244 old_state = a->state;
245 a->state = state;
246
247 if (state != AUTOMOUNT_WAITING &&
248 state != AUTOMOUNT_RUNNING)
249 unmount_autofs(a);
250
251 if (state != old_state)
f2341e0a 252 log_unit_debug(UNIT(a), "Changed %s -> %s", automount_state_to_string(old_state), automount_state_to_string(state));
8d567588 253
e2f3b44c 254 unit_notify(UNIT(a), state_translation_table[old_state], state_translation_table[state], true);
034c6ed7
LP
255}
256
be847e82 257static int automount_coldplug(Unit *u) {
a16e1123
LP
258 Automount *a = AUTOMOUNT(u);
259 int r;
260
261 assert(a);
262 assert(a->state == AUTOMOUNT_DEAD);
263
264 if (a->deserialized_state != a->state) {
265
0b2665c3
LP
266 r = open_dev_autofs(u->manager);
267 if (r < 0)
a16e1123
LP
268 return r;
269
270 if (a->deserialized_state == AUTOMOUNT_WAITING ||
271 a->deserialized_state == AUTOMOUNT_RUNNING) {
a16e1123
LP
272 assert(a->pipe_fd >= 0);
273
151b9b96 274 r = sd_event_add_io(u->manager->event, &a->pipe_event_source, a->pipe_fd, EPOLLIN, automount_dispatch_io, u);
0b2665c3 275 if (r < 0)
a16e1123 276 return r;
7dfbe2e3
TG
277
278 (void) sd_event_source_set_description(a->pipe_event_source, "automount-io");
a16e1123
LP
279 }
280
281 automount_set_state(a, a->deserialized_state);
282 }
283
284 return 0;
285}
286
87f0e418 287static void automount_dump(Unit *u, FILE *f, const char *prefix) {
deb0a77c 288 char time_string[FORMAT_TIMESPAN_MAX];
a16e1123 289 Automount *a = AUTOMOUNT(u);
5cb5a6ff 290
a16e1123 291 assert(a);
5cb5a6ff
LP
292
293 fprintf(f,
a16e1123 294 "%sAutomount State: %s\n"
81a5c6d0 295 "%sResult: %s\n"
1cf18f27 296 "%sWhere: %s\n"
deb0a77c
MO
297 "%sDirectoryMode: %04o\n"
298 "%sTimeoutIdleUSec: %s\n",
a16e1123 299 prefix, automount_state_to_string(a->state),
81a5c6d0 300 prefix, automount_result_to_string(a->result),
1cf18f27 301 prefix, a->where,
deb0a77c
MO
302 prefix, a->directory_mode,
303 prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX, a->timeout_idle_usec, USEC_PER_SEC));
5cb5a6ff
LP
304}
305
81a5c6d0 306static void automount_enter_dead(Automount *a, AutomountResult f) {
8d567588
LP
307 assert(a);
308
81a5c6d0
LP
309 if (f != AUTOMOUNT_SUCCESS)
310 a->result = f;
8d567588 311
81a5c6d0 312 automount_set_state(a, a->result != AUTOMOUNT_SUCCESS ? AUTOMOUNT_FAILED : AUTOMOUNT_DEAD);
8d567588
LP
313}
314
315static int open_dev_autofs(Manager *m) {
316 struct autofs_dev_ioctl param;
317
318 assert(m);
319
320 if (m->dev_autofs_fd >= 0)
321 return m->dev_autofs_fd;
322
c9bc0764 323 label_fix("/dev/autofs", false, false);
56cf987f 324
0b2665c3 325 m->dev_autofs_fd = open("/dev/autofs", O_CLOEXEC|O_RDONLY);
4a62c710
MS
326 if (m->dev_autofs_fd < 0)
327 return log_error_errno(errno, "Failed to open /dev/autofs: %m");
8d567588
LP
328
329 init_autofs_dev_ioctl(&param);
330 if (ioctl(m->dev_autofs_fd, AUTOFS_DEV_IOCTL_VERSION, &param) < 0) {
03e334a1 331 m->dev_autofs_fd = safe_close(m->dev_autofs_fd);
8d567588
LP
332 return -errno;
333 }
334
335 log_debug("Autofs kernel version %i.%i", param.ver_major, param.ver_minor);
336
337 return m->dev_autofs_fd;
338}
339
340static int open_ioctl_fd(int dev_autofs_fd, const char *where, dev_t devid) {
341 struct autofs_dev_ioctl *param;
342 size_t l;
8d567588
LP
343
344 assert(dev_autofs_fd >= 0);
345 assert(where);
346
347 l = sizeof(struct autofs_dev_ioctl) + strlen(where) + 1;
0b2665c3 348 param = alloca(l);
8d567588
LP
349
350 init_autofs_dev_ioctl(param);
351 param->size = l;
352 param->ioctlfd = -1;
353 param->openmount.devid = devid;
354 strcpy(param->path, where);
355
0b2665c3
LP
356 if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_OPENMOUNT, param) < 0)
357 return -errno;
8d567588 358
0b2665c3
LP
359 if (param->ioctlfd < 0)
360 return -EIO;
8d567588 361
f34beace 362 (void) fd_cloexec(param->ioctlfd, true);
0b2665c3 363 return param->ioctlfd;
8d567588
LP
364}
365
366static int autofs_protocol(int dev_autofs_fd, int ioctl_fd) {
367 uint32_t major, minor;
368 struct autofs_dev_ioctl param;
369
370 assert(dev_autofs_fd >= 0);
371 assert(ioctl_fd >= 0);
372
373 init_autofs_dev_ioctl(&param);
374 param.ioctlfd = ioctl_fd;
375
376 if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_PROTOVER, &param) < 0)
377 return -errno;
378
379 major = param.protover.version;
380
381 init_autofs_dev_ioctl(&param);
382 param.ioctlfd = ioctl_fd;
383
384 if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_PROTOSUBVER, &param) < 0)
385 return -errno;
386
387 minor = param.protosubver.sub_version;
388
389 log_debug("Autofs protocol version %i.%i", major, minor);
390 return 0;
391}
392
deb0a77c 393static int autofs_set_timeout(int dev_autofs_fd, int ioctl_fd, usec_t usec) {
8d567588
LP
394 struct autofs_dev_ioctl param;
395
396 assert(dev_autofs_fd >= 0);
397 assert(ioctl_fd >= 0);
398
399 init_autofs_dev_ioctl(&param);
400 param.ioctlfd = ioctl_fd;
deb0a77c
MO
401
402 /* Convert to seconds, rounding up. */
403 param.timeout.timeout = (usec + USEC_PER_SEC - 1) / USEC_PER_SEC;
8d567588
LP
404
405 if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_TIMEOUT, &param) < 0)
406 return -errno;
407
408 return 0;
409}
410
411static int autofs_send_ready(int dev_autofs_fd, int ioctl_fd, uint32_t token, int status) {
412 struct autofs_dev_ioctl param;
413
414 assert(dev_autofs_fd >= 0);
415 assert(ioctl_fd >= 0);
416
417 init_autofs_dev_ioctl(&param);
418 param.ioctlfd = ioctl_fd;
419
420 if (status) {
421 param.fail.token = token;
422 param.fail.status = status;
423 } else
424 param.ready.token = token;
425
426 if (ioctl(dev_autofs_fd, status ? AUTOFS_DEV_IOCTL_FAIL : AUTOFS_DEV_IOCTL_READY, &param) < 0)
427 return -errno;
428
429 return 0;
430}
431
deb0a77c 432static int automount_send_ready(Automount *a, Set *tokens, int status) {
03e334a1 433 _cleanup_close_ int ioctl_fd = -1;
8d567588 434 unsigned token;
03e334a1 435 int r;
8d567588
LP
436
437 assert(a);
438 assert(status <= 0);
439
deb0a77c 440 if (set_isempty(tokens))
8d567588
LP
441 return 0;
442
0b2665c3 443 ioctl_fd = open_ioctl_fd(UNIT(a)->manager->dev_autofs_fd, a->where, a->dev_id);
03e334a1
LP
444 if (ioctl_fd < 0)
445 return ioctl_fd;
8d567588
LP
446
447 if (status)
f2341e0a 448 log_unit_debug_errno(UNIT(a), status, "Sending failure: %m");
8d567588 449 else
f2341e0a 450 log_unit_debug(UNIT(a), "Sending success.");
8d567588 451
e364ad06
LP
452 r = 0;
453
8d567588 454 /* Autofs thankfully does not hand out 0 as a token */
deb0a77c 455 while ((token = PTR_TO_UINT(set_steal_first(tokens)))) {
8d567588
LP
456 int k;
457
458 /* Autofs fun fact II:
459 *
460 * if you pass a positive status code here, the kernel will
461 * freeze! Yay! */
462
0b2665c3
LP
463 k = autofs_send_ready(UNIT(a)->manager->dev_autofs_fd,
464 ioctl_fd,
465 token,
466 status);
467 if (k < 0)
8d567588
LP
468 r = k;
469 }
470
8d567588
LP
471 return r;
472}
473
deb0a77c 474int automount_update_mount(Automount *a, MountState old_state, MountState state) {
deb0a77c
MO
475 assert(a);
476
477 switch (state) {
478 case MOUNT_MOUNTED:
479 case MOUNT_REMOUNTING:
480 automount_send_ready(a, a->tokens, 0);
481 break;
482 case MOUNT_DEAD:
483 case MOUNT_UNMOUNTING:
484 case MOUNT_MOUNTING_SIGTERM:
485 case MOUNT_MOUNTING_SIGKILL:
486 case MOUNT_REMOUNTING_SIGTERM:
487 case MOUNT_REMOUNTING_SIGKILL:
488 case MOUNT_UNMOUNTING_SIGTERM:
489 case MOUNT_UNMOUNTING_SIGKILL:
490 case MOUNT_FAILED:
491 if (old_state != state)
492 automount_send_ready(a, a->tokens, -ENODEV);
493 break;
494 default:
495 break;
496 }
497
498 switch (state) {
499 case MOUNT_DEAD:
500 automount_send_ready(a, a->expire_tokens, 0);
501 break;
502 case MOUNT_MOUNTING:
503 case MOUNT_MOUNTING_DONE:
504 case MOUNT_MOUNTING_SIGTERM:
505 case MOUNT_MOUNTING_SIGKILL:
506 case MOUNT_REMOUNTING_SIGTERM:
507 case MOUNT_REMOUNTING_SIGKILL:
508 case MOUNT_UNMOUNTING_SIGTERM:
509 case MOUNT_UNMOUNTING_SIGKILL:
510 case MOUNT_FAILED:
511 if (old_state != state)
512 automount_send_ready(a, a->expire_tokens, -ENODEV);
513 break;
514 default:
515 break;
516 }
517
518 return 0;
519}
520
8d567588 521static void automount_enter_waiting(Automount *a) {
03e334a1 522 _cleanup_close_ int ioctl_fd = -1;
8d567588 523 int p[2] = { -1, -1 };
5ffa8c81
ZJS
524 char name[sizeof("systemd-")-1 + DECIMAL_STR_MAX(pid_t) + 1];
525 char options[sizeof("fd=,pgrp=,minproto=5,maxproto=5,direct")-1
526 + DECIMAL_STR_MAX(int) + DECIMAL_STR_MAX(gid_t) + 1];
8d567588 527 bool mounted = false;
03e334a1 528 int r, dev_autofs_fd;
8d567588
LP
529 struct stat st;
530
531 assert(a);
532 assert(a->pipe_fd < 0);
533 assert(a->where);
534
f2341e0a
LP
535 set_clear(a->tokens);
536
537 r = unit_fail_if_symlink(UNIT(a), a->where);
538 if (r < 0)
539 goto fail;
540
541 (void) mkdir_p_label(a->where, 0555);
542
543 unit_warn_if_dir_nonempty(UNIT(a), a->where);
8d567588 544
0b2665c3
LP
545 dev_autofs_fd = open_dev_autofs(UNIT(a)->manager);
546 if (dev_autofs_fd < 0) {
8d567588
LP
547 r = dev_autofs_fd;
548 goto fail;
549 }
550
a16e1123 551 if (pipe2(p, O_NONBLOCK|O_CLOEXEC) < 0) {
8d567588
LP
552 r = -errno;
553 goto fail;
554 }
555
5ffa8c81
ZJS
556 xsprintf(options, "fd=%i,pgrp="PID_FMT",minproto=5,maxproto=5,direct", p[1], getpgrp());
557 xsprintf(name, "systemd-"PID_FMT, getpid());
8d567588
LP
558 if (mount(name, a->where, "autofs", 0, options) < 0) {
559 r = -errno;
560 goto fail;
561 }
562
563 mounted = true;
564
03e334a1 565 p[1] = safe_close(p[1]);
8d567588
LP
566
567 if (stat(a->where, &st) < 0) {
568 r = -errno;
569 goto fail;
570 }
571
0b2665c3
LP
572 ioctl_fd = open_ioctl_fd(dev_autofs_fd, a->where, st.st_dev);
573 if (ioctl_fd < 0) {
8d567588
LP
574 r = ioctl_fd;
575 goto fail;
576 }
577
0b2665c3
LP
578 r = autofs_protocol(dev_autofs_fd, ioctl_fd);
579 if (r < 0)
8d567588
LP
580 goto fail;
581
deb0a77c 582 r = autofs_set_timeout(dev_autofs_fd, ioctl_fd, a->timeout_idle_usec);
0b2665c3 583 if (r < 0)
8d567588
LP
584 goto fail;
585
586 /* Autofs fun fact:
587 *
588 * Unless we close the ioctl fd here, for some weird reason
589 * the direct mount will not receive events from the
590 * kernel. */
591
151b9b96 592 r = sd_event_add_io(UNIT(a)->manager->event, &a->pipe_event_source, p[0], EPOLLIN, automount_dispatch_io, a);
0b2665c3 593 if (r < 0)
8d567588
LP
594 goto fail;
595
7dfbe2e3
TG
596 (void) sd_event_source_set_description(a->pipe_event_source, "automount-io");
597
8d567588
LP
598 a->pipe_fd = p[0];
599 a->dev_id = st.st_dev;
600
601 automount_set_state(a, AUTOMOUNT_WAITING);
602
603 return;
604
605fail:
3d94f76c 606 safe_close_pair(p);
8d567588
LP
607
608 if (mounted)
a5e41bdb 609 repeat_unmount(a->where);
8d567588 610
f2341e0a 611 log_unit_error_errno(UNIT(a), r, "Failed to initialize automounter: %m");
81a5c6d0 612 automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
8d567588
LP
613}
614
deb0a77c
MO
615static void *expire_thread(void *p) {
616 struct autofs_dev_ioctl param;
617 _cleanup_(expire_data_freep) struct expire_data *data = (struct expire_data*)p;
618 int r;
619
620 assert(data->dev_autofs_fd >= 0);
621 assert(data->ioctl_fd >= 0);
622
623 init_autofs_dev_ioctl(&param);
624 param.ioctlfd = data->ioctl_fd;
625
626 do {
627 r = ioctl(data->dev_autofs_fd, AUTOFS_DEV_IOCTL_EXPIRE, &param);
628 } while (r >= 0);
629
630 if (errno != EAGAIN)
631 log_warning_errno(errno, "Failed to expire automount, ignoring: %m");
632
633 return NULL;
634}
635
636static int automount_start_expire(Automount *a);
637
638static int automount_dispatch_expire(sd_event_source *source, usec_t usec, void *userdata) {
639 Automount *a = AUTOMOUNT(userdata);
640 _cleanup_(expire_data_freep) struct expire_data *data = NULL;
641 int r;
642
643 assert(a);
644 assert(source == a->expire_event_source);
645
646 data = new0(struct expire_data, 1);
647 if (!data)
648 return log_oom();
649
650 data->ioctl_fd = -1;
651
652 data->dev_autofs_fd = fcntl(UNIT(a)->manager->dev_autofs_fd, F_DUPFD_CLOEXEC, 3);
653 if (data->dev_autofs_fd < 0)
f2341e0a 654 return log_unit_error_errno(UNIT(a), errno, "Failed to duplicate autofs fd: %m");
deb0a77c
MO
655
656 data->ioctl_fd = open_ioctl_fd(UNIT(a)->manager->dev_autofs_fd, a->where, a->dev_id);
657 if (data->ioctl_fd < 0)
f2341e0a 658 return log_unit_error_errno(UNIT(a), data->ioctl_fd, "Couldn't open autofs ioctl fd: %m");
deb0a77c
MO
659
660 r = asynchronous_job(expire_thread, data);
661 if (r < 0)
f2341e0a 662 return log_unit_error_errno(UNIT(a), r, "Failed to start expire job: %m");
deb0a77c
MO
663
664 data = NULL;
665
666 return automount_start_expire(a);
667}
668
669static int automount_start_expire(Automount *a) {
670 int r;
671 usec_t timeout;
672
673 assert(a);
674
93a3b53b
DM
675 if (a->timeout_idle_usec == 0)
676 return 0;
677
dbf5cc47 678 timeout = now(CLOCK_MONOTONIC) + MAX(a->timeout_idle_usec/3, USEC_PER_SEC);
deb0a77c
MO
679
680 if (a->expire_event_source) {
681 r = sd_event_source_set_time(a->expire_event_source, timeout);
682 if (r < 0)
683 return r;
684
685 return sd_event_source_set_enabled(a->expire_event_source, SD_EVENT_ONESHOT);
686 }
687
7dfbe2e3 688 r = sd_event_add_time(
deb0a77c
MO
689 UNIT(a)->manager->event,
690 &a->expire_event_source,
691 CLOCK_MONOTONIC, timeout, 0,
692 automount_dispatch_expire, a);
7dfbe2e3
TG
693 if (r < 0)
694 return r;
695
696 (void) sd_event_source_set_description(a->expire_event_source, "automount-expire");
697
698 return 0;
deb0a77c
MO
699}
700
8d567588 701static void automount_enter_runnning(Automount *a) {
718db961 702 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3ecaa09b
LP
703 struct stat st;
704 int r;
8d567588
LP
705
706 assert(a);
8d567588 707
ba3e67a7
LP
708 /* We don't take mount requests anymore if we are supposed to
709 * shut down anyway */
31afa0a4 710 if (unit_stop_pending(UNIT(a))) {
f2341e0a 711 log_unit_debug(UNIT(a), "Suppressing automount request since unit stop is scheduled.");
deb0a77c
MO
712 automount_send_ready(a, a->tokens, -EHOSTDOWN);
713 automount_send_ready(a, a->expire_tokens, -EHOSTDOWN);
ba3e67a7
LP
714 return;
715 }
716
d2e54fae 717 mkdir_p_label(a->where, a->directory_mode);
8d567588 718
1cf18f27
LP
719 /* Before we do anything, let's see if somebody is playing games with us? */
720 if (lstat(a->where, &st) < 0) {
f2341e0a 721 log_unit_warning_errno(UNIT(a), errno, "Failed to stat automount point: %m");
8d567588
LP
722 goto fail;
723 }
724
725 if (!S_ISDIR(st.st_mode) || st.st_dev != a->dev_id)
f2341e0a 726 log_unit_info(UNIT(a), "Automount point already active?");
3ecaa09b
LP
727 else {
728 r = manager_add_job(UNIT(a)->manager, JOB_START, UNIT_TRIGGER(UNIT(a)),
729 JOB_REPLACE, true, &error, NULL);
730 if (r < 0) {
f2341e0a 731 log_unit_warning(UNIT(a), "Failed to queue mount startup job: %s", bus_error_message(&error, r));
3ecaa09b
LP
732 goto fail;
733 }
8d567588
LP
734 }
735
deb0a77c
MO
736 r = automount_start_expire(a);
737 if (r < 0)
f2341e0a 738 log_unit_warning_errno(UNIT(a), r, "Failed to start expiration timer, ignoring: %m");
deb0a77c 739
8d567588
LP
740 automount_set_state(a, AUTOMOUNT_RUNNING);
741 return;
742
743fail:
81a5c6d0 744 automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
8d567588
LP
745}
746
747static int automount_start(Unit *u) {
748 Automount *a = AUTOMOUNT(u);
749
750 assert(a);
74ac3cbd 751 assert(a->state == AUTOMOUNT_DEAD || a->state == AUTOMOUNT_FAILED);
01f78473 752
e26d6ce5 753 if (path_is_mount_point(a->where, 0) > 0) {
f2341e0a 754 log_unit_error(u, "Path %s is already a mount point, refusing start.", a->where);
8d567588
LP
755 return -EEXIST;
756 }
757
3ecaa09b 758 if (UNIT_TRIGGER(u)->load_state != UNIT_LOADED)
01f78473 759 return -ENOENT;
8d567588 760
81a5c6d0 761 a->result = AUTOMOUNT_SUCCESS;
8d567588 762 automount_enter_waiting(a);
82a2b6bb 763 return 1;
8d567588
LP
764}
765
766static int automount_stop(Unit *u) {
767 Automount *a = AUTOMOUNT(u);
768
769 assert(a);
8d567588
LP
770 assert(a->state == AUTOMOUNT_WAITING || a->state == AUTOMOUNT_RUNNING);
771
81a5c6d0 772 automount_enter_dead(a, AUTOMOUNT_SUCCESS);
82a2b6bb 773 return 1;
8d567588
LP
774}
775
a16e1123
LP
776static int automount_serialize(Unit *u, FILE *f, FDSet *fds) {
777 Automount *a = AUTOMOUNT(u);
778 void *p;
779 Iterator i;
780
781 assert(a);
782 assert(f);
783 assert(fds);
784
785 unit_serialize_item(u, f, "state", automount_state_to_string(a->state));
81a5c6d0 786 unit_serialize_item(u, f, "result", automount_result_to_string(a->result));
a16e1123
LP
787 unit_serialize_item_format(u, f, "dev-id", "%u", (unsigned) a->dev_id);
788
789 SET_FOREACH(p, a->tokens, i)
790 unit_serialize_item_format(u, f, "token", "%u", PTR_TO_UINT(p));
deb0a77c
MO
791 SET_FOREACH(p, a->expire_tokens, i)
792 unit_serialize_item_format(u, f, "expire-token", "%u", PTR_TO_UINT(p));
a16e1123
LP
793
794 if (a->pipe_fd >= 0) {
795 int copy;
796
0b2665c3
LP
797 copy = fdset_put_dup(fds, a->pipe_fd);
798 if (copy < 0)
a16e1123
LP
799 return copy;
800
801 unit_serialize_item_format(u, f, "pipe-fd", "%i", copy);
802 }
803
804 return 0;
805}
806
807static int automount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
808 Automount *a = AUTOMOUNT(u);
809 int r;
810
811 assert(a);
812 assert(fds);
813
814 if (streq(key, "state")) {
815 AutomountState state;
816
0b2665c3
LP
817 state = automount_state_from_string(value);
818 if (state < 0)
f2341e0a 819 log_unit_debug(u, "Failed to parse state value: %s", value);
a16e1123
LP
820 else
821 a->deserialized_state = state;
81a5c6d0
LP
822 } else if (streq(key, "result")) {
823 AutomountResult f;
824
825 f = automount_result_from_string(value);
826 if (f < 0)
f2341e0a 827 log_unit_debug(u, "Failed to parse result value: %s", value);
81a5c6d0
LP
828 else if (f != AUTOMOUNT_SUCCESS)
829 a->result = f;
a16e1123 830
a16e1123
LP
831 } else if (streq(key, "dev-id")) {
832 unsigned d;
833
834 if (safe_atou(value, &d) < 0)
f2341e0a 835 log_unit_debug(u, "Failed to parse dev-id value: %s", value);
a16e1123
LP
836 else
837 a->dev_id = (unsigned) d;
838 } else if (streq(key, "token")) {
839 unsigned token;
840
841 if (safe_atou(value, &token) < 0)
f2341e0a 842 log_unit_debug(u, "Failed to parse token value: %s", value);
a16e1123 843 else {
f34beace
LP
844 r = set_ensure_allocated(&a->tokens, NULL);
845 if (r < 0) {
846 log_oom();
847 return 0;
848 }
a16e1123 849
0b2665c3
LP
850 r = set_put(a->tokens, UINT_TO_PTR(token));
851 if (r < 0)
f2341e0a 852 log_unit_error_errno(u, r, "Failed to add token to set: %m");
a16e1123 853 }
deb0a77c
MO
854 } else if (streq(key, "expire-token")) {
855 unsigned token;
856
857 if (safe_atou(value, &token) < 0)
f2341e0a 858 log_unit_debug(u, "Failed to parse token value: %s", value);
deb0a77c
MO
859 else {
860 r = set_ensure_allocated(&a->expire_tokens, NULL);
861 if (r < 0) {
862 log_oom();
863 return 0;
864 }
865
866 r = set_put(a->expire_tokens, UINT_TO_PTR(token));
867 if (r < 0)
f2341e0a 868 log_unit_error_errno(u, r, "Failed to add expire token to set: %m");
deb0a77c 869 }
a16e1123
LP
870 } else if (streq(key, "pipe-fd")) {
871 int fd;
872
873 if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
f2341e0a 874 log_unit_debug(u, "Failed to parse pipe-fd value: %s", value);
a16e1123 875 else {
03e334a1 876 safe_close(a->pipe_fd);
a16e1123
LP
877 a->pipe_fd = fdset_remove(fds, fd);
878 }
879 } else
f2341e0a 880 log_unit_debug(u, "Unknown serialization key: %s", key);
a16e1123
LP
881
882 return 0;
883}
884
87f0e418 885static UnitActiveState automount_active_state(Unit *u) {
a16e1123 886 assert(u);
87f0e418 887
e537352b 888 return state_translation_table[AUTOMOUNT(u)->state];
5cb5a6ff
LP
889}
890
10a94420
LP
891static const char *automount_sub_state_to_string(Unit *u) {
892 assert(u);
893
a16e1123 894 return automount_state_to_string(AUTOMOUNT(u)->state);
10a94420
LP
895}
896
701cc384 897static bool automount_check_gc(Unit *u) {
3ecaa09b 898 assert(u);
701cc384 899
3ecaa09b 900 if (!UNIT_TRIGGER(u))
7573916f
LP
901 return false;
902
3ecaa09b 903 return UNIT_VTABLE(UNIT_TRIGGER(u))->check_gc(UNIT_TRIGGER(u));
701cc384
LP
904}
905
718db961 906static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata) {
deb0a77c 907 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
8d567588 908 union autofs_v5_packet_union packet;
718db961 909 Automount *a = AUTOMOUNT(userdata);
5f8ae398 910 struct stat st;
8d567588
LP
911 int r;
912
8d567588
LP
913 assert(a);
914 assert(fd == a->pipe_fd);
915
916 if (events != EPOLLIN) {
f2341e0a 917 log_unit_error(UNIT(a), "Got invalid poll event %"PRIu32" on pipe (fd=%d)", events, fd);
8d567588
LP
918 goto fail;
919 }
920
a6dcc7e5
ZJS
921 r = loop_read_exact(a->pipe_fd, &packet, sizeof(packet), true);
922 if (r < 0) {
f2341e0a 923 log_unit_error_errno(UNIT(a), r, "Invalid read from pipe: %m");
8d567588
LP
924 goto fail;
925 }
926
927 switch (packet.hdr.type) {
928
929 case autofs_ptype_missing_direct:
941a4041
LP
930
931 if (packet.v5_packet.pid > 0) {
e42e801b 932 _cleanup_free_ char *p = NULL;
941a4041 933
87d2c1ff 934 get_process_comm(packet.v5_packet.pid, &p);
f2341e0a 935 log_unit_info(UNIT(a), "Got automount request for %s, triggered by %"PRIu32" (%s)", a->where, packet.v5_packet.pid, strna(p));
941a4041 936 } else
f2341e0a 937 log_unit_debug(UNIT(a), "Got direct mount request on %s", a->where);
8d567588 938
d5099efc 939 r = set_ensure_allocated(&a->tokens, NULL);
0b2665c3 940 if (r < 0) {
f2341e0a 941 log_unit_error(UNIT(a), "Failed to allocate token set.");
0b2665c3
LP
942 goto fail;
943 }
a16e1123 944
0b2665c3
LP
945 r = set_put(a->tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token));
946 if (r < 0) {
f2341e0a 947 log_unit_error_errno(UNIT(a), r, "Failed to remember token: %m");
8d567588
LP
948 goto fail;
949 }
950
951 automount_enter_runnning(a);
952 break;
953
deb0a77c 954 case autofs_ptype_expire_direct:
f2341e0a 955 log_unit_debug(UNIT(a), "Got direct umount request on %s", a->where);
deb0a77c
MO
956
957 (void) sd_event_source_set_enabled(a->expire_event_source, SD_EVENT_OFF);
958
959 r = set_ensure_allocated(&a->expire_tokens, NULL);
960 if (r < 0) {
f2341e0a 961 log_unit_error(UNIT(a), "Failed to allocate token set.");
deb0a77c
MO
962 goto fail;
963 }
964
965 r = set_put(a->expire_tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token));
966 if (r < 0) {
f2341e0a 967 log_unit_error_errno(UNIT(a), r, "Failed to remember token: %m");
deb0a77c
MO
968 goto fail;
969 }
5f8ae398
MO
970
971 /* Before we do anything, let's see if somebody is playing games with us? */
972 if (lstat(a->where, &st) < 0) {
973 log_unit_warning_errno(UNIT(a), errno, "Failed to stat automount point: %m");
974 goto fail;
975 }
976
977 if (!S_ISDIR(st.st_mode) || st.st_dev == a->dev_id) {
978 log_unit_info(UNIT(a), "Automount point already unmounted?");
979 automount_send_ready(a, a->expire_tokens, 0);
980 break;
981 }
982
deb0a77c
MO
983 r = manager_add_job(UNIT(a)->manager, JOB_STOP, UNIT_TRIGGER(UNIT(a)), JOB_REPLACE, true, &error, NULL);
984 if (r < 0) {
f2341e0a 985 log_unit_warning(UNIT(a), "Failed to queue umount startup job: %s", bus_error_message(&error, r));
deb0a77c
MO
986 goto fail;
987 }
988 break;
989
8d567588 990 default:
f2341e0a 991 log_unit_error(UNIT(a), "Received unknown automount request %i", packet.hdr.type);
8d567588
LP
992 break;
993 }
994
718db961 995 return 0;
8d567588
LP
996
997fail:
81a5c6d0 998 automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
718db961 999 return 0;
8d567588
LP
1000}
1001
1002static void automount_shutdown(Manager *m) {
1003 assert(m);
1004
03e334a1 1005 m->dev_autofs_fd = safe_close(m->dev_autofs_fd);
8d567588
LP
1006}
1007
74ac3cbd 1008static void automount_reset_failed(Unit *u) {
5632e374
LP
1009 Automount *a = AUTOMOUNT(u);
1010
1011 assert(a);
1012
74ac3cbd 1013 if (a->state == AUTOMOUNT_FAILED)
5632e374
LP
1014 automount_set_state(a, AUTOMOUNT_DEAD);
1015
81a5c6d0 1016 a->result = AUTOMOUNT_SUCCESS;
5632e374
LP
1017}
1018
1c2e9646 1019static bool automount_supported(void) {
0faacd47
LP
1020 static int supported = -1;
1021
0faacd47
LP
1022 if (supported < 0)
1023 supported = access("/dev/autofs", F_OK) >= 0;
1024
1025 return supported;
1026}
1027
a16e1123
LP
1028static const char* const automount_state_table[_AUTOMOUNT_STATE_MAX] = {
1029 [AUTOMOUNT_DEAD] = "dead",
1030 [AUTOMOUNT_WAITING] = "waiting",
1031 [AUTOMOUNT_RUNNING] = "running",
74ac3cbd 1032 [AUTOMOUNT_FAILED] = "failed"
a16e1123
LP
1033};
1034
1035DEFINE_STRING_TABLE_LOOKUP(automount_state, AutomountState);
1036
81a5c6d0
LP
1037static const char* const automount_result_table[_AUTOMOUNT_RESULT_MAX] = {
1038 [AUTOMOUNT_SUCCESS] = "success",
1039 [AUTOMOUNT_FAILURE_RESOURCES] = "resources"
1040};
1041
1042DEFINE_STRING_TABLE_LOOKUP(automount_result, AutomountResult);
1043
87f0e418 1044const UnitVTable automount_vtable = {
7d17cfbc 1045 .object_size = sizeof(Automount),
718db961 1046
f975e971
LP
1047 .sections =
1048 "Unit\0"
1049 "Automount\0"
1050 "Install\0",
5cb5a6ff 1051
e537352b 1052 .no_alias = true,
8d567588 1053 .no_instances = true,
e537352b 1054
034c6ed7 1055 .init = automount_init,
e537352b 1056 .load = automount_load,
034c6ed7 1057 .done = automount_done,
5cb5a6ff 1058
a16e1123
LP
1059 .coldplug = automount_coldplug,
1060
034c6ed7 1061 .dump = automount_dump,
5cb5a6ff 1062
8d567588
LP
1063 .start = automount_start,
1064 .stop = automount_stop,
1065
a16e1123
LP
1066 .serialize = automount_serialize,
1067 .deserialize_item = automount_deserialize_item,
1068
10a94420 1069 .active_state = automount_active_state,
8d567588
LP
1070 .sub_state_to_string = automount_sub_state_to_string,
1071
701cc384
LP
1072 .check_gc = automount_check_gc,
1073
74ac3cbd 1074 .reset_failed = automount_reset_failed,
5632e374 1075
c4e2ceae 1076 .bus_interface = "org.freedesktop.systemd1.Automount",
718db961 1077 .bus_vtable = bus_automount_vtable,
4139c1b2 1078
c6918296 1079 .shutdown = automount_shutdown,
0faacd47 1080 .supported = automount_supported,
c6918296
MS
1081
1082 .status_message_formats = {
1083 .finished_start_job = {
1084 [JOB_DONE] = "Set up automount %s.",
1085 [JOB_FAILED] = "Failed to set up automount %s.",
c6918296
MS
1086 },
1087 .finished_stop_job = {
1088 [JOB_DONE] = "Unset automount %s.",
1089 [JOB_FAILED] = "Failed to unset automount %s.",
1090 },
1091 },
5cb5a6ff 1092};