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