]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/automount.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / core / automount.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
a7334b09
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2010 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
a7334b09
LP
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 15 Lesser General Public License for more details.
a7334b09 16
5430f7f2 17 You should have received a copy of the GNU Lesser General Public License
a7334b09
LP
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
5cb5a6ff 21#include <errno.h>
8d567588 22#include <fcntl.h>
07630cea
LP
23#include <limits.h>
24#include <linux/auto_dev-ioctl.h>
25#include <linux/auto_fs4.h>
8d567588 26#include <sys/epoll.h>
07630cea 27#include <sys/mount.h>
8d567588 28#include <sys/stat.h>
07630cea 29#include <unistd.h>
5cb5a6ff 30
b5efdb8a 31#include "alloc-util.h"
07630cea 32#include "async.h"
3ffd4af2 33#include "automount.h"
07630cea
LP
34#include "bus-error.h"
35#include "bus-util.h"
36#include "dbus-automount.h"
3ffd4af2 37#include "fd-util.h"
f97b34a6 38#include "format-util.h"
c004493c 39#include "io-util.h"
e51bc1a2 40#include "label.h"
49e942b2 41#include "mkdir.h"
4349cd7c 42#include "mount-util.h"
07630cea 43#include "mount.h"
6bedfcbb 44#include "parse-util.h"
9eb977db 45#include "path-util.h"
0b452006 46#include "process-util.h"
07630cea 47#include "special.h"
15a5e950 48#include "stdio-util.h"
8b43440b 49#include "string-table.h"
07630cea
LP
50#include "string-util.h"
51#include "unit-name.h"
52#include "unit.h"
5cb5a6ff 53
e537352b
LP
54static const UnitActiveState state_translation_table[_AUTOMOUNT_STATE_MAX] = {
55 [AUTOMOUNT_DEAD] = UNIT_INACTIVE,
56 [AUTOMOUNT_WAITING] = UNIT_ACTIVE,
57 [AUTOMOUNT_RUNNING] = UNIT_ACTIVE,
74ac3cbd 58 [AUTOMOUNT_FAILED] = UNIT_FAILED
e537352b 59};
5cb5a6ff 60
deb0a77c
MO
61struct expire_data {
62 int dev_autofs_fd;
63 int ioctl_fd;
64};
65
66static inline void expire_data_free(struct expire_data *data) {
67 if (!data)
68 return;
69
70 safe_close(data->dev_autofs_fd);
71 safe_close(data->ioctl_fd);
72 free(data);
73}
74
75DEFINE_TRIVIAL_CLEANUP_FUNC(struct expire_data*, expire_data_free);
76
a16e1123 77static int open_dev_autofs(Manager *m);
718db961 78static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata);
dbb0578e
LP
79static int automount_start_expire(Automount *a);
80static void automount_stop_expire(Automount *a);
81static int automount_send_ready(Automount *a, Set *tokens, int status);
8d567588 82
e537352b
LP
83static void automount_init(Unit *u) {
84 Automount *a = AUTOMOUNT(u);
5cb5a6ff 85
8d567588 86 assert(u);
ac155bb8 87 assert(u->load_state == UNIT_STUB);
8d567588 88
718db961 89 a->pipe_fd = -1;
1cf18f27 90 a->directory_mode = 0755;
1124fe6f 91 UNIT(a)->ignore_on_isolate = true;
8d567588
LP
92}
93
8d567588 94static void unmount_autofs(Automount *a) {
3f2c0bec
LP
95 int r;
96
8d567588
LP
97 assert(a);
98
99 if (a->pipe_fd < 0)
100 return;
101
718db961 102 a->pipe_event_source = sd_event_source_unref(a->pipe_event_source);
03e334a1 103 a->pipe_fd = safe_close(a->pipe_fd);
8d567588 104
e350ca3f
LP
105 /* If we reload/reexecute things we keep the mount point around */
106 if (!IN_SET(UNIT(a)->manager->exit_code, MANAGER_RELOAD, MANAGER_REEXECUTE)) {
107
87d41d62
MO
108 automount_send_ready(a, a->tokens, -EHOSTDOWN);
109 automount_send_ready(a, a->expire_tokens, -EHOSTDOWN);
110
e350ca3f
LP
111 if (a->where) {
112 r = repeat_unmount(a->where, MNT_DETACH);
113 if (r < 0)
114 log_error_errno(r, "Failed to unmount: %m");
115 }
3f2c0bec 116 }
8d567588
LP
117}
118
119static void automount_done(Unit *u) {
120 Automount *a = AUTOMOUNT(u);
121
122 assert(a);
123
124 unmount_autofs(a);
8d567588 125
a1e58e8e 126 a->where = mfree(a->where);
a16e1123 127
525d3cc7
LP
128 a->tokens = set_free(a->tokens);
129 a->expire_tokens = set_free(a->expire_tokens);
deb0a77c
MO
130
131 a->expire_event_source = sd_event_source_unref(a->expire_event_source);
8d567588
LP
132}
133
eef85c4a
LP
134static int automount_add_trigger_dependencies(Automount *a) {
135 Unit *x;
136 int r;
137
138 assert(a);
139
140 r = unit_load_related_unit(UNIT(a), ".mount", &x);
141 if (r < 0)
142 return r;
143
144 return unit_add_two_dependencies(UNIT(a), UNIT_BEFORE, UNIT_TRIGGERS, x, true, UNIT_DEPENDENCY_IMPLICIT);
145}
146
147static int automount_add_mount_dependencies(Automount *a) {
a57f7e2c 148 _cleanup_free_ char *parent = NULL;
6e2ef85b
LP
149
150 assert(a);
1b560190 151
5f311f8c
LP
152 parent = dirname_malloc(a->where);
153 if (!parent)
154 return -ENOMEM;
6e2ef85b 155
eef85c4a 156 return unit_require_mounts_for(UNIT(a), parent, UNIT_DEPENDENCY_IMPLICIT);
6e2ef85b
LP
157}
158
2edd4434
LP
159static int automount_add_default_dependencies(Automount *a) {
160 int r;
161
162 assert(a);
163
4c9ea260
LP
164 if (!UNIT(a)->default_dependencies)
165 return 0;
166
463d0d15 167 if (!MANAGER_IS_SYSTEM(UNIT(a)->manager))
6b1dc2bd 168 return 0;
2a77d31d 169
eef85c4a 170 r = unit_add_two_dependencies_by_name(UNIT(a), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true, UNIT_DEPENDENCY_DEFAULT);
6b1dc2bd
LP
171 if (r < 0)
172 return r;
2edd4434
LP
173
174 return 0;
175}
176
8d567588 177static int automount_verify(Automount *a) {
e1d75803 178 _cleanup_free_ char *e = NULL;
7410616c
LP
179 int r;
180
8d567588
LP
181 assert(a);
182
1124fe6f 183 if (UNIT(a)->load_state != UNIT_LOADED)
8d567588
LP
184 return 0;
185
41e45059 186 if (path_equal(a->where, "/")) {
f2341e0a 187 log_unit_error(UNIT(a), "Cannot have an automount unit for the root directory. Refusing.");
41e45059
LP
188 return -EINVAL;
189 }
190
7410616c
LP
191 r = unit_name_from_path(a->where, ".automount", &e);
192 if (r < 0)
f2341e0a 193 return log_unit_error(UNIT(a), "Failed to generate unit name from path: %m");
8d567588 194
7410616c 195 if (!unit_has_name(UNIT(a), e)) {
f2341e0a 196 log_unit_error(UNIT(a), "Where= setting doesn't match unit name. Refusing.");
8d567588
LP
197 return -EINVAL;
198 }
199
200 return 0;
e537352b 201}
5cb5a6ff 202
e350ca3f
LP
203static int automount_set_where(Automount *a) {
204 int r;
205
206 assert(a);
207
208 if (a->where)
209 return 0;
210
211 r = unit_name_to_path(UNIT(a)->id, &a->where);
212 if (r < 0)
213 return r;
214
215 path_kill_slashes(a->where);
216 return 1;
217}
218
e537352b 219static int automount_load(Unit *u) {
e537352b 220 Automount *a = AUTOMOUNT(u);
3ecaa09b 221 int r;
23a177ef 222
e537352b 223 assert(u);
ac155bb8 224 assert(u->load_state == UNIT_STUB);
5cb5a6ff 225
e537352b 226 /* Load a .automount file */
0b2665c3
LP
227 r = unit_load_fragment_and_dropin_optional(u);
228 if (r < 0)
e537352b 229 return r;
23a177ef 230
ac155bb8 231 if (u->load_state == UNIT_LOADED) {
e350ca3f
LP
232 r = automount_set_where(a);
233 if (r < 0)
234 return r;
a16e1123 235
eef85c4a 236 r = automount_add_trigger_dependencies(a);
57020a3a 237 if (r < 0)
23a177ef
LP
238 return r;
239
eef85c4a 240 r = automount_add_mount_dependencies(a);
57020a3a 241 if (r < 0)
23a177ef 242 return r;
4e67ddd6 243
4c9ea260
LP
244 r = automount_add_default_dependencies(a);
245 if (r < 0)
246 return r;
23a177ef
LP
247 }
248
8d567588 249 return automount_verify(a);
5cb5a6ff
LP
250}
251
8d567588
LP
252static void automount_set_state(Automount *a, AutomountState state) {
253 AutomountState old_state;
e537352b 254 assert(a);
034c6ed7 255
8d567588
LP
256 old_state = a->state;
257 a->state = state;
258
dbb0578e
LP
259 if (state != AUTOMOUNT_RUNNING)
260 automount_stop_expire(a);
261
ec2ce0c5 262 if (!IN_SET(state, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING))
8d567588
LP
263 unmount_autofs(a);
264
265 if (state != old_state)
f2341e0a 266 log_unit_debug(UNIT(a), "Changed %s -> %s", automount_state_to_string(old_state), automount_state_to_string(state));
8d567588 267
e2f3b44c 268 unit_notify(UNIT(a), state_translation_table[old_state], state_translation_table[state], true);
034c6ed7
LP
269}
270
be847e82 271static int automount_coldplug(Unit *u) {
a16e1123
LP
272 Automount *a = AUTOMOUNT(u);
273 int r;
274
275 assert(a);
276 assert(a->state == AUTOMOUNT_DEAD);
277
e350ca3f
LP
278 if (a->deserialized_state == a->state)
279 return 0;
280
281 if (IN_SET(a->deserialized_state, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING)) {
282
283 r = automount_set_where(a);
284 if (r < 0)
285 return r;
a16e1123 286
0b2665c3
LP
287 r = open_dev_autofs(u->manager);
288 if (r < 0)
a16e1123
LP
289 return r;
290
e350ca3f
LP
291 assert(a->pipe_fd >= 0);
292
293 r = sd_event_add_io(u->manager->event, &a->pipe_event_source, a->pipe_fd, EPOLLIN, automount_dispatch_io, u);
294 if (r < 0)
295 return r;
a16e1123 296
e350ca3f
LP
297 (void) sd_event_source_set_description(a->pipe_event_source, "automount-io");
298 if (a->deserialized_state == AUTOMOUNT_RUNNING) {
299 r = automount_start_expire(a);
0b2665c3 300 if (r < 0)
e350ca3f 301 log_unit_warning_errno(UNIT(a), r, "Failed to start expiration timer, ignoring: %m");
a16e1123
LP
302 }
303
304 automount_set_state(a, a->deserialized_state);
305 }
306
307 return 0;
308}
309
87f0e418 310static void automount_dump(Unit *u, FILE *f, const char *prefix) {
deb0a77c 311 char time_string[FORMAT_TIMESPAN_MAX];
a16e1123 312 Automount *a = AUTOMOUNT(u);
5cb5a6ff 313
a16e1123 314 assert(a);
5cb5a6ff
LP
315
316 fprintf(f,
a16e1123 317 "%sAutomount State: %s\n"
81a5c6d0 318 "%sResult: %s\n"
1cf18f27 319 "%sWhere: %s\n"
deb0a77c
MO
320 "%sDirectoryMode: %04o\n"
321 "%sTimeoutIdleUSec: %s\n",
a16e1123 322 prefix, automount_state_to_string(a->state),
81a5c6d0 323 prefix, automount_result_to_string(a->result),
1cf18f27 324 prefix, a->where,
deb0a77c
MO
325 prefix, a->directory_mode,
326 prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX, a->timeout_idle_usec, USEC_PER_SEC));
5cb5a6ff
LP
327}
328
81a5c6d0 329static void automount_enter_dead(Automount *a, AutomountResult f) {
8d567588
LP
330 assert(a);
331
a0fef983 332 if (a->result == AUTOMOUNT_SUCCESS)
81a5c6d0 333 a->result = f;
8d567588 334
ed77d407
LP
335 if (a->result != AUTOMOUNT_SUCCESS)
336 log_unit_warning(UNIT(a), "Failed with result '%s'.", automount_result_to_string(a->result));
337
81a5c6d0 338 automount_set_state(a, a->result != AUTOMOUNT_SUCCESS ? AUTOMOUNT_FAILED : AUTOMOUNT_DEAD);
8d567588
LP
339}
340
341static int open_dev_autofs(Manager *m) {
342 struct autofs_dev_ioctl param;
343
344 assert(m);
345
346 if (m->dev_autofs_fd >= 0)
347 return m->dev_autofs_fd;
348
c9bc0764 349 label_fix("/dev/autofs", false, false);
56cf987f 350
0b2665c3 351 m->dev_autofs_fd = open("/dev/autofs", O_CLOEXEC|O_RDONLY);
4a62c710
MS
352 if (m->dev_autofs_fd < 0)
353 return log_error_errno(errno, "Failed to open /dev/autofs: %m");
8d567588
LP
354
355 init_autofs_dev_ioctl(&param);
356 if (ioctl(m->dev_autofs_fd, AUTOFS_DEV_IOCTL_VERSION, &param) < 0) {
03e334a1 357 m->dev_autofs_fd = safe_close(m->dev_autofs_fd);
8d567588
LP
358 return -errno;
359 }
360
361 log_debug("Autofs kernel version %i.%i", param.ver_major, param.ver_minor);
362
363 return m->dev_autofs_fd;
364}
365
366static int open_ioctl_fd(int dev_autofs_fd, const char *where, dev_t devid) {
367 struct autofs_dev_ioctl *param;
368 size_t l;
8d567588
LP
369
370 assert(dev_autofs_fd >= 0);
371 assert(where);
372
373 l = sizeof(struct autofs_dev_ioctl) + strlen(where) + 1;
0b2665c3 374 param = alloca(l);
8d567588
LP
375
376 init_autofs_dev_ioctl(param);
377 param->size = l;
378 param->ioctlfd = -1;
379 param->openmount.devid = devid;
380 strcpy(param->path, where);
381
0b2665c3
LP
382 if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_OPENMOUNT, param) < 0)
383 return -errno;
8d567588 384
0b2665c3
LP
385 if (param->ioctlfd < 0)
386 return -EIO;
8d567588 387
f34beace 388 (void) fd_cloexec(param->ioctlfd, true);
0b2665c3 389 return param->ioctlfd;
8d567588
LP
390}
391
392static int autofs_protocol(int dev_autofs_fd, int ioctl_fd) {
393 uint32_t major, minor;
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 if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_PROTOVER, &param) < 0)
403 return -errno;
404
405 major = param.protover.version;
406
407 init_autofs_dev_ioctl(&param);
408 param.ioctlfd = ioctl_fd;
409
410 if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_PROTOSUBVER, &param) < 0)
411 return -errno;
412
413 minor = param.protosubver.sub_version;
414
415 log_debug("Autofs protocol version %i.%i", major, minor);
416 return 0;
417}
418
deb0a77c 419static int autofs_set_timeout(int dev_autofs_fd, int ioctl_fd, usec_t usec) {
8d567588
LP
420 struct autofs_dev_ioctl param;
421
422 assert(dev_autofs_fd >= 0);
423 assert(ioctl_fd >= 0);
424
425 init_autofs_dev_ioctl(&param);
426 param.ioctlfd = ioctl_fd;
deb0a77c 427
2d79a0bb
N
428 if (usec == USEC_INFINITY)
429 param.timeout.timeout = 0;
430 else
431 /* Convert to seconds, rounding up. */
432 param.timeout.timeout = (usec + USEC_PER_SEC - 1) / USEC_PER_SEC;
8d567588
LP
433
434 if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_TIMEOUT, &param) < 0)
435 return -errno;
436
437 return 0;
438}
439
440static int autofs_send_ready(int dev_autofs_fd, int ioctl_fd, uint32_t token, int status) {
441 struct autofs_dev_ioctl param;
442
443 assert(dev_autofs_fd >= 0);
444 assert(ioctl_fd >= 0);
445
446 init_autofs_dev_ioctl(&param);
447 param.ioctlfd = ioctl_fd;
448
9703a8ad 449 if (status != 0) {
8d567588
LP
450 param.fail.token = token;
451 param.fail.status = status;
452 } else
453 param.ready.token = token;
454
455 if (ioctl(dev_autofs_fd, status ? AUTOFS_DEV_IOCTL_FAIL : AUTOFS_DEV_IOCTL_READY, &param) < 0)
456 return -errno;
457
458 return 0;
459}
460
deb0a77c 461static int automount_send_ready(Automount *a, Set *tokens, int status) {
03e334a1 462 _cleanup_close_ int ioctl_fd = -1;
8d567588 463 unsigned token;
03e334a1 464 int r;
8d567588
LP
465
466 assert(a);
467 assert(status <= 0);
468
deb0a77c 469 if (set_isempty(tokens))
8d567588
LP
470 return 0;
471
0b2665c3 472 ioctl_fd = open_ioctl_fd(UNIT(a)->manager->dev_autofs_fd, a->where, a->dev_id);
03e334a1
LP
473 if (ioctl_fd < 0)
474 return ioctl_fd;
8d567588 475
9703a8ad 476 if (status != 0)
f2341e0a 477 log_unit_debug_errno(UNIT(a), status, "Sending failure: %m");
8d567588 478 else
f2341e0a 479 log_unit_debug(UNIT(a), "Sending success.");
8d567588 480
e364ad06
LP
481 r = 0;
482
8d567588 483 /* Autofs thankfully does not hand out 0 as a token */
deb0a77c 484 while ((token = PTR_TO_UINT(set_steal_first(tokens)))) {
8d567588
LP
485 int k;
486
ca5b440a 487 /* Autofs fun fact:
8d567588 488 *
ca5b440a
N
489 * if you pass a positive status code here, kernels
490 * prior to 4.12 will freeze! Yay! */
8d567588 491
0b2665c3
LP
492 k = autofs_send_ready(UNIT(a)->manager->dev_autofs_fd,
493 ioctl_fd,
494 token,
495 status);
496 if (k < 0)
8d567588
LP
497 r = k;
498 }
499
8d567588
LP
500 return r;
501}
502
fae03ed3
LP
503static void automount_trigger_notify(Unit *u, Unit *other) {
504 Automount *a = AUTOMOUNT(u);
3dbadf9e
MO
505 int r;
506
deb0a77c 507 assert(a);
fae03ed3
LP
508 assert(other);
509
510 /* Filter out invocations with bogus state */
511 if (other->load_state != UNIT_LOADED || other->type != UNIT_MOUNT)
512 return;
513
514 /* Don't propagate state changes from the mount if we are already down */
515 if (!IN_SET(a->state, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING))
516 return;
deb0a77c 517
fae03ed3
LP
518 /* Propagate start limit hit state */
519 if (other->start_limit_hit) {
520 automount_enter_dead(a, AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT);
521 return;
522 }
9703a8ad 523
fae03ed3
LP
524 /* Don't propagate anything if there's still a job queued */
525 if (other->job)
526 return;
527
528 /* The mount is successfully established */
529 if (IN_SET(MOUNT(other)->state, MOUNT_MOUNTED, MOUNT_REMOUNTING)) {
530 (void) automount_send_ready(a, a->tokens, 0);
deb0a77c 531
3dbadf9e
MO
532 r = automount_start_expire(a);
533 if (r < 0)
534 log_unit_warning_errno(UNIT(a), r, "Failed to start expiration timer, ignoring: %m");
deb0a77c 535
fae03ed3 536 automount_set_state(a, AUTOMOUNT_RUNNING);
deb0a77c
MO
537 }
538
0a62f810
MO
539 if (IN_SET(MOUNT(other)->state,
540 MOUNT_MOUNTING, MOUNT_MOUNTING_DONE,
541 MOUNT_MOUNTED, MOUNT_REMOUNTING,
0a62f810
MO
542 MOUNT_REMOUNTING_SIGTERM, MOUNT_REMOUNTING_SIGKILL,
543 MOUNT_UNMOUNTING_SIGTERM, MOUNT_UNMOUNTING_SIGKILL,
544 MOUNT_FAILED)) {
545
546 (void) automount_send_ready(a, a->expire_tokens, -ENODEV);
547 }
548
549 if (MOUNT(other)->state == MOUNT_DEAD)
550 (void) automount_send_ready(a, a->expire_tokens, 0);
551
fae03ed3
LP
552 /* The mount is in some unhappy state now, let's unfreeze any waiting clients */
553 if (IN_SET(MOUNT(other)->state,
554 MOUNT_DEAD, MOUNT_UNMOUNTING,
fae03ed3
LP
555 MOUNT_REMOUNTING_SIGTERM, MOUNT_REMOUNTING_SIGKILL,
556 MOUNT_UNMOUNTING_SIGTERM, MOUNT_UNMOUNTING_SIGKILL,
557 MOUNT_FAILED)) {
deb0a77c 558
fae03ed3 559 (void) automount_send_ready(a, a->tokens, -ENODEV);
deb0a77c 560
fae03ed3
LP
561 automount_set_state(a, AUTOMOUNT_WAITING);
562 }
deb0a77c
MO
563}
564
8d567588 565static void automount_enter_waiting(Automount *a) {
03e334a1 566 _cleanup_close_ int ioctl_fd = -1;
8d567588 567 int p[2] = { -1, -1 };
5ffa8c81
ZJS
568 char name[sizeof("systemd-")-1 + DECIMAL_STR_MAX(pid_t) + 1];
569 char options[sizeof("fd=,pgrp=,minproto=5,maxproto=5,direct")-1
570 + DECIMAL_STR_MAX(int) + DECIMAL_STR_MAX(gid_t) + 1];
8d567588 571 bool mounted = false;
03e334a1 572 int r, dev_autofs_fd;
8d567588
LP
573 struct stat st;
574
575 assert(a);
576 assert(a->pipe_fd < 0);
577 assert(a->where);
578
f2341e0a
LP
579 set_clear(a->tokens);
580
581 r = unit_fail_if_symlink(UNIT(a), a->where);
582 if (r < 0)
583 goto fail;
584
585 (void) mkdir_p_label(a->where, 0555);
586
587 unit_warn_if_dir_nonempty(UNIT(a), a->where);
8d567588 588
0b2665c3
LP
589 dev_autofs_fd = open_dev_autofs(UNIT(a)->manager);
590 if (dev_autofs_fd < 0) {
8d567588
LP
591 r = dev_autofs_fd;
592 goto fail;
593 }
594
a16e1123 595 if (pipe2(p, O_NONBLOCK|O_CLOEXEC) < 0) {
8d567588
LP
596 r = -errno;
597 goto fail;
598 }
599
5ffa8c81 600 xsprintf(options, "fd=%i,pgrp="PID_FMT",minproto=5,maxproto=5,direct", p[1], getpgrp());
df0ff127 601 xsprintf(name, "systemd-"PID_FMT, getpid_cached());
8d567588
LP
602 if (mount(name, a->where, "autofs", 0, options) < 0) {
603 r = -errno;
604 goto fail;
605 }
606
607 mounted = true;
608
03e334a1 609 p[1] = safe_close(p[1]);
8d567588
LP
610
611 if (stat(a->where, &st) < 0) {
612 r = -errno;
613 goto fail;
614 }
615
0b2665c3
LP
616 ioctl_fd = open_ioctl_fd(dev_autofs_fd, a->where, st.st_dev);
617 if (ioctl_fd < 0) {
8d567588
LP
618 r = ioctl_fd;
619 goto fail;
620 }
621
0b2665c3
LP
622 r = autofs_protocol(dev_autofs_fd, ioctl_fd);
623 if (r < 0)
8d567588
LP
624 goto fail;
625
deb0a77c 626 r = autofs_set_timeout(dev_autofs_fd, ioctl_fd, a->timeout_idle_usec);
0b2665c3 627 if (r < 0)
8d567588
LP
628 goto fail;
629
151b9b96 630 r = sd_event_add_io(UNIT(a)->manager->event, &a->pipe_event_source, p[0], EPOLLIN, automount_dispatch_io, a);
0b2665c3 631 if (r < 0)
8d567588
LP
632 goto fail;
633
7dfbe2e3
TG
634 (void) sd_event_source_set_description(a->pipe_event_source, "automount-io");
635
8d567588
LP
636 a->pipe_fd = p[0];
637 a->dev_id = st.st_dev;
638
639 automount_set_state(a, AUTOMOUNT_WAITING);
640
641 return;
642
643fail:
3f2c0bec
LP
644 log_unit_error_errno(UNIT(a), r, "Failed to initialize automounter: %m");
645
3d94f76c 646 safe_close_pair(p);
8d567588 647
3f2c0bec
LP
648 if (mounted) {
649 r = repeat_unmount(a->where, MNT_DETACH);
650 if (r < 0)
651 log_error_errno(r, "Failed to unmount, ignoring: %m");
652 }
8d567588 653
81a5c6d0 654 automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
8d567588
LP
655}
656
deb0a77c
MO
657static void *expire_thread(void *p) {
658 struct autofs_dev_ioctl param;
659 _cleanup_(expire_data_freep) struct expire_data *data = (struct expire_data*)p;
660 int r;
661
662 assert(data->dev_autofs_fd >= 0);
663 assert(data->ioctl_fd >= 0);
664
665 init_autofs_dev_ioctl(&param);
666 param.ioctlfd = data->ioctl_fd;
667
668 do {
669 r = ioctl(data->dev_autofs_fd, AUTOFS_DEV_IOCTL_EXPIRE, &param);
670 } while (r >= 0);
671
672 if (errno != EAGAIN)
673 log_warning_errno(errno, "Failed to expire automount, ignoring: %m");
674
675 return NULL;
676}
677
deb0a77c
MO
678static int automount_dispatch_expire(sd_event_source *source, usec_t usec, void *userdata) {
679 Automount *a = AUTOMOUNT(userdata);
680 _cleanup_(expire_data_freep) struct expire_data *data = NULL;
681 int r;
682
683 assert(a);
684 assert(source == a->expire_event_source);
685
686 data = new0(struct expire_data, 1);
687 if (!data)
688 return log_oom();
689
690 data->ioctl_fd = -1;
691
692 data->dev_autofs_fd = fcntl(UNIT(a)->manager->dev_autofs_fd, F_DUPFD_CLOEXEC, 3);
693 if (data->dev_autofs_fd < 0)
f2341e0a 694 return log_unit_error_errno(UNIT(a), errno, "Failed to duplicate autofs fd: %m");
deb0a77c
MO
695
696 data->ioctl_fd = open_ioctl_fd(UNIT(a)->manager->dev_autofs_fd, a->where, a->dev_id);
697 if (data->ioctl_fd < 0)
f2341e0a 698 return log_unit_error_errno(UNIT(a), data->ioctl_fd, "Couldn't open autofs ioctl fd: %m");
deb0a77c
MO
699
700 r = asynchronous_job(expire_thread, data);
701 if (r < 0)
f2341e0a 702 return log_unit_error_errno(UNIT(a), r, "Failed to start expire job: %m");
deb0a77c
MO
703
704 data = NULL;
705
706 return automount_start_expire(a);
707}
708
709static int automount_start_expire(Automount *a) {
710 int r;
711 usec_t timeout;
712
713 assert(a);
714
93a3b53b
DM
715 if (a->timeout_idle_usec == 0)
716 return 0;
717
dbf5cc47 718 timeout = now(CLOCK_MONOTONIC) + MAX(a->timeout_idle_usec/3, USEC_PER_SEC);
deb0a77c
MO
719
720 if (a->expire_event_source) {
721 r = sd_event_source_set_time(a->expire_event_source, timeout);
722 if (r < 0)
723 return r;
724
725 return sd_event_source_set_enabled(a->expire_event_source, SD_EVENT_ONESHOT);
726 }
727
7dfbe2e3 728 r = sd_event_add_time(
deb0a77c
MO
729 UNIT(a)->manager->event,
730 &a->expire_event_source,
731 CLOCK_MONOTONIC, timeout, 0,
732 automount_dispatch_expire, a);
7dfbe2e3
TG
733 if (r < 0)
734 return r;
735
736 (void) sd_event_source_set_description(a->expire_event_source, "automount-expire");
737
738 return 0;
deb0a77c
MO
739}
740
dbb0578e
LP
741static void automount_stop_expire(Automount *a) {
742 assert(a);
743
744 if (!a->expire_event_source)
745 return;
746
747 (void) sd_event_source_set_enabled(a->expire_event_source, SD_EVENT_OFF);
748}
749
e7d54bf5 750static void automount_enter_running(Automount *a) {
4afd3348 751 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
e7d54bf5 752 Unit *trigger;
3ecaa09b
LP
753 struct stat st;
754 int r;
8d567588
LP
755
756 assert(a);
8d567588 757
e350ca3f
LP
758 /* If the user masked our unit in the meantime, fail */
759 if (UNIT(a)->load_state != UNIT_LOADED) {
760 log_unit_error(UNIT(a), "Suppressing automount event since unit is no longer loaded.");
761 goto fail;
762 }
763
ba3e67a7
LP
764 /* We don't take mount requests anymore if we are supposed to
765 * shut down anyway */
31afa0a4 766 if (unit_stop_pending(UNIT(a))) {
f2341e0a 767 log_unit_debug(UNIT(a), "Suppressing automount request since unit stop is scheduled.");
deb0a77c
MO
768 automount_send_ready(a, a->tokens, -EHOSTDOWN);
769 automount_send_ready(a, a->expire_tokens, -EHOSTDOWN);
ba3e67a7
LP
770 return;
771 }
772
d2e54fae 773 mkdir_p_label(a->where, a->directory_mode);
8d567588 774
1cf18f27
LP
775 /* Before we do anything, let's see if somebody is playing games with us? */
776 if (lstat(a->where, &st) < 0) {
f2341e0a 777 log_unit_warning_errno(UNIT(a), errno, "Failed to stat automount point: %m");
8d567588
LP
778 goto fail;
779 }
780
e7d54bf5
AC
781 /* The mount unit may have been explicitly started before we got the
782 * autofs request. Ack it to unblock anything waiting on the mount point. */
783 if (!S_ISDIR(st.st_mode) || st.st_dev != a->dev_id) {
f2341e0a 784 log_unit_info(UNIT(a), "Automount point already active?");
e7d54bf5
AC
785 automount_send_ready(a, a->tokens, 0);
786 return;
787 }
e903182e 788
e7d54bf5
AC
789 trigger = UNIT_TRIGGER(UNIT(a));
790 if (!trigger) {
791 log_unit_error(UNIT(a), "Unit to trigger vanished.");
792 goto fail;
793 }
e903182e 794
e7d54bf5
AC
795 r = manager_add_job(UNIT(a)->manager, JOB_START, trigger, JOB_REPLACE, &error, NULL);
796 if (r < 0) {
797 log_unit_warning(UNIT(a), "Failed to queue mount startup job: %s", bus_error_message(&error, r));
798 goto fail;
8d567588
LP
799 }
800
801 automount_set_state(a, AUTOMOUNT_RUNNING);
802 return;
803
804fail:
81a5c6d0 805 automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
8d567588
LP
806}
807
808static int automount_start(Unit *u) {
809 Automount *a = AUTOMOUNT(u);
e903182e 810 Unit *trigger;
07299350 811 int r;
8d567588
LP
812
813 assert(a);
3742095b 814 assert(IN_SET(a->state, AUTOMOUNT_DEAD, AUTOMOUNT_FAILED));
01f78473 815
e1873695 816 if (path_is_mount_point(a->where, NULL, 0) > 0) {
f2341e0a 817 log_unit_error(u, "Path %s is already a mount point, refusing start.", a->where);
8d567588
LP
818 return -EEXIST;
819 }
820
e903182e
LP
821 trigger = UNIT_TRIGGER(u);
822 if (!trigger || trigger->load_state != UNIT_LOADED) {
823 log_unit_error(u, "Refusing to start, unit to trigger not loaded.");
01f78473 824 return -ENOENT;
e903182e 825 }
8d567588 826
07299350
LP
827 r = unit_start_limit_test(u);
828 if (r < 0) {
829 automount_enter_dead(a, AUTOMOUNT_FAILURE_START_LIMIT_HIT);
830 return r;
831 }
832
4b58153d
LP
833 r = unit_acquire_invocation_id(u);
834 if (r < 0)
835 return r;
836
81a5c6d0 837 a->result = AUTOMOUNT_SUCCESS;
8d567588 838 automount_enter_waiting(a);
82a2b6bb 839 return 1;
8d567588
LP
840}
841
842static int automount_stop(Unit *u) {
843 Automount *a = AUTOMOUNT(u);
844
845 assert(a);
3742095b 846 assert(IN_SET(a->state, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING));
8d567588 847
81a5c6d0 848 automount_enter_dead(a, AUTOMOUNT_SUCCESS);
82a2b6bb 849 return 1;
8d567588
LP
850}
851
a16e1123
LP
852static int automount_serialize(Unit *u, FILE *f, FDSet *fds) {
853 Automount *a = AUTOMOUNT(u);
a16e1123 854 Iterator i;
a34ceba6
LP
855 void *p;
856 int r;
a16e1123
LP
857
858 assert(a);
859 assert(f);
860 assert(fds);
861
862 unit_serialize_item(u, f, "state", automount_state_to_string(a->state));
81a5c6d0 863 unit_serialize_item(u, f, "result", automount_result_to_string(a->result));
a16e1123
LP
864 unit_serialize_item_format(u, f, "dev-id", "%u", (unsigned) a->dev_id);
865
866 SET_FOREACH(p, a->tokens, i)
867 unit_serialize_item_format(u, f, "token", "%u", PTR_TO_UINT(p));
deb0a77c
MO
868 SET_FOREACH(p, a->expire_tokens, i)
869 unit_serialize_item_format(u, f, "expire-token", "%u", PTR_TO_UINT(p));
a16e1123 870
a34ceba6
LP
871 r = unit_serialize_item_fd(u, f, fds, "pipe-fd", a->pipe_fd);
872 if (r < 0)
873 return r;
a16e1123
LP
874
875 return 0;
876}
877
878static int automount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
879 Automount *a = AUTOMOUNT(u);
880 int r;
881
882 assert(a);
883 assert(fds);
884
885 if (streq(key, "state")) {
886 AutomountState state;
887
0b2665c3
LP
888 state = automount_state_from_string(value);
889 if (state < 0)
f2341e0a 890 log_unit_debug(u, "Failed to parse state value: %s", value);
a16e1123
LP
891 else
892 a->deserialized_state = state;
81a5c6d0
LP
893 } else if (streq(key, "result")) {
894 AutomountResult f;
895
896 f = automount_result_from_string(value);
897 if (f < 0)
f2341e0a 898 log_unit_debug(u, "Failed to parse result value: %s", value);
81a5c6d0
LP
899 else if (f != AUTOMOUNT_SUCCESS)
900 a->result = f;
a16e1123 901
a16e1123
LP
902 } else if (streq(key, "dev-id")) {
903 unsigned d;
904
905 if (safe_atou(value, &d) < 0)
f2341e0a 906 log_unit_debug(u, "Failed to parse dev-id value: %s", value);
a16e1123
LP
907 else
908 a->dev_id = (unsigned) d;
909 } else if (streq(key, "token")) {
910 unsigned token;
911
912 if (safe_atou(value, &token) < 0)
f2341e0a 913 log_unit_debug(u, "Failed to parse token value: %s", value);
a16e1123 914 else {
f34beace
LP
915 r = set_ensure_allocated(&a->tokens, NULL);
916 if (r < 0) {
917 log_oom();
918 return 0;
919 }
a16e1123 920
0b2665c3
LP
921 r = set_put(a->tokens, UINT_TO_PTR(token));
922 if (r < 0)
f2341e0a 923 log_unit_error_errno(u, r, "Failed to add token to set: %m");
a16e1123 924 }
deb0a77c
MO
925 } else if (streq(key, "expire-token")) {
926 unsigned token;
927
928 if (safe_atou(value, &token) < 0)
f2341e0a 929 log_unit_debug(u, "Failed to parse token value: %s", value);
deb0a77c
MO
930 else {
931 r = set_ensure_allocated(&a->expire_tokens, NULL);
932 if (r < 0) {
933 log_oom();
934 return 0;
935 }
936
937 r = set_put(a->expire_tokens, UINT_TO_PTR(token));
938 if (r < 0)
f2341e0a 939 log_unit_error_errno(u, r, "Failed to add expire token to set: %m");
deb0a77c 940 }
a16e1123
LP
941 } else if (streq(key, "pipe-fd")) {
942 int fd;
943
944 if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
f2341e0a 945 log_unit_debug(u, "Failed to parse pipe-fd value: %s", value);
a16e1123 946 else {
03e334a1 947 safe_close(a->pipe_fd);
a16e1123
LP
948 a->pipe_fd = fdset_remove(fds, fd);
949 }
950 } else
f2341e0a 951 log_unit_debug(u, "Unknown serialization key: %s", key);
a16e1123
LP
952
953 return 0;
954}
955
87f0e418 956static UnitActiveState automount_active_state(Unit *u) {
a16e1123 957 assert(u);
87f0e418 958
e537352b 959 return state_translation_table[AUTOMOUNT(u)->state];
5cb5a6ff
LP
960}
961
10a94420
LP
962static const char *automount_sub_state_to_string(Unit *u) {
963 assert(u);
964
a16e1123 965 return automount_state_to_string(AUTOMOUNT(u)->state);
10a94420
LP
966}
967
701cc384 968static bool automount_check_gc(Unit *u) {
3ecaa09b 969 assert(u);
701cc384 970
3ecaa09b 971 if (!UNIT_TRIGGER(u))
7573916f
LP
972 return false;
973
3ecaa09b 974 return UNIT_VTABLE(UNIT_TRIGGER(u))->check_gc(UNIT_TRIGGER(u));
701cc384
LP
975}
976
718db961 977static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata) {
4afd3348 978 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
8d567588 979 union autofs_v5_packet_union packet;
718db961 980 Automount *a = AUTOMOUNT(userdata);
e903182e 981 Unit *trigger;
8d567588
LP
982 int r;
983
8d567588
LP
984 assert(a);
985 assert(fd == a->pipe_fd);
986
987 if (events != EPOLLIN) {
f2341e0a 988 log_unit_error(UNIT(a), "Got invalid poll event %"PRIu32" on pipe (fd=%d)", events, fd);
8d567588
LP
989 goto fail;
990 }
991
a6dcc7e5
ZJS
992 r = loop_read_exact(a->pipe_fd, &packet, sizeof(packet), true);
993 if (r < 0) {
f2341e0a 994 log_unit_error_errno(UNIT(a), r, "Invalid read from pipe: %m");
8d567588
LP
995 goto fail;
996 }
997
998 switch (packet.hdr.type) {
999
1000 case autofs_ptype_missing_direct:
941a4041
LP
1001
1002 if (packet.v5_packet.pid > 0) {
e42e801b 1003 _cleanup_free_ char *p = NULL;
941a4041 1004
87d2c1ff 1005 get_process_comm(packet.v5_packet.pid, &p);
f2341e0a 1006 log_unit_info(UNIT(a), "Got automount request for %s, triggered by %"PRIu32" (%s)", a->where, packet.v5_packet.pid, strna(p));
941a4041 1007 } else
f2341e0a 1008 log_unit_debug(UNIT(a), "Got direct mount request on %s", a->where);
8d567588 1009
d5099efc 1010 r = set_ensure_allocated(&a->tokens, NULL);
0b2665c3 1011 if (r < 0) {
f2341e0a 1012 log_unit_error(UNIT(a), "Failed to allocate token set.");
0b2665c3
LP
1013 goto fail;
1014 }
a16e1123 1015
0b2665c3
LP
1016 r = set_put(a->tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token));
1017 if (r < 0) {
f2341e0a 1018 log_unit_error_errno(UNIT(a), r, "Failed to remember token: %m");
8d567588
LP
1019 goto fail;
1020 }
1021
e7d54bf5 1022 automount_enter_running(a);
8d567588
LP
1023 break;
1024
deb0a77c 1025 case autofs_ptype_expire_direct:
f2341e0a 1026 log_unit_debug(UNIT(a), "Got direct umount request on %s", a->where);
deb0a77c 1027
dbb0578e 1028 automount_stop_expire(a);
deb0a77c
MO
1029
1030 r = set_ensure_allocated(&a->expire_tokens, NULL);
1031 if (r < 0) {
f2341e0a 1032 log_unit_error(UNIT(a), "Failed to allocate token set.");
deb0a77c
MO
1033 goto fail;
1034 }
1035
1036 r = set_put(a->expire_tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token));
1037 if (r < 0) {
f2341e0a 1038 log_unit_error_errno(UNIT(a), r, "Failed to remember token: %m");
deb0a77c
MO
1039 goto fail;
1040 }
5f8ae398 1041
e903182e
LP
1042 trigger = UNIT_TRIGGER(UNIT(a));
1043 if (!trigger) {
1044 log_unit_error(UNIT(a), "Unit to trigger vanished.");
1045 goto fail;
1046 }
1047
1048 r = manager_add_job(UNIT(a)->manager, JOB_STOP, trigger, JOB_REPLACE, &error, NULL);
deb0a77c 1049 if (r < 0) {
f2341e0a 1050 log_unit_warning(UNIT(a), "Failed to queue umount startup job: %s", bus_error_message(&error, r));
deb0a77c
MO
1051 goto fail;
1052 }
1053 break;
1054
8d567588 1055 default:
f2341e0a 1056 log_unit_error(UNIT(a), "Received unknown automount request %i", packet.hdr.type);
8d567588
LP
1057 break;
1058 }
1059
718db961 1060 return 0;
8d567588
LP
1061
1062fail:
81a5c6d0 1063 automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
718db961 1064 return 0;
8d567588
LP
1065}
1066
1067static void automount_shutdown(Manager *m) {
1068 assert(m);
1069
03e334a1 1070 m->dev_autofs_fd = safe_close(m->dev_autofs_fd);
8d567588
LP
1071}
1072
74ac3cbd 1073static void automount_reset_failed(Unit *u) {
5632e374
LP
1074 Automount *a = AUTOMOUNT(u);
1075
1076 assert(a);
1077
74ac3cbd 1078 if (a->state == AUTOMOUNT_FAILED)
5632e374
LP
1079 automount_set_state(a, AUTOMOUNT_DEAD);
1080
81a5c6d0 1081 a->result = AUTOMOUNT_SUCCESS;
5632e374
LP
1082}
1083
1c2e9646 1084static bool automount_supported(void) {
0faacd47
LP
1085 static int supported = -1;
1086
0faacd47
LP
1087 if (supported < 0)
1088 supported = access("/dev/autofs", F_OK) >= 0;
1089
1090 return supported;
1091}
1092
81a5c6d0
LP
1093static const char* const automount_result_table[_AUTOMOUNT_RESULT_MAX] = {
1094 [AUTOMOUNT_SUCCESS] = "success",
07299350
LP
1095 [AUTOMOUNT_FAILURE_RESOURCES] = "resources",
1096 [AUTOMOUNT_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
fae03ed3 1097 [AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT] = "mount-start-limit-hit",
81a5c6d0
LP
1098};
1099
1100DEFINE_STRING_TABLE_LOOKUP(automount_result, AutomountResult);
1101
87f0e418 1102const UnitVTable automount_vtable = {
7d17cfbc 1103 .object_size = sizeof(Automount),
718db961 1104
f975e971
LP
1105 .sections =
1106 "Unit\0"
1107 "Automount\0"
1108 "Install\0",
5cb5a6ff 1109
034c6ed7 1110 .init = automount_init,
e537352b 1111 .load = automount_load,
034c6ed7 1112 .done = automount_done,
5cb5a6ff 1113
a16e1123
LP
1114 .coldplug = automount_coldplug,
1115
034c6ed7 1116 .dump = automount_dump,
5cb5a6ff 1117
8d567588
LP
1118 .start = automount_start,
1119 .stop = automount_stop,
1120
a16e1123
LP
1121 .serialize = automount_serialize,
1122 .deserialize_item = automount_deserialize_item,
1123
10a94420 1124 .active_state = automount_active_state,
8d567588
LP
1125 .sub_state_to_string = automount_sub_state_to_string,
1126
701cc384
LP
1127 .check_gc = automount_check_gc,
1128
fae03ed3
LP
1129 .trigger_notify = automount_trigger_notify,
1130
74ac3cbd 1131 .reset_failed = automount_reset_failed,
5632e374 1132
718db961 1133 .bus_vtable = bus_automount_vtable,
afb14803
MO
1134 .bus_set_property = bus_automount_set_property,
1135
1136 .can_transient = true,
4139c1b2 1137
c6918296 1138 .shutdown = automount_shutdown,
0faacd47 1139 .supported = automount_supported,
c6918296
MS
1140
1141 .status_message_formats = {
1142 .finished_start_job = {
1143 [JOB_DONE] = "Set up automount %s.",
1144 [JOB_FAILED] = "Failed to set up automount %s.",
c6918296
MS
1145 },
1146 .finished_stop_job = {
1147 [JOB_DONE] = "Unset automount %s.",
1148 [JOB_FAILED] = "Failed to unset automount %s.",
1149 },
1150 },
5cb5a6ff 1151};