]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/automount.c
Merge pull request #74 from systemd-mailing-devs/1432753344-31461-1-git-send-email...
[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 #include "async.h"
46
47 static const UnitActiveState state_translation_table[_AUTOMOUNT_STATE_MAX] = {
48 [AUTOMOUNT_DEAD] = UNIT_INACTIVE,
49 [AUTOMOUNT_WAITING] = UNIT_ACTIVE,
50 [AUTOMOUNT_RUNNING] = UNIT_ACTIVE,
51 [AUTOMOUNT_FAILED] = UNIT_FAILED
52 };
53
54 struct expire_data {
55 int dev_autofs_fd;
56 int ioctl_fd;
57 };
58
59 static inline void expire_data_free(struct expire_data *data) {
60 if (!data)
61 return;
62
63 safe_close(data->dev_autofs_fd);
64 safe_close(data->ioctl_fd);
65 free(data);
66 }
67
68 DEFINE_TRIVIAL_CLEANUP_FUNC(struct expire_data*, expire_data_free);
69
70 static int open_dev_autofs(Manager *m);
71 static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata);
72
73 static void automount_init(Unit *u) {
74 Automount *a = AUTOMOUNT(u);
75
76 assert(u);
77 assert(u->load_state == UNIT_STUB);
78
79 a->pipe_fd = -1;
80 a->directory_mode = 0755;
81 UNIT(a)->ignore_on_isolate = true;
82 }
83
84 static void repeat_unmount(const char *path) {
85 assert(path);
86
87 for (;;) {
88 /* If there are multiple mounts on a mount point, this
89 * removes them all */
90
91 if (umount2(path, MNT_DETACH) >= 0)
92 continue;
93
94 if (errno != EINVAL)
95 log_error_errno(errno, "Failed to unmount: %m");
96
97 break;
98 }
99 }
100
101 static int automount_send_ready(Automount *a, Set *tokens, int status);
102
103 static void unmount_autofs(Automount *a) {
104 assert(a);
105
106 if (a->pipe_fd < 0)
107 return;
108
109 automount_send_ready(a, a->tokens, -EHOSTDOWN);
110 automount_send_ready(a, a->expire_tokens, -EHOSTDOWN);
111
112 a->pipe_event_source = sd_event_source_unref(a->pipe_event_source);
113 a->pipe_fd = safe_close(a->pipe_fd);
114
115 /* If we reload/reexecute things we keep the mount point
116 * around */
117 if (a->where &&
118 (UNIT(a)->manager->exit_code != MANAGER_RELOAD &&
119 UNIT(a)->manager->exit_code != MANAGER_REEXECUTE))
120 repeat_unmount(a->where);
121 }
122
123 static void automount_done(Unit *u) {
124 Automount *a = AUTOMOUNT(u);
125
126 assert(a);
127
128 unmount_autofs(a);
129
130 free(a->where);
131 a->where = NULL;
132
133 set_free(a->tokens);
134 a->tokens = NULL;
135 set_free(a->expire_tokens);
136 a->expire_tokens = NULL;
137
138 a->expire_event_source = sd_event_source_unref(a->expire_event_source);
139 }
140
141 static int automount_add_mount_links(Automount *a) {
142 _cleanup_free_ char *parent = NULL;
143 int r;
144
145 assert(a);
146
147 r = path_get_parent(a->where, &parent);
148 if (r < 0)
149 return r;
150
151 return unit_require_mounts_for(UNIT(a), parent);
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 != MANAGER_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 _cleanup_free_ char *e = NULL;
171 int r;
172
173 assert(a);
174
175 if (UNIT(a)->load_state != UNIT_LOADED)
176 return 0;
177
178 if (path_equal(a->where, "/")) {
179 log_unit_error(UNIT(a), "Cannot have an automount unit for the root directory. Refusing.");
180 return -EINVAL;
181 }
182
183 r = unit_name_from_path(a->where, ".automount", &e);
184 if (r < 0)
185 return log_unit_error(UNIT(a), "Failed to generate unit name from path: %m");
186
187 if (!unit_has_name(UNIT(a), e)) {
188 log_unit_error(UNIT(a), "Where= setting doesn't match unit name. Refusing.");
189 return -EINVAL;
190 }
191
192 return 0;
193 }
194
195 static int automount_load(Unit *u) {
196 Automount *a = AUTOMOUNT(u);
197 int r;
198
199 assert(u);
200 assert(u->load_state == UNIT_STUB);
201
202 /* Load a .automount file */
203 r = unit_load_fragment_and_dropin_optional(u);
204 if (r < 0)
205 return r;
206
207 if (u->load_state == UNIT_LOADED) {
208 Unit *x;
209
210 if (!a->where) {
211 r = unit_name_to_path(u->id, &a->where);
212 if (r < 0)
213 return r;
214 }
215
216 path_kill_slashes(a->where);
217
218 r = unit_load_related_unit(u, ".mount", &x);
219 if (r < 0)
220 return r;
221
222 r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, x, true);
223 if (r < 0)
224 return r;
225
226 r = automount_add_mount_links(a);
227 if (r < 0)
228 return r;
229
230 if (UNIT(a)->default_dependencies) {
231 r = automount_add_default_dependencies(a);
232 if (r < 0)
233 return r;
234 }
235 }
236
237 return automount_verify(a);
238 }
239
240 static void automount_set_state(Automount *a, AutomountState state) {
241 AutomountState old_state;
242 assert(a);
243
244 old_state = a->state;
245 a->state = state;
246
247 if (state != AUTOMOUNT_WAITING &&
248 state != AUTOMOUNT_RUNNING)
249 unmount_autofs(a);
250
251 if (state != old_state)
252 log_unit_debug(UNIT(a), "Changed %s -> %s", automount_state_to_string(old_state), 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 r = open_dev_autofs(u->manager);
267 if (r < 0)
268 return r;
269
270 if (a->deserialized_state == AUTOMOUNT_WAITING ||
271 a->deserialized_state == AUTOMOUNT_RUNNING) {
272 assert(a->pipe_fd >= 0);
273
274 r = sd_event_add_io(u->manager->event, &a->pipe_event_source, a->pipe_fd, EPOLLIN, automount_dispatch_io, u);
275 if (r < 0)
276 return r;
277
278 (void) sd_event_source_set_description(a->pipe_event_source, "automount-io");
279 }
280
281 automount_set_state(a, a->deserialized_state);
282 }
283
284 return 0;
285 }
286
287 static void automount_dump(Unit *u, FILE *f, const char *prefix) {
288 char time_string[FORMAT_TIMESPAN_MAX];
289 Automount *a = AUTOMOUNT(u);
290
291 assert(a);
292
293 fprintf(f,
294 "%sAutomount State: %s\n"
295 "%sResult: %s\n"
296 "%sWhere: %s\n"
297 "%sDirectoryMode: %04o\n"
298 "%sTimeoutIdleUSec: %s\n",
299 prefix, automount_state_to_string(a->state),
300 prefix, automount_result_to_string(a->result),
301 prefix, a->where,
302 prefix, a->directory_mode,
303 prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX, a->timeout_idle_usec, USEC_PER_SEC));
304 }
305
306 static void automount_enter_dead(Automount *a, AutomountResult f) {
307 assert(a);
308
309 if (f != AUTOMOUNT_SUCCESS)
310 a->result = f;
311
312 automount_set_state(a, a->result != AUTOMOUNT_SUCCESS ? AUTOMOUNT_FAILED : AUTOMOUNT_DEAD);
313 }
314
315 static int open_dev_autofs(Manager *m) {
316 struct autofs_dev_ioctl param;
317
318 assert(m);
319
320 if (m->dev_autofs_fd >= 0)
321 return m->dev_autofs_fd;
322
323 label_fix("/dev/autofs", false, false);
324
325 m->dev_autofs_fd = open("/dev/autofs", O_CLOEXEC|O_RDONLY);
326 if (m->dev_autofs_fd < 0)
327 return log_error_errno(errno, "Failed to open /dev/autofs: %m");
328
329 init_autofs_dev_ioctl(&param);
330 if (ioctl(m->dev_autofs_fd, AUTOFS_DEV_IOCTL_VERSION, &param) < 0) {
331 m->dev_autofs_fd = safe_close(m->dev_autofs_fd);
332 return -errno;
333 }
334
335 log_debug("Autofs kernel version %i.%i", param.ver_major, param.ver_minor);
336
337 return m->dev_autofs_fd;
338 }
339
340 static int open_ioctl_fd(int dev_autofs_fd, const char *where, dev_t devid) {
341 struct autofs_dev_ioctl *param;
342 size_t l;
343
344 assert(dev_autofs_fd >= 0);
345 assert(where);
346
347 l = sizeof(struct autofs_dev_ioctl) + strlen(where) + 1;
348 param = alloca(l);
349
350 init_autofs_dev_ioctl(param);
351 param->size = l;
352 param->ioctlfd = -1;
353 param->openmount.devid = devid;
354 strcpy(param->path, where);
355
356 if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_OPENMOUNT, param) < 0)
357 return -errno;
358
359 if (param->ioctlfd < 0)
360 return -EIO;
361
362 (void) fd_cloexec(param->ioctlfd, true);
363 return param->ioctlfd;
364 }
365
366 static int autofs_protocol(int dev_autofs_fd, int ioctl_fd) {
367 uint32_t major, minor;
368 struct autofs_dev_ioctl param;
369
370 assert(dev_autofs_fd >= 0);
371 assert(ioctl_fd >= 0);
372
373 init_autofs_dev_ioctl(&param);
374 param.ioctlfd = ioctl_fd;
375
376 if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_PROTOVER, &param) < 0)
377 return -errno;
378
379 major = param.protover.version;
380
381 init_autofs_dev_ioctl(&param);
382 param.ioctlfd = ioctl_fd;
383
384 if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_PROTOSUBVER, &param) < 0)
385 return -errno;
386
387 minor = param.protosubver.sub_version;
388
389 log_debug("Autofs protocol version %i.%i", major, minor);
390 return 0;
391 }
392
393 static int autofs_set_timeout(int dev_autofs_fd, int ioctl_fd, usec_t usec) {
394 struct autofs_dev_ioctl param;
395
396 assert(dev_autofs_fd >= 0);
397 assert(ioctl_fd >= 0);
398
399 init_autofs_dev_ioctl(&param);
400 param.ioctlfd = ioctl_fd;
401
402 /* Convert to seconds, rounding up. */
403 param.timeout.timeout = (usec + USEC_PER_SEC - 1) / USEC_PER_SEC;
404
405 if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_TIMEOUT, &param) < 0)
406 return -errno;
407
408 return 0;
409 }
410
411 static int autofs_send_ready(int dev_autofs_fd, int ioctl_fd, uint32_t token, int status) {
412 struct autofs_dev_ioctl param;
413
414 assert(dev_autofs_fd >= 0);
415 assert(ioctl_fd >= 0);
416
417 init_autofs_dev_ioctl(&param);
418 param.ioctlfd = ioctl_fd;
419
420 if (status) {
421 param.fail.token = token;
422 param.fail.status = status;
423 } else
424 param.ready.token = token;
425
426 if (ioctl(dev_autofs_fd, status ? AUTOFS_DEV_IOCTL_FAIL : AUTOFS_DEV_IOCTL_READY, &param) < 0)
427 return -errno;
428
429 return 0;
430 }
431
432 static int automount_send_ready(Automount *a, Set *tokens, int status) {
433 _cleanup_close_ int ioctl_fd = -1;
434 unsigned token;
435 int r;
436
437 assert(a);
438 assert(status <= 0);
439
440 if (set_isempty(tokens))
441 return 0;
442
443 ioctl_fd = open_ioctl_fd(UNIT(a)->manager->dev_autofs_fd, a->where, a->dev_id);
444 if (ioctl_fd < 0)
445 return ioctl_fd;
446
447 if (status)
448 log_unit_debug_errno(UNIT(a), status, "Sending failure: %m");
449 else
450 log_unit_debug(UNIT(a), "Sending success.");
451
452 r = 0;
453
454 /* Autofs thankfully does not hand out 0 as a token */
455 while ((token = PTR_TO_UINT(set_steal_first(tokens)))) {
456 int k;
457
458 /* Autofs fun fact II:
459 *
460 * if you pass a positive status code here, the kernel will
461 * freeze! Yay! */
462
463 k = autofs_send_ready(UNIT(a)->manager->dev_autofs_fd,
464 ioctl_fd,
465 token,
466 status);
467 if (k < 0)
468 r = k;
469 }
470
471 return r;
472 }
473
474 int automount_update_mount(Automount *a, MountState old_state, MountState state) {
475 assert(a);
476
477 switch (state) {
478 case MOUNT_MOUNTED:
479 case MOUNT_REMOUNTING:
480 automount_send_ready(a, a->tokens, 0);
481 break;
482 case MOUNT_DEAD:
483 case MOUNT_UNMOUNTING:
484 case MOUNT_MOUNTING_SIGTERM:
485 case MOUNT_MOUNTING_SIGKILL:
486 case MOUNT_REMOUNTING_SIGTERM:
487 case MOUNT_REMOUNTING_SIGKILL:
488 case MOUNT_UNMOUNTING_SIGTERM:
489 case MOUNT_UNMOUNTING_SIGKILL:
490 case MOUNT_FAILED:
491 if (old_state != state)
492 automount_send_ready(a, a->tokens, -ENODEV);
493 break;
494 default:
495 break;
496 }
497
498 switch (state) {
499 case MOUNT_DEAD:
500 automount_send_ready(a, a->expire_tokens, 0);
501 break;
502 case MOUNT_MOUNTING:
503 case MOUNT_MOUNTING_DONE:
504 case MOUNT_MOUNTING_SIGTERM:
505 case MOUNT_MOUNTING_SIGKILL:
506 case MOUNT_REMOUNTING_SIGTERM:
507 case MOUNT_REMOUNTING_SIGKILL:
508 case MOUNT_UNMOUNTING_SIGTERM:
509 case MOUNT_UNMOUNTING_SIGKILL:
510 case MOUNT_FAILED:
511 if (old_state != state)
512 automount_send_ready(a, a->expire_tokens, -ENODEV);
513 break;
514 default:
515 break;
516 }
517
518 return 0;
519 }
520
521 static void automount_enter_waiting(Automount *a) {
522 _cleanup_close_ int ioctl_fd = -1;
523 int p[2] = { -1, -1 };
524 char name[sizeof("systemd-")-1 + DECIMAL_STR_MAX(pid_t) + 1];
525 char options[sizeof("fd=,pgrp=,minproto=5,maxproto=5,direct")-1
526 + DECIMAL_STR_MAX(int) + DECIMAL_STR_MAX(gid_t) + 1];
527 bool mounted = false;
528 int r, dev_autofs_fd;
529 struct stat st;
530
531 assert(a);
532 assert(a->pipe_fd < 0);
533 assert(a->where);
534
535 set_clear(a->tokens);
536
537 r = unit_fail_if_symlink(UNIT(a), a->where);
538 if (r < 0)
539 goto fail;
540
541 (void) mkdir_p_label(a->where, 0555);
542
543 unit_warn_if_dir_nonempty(UNIT(a), a->where);
544
545 dev_autofs_fd = open_dev_autofs(UNIT(a)->manager);
546 if (dev_autofs_fd < 0) {
547 r = dev_autofs_fd;
548 goto fail;
549 }
550
551 if (pipe2(p, O_NONBLOCK|O_CLOEXEC) < 0) {
552 r = -errno;
553 goto fail;
554 }
555
556 xsprintf(options, "fd=%i,pgrp="PID_FMT",minproto=5,maxproto=5,direct", p[1], getpgrp());
557 xsprintf(name, "systemd-"PID_FMT, getpid());
558 if (mount(name, a->where, "autofs", 0, options) < 0) {
559 r = -errno;
560 goto fail;
561 }
562
563 mounted = true;
564
565 p[1] = safe_close(p[1]);
566
567 if (stat(a->where, &st) < 0) {
568 r = -errno;
569 goto fail;
570 }
571
572 ioctl_fd = open_ioctl_fd(dev_autofs_fd, a->where, st.st_dev);
573 if (ioctl_fd < 0) {
574 r = ioctl_fd;
575 goto fail;
576 }
577
578 r = autofs_protocol(dev_autofs_fd, ioctl_fd);
579 if (r < 0)
580 goto fail;
581
582 r = autofs_set_timeout(dev_autofs_fd, ioctl_fd, a->timeout_idle_usec);
583 if (r < 0)
584 goto fail;
585
586 /* Autofs fun fact:
587 *
588 * Unless we close the ioctl fd here, for some weird reason
589 * the direct mount will not receive events from the
590 * kernel. */
591
592 r = sd_event_add_io(UNIT(a)->manager->event, &a->pipe_event_source, p[0], EPOLLIN, automount_dispatch_io, a);
593 if (r < 0)
594 goto fail;
595
596 (void) sd_event_source_set_description(a->pipe_event_source, "automount-io");
597
598 a->pipe_fd = p[0];
599 a->dev_id = st.st_dev;
600
601 automount_set_state(a, AUTOMOUNT_WAITING);
602
603 return;
604
605 fail:
606 safe_close_pair(p);
607
608 if (mounted)
609 repeat_unmount(a->where);
610
611 log_unit_error_errno(UNIT(a), r, "Failed to initialize automounter: %m");
612 automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
613 }
614
615 static void *expire_thread(void *p) {
616 struct autofs_dev_ioctl param;
617 _cleanup_(expire_data_freep) struct expire_data *data = (struct expire_data*)p;
618 int r;
619
620 assert(data->dev_autofs_fd >= 0);
621 assert(data->ioctl_fd >= 0);
622
623 init_autofs_dev_ioctl(&param);
624 param.ioctlfd = data->ioctl_fd;
625
626 do {
627 r = ioctl(data->dev_autofs_fd, AUTOFS_DEV_IOCTL_EXPIRE, &param);
628 } while (r >= 0);
629
630 if (errno != EAGAIN)
631 log_warning_errno(errno, "Failed to expire automount, ignoring: %m");
632
633 return NULL;
634 }
635
636 static int automount_start_expire(Automount *a);
637
638 static int automount_dispatch_expire(sd_event_source *source, usec_t usec, void *userdata) {
639 Automount *a = AUTOMOUNT(userdata);
640 _cleanup_(expire_data_freep) struct expire_data *data = NULL;
641 int r;
642
643 assert(a);
644 assert(source == a->expire_event_source);
645
646 data = new0(struct expire_data, 1);
647 if (!data)
648 return log_oom();
649
650 data->ioctl_fd = -1;
651
652 data->dev_autofs_fd = fcntl(UNIT(a)->manager->dev_autofs_fd, F_DUPFD_CLOEXEC, 3);
653 if (data->dev_autofs_fd < 0)
654 return log_unit_error_errno(UNIT(a), errno, "Failed to duplicate autofs fd: %m");
655
656 data->ioctl_fd = open_ioctl_fd(UNIT(a)->manager->dev_autofs_fd, a->where, a->dev_id);
657 if (data->ioctl_fd < 0)
658 return log_unit_error_errno(UNIT(a), data->ioctl_fd, "Couldn't open autofs ioctl fd: %m");
659
660 r = asynchronous_job(expire_thread, data);
661 if (r < 0)
662 return log_unit_error_errno(UNIT(a), r, "Failed to start expire job: %m");
663
664 data = NULL;
665
666 return automount_start_expire(a);
667 }
668
669 static int automount_start_expire(Automount *a) {
670 int r;
671 usec_t timeout;
672
673 assert(a);
674
675 timeout = now(CLOCK_MONOTONIC) + MAX(a->timeout_idle_usec/10, USEC_PER_SEC);
676
677 if (a->expire_event_source) {
678 r = sd_event_source_set_time(a->expire_event_source, timeout);
679 if (r < 0)
680 return r;
681
682 return sd_event_source_set_enabled(a->expire_event_source, SD_EVENT_ONESHOT);
683 }
684
685 r = sd_event_add_time(
686 UNIT(a)->manager->event,
687 &a->expire_event_source,
688 CLOCK_MONOTONIC, timeout, 0,
689 automount_dispatch_expire, a);
690 if (r < 0)
691 return r;
692
693 (void) sd_event_source_set_description(a->expire_event_source, "automount-expire");
694
695 return 0;
696 }
697
698 static void automount_enter_runnning(Automount *a) {
699 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
700 struct stat st;
701 int r;
702
703 assert(a);
704
705 /* We don't take mount requests anymore if we are supposed to
706 * shut down anyway */
707 if (unit_stop_pending(UNIT(a))) {
708 log_unit_debug(UNIT(a), "Suppressing automount request since unit stop is scheduled.");
709 automount_send_ready(a, a->tokens, -EHOSTDOWN);
710 automount_send_ready(a, a->expire_tokens, -EHOSTDOWN);
711 return;
712 }
713
714 mkdir_p_label(a->where, a->directory_mode);
715
716 /* Before we do anything, let's see if somebody is playing games with us? */
717 if (lstat(a->where, &st) < 0) {
718 log_unit_warning_errno(UNIT(a), errno, "Failed to stat automount point: %m");
719 goto fail;
720 }
721
722 if (!S_ISDIR(st.st_mode) || st.st_dev != a->dev_id)
723 log_unit_info(UNIT(a), "Automount point already active?");
724 else {
725 r = manager_add_job(UNIT(a)->manager, JOB_START, UNIT_TRIGGER(UNIT(a)),
726 JOB_REPLACE, true, &error, NULL);
727 if (r < 0) {
728 log_unit_warning(UNIT(a), "Failed to queue mount startup job: %s", bus_error_message(&error, r));
729 goto fail;
730 }
731 }
732
733 r = automount_start_expire(a);
734 if (r < 0)
735 log_unit_warning_errno(UNIT(a), r, "Failed to start expiration timer, ignoring: %m");
736
737 automount_set_state(a, AUTOMOUNT_RUNNING);
738 return;
739
740 fail:
741 automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
742 }
743
744 static int automount_start(Unit *u) {
745 Automount *a = AUTOMOUNT(u);
746
747 assert(a);
748 assert(a->state == AUTOMOUNT_DEAD || a->state == AUTOMOUNT_FAILED);
749
750 if (path_is_mount_point(a->where, 0) > 0) {
751 log_unit_error(u, "Path %s is already a mount point, refusing start.", a->where);
752 return -EEXIST;
753 }
754
755 if (UNIT_TRIGGER(u)->load_state != UNIT_LOADED)
756 return -ENOENT;
757
758 a->result = AUTOMOUNT_SUCCESS;
759 automount_enter_waiting(a);
760 return 1;
761 }
762
763 static int automount_stop(Unit *u) {
764 Automount *a = AUTOMOUNT(u);
765
766 assert(a);
767 assert(a->state == AUTOMOUNT_WAITING || a->state == AUTOMOUNT_RUNNING);
768
769 automount_enter_dead(a, AUTOMOUNT_SUCCESS);
770 return 1;
771 }
772
773 static int automount_serialize(Unit *u, FILE *f, FDSet *fds) {
774 Automount *a = AUTOMOUNT(u);
775 void *p;
776 Iterator i;
777
778 assert(a);
779 assert(f);
780 assert(fds);
781
782 unit_serialize_item(u, f, "state", automount_state_to_string(a->state));
783 unit_serialize_item(u, f, "result", automount_result_to_string(a->result));
784 unit_serialize_item_format(u, f, "dev-id", "%u", (unsigned) a->dev_id);
785
786 SET_FOREACH(p, a->tokens, i)
787 unit_serialize_item_format(u, f, "token", "%u", PTR_TO_UINT(p));
788 SET_FOREACH(p, a->expire_tokens, i)
789 unit_serialize_item_format(u, f, "expire-token", "%u", PTR_TO_UINT(p));
790
791 if (a->pipe_fd >= 0) {
792 int copy;
793
794 copy = fdset_put_dup(fds, a->pipe_fd);
795 if (copy < 0)
796 return copy;
797
798 unit_serialize_item_format(u, f, "pipe-fd", "%i", copy);
799 }
800
801 return 0;
802 }
803
804 static int automount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
805 Automount *a = AUTOMOUNT(u);
806 int r;
807
808 assert(a);
809 assert(fds);
810
811 if (streq(key, "state")) {
812 AutomountState state;
813
814 state = automount_state_from_string(value);
815 if (state < 0)
816 log_unit_debug(u, "Failed to parse state value: %s", value);
817 else
818 a->deserialized_state = state;
819 } else if (streq(key, "result")) {
820 AutomountResult f;
821
822 f = automount_result_from_string(value);
823 if (f < 0)
824 log_unit_debug(u, "Failed to parse result value: %s", value);
825 else if (f != AUTOMOUNT_SUCCESS)
826 a->result = f;
827
828 } else if (streq(key, "dev-id")) {
829 unsigned d;
830
831 if (safe_atou(value, &d) < 0)
832 log_unit_debug(u, "Failed to parse dev-id value: %s", value);
833 else
834 a->dev_id = (unsigned) d;
835 } else if (streq(key, "token")) {
836 unsigned token;
837
838 if (safe_atou(value, &token) < 0)
839 log_unit_debug(u, "Failed to parse token value: %s", value);
840 else {
841 r = set_ensure_allocated(&a->tokens, NULL);
842 if (r < 0) {
843 log_oom();
844 return 0;
845 }
846
847 r = set_put(a->tokens, UINT_TO_PTR(token));
848 if (r < 0)
849 log_unit_error_errno(u, r, "Failed to add token to set: %m");
850 }
851 } else if (streq(key, "expire-token")) {
852 unsigned token;
853
854 if (safe_atou(value, &token) < 0)
855 log_unit_debug(u, "Failed to parse token value: %s", value);
856 else {
857 r = set_ensure_allocated(&a->expire_tokens, NULL);
858 if (r < 0) {
859 log_oom();
860 return 0;
861 }
862
863 r = set_put(a->expire_tokens, UINT_TO_PTR(token));
864 if (r < 0)
865 log_unit_error_errno(u, r, "Failed to add expire token to set: %m");
866 }
867 } else if (streq(key, "pipe-fd")) {
868 int fd;
869
870 if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
871 log_unit_debug(u, "Failed to parse pipe-fd value: %s", value);
872 else {
873 safe_close(a->pipe_fd);
874 a->pipe_fd = fdset_remove(fds, fd);
875 }
876 } else
877 log_unit_debug(u, "Unknown serialization key: %s", key);
878
879 return 0;
880 }
881
882 static UnitActiveState automount_active_state(Unit *u) {
883 assert(u);
884
885 return state_translation_table[AUTOMOUNT(u)->state];
886 }
887
888 static const char *automount_sub_state_to_string(Unit *u) {
889 assert(u);
890
891 return automount_state_to_string(AUTOMOUNT(u)->state);
892 }
893
894 static bool automount_check_gc(Unit *u) {
895 assert(u);
896
897 if (!UNIT_TRIGGER(u))
898 return false;
899
900 return UNIT_VTABLE(UNIT_TRIGGER(u))->check_gc(UNIT_TRIGGER(u));
901 }
902
903 static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata) {
904 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
905 union autofs_v5_packet_union packet;
906 Automount *a = AUTOMOUNT(userdata);
907 int r;
908
909 assert(a);
910 assert(fd == a->pipe_fd);
911
912 if (events != EPOLLIN) {
913 log_unit_error(UNIT(a), "Got invalid poll event %"PRIu32" on pipe (fd=%d)", events, fd);
914 goto fail;
915 }
916
917 r = loop_read_exact(a->pipe_fd, &packet, sizeof(packet), true);
918 if (r < 0) {
919 log_unit_error_errno(UNIT(a), r, "Invalid read from pipe: %m");
920 goto fail;
921 }
922
923 switch (packet.hdr.type) {
924
925 case autofs_ptype_missing_direct:
926
927 if (packet.v5_packet.pid > 0) {
928 _cleanup_free_ char *p = NULL;
929
930 get_process_comm(packet.v5_packet.pid, &p);
931 log_unit_info(UNIT(a), "Got automount request for %s, triggered by %"PRIu32" (%s)", a->where, packet.v5_packet.pid, strna(p));
932 } else
933 log_unit_debug(UNIT(a), "Got direct mount request on %s", a->where);
934
935 r = set_ensure_allocated(&a->tokens, NULL);
936 if (r < 0) {
937 log_unit_error(UNIT(a), "Failed to allocate token set.");
938 goto fail;
939 }
940
941 r = set_put(a->tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token));
942 if (r < 0) {
943 log_unit_error_errno(UNIT(a), r, "Failed to remember token: %m");
944 goto fail;
945 }
946
947 automount_enter_runnning(a);
948 break;
949
950 case autofs_ptype_expire_direct:
951 log_unit_debug(UNIT(a), "Got direct umount request on %s", a->where);
952
953 (void) sd_event_source_set_enabled(a->expire_event_source, SD_EVENT_OFF);
954
955 r = set_ensure_allocated(&a->expire_tokens, NULL);
956 if (r < 0) {
957 log_unit_error(UNIT(a), "Failed to allocate token set.");
958 goto fail;
959 }
960
961 r = set_put(a->expire_tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token));
962 if (r < 0) {
963 log_unit_error_errno(UNIT(a), r, "Failed to remember token: %m");
964 goto fail;
965 }
966 r = manager_add_job(UNIT(a)->manager, JOB_STOP, UNIT_TRIGGER(UNIT(a)), JOB_REPLACE, true, &error, NULL);
967 if (r < 0) {
968 log_unit_warning(UNIT(a), "Failed to queue umount startup job: %s", bus_error_message(&error, r));
969 goto fail;
970 }
971 break;
972
973 default:
974 log_unit_error(UNIT(a), "Received unknown automount request %i", packet.hdr.type);
975 break;
976 }
977
978 return 0;
979
980 fail:
981 automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
982 return 0;
983 }
984
985 static void automount_shutdown(Manager *m) {
986 assert(m);
987
988 m->dev_autofs_fd = safe_close(m->dev_autofs_fd);
989 }
990
991 static void automount_reset_failed(Unit *u) {
992 Automount *a = AUTOMOUNT(u);
993
994 assert(a);
995
996 if (a->state == AUTOMOUNT_FAILED)
997 automount_set_state(a, AUTOMOUNT_DEAD);
998
999 a->result = AUTOMOUNT_SUCCESS;
1000 }
1001
1002 static bool automount_supported(void) {
1003 static int supported = -1;
1004
1005 if (supported < 0)
1006 supported = access("/dev/autofs", F_OK) >= 0;
1007
1008 return supported;
1009 }
1010
1011 static const char* const automount_state_table[_AUTOMOUNT_STATE_MAX] = {
1012 [AUTOMOUNT_DEAD] = "dead",
1013 [AUTOMOUNT_WAITING] = "waiting",
1014 [AUTOMOUNT_RUNNING] = "running",
1015 [AUTOMOUNT_FAILED] = "failed"
1016 };
1017
1018 DEFINE_STRING_TABLE_LOOKUP(automount_state, AutomountState);
1019
1020 static const char* const automount_result_table[_AUTOMOUNT_RESULT_MAX] = {
1021 [AUTOMOUNT_SUCCESS] = "success",
1022 [AUTOMOUNT_FAILURE_RESOURCES] = "resources"
1023 };
1024
1025 DEFINE_STRING_TABLE_LOOKUP(automount_result, AutomountResult);
1026
1027 const UnitVTable automount_vtable = {
1028 .object_size = sizeof(Automount),
1029
1030 .sections =
1031 "Unit\0"
1032 "Automount\0"
1033 "Install\0",
1034
1035 .no_alias = true,
1036 .no_instances = true,
1037
1038 .init = automount_init,
1039 .load = automount_load,
1040 .done = automount_done,
1041
1042 .coldplug = automount_coldplug,
1043
1044 .dump = automount_dump,
1045
1046 .start = automount_start,
1047 .stop = automount_stop,
1048
1049 .serialize = automount_serialize,
1050 .deserialize_item = automount_deserialize_item,
1051
1052 .active_state = automount_active_state,
1053 .sub_state_to_string = automount_sub_state_to_string,
1054
1055 .check_gc = automount_check_gc,
1056
1057 .reset_failed = automount_reset_failed,
1058
1059 .bus_interface = "org.freedesktop.systemd1.Automount",
1060 .bus_vtable = bus_automount_vtable,
1061
1062 .shutdown = automount_shutdown,
1063 .supported = automount_supported,
1064
1065 .status_message_formats = {
1066 .finished_start_job = {
1067 [JOB_DONE] = "Set up automount %s.",
1068 [JOB_FAILED] = "Failed to set up automount %s.",
1069 [JOB_DEPENDENCY] = "Dependency failed for %s.",
1070 },
1071 .finished_stop_job = {
1072 [JOB_DONE] = "Unset automount %s.",
1073 [JOB_FAILED] = "Failed to unset automount %s.",
1074 },
1075 },
1076 };