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