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