]> git.ipfire.org Git - thirdparty/systemd.git/blame_incremental - src/core/automount.c
adjust for time spent in timedated even without dbus timestamp
[thirdparty/systemd.git] / src / core / automount.c
... / ...
CommitLineData
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
44static const UnitActiveState state_translation_table[_AUTOMOUNT_STATE_MAX] = {
45 [AUTOMOUNT_DEAD] = UNIT_INACTIVE,
46 [AUTOMOUNT_WAITING] = UNIT_ACTIVE,
47 [AUTOMOUNT_RUNNING] = UNIT_ACTIVE,
48 [AUTOMOUNT_FAILED] = UNIT_FAILED
49};
50
51static int open_dev_autofs(Manager *m);
52static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata);
53
54static void automount_init(Unit *u) {
55 Automount *a = AUTOMOUNT(u);
56
57 assert(u);
58 assert(u->load_state == UNIT_STUB);
59
60 a->pipe_fd = -1;
61 a->directory_mode = 0755;
62 UNIT(a)->ignore_on_isolate = true;
63}
64
65static void repeat_unmount(const char *path) {
66 assert(path);
67
68 for (;;) {
69 /* If there are multiple mounts on a mount point, this
70 * removes them all */
71
72 if (umount2(path, MNT_DETACH) >= 0)
73 continue;
74
75 if (errno != EINVAL)
76 log_error_errno(errno, "Failed to unmount: %m");
77
78 break;
79 }
80}
81
82static void unmount_autofs(Automount *a) {
83 assert(a);
84
85 if (a->pipe_fd < 0)
86 return;
87
88 automount_send_ready(a, -EHOSTDOWN);
89
90 a->pipe_event_source = sd_event_source_unref(a->pipe_event_source);
91 a->pipe_fd = safe_close(a->pipe_fd);
92
93 /* If we reload/reexecute things we keep the mount point
94 * around */
95 if (a->where &&
96 (UNIT(a)->manager->exit_code != MANAGER_RELOAD &&
97 UNIT(a)->manager->exit_code != MANAGER_REEXECUTE))
98 repeat_unmount(a->where);
99}
100
101static void automount_done(Unit *u) {
102 Automount *a = AUTOMOUNT(u);
103
104 assert(a);
105
106 unmount_autofs(a);
107
108 free(a->where);
109 a->where = NULL;
110
111 set_free(a->tokens);
112 a->tokens = NULL;
113}
114
115static int automount_add_mount_links(Automount *a) {
116 _cleanup_free_ char *parent = NULL;
117 int r;
118
119 assert(a);
120
121 r = path_get_parent(a->where, &parent);
122 if (r < 0)
123 return r;
124
125 return unit_require_mounts_for(UNIT(a), parent);
126}
127
128static int automount_add_default_dependencies(Automount *a) {
129 int r;
130
131 assert(a);
132
133 if (UNIT(a)->manager->running_as != SYSTEMD_SYSTEM)
134 return 0;
135
136 r = unit_add_two_dependencies_by_name(UNIT(a), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
137 if (r < 0)
138 return r;
139
140 return 0;
141}
142
143static int automount_verify(Automount *a) {
144 bool b;
145 _cleanup_free_ char *e = NULL;
146 assert(a);
147
148 if (UNIT(a)->load_state != UNIT_LOADED)
149 return 0;
150
151 if (path_equal(a->where, "/")) {
152 log_unit_error(UNIT(a)->id, "Cannot have an automount unit for the root directory. Refusing.");
153 return -EINVAL;
154 }
155
156 e = unit_name_from_path(a->where, ".automount");
157 if (!e)
158 return -ENOMEM;
159
160 b = unit_has_name(UNIT(a), e);
161
162 if (!b) {
163 log_unit_error(UNIT(a)->id, "%s's Where setting doesn't match unit name. Refusing.", UNIT(a)->id);
164 return -EINVAL;
165 }
166
167 return 0;
168}
169
170static int automount_load(Unit *u) {
171 Automount *a = AUTOMOUNT(u);
172 int r;
173
174 assert(u);
175 assert(u->load_state == UNIT_STUB);
176
177 /* Load a .automount file */
178 r = unit_load_fragment_and_dropin_optional(u);
179 if (r < 0)
180 return r;
181
182 if (u->load_state == UNIT_LOADED) {
183 Unit *x;
184
185 if (!a->where) {
186 a->where = unit_name_to_path(u->id);
187 if (!a->where)
188 return -ENOMEM;
189 }
190
191 path_kill_slashes(a->where);
192
193 r = unit_load_related_unit(u, ".mount", &x);
194 if (r < 0)
195 return r;
196
197 r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, x, true);
198 if (r < 0)
199 return r;
200
201 r = automount_add_mount_links(a);
202 if (r < 0)
203 return r;
204
205 if (UNIT(a)->default_dependencies) {
206 r = automount_add_default_dependencies(a);
207 if (r < 0)
208 return r;
209 }
210 }
211
212 return automount_verify(a);
213}
214
215static void automount_set_state(Automount *a, AutomountState state) {
216 AutomountState old_state;
217 assert(a);
218
219 old_state = a->state;
220 a->state = state;
221
222 if (state != AUTOMOUNT_WAITING &&
223 state != AUTOMOUNT_RUNNING)
224 unmount_autofs(a);
225
226 if (state != old_state)
227 log_unit_debug(UNIT(a)->id,
228 "%s changed %s -> %s",
229 UNIT(a)->id,
230 automount_state_to_string(old_state),
231 automount_state_to_string(state));
232
233 unit_notify(UNIT(a), state_translation_table[old_state], state_translation_table[state], true);
234}
235
236static int automount_coldplug(Unit *u) {
237 Automount *a = AUTOMOUNT(u);
238 int r;
239
240 assert(a);
241 assert(a->state == AUTOMOUNT_DEAD);
242
243 if (a->deserialized_state != a->state) {
244
245 r = open_dev_autofs(u->manager);
246 if (r < 0)
247 return r;
248
249 if (a->deserialized_state == AUTOMOUNT_WAITING ||
250 a->deserialized_state == AUTOMOUNT_RUNNING) {
251
252 assert(a->pipe_fd >= 0);
253
254 r = sd_event_add_io(u->manager->event, &a->pipe_event_source, a->pipe_fd, EPOLLIN, automount_dispatch_io, u);
255 if (r < 0)
256 return r;
257 }
258
259 automount_set_state(a, a->deserialized_state);
260 }
261
262 return 0;
263}
264
265static void automount_dump(Unit *u, FILE *f, const char *prefix) {
266 Automount *a = AUTOMOUNT(u);
267
268 assert(a);
269
270 fprintf(f,
271 "%sAutomount State: %s\n"
272 "%sResult: %s\n"
273 "%sWhere: %s\n"
274 "%sDirectoryMode: %04o\n",
275 prefix, automount_state_to_string(a->state),
276 prefix, automount_result_to_string(a->result),
277 prefix, a->where,
278 prefix, a->directory_mode);
279}
280
281static void automount_enter_dead(Automount *a, AutomountResult f) {
282 assert(a);
283
284 if (f != AUTOMOUNT_SUCCESS)
285 a->result = f;
286
287 automount_set_state(a, a->result != AUTOMOUNT_SUCCESS ? AUTOMOUNT_FAILED : AUTOMOUNT_DEAD);
288}
289
290static int open_dev_autofs(Manager *m) {
291 struct autofs_dev_ioctl param;
292
293 assert(m);
294
295 if (m->dev_autofs_fd >= 0)
296 return m->dev_autofs_fd;
297
298 label_fix("/dev/autofs", false, false);
299
300 m->dev_autofs_fd = open("/dev/autofs", O_CLOEXEC|O_RDONLY);
301 if (m->dev_autofs_fd < 0)
302 return log_error_errno(errno, "Failed to open /dev/autofs: %m");
303
304 init_autofs_dev_ioctl(&param);
305 if (ioctl(m->dev_autofs_fd, AUTOFS_DEV_IOCTL_VERSION, &param) < 0) {
306 m->dev_autofs_fd = safe_close(m->dev_autofs_fd);
307 return -errno;
308 }
309
310 log_debug("Autofs kernel version %i.%i", param.ver_major, param.ver_minor);
311
312 return m->dev_autofs_fd;
313}
314
315static int open_ioctl_fd(int dev_autofs_fd, const char *where, dev_t devid) {
316 struct autofs_dev_ioctl *param;
317 size_t l;
318
319 assert(dev_autofs_fd >= 0);
320 assert(where);
321
322 l = sizeof(struct autofs_dev_ioctl) + strlen(where) + 1;
323 param = alloca(l);
324
325 init_autofs_dev_ioctl(param);
326 param->size = l;
327 param->ioctlfd = -1;
328 param->openmount.devid = devid;
329 strcpy(param->path, where);
330
331 if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_OPENMOUNT, param) < 0)
332 return -errno;
333
334 if (param->ioctlfd < 0)
335 return -EIO;
336
337 fd_cloexec(param->ioctlfd, true);
338 return param->ioctlfd;
339}
340
341static int autofs_protocol(int dev_autofs_fd, int ioctl_fd) {
342 uint32_t major, minor;
343 struct autofs_dev_ioctl param;
344
345 assert(dev_autofs_fd >= 0);
346 assert(ioctl_fd >= 0);
347
348 init_autofs_dev_ioctl(&param);
349 param.ioctlfd = ioctl_fd;
350
351 if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_PROTOVER, &param) < 0)
352 return -errno;
353
354 major = param.protover.version;
355
356 init_autofs_dev_ioctl(&param);
357 param.ioctlfd = ioctl_fd;
358
359 if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_PROTOSUBVER, &param) < 0)
360 return -errno;
361
362 minor = param.protosubver.sub_version;
363
364 log_debug("Autofs protocol version %i.%i", major, minor);
365 return 0;
366}
367
368static int autofs_set_timeout(int dev_autofs_fd, int ioctl_fd, time_t sec) {
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 param.timeout.timeout = sec;
377
378 if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_TIMEOUT, &param) < 0)
379 return -errno;
380
381 return 0;
382}
383
384static int autofs_send_ready(int dev_autofs_fd, int ioctl_fd, uint32_t token, int status) {
385 struct autofs_dev_ioctl param;
386
387 assert(dev_autofs_fd >= 0);
388 assert(ioctl_fd >= 0);
389
390 init_autofs_dev_ioctl(&param);
391 param.ioctlfd = ioctl_fd;
392
393 if (status) {
394 param.fail.token = token;
395 param.fail.status = status;
396 } else
397 param.ready.token = token;
398
399 if (ioctl(dev_autofs_fd, status ? AUTOFS_DEV_IOCTL_FAIL : AUTOFS_DEV_IOCTL_READY, &param) < 0)
400 return -errno;
401
402 return 0;
403}
404
405int automount_send_ready(Automount *a, int status) {
406 _cleanup_close_ int ioctl_fd = -1;
407 unsigned token;
408 int r;
409
410 assert(a);
411 assert(status <= 0);
412
413 if (set_isempty(a->tokens))
414 return 0;
415
416 ioctl_fd = open_ioctl_fd(UNIT(a)->manager->dev_autofs_fd, a->where, a->dev_id);
417 if (ioctl_fd < 0)
418 return ioctl_fd;
419
420 if (status)
421 log_unit_debug_errno(UNIT(a)->id, status, "Sending failure: %m");
422 else
423 log_unit_debug(UNIT(a)->id, "Sending success.");
424
425 r = 0;
426
427 /* Autofs thankfully does not hand out 0 as a token */
428 while ((token = PTR_TO_UINT(set_steal_first(a->tokens)))) {
429 int k;
430
431 /* Autofs fun fact II:
432 *
433 * if you pass a positive status code here, the kernel will
434 * freeze! Yay! */
435
436 k = autofs_send_ready(UNIT(a)->manager->dev_autofs_fd,
437 ioctl_fd,
438 token,
439 status);
440 if (k < 0)
441 r = k;
442 }
443
444 return r;
445}
446
447static void automount_enter_waiting(Automount *a) {
448 _cleanup_close_ int ioctl_fd = -1;
449 int p[2] = { -1, -1 };
450 char name[sizeof("systemd-")-1 + DECIMAL_STR_MAX(pid_t) + 1];
451 char options[sizeof("fd=,pgrp=,minproto=5,maxproto=5,direct")-1
452 + DECIMAL_STR_MAX(int) + DECIMAL_STR_MAX(gid_t) + 1];
453 bool mounted = false;
454 int r, dev_autofs_fd;
455 struct stat st;
456
457 assert(a);
458 assert(a->pipe_fd < 0);
459 assert(a->where);
460
461 if (a->tokens)
462 set_clear(a->tokens);
463
464 dev_autofs_fd = open_dev_autofs(UNIT(a)->manager);
465 if (dev_autofs_fd < 0) {
466 r = dev_autofs_fd;
467 goto fail;
468 }
469
470 /* We knowingly ignore the results of this call */
471 mkdir_p_label(a->where, 0555);
472
473 warn_if_dir_nonempty(a->meta.id, a->where);
474
475 if (pipe2(p, O_NONBLOCK|O_CLOEXEC) < 0) {
476 r = -errno;
477 goto fail;
478 }
479
480 xsprintf(options, "fd=%i,pgrp="PID_FMT",minproto=5,maxproto=5,direct", p[1], getpgrp());
481 xsprintf(name, "systemd-"PID_FMT, getpid());
482 if (mount(name, a->where, "autofs", 0, options) < 0) {
483 r = -errno;
484 goto fail;
485 }
486
487 mounted = true;
488
489 p[1] = safe_close(p[1]);
490
491 if (stat(a->where, &st) < 0) {
492 r = -errno;
493 goto fail;
494 }
495
496 ioctl_fd = open_ioctl_fd(dev_autofs_fd, a->where, st.st_dev);
497 if (ioctl_fd < 0) {
498 r = ioctl_fd;
499 goto fail;
500 }
501
502 r = autofs_protocol(dev_autofs_fd, ioctl_fd);
503 if (r < 0)
504 goto fail;
505
506 r = autofs_set_timeout(dev_autofs_fd, ioctl_fd, 300);
507 if (r < 0)
508 goto fail;
509
510 /* Autofs fun fact:
511 *
512 * Unless we close the ioctl fd here, for some weird reason
513 * the direct mount will not receive events from the
514 * kernel. */
515
516 r = sd_event_add_io(UNIT(a)->manager->event, &a->pipe_event_source, p[0], EPOLLIN, automount_dispatch_io, a);
517 if (r < 0)
518 goto fail;
519
520 a->pipe_fd = p[0];
521 a->dev_id = st.st_dev;
522
523 automount_set_state(a, AUTOMOUNT_WAITING);
524
525 return;
526
527fail:
528 safe_close_pair(p);
529
530 if (mounted)
531 repeat_unmount(a->where);
532
533 log_unit_error(UNIT(a)->id,
534 "Failed to initialize automounter: %s", strerror(-r));
535 automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
536}
537
538static void automount_enter_runnning(Automount *a) {
539 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
540 struct stat st;
541 int r;
542
543 assert(a);
544
545 /* We don't take mount requests anymore if we are supposed to
546 * shut down anyway */
547 if (unit_stop_pending(UNIT(a))) {
548 log_unit_debug(UNIT(a)->id,
549 "Suppressing automount request on %s since unit stop is scheduled.", UNIT(a)->id);
550 automount_send_ready(a, -EHOSTDOWN);
551 return;
552 }
553
554 mkdir_p_label(a->where, a->directory_mode);
555
556 /* Before we do anything, let's see if somebody is playing games with us? */
557 if (lstat(a->where, &st) < 0) {
558 log_unit_warning(UNIT(a)->id,
559 "%s failed to stat automount point: %m", UNIT(a)->id);
560 goto fail;
561 }
562
563 if (!S_ISDIR(st.st_mode) || st.st_dev != a->dev_id)
564 log_unit_info(UNIT(a)->id,
565 "%s's automount point already active?", UNIT(a)->id);
566 else {
567 r = manager_add_job(UNIT(a)->manager, JOB_START, UNIT_TRIGGER(UNIT(a)),
568 JOB_REPLACE, true, &error, NULL);
569 if (r < 0) {
570 log_unit_warning(UNIT(a)->id,
571 "%s failed to queue mount startup job: %s",
572 UNIT(a)->id, bus_error_message(&error, r));
573 goto fail;
574 }
575 }
576
577 automount_set_state(a, AUTOMOUNT_RUNNING);
578 return;
579
580fail:
581 automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
582}
583
584static int automount_start(Unit *u) {
585 Automount *a = AUTOMOUNT(u);
586
587 assert(a);
588 assert(a->state == AUTOMOUNT_DEAD || a->state == AUTOMOUNT_FAILED);
589
590 if (path_is_mount_point(a->where, false)) {
591 log_unit_error(u->id,
592 "Path %s is already a mount point, refusing start for %s",
593 a->where, u->id);
594 return -EEXIST;
595 }
596
597 if (UNIT_TRIGGER(u)->load_state != UNIT_LOADED)
598 return -ENOENT;
599
600 a->result = AUTOMOUNT_SUCCESS;
601 automount_enter_waiting(a);
602 return 1;
603}
604
605static int automount_stop(Unit *u) {
606 Automount *a = AUTOMOUNT(u);
607
608 assert(a);
609 assert(a->state == AUTOMOUNT_WAITING || a->state == AUTOMOUNT_RUNNING);
610
611 automount_enter_dead(a, AUTOMOUNT_SUCCESS);
612 return 1;
613}
614
615static int automount_serialize(Unit *u, FILE *f, FDSet *fds) {
616 Automount *a = AUTOMOUNT(u);
617 void *p;
618 Iterator i;
619
620 assert(a);
621 assert(f);
622 assert(fds);
623
624 unit_serialize_item(u, f, "state", automount_state_to_string(a->state));
625 unit_serialize_item(u, f, "result", automount_result_to_string(a->result));
626 unit_serialize_item_format(u, f, "dev-id", "%u", (unsigned) a->dev_id);
627
628 SET_FOREACH(p, a->tokens, i)
629 unit_serialize_item_format(u, f, "token", "%u", PTR_TO_UINT(p));
630
631 if (a->pipe_fd >= 0) {
632 int copy;
633
634 copy = fdset_put_dup(fds, a->pipe_fd);
635 if (copy < 0)
636 return copy;
637
638 unit_serialize_item_format(u, f, "pipe-fd", "%i", copy);
639 }
640
641 return 0;
642}
643
644static int automount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
645 Automount *a = AUTOMOUNT(u);
646 int r;
647
648 assert(a);
649 assert(fds);
650
651 if (streq(key, "state")) {
652 AutomountState state;
653
654 state = automount_state_from_string(value);
655 if (state < 0)
656 log_unit_debug(u->id, "Failed to parse state value %s", value);
657 else
658 a->deserialized_state = state;
659 } else if (streq(key, "result")) {
660 AutomountResult f;
661
662 f = automount_result_from_string(value);
663 if (f < 0)
664 log_unit_debug(u->id, "Failed to parse result value %s", value);
665 else if (f != AUTOMOUNT_SUCCESS)
666 a->result = f;
667
668 } else if (streq(key, "dev-id")) {
669 unsigned d;
670
671 if (safe_atou(value, &d) < 0)
672 log_unit_debug(u->id, "Failed to parse dev-id value %s", value);
673 else
674 a->dev_id = (unsigned) d;
675 } else if (streq(key, "token")) {
676 unsigned token;
677
678 if (safe_atou(value, &token) < 0)
679 log_unit_debug(u->id, "Failed to parse token value %s", value);
680 else {
681 if (!a->tokens)
682 if (!(a->tokens = set_new(NULL)))
683 return -ENOMEM;
684
685 r = set_put(a->tokens, UINT_TO_PTR(token));
686 if (r < 0)
687 return r;
688 }
689 } else if (streq(key, "pipe-fd")) {
690 int fd;
691
692 if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
693 log_unit_debug(u->id, "Failed to parse pipe-fd value %s", value);
694 else {
695 safe_close(a->pipe_fd);
696 a->pipe_fd = fdset_remove(fds, fd);
697 }
698 } else
699 log_unit_debug(u->id, "Unknown serialization key '%s'", key);
700
701 return 0;
702}
703
704static UnitActiveState automount_active_state(Unit *u) {
705 assert(u);
706
707 return state_translation_table[AUTOMOUNT(u)->state];
708}
709
710static const char *automount_sub_state_to_string(Unit *u) {
711 assert(u);
712
713 return automount_state_to_string(AUTOMOUNT(u)->state);
714}
715
716static bool automount_check_gc(Unit *u) {
717 assert(u);
718
719 if (!UNIT_TRIGGER(u))
720 return false;
721
722 return UNIT_VTABLE(UNIT_TRIGGER(u))->check_gc(UNIT_TRIGGER(u));
723}
724
725static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata) {
726 union autofs_v5_packet_union packet;
727 Automount *a = AUTOMOUNT(userdata);
728 ssize_t l;
729 int r;
730
731 assert(a);
732 assert(fd == a->pipe_fd);
733
734 if (events != EPOLLIN) {
735 log_unit_error(UNIT(a)->id, "Got invalid poll event on pipe.");
736 goto fail;
737 }
738
739 l = loop_read(a->pipe_fd, &packet, sizeof(packet), true);
740 if (l != sizeof(packet)) {
741 if (l < 0)
742 log_unit_error_errno(UNIT(a)->id, l, "Invalid read from pipe: %m");
743 else
744 log_unit_error(UNIT(a)->id, "Invalid read from pipe: short read");
745 goto fail;
746 }
747
748 switch (packet.hdr.type) {
749
750 case autofs_ptype_missing_direct:
751
752 if (packet.v5_packet.pid > 0) {
753 _cleanup_free_ char *p = NULL;
754
755 get_process_comm(packet.v5_packet.pid, &p);
756 log_unit_info(UNIT(a)->id,
757 "Got automount request for %s, triggered by %"PRIu32" (%s)",
758 a->where, packet.v5_packet.pid, strna(p));
759 } else
760 log_unit_debug(UNIT(a)->id, "Got direct mount request on %s", a->where);
761
762 r = set_ensure_allocated(&a->tokens, NULL);
763 if (r < 0) {
764 log_unit_error(UNIT(a)->id, "Failed to allocate token set.");
765 goto fail;
766 }
767
768 r = set_put(a->tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token));
769 if (r < 0) {
770 log_unit_error_errno(UNIT(a)->id, r, "Failed to remember token: %m");
771 goto fail;
772 }
773
774 automount_enter_runnning(a);
775 break;
776
777 default:
778 log_unit_error(UNIT(a)->id, "Received unknown automount request %i", packet.hdr.type);
779 break;
780 }
781
782 return 0;
783
784fail:
785 automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
786 return 0;
787}
788
789static void automount_shutdown(Manager *m) {
790 assert(m);
791
792 m->dev_autofs_fd = safe_close(m->dev_autofs_fd);
793}
794
795static void automount_reset_failed(Unit *u) {
796 Automount *a = AUTOMOUNT(u);
797
798 assert(a);
799
800 if (a->state == AUTOMOUNT_FAILED)
801 automount_set_state(a, AUTOMOUNT_DEAD);
802
803 a->result = AUTOMOUNT_SUCCESS;
804}
805
806static bool automount_supported(Manager *m) {
807 static int supported = -1;
808
809 assert(m);
810
811 if (supported < 0)
812 supported = access("/dev/autofs", F_OK) >= 0;
813
814 return supported;
815}
816
817static const char* const automount_state_table[_AUTOMOUNT_STATE_MAX] = {
818 [AUTOMOUNT_DEAD] = "dead",
819 [AUTOMOUNT_WAITING] = "waiting",
820 [AUTOMOUNT_RUNNING] = "running",
821 [AUTOMOUNT_FAILED] = "failed"
822};
823
824DEFINE_STRING_TABLE_LOOKUP(automount_state, AutomountState);
825
826static const char* const automount_result_table[_AUTOMOUNT_RESULT_MAX] = {
827 [AUTOMOUNT_SUCCESS] = "success",
828 [AUTOMOUNT_FAILURE_RESOURCES] = "resources"
829};
830
831DEFINE_STRING_TABLE_LOOKUP(automount_result, AutomountResult);
832
833const UnitVTable automount_vtable = {
834 .object_size = sizeof(Automount),
835
836 .sections =
837 "Unit\0"
838 "Automount\0"
839 "Install\0",
840
841 .no_alias = true,
842 .no_instances = true,
843
844 .init = automount_init,
845 .load = automount_load,
846 .done = automount_done,
847
848 .coldplug = automount_coldplug,
849
850 .dump = automount_dump,
851
852 .start = automount_start,
853 .stop = automount_stop,
854
855 .serialize = automount_serialize,
856 .deserialize_item = automount_deserialize_item,
857
858 .active_state = automount_active_state,
859 .sub_state_to_string = automount_sub_state_to_string,
860
861 .check_gc = automount_check_gc,
862
863 .reset_failed = automount_reset_failed,
864
865 .bus_interface = "org.freedesktop.systemd1.Automount",
866 .bus_vtable = bus_automount_vtable,
867
868 .shutdown = automount_shutdown,
869 .supported = automount_supported,
870
871 .status_message_formats = {
872 .finished_start_job = {
873 [JOB_DONE] = "Set up automount %s.",
874 [JOB_FAILED] = "Failed to set up automount %s.",
875 [JOB_DEPENDENCY] = "Dependency failed for %s.",
876 },
877 .finished_stop_job = {
878 [JOB_DONE] = "Unset automount %s.",
879 [JOB_FAILED] = "Failed to unset automount %s.",
880 },
881 },
882};