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