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