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