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