1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010 Lennart Poettering
11 #include <linux/auto_dev-ioctl.h>
12 #include <linux/auto_fs4.h>
13 #include <sys/epoll.h>
14 #include <sys/mount.h>
18 #include "alloc-util.h"
20 #include "automount.h"
21 #include "bus-error.h"
23 #include "dbus-automount.h"
25 #include "format-util.h"
29 #include "mount-util.h"
31 #include "parse-util.h"
32 #include "path-util.h"
33 #include "process-util.h"
35 #include "stdio-util.h"
36 #include "string-table.h"
37 #include "string-util.h"
38 #include "unit-name.h"
41 static const UnitActiveState state_translation_table
[_AUTOMOUNT_STATE_MAX
] = {
42 [AUTOMOUNT_DEAD
] = UNIT_INACTIVE
,
43 [AUTOMOUNT_WAITING
] = UNIT_ACTIVE
,
44 [AUTOMOUNT_RUNNING
] = UNIT_ACTIVE
,
45 [AUTOMOUNT_FAILED
] = UNIT_FAILED
53 static inline void expire_data_free(struct expire_data
*data
) {
57 safe_close(data
->dev_autofs_fd
);
58 safe_close(data
->ioctl_fd
);
62 DEFINE_TRIVIAL_CLEANUP_FUNC(struct expire_data
*, expire_data_free
);
64 static int open_dev_autofs(Manager
*m
);
65 static int automount_dispatch_io(sd_event_source
*s
, int fd
, uint32_t events
, void *userdata
);
66 static int automount_start_expire(Automount
*a
);
67 static void automount_stop_expire(Automount
*a
);
68 static int automount_send_ready(Automount
*a
, Set
*tokens
, int status
);
70 static void automount_init(Unit
*u
) {
71 Automount
*a
= AUTOMOUNT(u
);
74 assert(u
->load_state
== UNIT_STUB
);
77 a
->directory_mode
= 0755;
78 UNIT(a
)->ignore_on_isolate
= true;
81 static void unmount_autofs(Automount
*a
) {
89 a
->pipe_event_source
= sd_event_source_unref(a
->pipe_event_source
);
90 a
->pipe_fd
= safe_close(a
->pipe_fd
);
92 /* If we reload/reexecute things we keep the mount point around */
93 if (!IN_SET(UNIT(a
)->manager
->exit_code
, MANAGER_RELOAD
, MANAGER_REEXECUTE
)) {
95 automount_send_ready(a
, a
->tokens
, -EHOSTDOWN
);
96 automount_send_ready(a
, a
->expire_tokens
, -EHOSTDOWN
);
99 r
= repeat_unmount(a
->where
, MNT_DETACH
);
101 log_error_errno(r
, "Failed to unmount: %m");
106 static void automount_done(Unit
*u
) {
107 Automount
*a
= AUTOMOUNT(u
);
113 a
->where
= mfree(a
->where
);
115 a
->tokens
= set_free(a
->tokens
);
116 a
->expire_tokens
= set_free(a
->expire_tokens
);
118 a
->expire_event_source
= sd_event_source_unref(a
->expire_event_source
);
121 static int automount_add_trigger_dependencies(Automount
*a
) {
127 r
= unit_load_related_unit(UNIT(a
), ".mount", &x
);
131 return unit_add_two_dependencies(UNIT(a
), UNIT_BEFORE
, UNIT_TRIGGERS
, x
, true, UNIT_DEPENDENCY_IMPLICIT
);
134 static int automount_add_mount_dependencies(Automount
*a
) {
135 _cleanup_free_
char *parent
= NULL
;
139 parent
= dirname_malloc(a
->where
);
143 return unit_require_mounts_for(UNIT(a
), parent
, UNIT_DEPENDENCY_IMPLICIT
);
146 static int automount_add_default_dependencies(Automount
*a
) {
151 if (!UNIT(a
)->default_dependencies
)
154 if (!MANAGER_IS_SYSTEM(UNIT(a
)->manager
))
157 r
= unit_add_two_dependencies_by_name(UNIT(a
), UNIT_BEFORE
, UNIT_CONFLICTS
, SPECIAL_UMOUNT_TARGET
, NULL
, true, UNIT_DEPENDENCY_DEFAULT
);
164 static int automount_verify(Automount
*a
) {
165 _cleanup_free_
char *e
= NULL
;
170 if (UNIT(a
)->load_state
!= UNIT_LOADED
)
173 if (path_equal(a
->where
, "/")) {
174 log_unit_error(UNIT(a
), "Cannot have an automount unit for the root directory. Refusing.");
178 r
= unit_name_from_path(a
->where
, ".automount", &e
);
180 return log_unit_error(UNIT(a
), "Failed to generate unit name from path: %m");
182 if (!unit_has_name(UNIT(a
), e
)) {
183 log_unit_error(UNIT(a
), "Where= setting doesn't match unit name. Refusing.");
190 static int automount_set_where(Automount
*a
) {
198 r
= unit_name_to_path(UNIT(a
)->id
, &a
->where
);
202 path_kill_slashes(a
->where
);
206 static int automount_load(Unit
*u
) {
207 Automount
*a
= AUTOMOUNT(u
);
211 assert(u
->load_state
== UNIT_STUB
);
213 /* Load a .automount file */
214 r
= unit_load_fragment_and_dropin(u
);
218 if (u
->load_state
== UNIT_LOADED
) {
219 r
= automount_set_where(a
);
223 r
= automount_add_trigger_dependencies(a
);
227 r
= automount_add_mount_dependencies(a
);
231 r
= automount_add_default_dependencies(a
);
236 return automount_verify(a
);
239 static void automount_set_state(Automount
*a
, AutomountState state
) {
240 AutomountState old_state
;
243 old_state
= a
->state
;
246 if (state
!= AUTOMOUNT_RUNNING
)
247 automount_stop_expire(a
);
249 if (!IN_SET(state
, AUTOMOUNT_WAITING
, AUTOMOUNT_RUNNING
))
252 if (state
!= old_state
)
253 log_unit_debug(UNIT(a
), "Changed %s -> %s", automount_state_to_string(old_state
), automount_state_to_string(state
));
255 unit_notify(UNIT(a
), state_translation_table
[old_state
], state_translation_table
[state
], true);
258 static int automount_coldplug(Unit
*u
) {
259 Automount
*a
= AUTOMOUNT(u
);
263 assert(a
->state
== AUTOMOUNT_DEAD
);
265 if (a
->deserialized_state
== a
->state
)
268 if (IN_SET(a
->deserialized_state
, AUTOMOUNT_WAITING
, AUTOMOUNT_RUNNING
)) {
270 r
= automount_set_where(a
);
274 r
= open_dev_autofs(u
->manager
);
278 assert(a
->pipe_fd
>= 0);
280 r
= sd_event_add_io(u
->manager
->event
, &a
->pipe_event_source
, a
->pipe_fd
, EPOLLIN
, automount_dispatch_io
, u
);
284 (void) sd_event_source_set_description(a
->pipe_event_source
, "automount-io");
285 if (a
->deserialized_state
== AUTOMOUNT_RUNNING
) {
286 r
= automount_start_expire(a
);
288 log_unit_warning_errno(UNIT(a
), r
, "Failed to start expiration timer, ignoring: %m");
291 automount_set_state(a
, a
->deserialized_state
);
297 static void automount_dump(Unit
*u
, FILE *f
, const char *prefix
) {
298 char time_string
[FORMAT_TIMESPAN_MAX
];
299 Automount
*a
= AUTOMOUNT(u
);
304 "%sAutomount State: %s\n"
307 "%sDirectoryMode: %04o\n"
308 "%sTimeoutIdleUSec: %s\n",
309 prefix
, automount_state_to_string(a
->state
),
310 prefix
, automount_result_to_string(a
->result
),
312 prefix
, a
->directory_mode
,
313 prefix
, format_timespan(time_string
, FORMAT_TIMESPAN_MAX
, a
->timeout_idle_usec
, USEC_PER_SEC
));
316 static void automount_enter_dead(Automount
*a
, AutomountResult f
) {
319 if (a
->result
== AUTOMOUNT_SUCCESS
)
322 if (a
->result
!= AUTOMOUNT_SUCCESS
)
323 log_unit_warning(UNIT(a
), "Failed with result '%s'.", automount_result_to_string(a
->result
));
325 automount_set_state(a
, a
->result
!= AUTOMOUNT_SUCCESS
? AUTOMOUNT_FAILED
: AUTOMOUNT_DEAD
);
328 static int open_dev_autofs(Manager
*m
) {
329 struct autofs_dev_ioctl param
;
333 if (m
->dev_autofs_fd
>= 0)
334 return m
->dev_autofs_fd
;
336 (void) label_fix("/dev/autofs", 0);
338 m
->dev_autofs_fd
= open("/dev/autofs", O_CLOEXEC
|O_RDONLY
);
339 if (m
->dev_autofs_fd
< 0)
340 return log_error_errno(errno
, "Failed to open /dev/autofs: %m");
342 init_autofs_dev_ioctl(¶m
);
343 if (ioctl(m
->dev_autofs_fd
, AUTOFS_DEV_IOCTL_VERSION
, ¶m
) < 0) {
344 m
->dev_autofs_fd
= safe_close(m
->dev_autofs_fd
);
348 log_debug("Autofs kernel version %i.%i", param
.ver_major
, param
.ver_minor
);
350 return m
->dev_autofs_fd
;
353 static int open_ioctl_fd(int dev_autofs_fd
, const char *where
, dev_t devid
) {
354 struct autofs_dev_ioctl
*param
;
357 assert(dev_autofs_fd
>= 0);
360 l
= sizeof(struct autofs_dev_ioctl
) + strlen(where
) + 1;
363 init_autofs_dev_ioctl(param
);
366 param
->openmount
.devid
= devid
;
367 strcpy(param
->path
, where
);
369 if (ioctl(dev_autofs_fd
, AUTOFS_DEV_IOCTL_OPENMOUNT
, param
) < 0)
372 if (param
->ioctlfd
< 0)
375 (void) fd_cloexec(param
->ioctlfd
, true);
376 return param
->ioctlfd
;
379 static int autofs_protocol(int dev_autofs_fd
, int ioctl_fd
) {
380 uint32_t major
, minor
;
381 struct autofs_dev_ioctl param
;
383 assert(dev_autofs_fd
>= 0);
384 assert(ioctl_fd
>= 0);
386 init_autofs_dev_ioctl(¶m
);
387 param
.ioctlfd
= ioctl_fd
;
389 if (ioctl(dev_autofs_fd
, AUTOFS_DEV_IOCTL_PROTOVER
, ¶m
) < 0)
392 major
= param
.protover
.version
;
394 init_autofs_dev_ioctl(¶m
);
395 param
.ioctlfd
= ioctl_fd
;
397 if (ioctl(dev_autofs_fd
, AUTOFS_DEV_IOCTL_PROTOSUBVER
, ¶m
) < 0)
400 minor
= param
.protosubver
.sub_version
;
402 log_debug("Autofs protocol version %i.%i", major
, minor
);
406 static int autofs_set_timeout(int dev_autofs_fd
, int ioctl_fd
, usec_t usec
) {
407 struct autofs_dev_ioctl param
;
409 assert(dev_autofs_fd
>= 0);
410 assert(ioctl_fd
>= 0);
412 init_autofs_dev_ioctl(¶m
);
413 param
.ioctlfd
= ioctl_fd
;
415 if (usec
== USEC_INFINITY
)
416 param
.timeout
.timeout
= 0;
418 /* Convert to seconds, rounding up. */
419 param
.timeout
.timeout
= DIV_ROUND_UP(usec
, USEC_PER_SEC
);
421 if (ioctl(dev_autofs_fd
, AUTOFS_DEV_IOCTL_TIMEOUT
, ¶m
) < 0)
427 static int autofs_send_ready(int dev_autofs_fd
, int ioctl_fd
, uint32_t token
, int status
) {
428 struct autofs_dev_ioctl param
;
430 assert(dev_autofs_fd
>= 0);
431 assert(ioctl_fd
>= 0);
433 init_autofs_dev_ioctl(¶m
);
434 param
.ioctlfd
= ioctl_fd
;
437 param
.fail
.token
= token
;
438 param
.fail
.status
= status
;
440 param
.ready
.token
= token
;
442 if (ioctl(dev_autofs_fd
, status
? AUTOFS_DEV_IOCTL_FAIL
: AUTOFS_DEV_IOCTL_READY
, ¶m
) < 0)
448 static int automount_send_ready(Automount
*a
, Set
*tokens
, int status
) {
449 _cleanup_close_
int ioctl_fd
= -1;
456 if (set_isempty(tokens
))
459 ioctl_fd
= open_ioctl_fd(UNIT(a
)->manager
->dev_autofs_fd
, a
->where
, a
->dev_id
);
464 log_unit_debug_errno(UNIT(a
), status
, "Sending failure: %m");
466 log_unit_debug(UNIT(a
), "Sending success.");
470 /* Autofs thankfully does not hand out 0 as a token */
471 while ((token
= PTR_TO_UINT(set_steal_first(tokens
)))) {
476 * if you pass a positive status code here, kernels
477 * prior to 4.12 will freeze! Yay! */
479 k
= autofs_send_ready(UNIT(a
)->manager
->dev_autofs_fd
,
490 static void automount_trigger_notify(Unit
*u
, Unit
*other
) {
491 Automount
*a
= AUTOMOUNT(u
);
497 /* Filter out invocations with bogus state */
498 if (other
->load_state
!= UNIT_LOADED
|| other
->type
!= UNIT_MOUNT
)
501 /* Don't propagate state changes from the mount if we are already down */
502 if (!IN_SET(a
->state
, AUTOMOUNT_WAITING
, AUTOMOUNT_RUNNING
))
505 /* Propagate start limit hit state */
506 if (other
->start_limit_hit
) {
507 automount_enter_dead(a
, AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT
);
511 /* Don't propagate anything if there's still a job queued */
515 /* The mount is successfully established */
516 if (IN_SET(MOUNT(other
)->state
, MOUNT_MOUNTED
, MOUNT_REMOUNTING
)) {
517 (void) automount_send_ready(a
, a
->tokens
, 0);
519 r
= automount_start_expire(a
);
521 log_unit_warning_errno(UNIT(a
), r
, "Failed to start expiration timer, ignoring: %m");
523 automount_set_state(a
, AUTOMOUNT_RUNNING
);
526 if (IN_SET(MOUNT(other
)->state
,
527 MOUNT_MOUNTING
, MOUNT_MOUNTING_DONE
,
528 MOUNT_MOUNTED
, MOUNT_REMOUNTING
,
529 MOUNT_REMOUNTING_SIGTERM
, MOUNT_REMOUNTING_SIGKILL
,
530 MOUNT_UNMOUNTING_SIGTERM
, MOUNT_UNMOUNTING_SIGKILL
,
533 (void) automount_send_ready(a
, a
->expire_tokens
, -ENODEV
);
536 if (MOUNT(other
)->state
== MOUNT_DEAD
)
537 (void) automount_send_ready(a
, a
->expire_tokens
, 0);
539 /* The mount is in some unhappy state now, let's unfreeze any waiting clients */
540 if (IN_SET(MOUNT(other
)->state
,
541 MOUNT_DEAD
, MOUNT_UNMOUNTING
,
542 MOUNT_REMOUNTING_SIGTERM
, MOUNT_REMOUNTING_SIGKILL
,
543 MOUNT_UNMOUNTING_SIGTERM
, MOUNT_UNMOUNTING_SIGKILL
,
546 (void) automount_send_ready(a
, a
->tokens
, -ENODEV
);
548 automount_set_state(a
, AUTOMOUNT_WAITING
);
552 static void automount_enter_waiting(Automount
*a
) {
553 _cleanup_close_
int ioctl_fd
= -1;
554 int p
[2] = { -1, -1 };
555 char name
[STRLEN("systemd-") + DECIMAL_STR_MAX(pid_t
) + 1];
556 char options
[STRLEN("fd=,pgrp=,minproto=5,maxproto=5,direct")
557 + DECIMAL_STR_MAX(int) + DECIMAL_STR_MAX(gid_t
) + 1];
558 bool mounted
= false;
559 int r
, dev_autofs_fd
;
563 assert(a
->pipe_fd
< 0);
566 set_clear(a
->tokens
);
568 r
= unit_fail_if_noncanonical(UNIT(a
), a
->where
);
572 (void) mkdir_p_label(a
->where
, 0555);
574 unit_warn_if_dir_nonempty(UNIT(a
), a
->where
);
576 dev_autofs_fd
= open_dev_autofs(UNIT(a
)->manager
);
577 if (dev_autofs_fd
< 0) {
582 if (pipe2(p
, O_NONBLOCK
|O_CLOEXEC
) < 0) {
587 xsprintf(options
, "fd=%i,pgrp="PID_FMT
",minproto=5,maxproto=5,direct", p
[1], getpgrp());
588 xsprintf(name
, "systemd-"PID_FMT
, getpid_cached());
589 if (mount(name
, a
->where
, "autofs", 0, options
) < 0) {
596 p
[1] = safe_close(p
[1]);
598 if (stat(a
->where
, &st
) < 0) {
603 ioctl_fd
= open_ioctl_fd(dev_autofs_fd
, a
->where
, st
.st_dev
);
609 r
= autofs_protocol(dev_autofs_fd
, ioctl_fd
);
613 r
= autofs_set_timeout(dev_autofs_fd
, ioctl_fd
, a
->timeout_idle_usec
);
617 r
= sd_event_add_io(UNIT(a
)->manager
->event
, &a
->pipe_event_source
, p
[0], EPOLLIN
, automount_dispatch_io
, a
);
621 (void) sd_event_source_set_description(a
->pipe_event_source
, "automount-io");
624 a
->dev_id
= st
.st_dev
;
626 automount_set_state(a
, AUTOMOUNT_WAITING
);
631 log_unit_error_errno(UNIT(a
), r
, "Failed to initialize automounter: %m");
636 r
= repeat_unmount(a
->where
, MNT_DETACH
);
638 log_error_errno(r
, "Failed to unmount, ignoring: %m");
641 automount_enter_dead(a
, AUTOMOUNT_FAILURE_RESOURCES
);
644 static void *expire_thread(void *p
) {
645 struct autofs_dev_ioctl param
;
646 _cleanup_(expire_data_freep
) struct expire_data
*data
= (struct expire_data
*)p
;
649 assert(data
->dev_autofs_fd
>= 0);
650 assert(data
->ioctl_fd
>= 0);
652 init_autofs_dev_ioctl(¶m
);
653 param
.ioctlfd
= data
->ioctl_fd
;
656 r
= ioctl(data
->dev_autofs_fd
, AUTOFS_DEV_IOCTL_EXPIRE
, ¶m
);
660 log_warning_errno(errno
, "Failed to expire automount, ignoring: %m");
665 static int automount_dispatch_expire(sd_event_source
*source
, usec_t usec
, void *userdata
) {
666 Automount
*a
= AUTOMOUNT(userdata
);
667 _cleanup_(expire_data_freep
) struct expire_data
*data
= NULL
;
671 assert(source
== a
->expire_event_source
);
673 data
= new0(struct expire_data
, 1);
679 data
->dev_autofs_fd
= fcntl(UNIT(a
)->manager
->dev_autofs_fd
, F_DUPFD_CLOEXEC
, 3);
680 if (data
->dev_autofs_fd
< 0)
681 return log_unit_error_errno(UNIT(a
), errno
, "Failed to duplicate autofs fd: %m");
683 data
->ioctl_fd
= open_ioctl_fd(UNIT(a
)->manager
->dev_autofs_fd
, a
->where
, a
->dev_id
);
684 if (data
->ioctl_fd
< 0)
685 return log_unit_error_errno(UNIT(a
), data
->ioctl_fd
, "Couldn't open autofs ioctl fd: %m");
687 r
= asynchronous_job(expire_thread
, data
);
689 return log_unit_error_errno(UNIT(a
), r
, "Failed to start expire job: %m");
693 return automount_start_expire(a
);
696 static int automount_start_expire(Automount
*a
) {
702 if (a
->timeout_idle_usec
== 0)
705 timeout
= now(CLOCK_MONOTONIC
) + MAX(a
->timeout_idle_usec
/3, USEC_PER_SEC
);
707 if (a
->expire_event_source
) {
708 r
= sd_event_source_set_time(a
->expire_event_source
, timeout
);
712 return sd_event_source_set_enabled(a
->expire_event_source
, SD_EVENT_ONESHOT
);
715 r
= sd_event_add_time(
716 UNIT(a
)->manager
->event
,
717 &a
->expire_event_source
,
718 CLOCK_MONOTONIC
, timeout
, 0,
719 automount_dispatch_expire
, a
);
723 (void) sd_event_source_set_description(a
->expire_event_source
, "automount-expire");
728 static void automount_stop_expire(Automount
*a
) {
731 if (!a
->expire_event_source
)
734 (void) sd_event_source_set_enabled(a
->expire_event_source
, SD_EVENT_OFF
);
737 static void automount_enter_running(Automount
*a
) {
738 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
745 /* If the user masked our unit in the meantime, fail */
746 if (UNIT(a
)->load_state
!= UNIT_LOADED
) {
747 log_unit_error(UNIT(a
), "Suppressing automount event since unit is no longer loaded.");
751 /* We don't take mount requests anymore if we are supposed to
752 * shut down anyway */
753 if (unit_stop_pending(UNIT(a
))) {
754 log_unit_debug(UNIT(a
), "Suppressing automount request since unit stop is scheduled.");
755 automount_send_ready(a
, a
->tokens
, -EHOSTDOWN
);
756 automount_send_ready(a
, a
->expire_tokens
, -EHOSTDOWN
);
760 mkdir_p_label(a
->where
, a
->directory_mode
);
762 /* Before we do anything, let's see if somebody is playing games with us? */
763 if (lstat(a
->where
, &st
) < 0) {
764 log_unit_warning_errno(UNIT(a
), errno
, "Failed to stat automount point: %m");
768 /* The mount unit may have been explicitly started before we got the
769 * autofs request. Ack it to unblock anything waiting on the mount point. */
770 if (!S_ISDIR(st
.st_mode
) || st
.st_dev
!= a
->dev_id
) {
771 log_unit_info(UNIT(a
), "Automount point already active?");
772 automount_send_ready(a
, a
->tokens
, 0);
776 trigger
= UNIT_TRIGGER(UNIT(a
));
778 log_unit_error(UNIT(a
), "Unit to trigger vanished.");
782 r
= manager_add_job(UNIT(a
)->manager
, JOB_START
, trigger
, JOB_REPLACE
, &error
, NULL
);
784 log_unit_warning(UNIT(a
), "Failed to queue mount startup job: %s", bus_error_message(&error
, r
));
788 automount_set_state(a
, AUTOMOUNT_RUNNING
);
792 automount_enter_dead(a
, AUTOMOUNT_FAILURE_RESOURCES
);
795 static int automount_start(Unit
*u
) {
796 Automount
*a
= AUTOMOUNT(u
);
801 assert(IN_SET(a
->state
, AUTOMOUNT_DEAD
, AUTOMOUNT_FAILED
));
803 if (path_is_mount_point(a
->where
, NULL
, 0) > 0) {
804 log_unit_error(u
, "Path %s is already a mount point, refusing start.", a
->where
);
808 trigger
= UNIT_TRIGGER(u
);
809 if (!trigger
|| trigger
->load_state
!= UNIT_LOADED
) {
810 log_unit_error(u
, "Refusing to start, unit to trigger not loaded.");
814 r
= unit_start_limit_test(u
);
816 automount_enter_dead(a
, AUTOMOUNT_FAILURE_START_LIMIT_HIT
);
820 r
= unit_acquire_invocation_id(u
);
824 a
->result
= AUTOMOUNT_SUCCESS
;
825 automount_enter_waiting(a
);
829 static int automount_stop(Unit
*u
) {
830 Automount
*a
= AUTOMOUNT(u
);
833 assert(IN_SET(a
->state
, AUTOMOUNT_WAITING
, AUTOMOUNT_RUNNING
));
835 automount_enter_dead(a
, AUTOMOUNT_SUCCESS
);
839 static int automount_serialize(Unit
*u
, FILE *f
, FDSet
*fds
) {
840 Automount
*a
= AUTOMOUNT(u
);
849 unit_serialize_item(u
, f
, "state", automount_state_to_string(a
->state
));
850 unit_serialize_item(u
, f
, "result", automount_result_to_string(a
->result
));
851 unit_serialize_item_format(u
, f
, "dev-id", "%u", (unsigned) a
->dev_id
);
853 SET_FOREACH(p
, a
->tokens
, i
)
854 unit_serialize_item_format(u
, f
, "token", "%u", PTR_TO_UINT(p
));
855 SET_FOREACH(p
, a
->expire_tokens
, i
)
856 unit_serialize_item_format(u
, f
, "expire-token", "%u", PTR_TO_UINT(p
));
858 r
= unit_serialize_item_fd(u
, f
, fds
, "pipe-fd", a
->pipe_fd
);
865 static int automount_deserialize_item(Unit
*u
, const char *key
, const char *value
, FDSet
*fds
) {
866 Automount
*a
= AUTOMOUNT(u
);
872 if (streq(key
, "state")) {
873 AutomountState state
;
875 state
= automount_state_from_string(value
);
877 log_unit_debug(u
, "Failed to parse state value: %s", value
);
879 a
->deserialized_state
= state
;
880 } else if (streq(key
, "result")) {
883 f
= automount_result_from_string(value
);
885 log_unit_debug(u
, "Failed to parse result value: %s", value
);
886 else if (f
!= AUTOMOUNT_SUCCESS
)
889 } else if (streq(key
, "dev-id")) {
892 if (safe_atou(value
, &d
) < 0)
893 log_unit_debug(u
, "Failed to parse dev-id value: %s", value
);
895 a
->dev_id
= (unsigned) d
;
896 } else if (streq(key
, "token")) {
899 if (safe_atou(value
, &token
) < 0)
900 log_unit_debug(u
, "Failed to parse token value: %s", value
);
902 r
= set_ensure_allocated(&a
->tokens
, NULL
);
908 r
= set_put(a
->tokens
, UINT_TO_PTR(token
));
910 log_unit_error_errno(u
, r
, "Failed to add token to set: %m");
912 } else if (streq(key
, "expire-token")) {
915 if (safe_atou(value
, &token
) < 0)
916 log_unit_debug(u
, "Failed to parse token value: %s", value
);
918 r
= set_ensure_allocated(&a
->expire_tokens
, NULL
);
924 r
= set_put(a
->expire_tokens
, UINT_TO_PTR(token
));
926 log_unit_error_errno(u
, r
, "Failed to add expire token to set: %m");
928 } else if (streq(key
, "pipe-fd")) {
931 if (safe_atoi(value
, &fd
) < 0 || fd
< 0 || !fdset_contains(fds
, fd
))
932 log_unit_debug(u
, "Failed to parse pipe-fd value: %s", value
);
934 safe_close(a
->pipe_fd
);
935 a
->pipe_fd
= fdset_remove(fds
, fd
);
938 log_unit_debug(u
, "Unknown serialization key: %s", key
);
943 static UnitActiveState
automount_active_state(Unit
*u
) {
946 return state_translation_table
[AUTOMOUNT(u
)->state
];
949 static const char *automount_sub_state_to_string(Unit
*u
) {
952 return automount_state_to_string(AUTOMOUNT(u
)->state
);
955 static bool automount_may_gc(Unit
*u
) {
964 return UNIT_VTABLE(t
)->may_gc(t
);
967 static int automount_dispatch_io(sd_event_source
*s
, int fd
, uint32_t events
, void *userdata
) {
968 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
969 union autofs_v5_packet_union packet
;
970 Automount
*a
= AUTOMOUNT(userdata
);
975 assert(fd
== a
->pipe_fd
);
977 if (events
!= EPOLLIN
) {
978 log_unit_error(UNIT(a
), "Got invalid poll event %"PRIu32
" on pipe (fd=%d)", events
, fd
);
982 r
= loop_read_exact(a
->pipe_fd
, &packet
, sizeof(packet
), true);
984 log_unit_error_errno(UNIT(a
), r
, "Invalid read from pipe: %m");
988 switch (packet
.hdr
.type
) {
990 case autofs_ptype_missing_direct
:
992 if (packet
.v5_packet
.pid
> 0) {
993 _cleanup_free_
char *p
= NULL
;
995 get_process_comm(packet
.v5_packet
.pid
, &p
);
996 log_unit_info(UNIT(a
), "Got automount request for %s, triggered by %"PRIu32
" (%s)", a
->where
, packet
.v5_packet
.pid
, strna(p
));
998 log_unit_debug(UNIT(a
), "Got direct mount request on %s", a
->where
);
1000 r
= set_ensure_allocated(&a
->tokens
, NULL
);
1002 log_unit_error(UNIT(a
), "Failed to allocate token set.");
1006 r
= set_put(a
->tokens
, UINT_TO_PTR(packet
.v5_packet
.wait_queue_token
));
1008 log_unit_error_errno(UNIT(a
), r
, "Failed to remember token: %m");
1012 automount_enter_running(a
);
1015 case autofs_ptype_expire_direct
:
1016 log_unit_debug(UNIT(a
), "Got direct umount request on %s", a
->where
);
1018 automount_stop_expire(a
);
1020 r
= set_ensure_allocated(&a
->expire_tokens
, NULL
);
1022 log_unit_error(UNIT(a
), "Failed to allocate token set.");
1026 r
= set_put(a
->expire_tokens
, UINT_TO_PTR(packet
.v5_packet
.wait_queue_token
));
1028 log_unit_error_errno(UNIT(a
), r
, "Failed to remember token: %m");
1032 trigger
= UNIT_TRIGGER(UNIT(a
));
1034 log_unit_error(UNIT(a
), "Unit to trigger vanished.");
1038 r
= manager_add_job(UNIT(a
)->manager
, JOB_STOP
, trigger
, JOB_REPLACE
, &error
, NULL
);
1040 log_unit_warning(UNIT(a
), "Failed to queue umount startup job: %s", bus_error_message(&error
, r
));
1046 log_unit_error(UNIT(a
), "Received unknown automount request %i", packet
.hdr
.type
);
1053 automount_enter_dead(a
, AUTOMOUNT_FAILURE_RESOURCES
);
1057 static void automount_shutdown(Manager
*m
) {
1060 m
->dev_autofs_fd
= safe_close(m
->dev_autofs_fd
);
1063 static void automount_reset_failed(Unit
*u
) {
1064 Automount
*a
= AUTOMOUNT(u
);
1068 if (a
->state
== AUTOMOUNT_FAILED
)
1069 automount_set_state(a
, AUTOMOUNT_DEAD
);
1071 a
->result
= AUTOMOUNT_SUCCESS
;
1074 static bool automount_supported(void) {
1075 static int supported
= -1;
1078 supported
= access("/dev/autofs", F_OK
) >= 0;
1083 static const char* const automount_result_table
[_AUTOMOUNT_RESULT_MAX
] = {
1084 [AUTOMOUNT_SUCCESS
] = "success",
1085 [AUTOMOUNT_FAILURE_RESOURCES
] = "resources",
1086 [AUTOMOUNT_FAILURE_START_LIMIT_HIT
] = "start-limit-hit",
1087 [AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT
] = "mount-start-limit-hit",
1090 DEFINE_STRING_TABLE_LOOKUP(automount_result
, AutomountResult
);
1092 const UnitVTable automount_vtable
= {
1093 .object_size
= sizeof(Automount
),
1100 .init
= automount_init
,
1101 .load
= automount_load
,
1102 .done
= automount_done
,
1104 .coldplug
= automount_coldplug
,
1106 .dump
= automount_dump
,
1108 .start
= automount_start
,
1109 .stop
= automount_stop
,
1111 .serialize
= automount_serialize
,
1112 .deserialize_item
= automount_deserialize_item
,
1114 .active_state
= automount_active_state
,
1115 .sub_state_to_string
= automount_sub_state_to_string
,
1117 .may_gc
= automount_may_gc
,
1119 .trigger_notify
= automount_trigger_notify
,
1121 .reset_failed
= automount_reset_failed
,
1123 .bus_vtable
= bus_automount_vtable
,
1124 .bus_set_property
= bus_automount_set_property
,
1126 .can_transient
= true,
1128 .shutdown
= automount_shutdown
,
1129 .supported
= automount_supported
,
1131 .status_message_formats
= {
1132 .finished_start_job
= {
1133 [JOB_DONE
] = "Set up automount %s.",
1134 [JOB_FAILED
] = "Failed to set up automount %s.",
1136 .finished_stop_job
= {
1137 [JOB_DONE
] = "Unset automount %s.",
1138 [JOB_FAILED
] = "Failed to unset automount %s.",