]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/mount.c
Support negated fstab options
[thirdparty/systemd.git] / src / core / mount.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>
b08d03ff
LP
23#include <stdio.h>
24#include <mntent.h>
ef734fd6 25#include <sys/epoll.h>
e537352b 26#include <signal.h>
8d3ae2bd 27#include <libmount.h>
befb6d54 28#include <sys/inotify.h>
5cb5a6ff 29
c17ec25e 30#include "manager.h"
87f0e418 31#include "unit.h"
5cb5a6ff
LP
32#include "mount.h"
33#include "load-fragment.h"
5cb5a6ff 34#include "load-dropin.h"
b08d03ff 35#include "log.h"
20ad4cfd 36#include "sd-messages.h"
e537352b 37#include "strv.h"
49e942b2 38#include "mkdir.h"
9eb977db 39#include "path-util.h"
e537352b 40#include "mount-setup.h"
9e2f7c11 41#include "unit-name.h"
4139c1b2 42#include "dbus-mount.h"
514f4ef5 43#include "special.h"
96aad8d1 44#include "bus-common-errors.h"
9a57c629 45#include "exit-status.h"
f6a6225e 46#include "def.h"
d15d0333 47#include "fstab-util.h"
5cb5a6ff 48
7d54a03a
LP
49#define RETRY_UMOUNT_MAX 32
50
4e920142
ZJS
51DEFINE_TRIVIAL_CLEANUP_FUNC(struct libmnt_table*, mnt_free_table);
52DEFINE_TRIVIAL_CLEANUP_FUNC(struct libmnt_iter*, mnt_free_iter);
53
f50e0a01
LP
54static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = {
55 [MOUNT_DEAD] = UNIT_INACTIVE,
56 [MOUNT_MOUNTING] = UNIT_ACTIVATING,
e537352b 57 [MOUNT_MOUNTING_DONE] = UNIT_ACTIVE,
f50e0a01 58 [MOUNT_MOUNTED] = UNIT_ACTIVE,
032ff4af 59 [MOUNT_REMOUNTING] = UNIT_RELOADING,
f50e0a01 60 [MOUNT_UNMOUNTING] = UNIT_DEACTIVATING,
e537352b
LP
61 [MOUNT_MOUNTING_SIGTERM] = UNIT_DEACTIVATING,
62 [MOUNT_MOUNTING_SIGKILL] = UNIT_DEACTIVATING,
032ff4af
LP
63 [MOUNT_REMOUNTING_SIGTERM] = UNIT_RELOADING,
64 [MOUNT_REMOUNTING_SIGKILL] = UNIT_RELOADING,
e537352b
LP
65 [MOUNT_UNMOUNTING_SIGTERM] = UNIT_DEACTIVATING,
66 [MOUNT_UNMOUNTING_SIGKILL] = UNIT_DEACTIVATING,
fdf20a31 67 [MOUNT_FAILED] = UNIT_FAILED
f50e0a01 68};
5cb5a6ff 69
718db961
LP
70static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
71static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
72
affc3d83 73static bool mount_needs_network(const char *options, const char *fstype) {
d15d0333 74 if (fstab_test_option(options, "_netdev\0"))
fc676b00
ZJS
75 return true;
76
affc3d83 77 if (fstype && fstype_is_network(fstype))
fc676b00
ZJS
78 return true;
79
80 return false;
81}
82
e6a7b9f4 83static bool mount_is_network(const MountParameters *p) {
affc3d83
CL
84 assert(p);
85
86 return mount_needs_network(p->options, p->fstype);
87}
88
e6a7b9f4 89static bool mount_is_bind(const MountParameters *p) {
fc676b00
ZJS
90 assert(p);
91
d15d0333 92 if (fstab_test_option(p->options, "bind\0" "rbind\0"))
fc676b00
ZJS
93 return true;
94
d15d0333 95 if (p->fstype && STR_IN_SET(p->fstype, "bind", "rbind"))
fc676b00
ZJS
96 return true;
97
98 return false;
99}
100
e6a7b9f4 101static bool mount_is_auto(const MountParameters *p) {
fc676b00
ZJS
102 assert(p);
103
d15d0333 104 return !fstab_test_option(p->options, "noauto\0");
fc676b00
ZJS
105}
106
e6a7b9f4 107static bool needs_quota(const MountParameters *p) {
fc676b00
ZJS
108 assert(p);
109
110 if (mount_is_network(p))
111 return false;
112
113 if (mount_is_bind(p))
114 return false;
115
d15d0333
ZJS
116 return fstab_test_option(p->options,
117 "usrquota\0" "grpquota\0" "quota\0" "usrjquota\0" "grpjquota\0");
fc676b00
ZJS
118}
119
a16e1123
LP
120static void mount_init(Unit *u) {
121 Mount *m = MOUNT(u);
5cb5a6ff 122
a16e1123 123 assert(u);
ac155bb8 124 assert(u->load_state == UNIT_STUB);
a16e1123 125
1f19a534 126 m->timeout_usec = u->manager->default_timeout_start_usec;
3e5235b0
LP
127 m->directory_mode = 0755;
128
6b1dc2bd
LP
129 if (unit_has_name(u, "-.mount")) {
130 /* Don't allow start/stop for root directory */
5bcb0f2b
LP
131 u->refuse_manual_start = true;
132 u->refuse_manual_stop = true;
6b1dc2bd
LP
133 } else {
134 /* The stdio/kmsg bridge socket is on /, in order to avoid a
135 * dep loop, don't use kmsg logging for -.mount */
ac155bb8
MS
136 m->exec_context.std_output = u->manager->default_std_output;
137 m->exec_context.std_error = u->manager->default_std_error;
f6cebb3b 138 }
c3686083 139
a16e1123
LP
140 /* We need to make sure that /bin/mount is always called in
141 * the same process group as us, so that the autofs kernel
142 * side doesn't send us another mount request while we are
143 * already trying to comply its last one. */
74922904 144 m->exec_context.same_pgrp = true;
8d567588 145
a16e1123 146 m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
c8f4d764 147
5bcb0f2b 148 u->ignore_on_isolate = true;
8d567588
LP
149}
150
718db961
LP
151static int mount_arm_timer(Mount *m) {
152 int r;
153
154 assert(m);
155
156 if (m->timeout_usec <= 0) {
157 m->timer_event_source = sd_event_source_unref(m->timer_event_source);
158 return 0;
159 }
160
161 if (m->timer_event_source) {
162 r = sd_event_source_set_time(m->timer_event_source, now(CLOCK_MONOTONIC) + m->timeout_usec);
163 if (r < 0)
164 return r;
165
166 return sd_event_source_set_enabled(m->timer_event_source, SD_EVENT_ONESHOT);
167 }
168
6a0f1f6d
LP
169 return sd_event_add_time(
170 UNIT(m)->manager->event,
171 &m->timer_event_source,
172 CLOCK_MONOTONIC,
173 now(CLOCK_MONOTONIC) + m->timeout_usec, 0,
174 mount_dispatch_timer, m);
718db961
LP
175}
176
a16e1123 177static void mount_unwatch_control_pid(Mount *m) {
5e94833f
LP
178 assert(m);
179
180 if (m->control_pid <= 0)
181 return;
182
183 unit_unwatch_pid(UNIT(m), m->control_pid);
184 m->control_pid = 0;
185}
186
e537352b
LP
187static void mount_parameters_done(MountParameters *p) {
188 assert(p);
189
190 free(p->what);
191 free(p->options);
192 free(p->fstype);
193
194 p->what = p->options = p->fstype = NULL;
195}
196
87f0e418 197static void mount_done(Unit *u) {
ef734fd6 198 Mount *m = MOUNT(u);
034c6ed7 199
ef734fd6 200 assert(m);
034c6ed7 201
e537352b
LP
202 free(m->where);
203 m->where = NULL;
f50e0a01 204
e537352b
LP
205 mount_parameters_done(&m->parameters_proc_self_mountinfo);
206 mount_parameters_done(&m->parameters_fragment);
ef734fd6 207
613b411c 208 m->exec_runtime = exec_runtime_unref(m->exec_runtime);
e537352b
LP
209 exec_command_done_array(m->exec_command, _MOUNT_EXEC_COMMAND_MAX);
210 m->control_command = NULL;
f50e0a01 211
a16e1123 212 mount_unwatch_control_pid(m);
f50e0a01 213
718db961 214 m->timer_event_source = sd_event_source_unref(m->timer_event_source);
f50e0a01
LP
215}
216
44a6b1b6 217_pure_ static MountParameters* get_mount_parameters_fragment(Mount *m) {
cb39ed3f
LP
218 assert(m);
219
220 if (m->from_fragment)
221 return &m->parameters_fragment;
cb39ed3f
LP
222
223 return NULL;
224}
225
44a6b1b6 226_pure_ static MountParameters* get_mount_parameters(Mount *m) {
cb39ed3f
LP
227 assert(m);
228
229 if (m->from_proc_self_mountinfo)
230 return &m->parameters_proc_self_mountinfo;
231
6b1dc2bd 232 return get_mount_parameters_fragment(m);
cb39ed3f
LP
233}
234
6e2ef85b 235static int mount_add_mount_links(Mount *m) {
a57f7e2c 236 _cleanup_free_ char *parent = NULL;
5c78d8e2 237 MountParameters *pm;
ac155bb8 238 Unit *other;
a57f7e2c
LP
239 Iterator i;
240 Set *s;
b08d03ff
LP
241 int r;
242
6e2ef85b 243 assert(m);
b08d03ff 244
a57f7e2c
LP
245 if (!path_equal(m->where, "/")) {
246 /* Adds in links to other mount points that might lie further
247 * up in the hierarchy */
248 r = path_get_parent(m->where, &parent);
4f0eedb7 249 if (r < 0)
6e2ef85b 250 return r;
01f78473 251
a57f7e2c 252 r = unit_require_mounts_for(UNIT(m), parent);
4f0eedb7 253 if (r < 0)
01f78473 254 return r;
4f0eedb7 255 }
01f78473 256
a57f7e2c
LP
257 /* Adds in links to other mount points that might be needed
258 * for the source path (if this is a bind mount) to be
259 * available. */
260 pm = get_mount_parameters_fragment(m);
fc676b00
ZJS
261 if (pm && pm->what &&
262 path_is_absolute(pm->what) &&
263 !mount_is_network(pm)) {
264
a57f7e2c 265 r = unit_require_mounts_for(UNIT(m), pm->what);
4f0eedb7 266 if (r < 0)
6e2ef85b 267 return r;
4f0eedb7 268 }
b08d03ff 269
a57f7e2c
LP
270 /* Adds in links to other units that use this path or paths
271 * further down in the hierarchy */
272 s = manager_get_units_requiring_mounts_for(UNIT(m)->manager, m->where);
273 SET_FOREACH(other, s, i) {
b08d03ff 274
a57f7e2c
LP
275 if (other->load_state != UNIT_LOADED)
276 continue;
b08d03ff 277
a57f7e2c
LP
278 if (other == UNIT(m))
279 continue;
b08d03ff 280
a57f7e2c 281 r = unit_add_dependency(other, UNIT_AFTER, UNIT(m), true);
4f0eedb7 282 if (r < 0)
6e2ef85b 283 return r;
b08d03ff 284
a57f7e2c
LP
285 if (UNIT(m)->fragment_path) {
286 /* If we have fragment configuration, then make this dependency required */
287 r = unit_add_dependency(other, UNIT_REQUIRES, UNIT(m), true);
288 if (r < 0)
289 return r;
290 }
7c8fa05c
LP
291 }
292
293 return 0;
294}
295
173a8d04
LP
296static int mount_add_device_links(Mount *m) {
297 MountParameters *p;
5073f89f 298 bool device_wants_mount = false;
9fff8a1f 299 int r;
173a8d04
LP
300
301 assert(m);
302
6b1dc2bd
LP
303 p = get_mount_parameters_fragment(m);
304 if (!p)
173a8d04
LP
305 return 0;
306
9fff8a1f 307 if (!p->what)
173a8d04 308 return 0;
5c78d8e2 309
dd144c63
LP
310 if (mount_is_bind(p))
311 return 0;
312
313 if (!is_device_path(p->what))
314 return 0;
315
316 if (path_equal(m->where, "/"))
317 return 0;
318
5073f89f
TG
319 if (mount_is_auto(p) && UNIT(m)->manager->running_as == SYSTEMD_SYSTEM)
320 device_wants_mount = true;
321
322 r = unit_add_node_link(UNIT(m), p->what, device_wants_mount);
dd144c63
LP
323 if (r < 0)
324 return r;
9fff8a1f 325
9fff8a1f 326 return 0;
173a8d04
LP
327}
328
6b1dc2bd
LP
329static int mount_add_quota_links(Mount *m) {
330 int r;
331 MountParameters *p;
332
333 assert(m);
334
67445f4e 335 if (UNIT(m)->manager->running_as != SYSTEMD_SYSTEM)
6b1dc2bd
LP
336 return 0;
337
338 p = get_mount_parameters_fragment(m);
339 if (!p)
340 return 0;
341
342 if (!needs_quota(p))
343 return 0;
344
345 r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTACHECK_SERVICE, NULL, true);
346 if (r < 0)
347 return r;
348
349 r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTAON_SERVICE, NULL, true);
350 if (r < 0)
351 return r;
352
353 return 0;
354}
355
88ac30a1
TG
356static bool should_umount(Mount *m) {
357 MountParameters *p;
358
359 if (path_equal(m->where, "/") ||
360 path_equal(m->where, "/usr"))
361 return false;
362
363 p = get_mount_parameters(m);
d15d0333 364 if (p && fstab_test_option(p->options, "x-initrd.mount\0") &&
88ac30a1
TG
365 !in_initrd())
366 return false;
367
368 return true;
369}
370
2edd4434 371static int mount_add_default_dependencies(Mount *m) {
0c17fbce 372 const char *after, *after2, *online;
9ddc4a26 373 MountParameters *p;
0c17fbce 374 int r;
2edd4434
LP
375
376 assert(m);
377
67445f4e 378 if (UNIT(m)->manager->running_as != SYSTEMD_SYSTEM)
9ddc4a26 379 return 0;
cb39ed3f 380
4d4fe926
MS
381 p = get_mount_parameters(m);
382
6b1dc2bd
LP
383 if (!p)
384 return 0;
2edd4434 385
b24de9d2
JS
386 if (path_equal(m->where, "/") ||
387 path_equal(m->where, "/usr"))
6b1dc2bd
LP
388 return 0;
389
e8d2f6cd 390 if (mount_is_network(p)) {
6b1dc2bd 391 after = SPECIAL_REMOTE_FS_PRE_TARGET;
a63a5c46 392 after2 = SPECIAL_NETWORK_TARGET;
0c17fbce 393 online = SPECIAL_NETWORK_ONLINE_TARGET;
e8d2f6cd 394 } else {
6b1dc2bd 395 after = SPECIAL_LOCAL_FS_PRE_TARGET;
a63a5c46 396 after2 = NULL;
0c17fbce 397 online = NULL;
e8d2f6cd 398 }
6b1dc2bd 399
e8d2f6cd 400 r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, NULL, true);
6b1dc2bd
LP
401 if (r < 0)
402 return r;
403
a63a5c46
LP
404 if (after2) {
405 r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after2, NULL, true);
406 if (r < 0)
407 return r;
408 }
409
0c17fbce
LP
410 if (online) {
411 r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_WANTS, UNIT_AFTER, online, NULL, true);
e8d2f6cd
LP
412 if (r < 0)
413 return r;
414 }
415
88ac30a1
TG
416 if (should_umount(m)) {
417 r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
418 if (r < 0)
419 return r;
420 }
2edd4434
LP
421
422 return 0;
423}
424
8d567588 425static int mount_verify(Mount *m) {
a57f7e2c 426 _cleanup_free_ char *e = NULL;
8d567588 427 bool b;
a57f7e2c 428
8d567588
LP
429 assert(m);
430
1124fe6f 431 if (UNIT(m)->load_state != UNIT_LOADED)
8d567588
LP
432 return 0;
433
6b1dc2bd 434 if (!m->from_fragment && !m->from_proc_self_mountinfo)
8cbef760
LP
435 return -ENOENT;
436
a57f7e2c
LP
437 e = unit_name_from_path(m->where, ".mount");
438 if (!e)
8d567588
LP
439 return -ENOMEM;
440
441 b = unit_has_name(UNIT(m), e);
8d567588 442 if (!b) {
79008bdd 443 log_unit_error(UNIT(m)->id, "%s's Where= setting doesn't match unit name. Refusing.", UNIT(m)->id);
8d567588
LP
444 return -EINVAL;
445 }
446
33ff02c9 447 if (mount_point_is_api(m->where) || mount_point_ignore(m->where)) {
79008bdd 448 log_unit_error(UNIT(m)->id, "Cannot create mount unit for API file system %s. Refusing.", m->where);
33ff02c9
LP
449 return -EINVAL;
450 }
451
1124fe6f 452 if (UNIT(m)->fragment_path && !m->parameters_fragment.what) {
79008bdd 453 log_unit_error(UNIT(m)->id, "%s's What setting is missing. Refusing.", UNIT(m)->id);
4e85aff4
LP
454 return -EBADMSG;
455 }
456
4819ff03 457 if (m->exec_context.pam_name && m->kill_context.kill_mode != KILL_CONTROL_GROUP) {
79008bdd 458 log_unit_error(UNIT(m)->id, "%s has PAM enabled. Kill mode must be set to control-group'. Refusing.",UNIT(m)->id);
4d0e5dbd
LP
459 return -EINVAL;
460 }
461
8d567588
LP
462 return 0;
463}
464
1a4ac875
MS
465static int mount_add_extras(Mount *m) {
466 Unit *u = UNIT(m);
e537352b
LP
467 int r;
468
e821075a
LP
469 assert(m);
470
471 if (u->fragment_path)
1a4ac875 472 m->from_fragment = true;
e537352b 473
1a4ac875
MS
474 if (!m->where) {
475 m->where = unit_name_to_path(u->id);
a16e1123 476 if (!m->where)
1a4ac875
MS
477 return -ENOMEM;
478 }
a16e1123 479
1a4ac875 480 path_kill_slashes(m->where);
e537352b 481
e821075a 482 if (!u->description) {
1a4ac875
MS
483 r = unit_set_description(u, m->where);
484 if (r < 0)
173a8d04 485 return r;
1a4ac875 486 }
6e2ef85b 487
1a4ac875
MS
488 r = mount_add_device_links(m);
489 if (r < 0)
490 return r;
6e2ef85b 491
1a4ac875
MS
492 r = mount_add_mount_links(m);
493 if (r < 0)
494 return r;
6e2ef85b 495
1a4ac875
MS
496 r = mount_add_quota_links(m);
497 if (r < 0)
498 return r;
e537352b 499
598459ce
LP
500 r = unit_patch_contexts(u);
501 if (r < 0)
502 return r;
4e67ddd6 503
598459ce 504 r = unit_add_exec_dependencies(u, &m->exec_context);
a016b922
LP
505 if (r < 0)
506 return r;
507
598459ce 508 r = unit_add_default_slice(u, &m->cgroup_context);
1a4ac875
MS
509 if (r < 0)
510 return r;
511
598459ce
LP
512 if (u->default_dependencies) {
513 r = mount_add_default_dependencies(m);
514 if (r < 0)
515 return r;
516 }
517
1a4ac875
MS
518 return 0;
519}
520
521static int mount_load(Unit *u) {
522 Mount *m = MOUNT(u);
523 int r;
524
525 assert(u);
526 assert(u->load_state == UNIT_STUB);
527
8eba616f
MS
528 if (m->from_proc_self_mountinfo)
529 r = unit_load_fragment_and_dropin_optional(u);
530 else
531 r = unit_load_fragment_and_dropin(u);
532
1a4ac875
MS
533 if (r < 0)
534 return r;
155da457 535
1a4ac875
MS
536 /* This is a new unit? Then let's add in some extras */
537 if (u->load_state == UNIT_LOADED) {
538 r = mount_add_extras(m);
539 if (r < 0)
540 return r;
e537352b
LP
541 }
542
8d567588 543 return mount_verify(m);
e537352b
LP
544}
545
a16e1123
LP
546static int mount_notify_automount(Mount *m, int status) {
547 Unit *p;
548 int r;
57020a3a 549 Iterator i;
a16e1123
LP
550
551 assert(m);
552
1124fe6f 553 SET_FOREACH(p, UNIT(m)->dependencies[UNIT_TRIGGERED_BY], i)
ac155bb8 554 if (p->type == UNIT_AUTOMOUNT) {
57020a3a
LP
555 r = automount_send_ready(AUTOMOUNT(p), status);
556 if (r < 0)
557 return r;
558 }
a16e1123 559
57020a3a 560 return 0;
a16e1123
LP
561}
562
e537352b
LP
563static void mount_set_state(Mount *m, MountState state) {
564 MountState old_state;
565 assert(m);
566
567 old_state = m->state;
568 m->state = state;
569
570 if (state != MOUNT_MOUNTING &&
571 state != MOUNT_MOUNTING_DONE &&
572 state != MOUNT_REMOUNTING &&
573 state != MOUNT_UNMOUNTING &&
574 state != MOUNT_MOUNTING_SIGTERM &&
575 state != MOUNT_MOUNTING_SIGKILL &&
576 state != MOUNT_UNMOUNTING_SIGTERM &&
577 state != MOUNT_UNMOUNTING_SIGKILL &&
578 state != MOUNT_REMOUNTING_SIGTERM &&
579 state != MOUNT_REMOUNTING_SIGKILL) {
718db961 580 m->timer_event_source = sd_event_source_unref(m->timer_event_source);
a16e1123 581 mount_unwatch_control_pid(m);
e537352b 582 m->control_command = NULL;
a16e1123 583 m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
e537352b
LP
584 }
585
8d567588
LP
586 if (state == MOUNT_MOUNTED ||
587 state == MOUNT_REMOUNTING)
588 mount_notify_automount(m, 0);
589 else if (state == MOUNT_DEAD ||
590 state == MOUNT_UNMOUNTING ||
591 state == MOUNT_MOUNTING_SIGTERM ||
592 state == MOUNT_MOUNTING_SIGKILL ||
593 state == MOUNT_REMOUNTING_SIGTERM ||
594 state == MOUNT_REMOUNTING_SIGKILL ||
595 state == MOUNT_UNMOUNTING_SIGTERM ||
596 state == MOUNT_UNMOUNTING_SIGKILL ||
36fcd77e 597 state == MOUNT_FAILED) {
b929bf04
TA
598 if (state != old_state)
599 mount_notify_automount(m, -ENODEV);
600 }
8d567588 601
e537352b 602 if (state != old_state)
79008bdd 603 log_unit_debug(UNIT(m)->id,
66870f90
ZJS
604 "%s changed %s -> %s",
605 UNIT(m)->id,
606 mount_state_to_string(old_state),
607 mount_state_to_string(state));
e537352b 608
9d2f5178
LP
609 unit_notify(UNIT(m), state_translation_table[old_state], state_translation_table[state], m->reload_result == MOUNT_SUCCESS);
610 m->reload_result = MOUNT_SUCCESS;
e537352b
LP
611}
612
613static int mount_coldplug(Unit *u) {
614 Mount *m = MOUNT(u);
a16e1123
LP
615 MountState new_state = MOUNT_DEAD;
616 int r;
e537352b
LP
617
618 assert(m);
619 assert(m->state == MOUNT_DEAD);
620
a16e1123
LP
621 if (m->deserialized_state != m->state)
622 new_state = m->deserialized_state;
623 else if (m->from_proc_self_mountinfo)
624 new_state = MOUNT_MOUNTED;
e537352b 625
5bcb0f2b
LP
626 if (new_state == m->state)
627 return 0;
e537352b 628
5bcb0f2b
LP
629 if (new_state == MOUNT_MOUNTING ||
630 new_state == MOUNT_MOUNTING_DONE ||
631 new_state == MOUNT_REMOUNTING ||
632 new_state == MOUNT_UNMOUNTING ||
633 new_state == MOUNT_MOUNTING_SIGTERM ||
634 new_state == MOUNT_MOUNTING_SIGKILL ||
635 new_state == MOUNT_UNMOUNTING_SIGTERM ||
636 new_state == MOUNT_UNMOUNTING_SIGKILL ||
637 new_state == MOUNT_REMOUNTING_SIGTERM ||
638 new_state == MOUNT_REMOUNTING_SIGKILL) {
639
640 if (m->control_pid <= 0)
641 return -EBADMSG;
642
643 r = unit_watch_pid(UNIT(m), m->control_pid);
644 if (r < 0)
645 return r;
e537352b 646
5bcb0f2b
LP
647 r = mount_arm_timer(m);
648 if (r < 0)
649 return r;
a16e1123 650 }
e537352b 651
5bcb0f2b 652 mount_set_state(m, new_state);
e537352b 653 return 0;
e537352b
LP
654}
655
656static void mount_dump(Unit *u, FILE *f, const char *prefix) {
657 Mount *m = MOUNT(u);
658 MountParameters *p;
659
660 assert(m);
661 assert(f);
662
cb39ed3f 663 p = get_mount_parameters(m);
e537352b
LP
664
665 fprintf(f,
666 "%sMount State: %s\n"
81a5c6d0 667 "%sResult: %s\n"
e537352b
LP
668 "%sWhere: %s\n"
669 "%sWhat: %s\n"
670 "%sFile System Type: %s\n"
671 "%sOptions: %s\n"
e537352b
LP
672 "%sFrom /proc/self/mountinfo: %s\n"
673 "%sFrom fragment: %s\n"
3e5235b0 674 "%sDirectoryMode: %04o\n",
a16e1123 675 prefix, mount_state_to_string(m->state),
81a5c6d0 676 prefix, mount_result_to_string(m->result),
e537352b 677 prefix, m->where,
1e4fc9b1
HH
678 prefix, p ? strna(p->what) : "n/a",
679 prefix, p ? strna(p->fstype) : "n/a",
680 prefix, p ? strna(p->options) : "n/a",
e537352b
LP
681 prefix, yes_no(m->from_proc_self_mountinfo),
682 prefix, yes_no(m->from_fragment),
3e5235b0 683 prefix, m->directory_mode);
e537352b
LP
684
685 if (m->control_pid > 0)
686 fprintf(f,
ccd06097
ZJS
687 "%sControl PID: "PID_FMT"\n",
688 prefix, m->control_pid);
e537352b
LP
689
690 exec_context_dump(&m->exec_context, f, prefix);
4819ff03 691 kill_context_dump(&m->kill_context, f, prefix);
e537352b
LP
692}
693
a16e1123
LP
694static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
695 pid_t pid;
696 int r;
9fa95f85
DM
697 ExecParameters exec_params = {
698 .apply_permissions = true,
699 .apply_chroot = true,
700 .apply_tty_stdin = true,
701 };
a16e1123
LP
702
703 assert(m);
704 assert(c);
705 assert(_pid);
706
4ad49000
LP
707 unit_realize_cgroup(UNIT(m));
708
613b411c
LP
709 r = unit_setup_exec_runtime(UNIT(m));
710 if (r < 0)
711 goto fail;
712
718db961 713 r = mount_arm_timer(m);
36697dc0 714 if (r < 0)
a16e1123
LP
715 goto fail;
716
9fa95f85
DM
717 exec_params.environment = UNIT(m)->manager->environment;
718 exec_params.confirm_spawn = UNIT(m)->manager->confirm_spawn;
719 exec_params.cgroup_supported = UNIT(m)->manager->cgroup_supported;
720 exec_params.cgroup_path = UNIT(m)->cgroup_path;
a931ad47 721 exec_params.cgroup_delegate = m->cgroup_context.delegate;
9fa95f85
DM
722 exec_params.runtime_prefix = manager_get_runtime_prefix(UNIT(m)->manager);
723 exec_params.unit_id = UNIT(m)->id;
724
4ad49000 725 r = exec_spawn(c,
4ad49000 726 &m->exec_context,
9fa95f85 727 &exec_params,
613b411c 728 m->exec_runtime,
4ad49000
LP
729 &pid);
730 if (r < 0)
a16e1123
LP
731 goto fail;
732
4ad49000
LP
733 r = unit_watch_pid(UNIT(m), pid);
734 if (r < 0)
a16e1123
LP
735 /* FIXME: we need to do something here */
736 goto fail;
737
738 *_pid = pid;
739
740 return 0;
741
742fail:
718db961 743 m->timer_event_source = sd_event_source_unref(m->timer_event_source);
a16e1123
LP
744
745 return r;
746}
747
9d2f5178 748static void mount_enter_dead(Mount *m, MountResult f) {
e537352b
LP
749 assert(m);
750
9d2f5178
LP
751 if (f != MOUNT_SUCCESS)
752 m->result = f;
e537352b 753
613b411c
LP
754 exec_runtime_destroy(m->exec_runtime);
755 m->exec_runtime = exec_runtime_unref(m->exec_runtime);
756
e66cf1a3
LP
757 exec_context_destroy_runtime_directory(&m->exec_context, manager_get_runtime_prefix(UNIT(m)->manager));
758
9d2f5178 759 mount_set_state(m, m->result != MOUNT_SUCCESS ? MOUNT_FAILED : MOUNT_DEAD);
e537352b
LP
760}
761
9d2f5178 762static void mount_enter_mounted(Mount *m, MountResult f) {
80876c20
LP
763 assert(m);
764
9d2f5178
LP
765 if (f != MOUNT_SUCCESS)
766 m->result = f;
80876c20
LP
767
768 mount_set_state(m, MOUNT_MOUNTED);
769}
770
9d2f5178 771static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
e537352b
LP
772 int r;
773
774 assert(m);
775
9d2f5178
LP
776 if (f != MOUNT_SUCCESS)
777 m->result = f;
e537352b 778
cd2086fe
LP
779 r = unit_kill_context(
780 UNIT(m),
781 &m->kill_context,
db2cb23b
UTL
782 (state != MOUNT_MOUNTING_SIGTERM && state != MOUNT_UNMOUNTING_SIGTERM && state != MOUNT_REMOUNTING_SIGTERM) ?
783 KILL_KILL : KILL_TERMINATE,
cd2086fe
LP
784 -1,
785 m->control_pid,
786 false);
787 if (r < 0)
788 goto fail;
e537352b 789
cd2086fe 790 if (r > 0) {
718db961 791 r = mount_arm_timer(m);
36697dc0 792 if (r < 0)
80876c20 793 goto fail;
e537352b 794
80876c20 795 mount_set_state(m, state);
ac84d1fb
LP
796 } else if (state == MOUNT_REMOUNTING_SIGTERM)
797 mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_SUCCESS);
798 else if (state == MOUNT_REMOUNTING_SIGKILL)
9d2f5178 799 mount_enter_mounted(m, MOUNT_SUCCESS);
ac84d1fb
LP
800 else if (state == MOUNT_MOUNTING_SIGTERM)
801 mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, MOUNT_SUCCESS);
802 else if (state == MOUNT_UNMOUNTING_SIGTERM)
803 mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_SUCCESS);
80876c20 804 else
9d2f5178 805 mount_enter_dead(m, MOUNT_SUCCESS);
e537352b
LP
806
807 return;
808
809fail:
79008bdd 810 log_unit_warning(UNIT(m)->id,
66870f90 811 "%s failed to kill processes: %s", UNIT(m)->id, strerror(-r));
e537352b 812
80876c20 813 if (state == MOUNT_REMOUNTING_SIGTERM || state == MOUNT_REMOUNTING_SIGKILL)
9d2f5178 814 mount_enter_mounted(m, MOUNT_FAILURE_RESOURCES);
80876c20 815 else
9d2f5178 816 mount_enter_dead(m, MOUNT_FAILURE_RESOURCES);
e537352b
LP
817}
818
20ad4cfd 819void warn_if_dir_nonempty(const char *unit, const char* where) {
056edeb9
ZJS
820 int r;
821
cd2086fe
LP
822 assert(unit);
823 assert(where);
824
056edeb9
ZJS
825 r = dir_is_empty(where);
826 if (r > 0)
20ad4cfd 827 return;
056edeb9 828 else if (r == 0)
e2cc6eca
LP
829 log_unit_struct(unit,
830 LOG_NOTICE,
831 LOG_MESSAGE_ID(SD_MESSAGE_OVERMOUNTING),
832 LOG_MESSAGE("%s: Directory %s to mount over is not empty, mounting anyway.",
833 unit, where),
056edeb9 834 "WHERE=%s", where,
056edeb9
ZJS
835 NULL);
836 else
79008bdd 837 log_unit_warning(unit,
056edeb9
ZJS
838 "MESSAGE=Failed to check directory %s: %s",
839 where, strerror(-r));
20ad4cfd
ZJS
840}
841
5261ba90
TT
842static int fail_if_symlink(const char *unit, const char* where) {
843 assert(where);
844
845 if (is_symlink(where) > 0) {
e2cc6eca
LP
846 log_unit_struct(unit,
847 LOG_ERR,
848 LOG_MESSAGE_ID(SD_MESSAGE_OVERMOUNTING),
849 LOG_MESSAGE("%s: Mount on symlink %s not allowed.",
850 unit, where),
5261ba90 851 "WHERE=%s", where,
5261ba90
TT
852 NULL);
853
854 return -ELOOP;
855 }
856 return 0;
857}
858
9d2f5178 859static void mount_enter_unmounting(Mount *m) {
e537352b
LP
860 int r;
861
862 assert(m);
863
7d54a03a
LP
864 /* Start counting our attempts */
865 if (!IN_SET(m->state,
866 MOUNT_UNMOUNTING,
867 MOUNT_UNMOUNTING_SIGTERM,
868 MOUNT_UNMOUNTING_SIGKILL))
869 m->n_retry_umount = 0;
870
a16e1123
LP
871 m->control_command_id = MOUNT_EXEC_UNMOUNT;
872 m->control_command = m->exec_command + MOUNT_EXEC_UNMOUNT;
e537352b 873
e86b3761
ZJS
874 r = exec_command_set(m->control_command, "/bin/umount", m->where, NULL);
875 if (r >= 0 && UNIT(m)->manager->running_as == SYSTEMD_SYSTEM)
876 r = exec_command_append(m->control_command, "-n", NULL);
7d54a03a 877 if (r < 0)
e537352b
LP
878 goto fail;
879
a16e1123 880 mount_unwatch_control_pid(m);
5e94833f 881
7d54a03a
LP
882 r = mount_spawn(m, m->control_command, &m->control_pid);
883 if (r < 0)
e537352b
LP
884 goto fail;
885
886 mount_set_state(m, MOUNT_UNMOUNTING);
887
888 return;
889
890fail:
79008bdd 891 log_unit_warning(UNIT(m)->id,
66870f90
ZJS
892 "%s failed to run 'umount' task: %s",
893 UNIT(m)->id, strerror(-r));
9d2f5178 894 mount_enter_mounted(m, MOUNT_FAILURE_RESOURCES);
e537352b
LP
895}
896
8d567588 897static void mount_enter_mounting(Mount *m) {
e537352b 898 int r;
cb39ed3f 899 MountParameters *p;
e537352b
LP
900
901 assert(m);
902
a16e1123
LP
903 m->control_command_id = MOUNT_EXEC_MOUNT;
904 m->control_command = m->exec_command + MOUNT_EXEC_MOUNT;
e537352b 905
d2e54fae 906 mkdir_p_label(m->where, m->directory_mode);
3e5235b0 907
20ad4cfd 908 warn_if_dir_nonempty(m->meta.id, m->where);
257f1d8e 909
cb39ed3f 910 /* Create the source directory for bind-mounts if needed */
6b1dc2bd 911 p = get_mount_parameters_fragment(m);
cb39ed3f 912 if (p && mount_is_bind(p))
d2e54fae 913 mkdir_p_label(p->what, m->directory_mode);
2b583ce6 914
5261ba90
TT
915 r = fail_if_symlink(m->meta.id, m->where);
916 if (r < 0)
917 goto fail;
918
e86b3761
ZJS
919 if (m->from_fragment) {
920 r = exec_command_set(m->control_command, "/bin/mount",
921 m->parameters_fragment.what, m->where, NULL);
922 if (r >= 0 && UNIT(m)->manager->running_as == SYSTEMD_SYSTEM)
923 r = exec_command_append(m->control_command, "-n", NULL);
924 if (r >= 0 && m->sloppy_options)
925 r = exec_command_append(m->control_command, "-s", NULL);
926 if (r >= 0 && m->parameters_fragment.fstype)
927 r = exec_command_append(m->control_command, "-t", m->parameters_fragment.fstype, NULL);
928 if (r >= 0 && m->parameters_fragment.options)
929 r = exec_command_append(m->control_command, "-o", m->parameters_fragment.options, NULL);
930 } else
e537352b
LP
931 r = -ENOENT;
932
933 if (r < 0)
934 goto fail;
935
a16e1123 936 mount_unwatch_control_pid(m);
5e94833f 937
257f1d8e
LP
938 r = mount_spawn(m, m->control_command, &m->control_pid);
939 if (r < 0)
e537352b
LP
940 goto fail;
941
942 mount_set_state(m, MOUNT_MOUNTING);
943
944 return;
945
946fail:
79008bdd 947 log_unit_warning(UNIT(m)->id,
66870f90
ZJS
948 "%s failed to run 'mount' task: %s",
949 UNIT(m)->id, strerror(-r));
9d2f5178 950 mount_enter_dead(m, MOUNT_FAILURE_RESOURCES);
e537352b
LP
951}
952
9d2f5178 953static void mount_enter_remounting(Mount *m) {
e537352b
LP
954 int r;
955
956 assert(m);
957
a16e1123
LP
958 m->control_command_id = MOUNT_EXEC_REMOUNT;
959 m->control_command = m->exec_command + MOUNT_EXEC_REMOUNT;
e537352b
LP
960
961 if (m->from_fragment) {
e537352b
LP
962 const char *o;
963
718db961
LP
964 if (m->parameters_fragment.options)
965 o = strappenda("remount,", m->parameters_fragment.options);
966 else
e537352b
LP
967 o = "remount";
968
e86b3761
ZJS
969 r = exec_command_set(m->control_command, "/bin/mount",
970 m->parameters_fragment.what, m->where,
971 "-o", o, NULL);
972 if (r >= 0 && UNIT(m)->manager->running_as == SYSTEMD_SYSTEM)
973 r = exec_command_append(m->control_command, "-n", NULL);
974 if (r >= 0 && m->sloppy_options)
975 r = exec_command_append(m->control_command, "-s", NULL);
976 if (r >= 0 && m->parameters_fragment.fstype)
977 r = exec_command_append(m->control_command, "-t", m->parameters_fragment.fstype, NULL);
6b1dc2bd 978 } else
e537352b
LP
979 r = -ENOENT;
980
60b912f6 981 if (r < 0)
e537352b 982 goto fail;
e537352b 983
a16e1123 984 mount_unwatch_control_pid(m);
5e94833f 985
718db961
LP
986 r = mount_spawn(m, m->control_command, &m->control_pid);
987 if (r < 0)
e537352b
LP
988 goto fail;
989
990 mount_set_state(m, MOUNT_REMOUNTING);
991
992 return;
993
994fail:
79008bdd 995 log_unit_warning(UNIT(m)->id,
66870f90
ZJS
996 "%s failed to run 'remount' task: %s",
997 UNIT(m)->id, strerror(-r));
9d2f5178
LP
998 m->reload_result = MOUNT_FAILURE_RESOURCES;
999 mount_enter_mounted(m, MOUNT_SUCCESS);
e537352b
LP
1000}
1001
1002static int mount_start(Unit *u) {
1003 Mount *m = MOUNT(u);
1004
1005 assert(m);
1006
1007 /* We cannot fulfill this request right now, try again later
1008 * please! */
1009 if (m->state == MOUNT_UNMOUNTING ||
1010 m->state == MOUNT_UNMOUNTING_SIGTERM ||
60b912f6
LP
1011 m->state == MOUNT_UNMOUNTING_SIGKILL ||
1012 m->state == MOUNT_MOUNTING_SIGTERM ||
1013 m->state == MOUNT_MOUNTING_SIGKILL)
e537352b
LP
1014 return -EAGAIN;
1015
1016 /* Already on it! */
60b912f6 1017 if (m->state == MOUNT_MOUNTING)
e537352b
LP
1018 return 0;
1019
fdf20a31 1020 assert(m->state == MOUNT_DEAD || m->state == MOUNT_FAILED);
e537352b 1021
9d2f5178
LP
1022 m->result = MOUNT_SUCCESS;
1023 m->reload_result = MOUNT_SUCCESS;
1024
8d567588 1025 mount_enter_mounting(m);
e537352b
LP
1026 return 0;
1027}
1028
1029static int mount_stop(Unit *u) {
1030 Mount *m = MOUNT(u);
1031
1032 assert(m);
1033
e537352b
LP
1034 /* Already on it */
1035 if (m->state == MOUNT_UNMOUNTING ||
1036 m->state == MOUNT_UNMOUNTING_SIGKILL ||
60b912f6
LP
1037 m->state == MOUNT_UNMOUNTING_SIGTERM ||
1038 m->state == MOUNT_MOUNTING_SIGTERM ||
1039 m->state == MOUNT_MOUNTING_SIGKILL)
e537352b
LP
1040 return 0;
1041
3f6c78dc
LP
1042 assert(m->state == MOUNT_MOUNTING ||
1043 m->state == MOUNT_MOUNTING_DONE ||
1044 m->state == MOUNT_MOUNTED ||
3f6c78dc
LP
1045 m->state == MOUNT_REMOUNTING ||
1046 m->state == MOUNT_REMOUNTING_SIGTERM ||
1047 m->state == MOUNT_REMOUNTING_SIGKILL);
e537352b 1048
9d2f5178 1049 mount_enter_unmounting(m);
e537352b
LP
1050 return 0;
1051}
1052
1053static int mount_reload(Unit *u) {
1054 Mount *m = MOUNT(u);
1055
1056 assert(m);
1057
1058 if (m->state == MOUNT_MOUNTING_DONE)
1059 return -EAGAIN;
1060
1061 assert(m->state == MOUNT_MOUNTED);
1062
9d2f5178 1063 mount_enter_remounting(m);
e537352b
LP
1064 return 0;
1065}
1066
a16e1123
LP
1067static int mount_serialize(Unit *u, FILE *f, FDSet *fds) {
1068 Mount *m = MOUNT(u);
1069
1070 assert(m);
1071 assert(f);
1072 assert(fds);
1073
1074 unit_serialize_item(u, f, "state", mount_state_to_string(m->state));
9d2f5178
LP
1075 unit_serialize_item(u, f, "result", mount_result_to_string(m->result));
1076 unit_serialize_item(u, f, "reload-result", mount_result_to_string(m->reload_result));
a16e1123
LP
1077
1078 if (m->control_pid > 0)
ccd06097 1079 unit_serialize_item_format(u, f, "control-pid", PID_FMT, m->control_pid);
a16e1123
LP
1080
1081 if (m->control_command_id >= 0)
1082 unit_serialize_item(u, f, "control-command", mount_exec_command_to_string(m->control_command_id));
1083
1084 return 0;
1085}
1086
1087static int mount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
1088 Mount *m = MOUNT(u);
a16e1123
LP
1089
1090 assert(u);
1091 assert(key);
1092 assert(value);
1093 assert(fds);
1094
1095 if (streq(key, "state")) {
1096 MountState state;
1097
1098 if ((state = mount_state_from_string(value)) < 0)
79008bdd 1099 log_unit_debug(u->id, "Failed to parse state value %s", value);
a16e1123
LP
1100 else
1101 m->deserialized_state = state;
9d2f5178
LP
1102 } else if (streq(key, "result")) {
1103 MountResult f;
a16e1123 1104
9d2f5178
LP
1105 f = mount_result_from_string(value);
1106 if (f < 0)
79008bdd 1107 log_unit_debug(UNIT(m)->id,
66870f90 1108 "Failed to parse result value %s", value);
9d2f5178
LP
1109 else if (f != MOUNT_SUCCESS)
1110 m->result = f;
1111
1112 } else if (streq(key, "reload-result")) {
1113 MountResult f;
1114
1115 f = mount_result_from_string(value);
1116 if (f < 0)
79008bdd 1117 log_unit_debug(UNIT(m)->id,
66870f90 1118 "Failed to parse reload result value %s", value);
9d2f5178
LP
1119 else if (f != MOUNT_SUCCESS)
1120 m->reload_result = f;
a16e1123
LP
1121
1122 } else if (streq(key, "control-pid")) {
5925dd3c 1123 pid_t pid;
a16e1123 1124
e364ad06 1125 if (parse_pid(value, &pid) < 0)
79008bdd 1126 log_unit_debug(UNIT(m)->id,
66870f90 1127 "Failed to parse control-pid value %s", value);
a16e1123 1128 else
5925dd3c 1129 m->control_pid = pid;
a16e1123
LP
1130 } else if (streq(key, "control-command")) {
1131 MountExecCommand id;
1132
1133 if ((id = mount_exec_command_from_string(value)) < 0)
79008bdd 1134 log_unit_debug(UNIT(m)->id,
66870f90 1135 "Failed to parse exec-command value %s", value);
a16e1123
LP
1136 else {
1137 m->control_command_id = id;
1138 m->control_command = m->exec_command + id;
1139 }
a16e1123 1140 } else
79008bdd 1141 log_unit_debug(UNIT(m)->id,
66870f90 1142 "Unknown serialization key '%s'", key);
a16e1123
LP
1143
1144 return 0;
1145}
1146
44a6b1b6 1147_pure_ static UnitActiveState mount_active_state(Unit *u) {
e537352b
LP
1148 assert(u);
1149
1150 return state_translation_table[MOUNT(u)->state];
1151}
1152
44a6b1b6 1153_pure_ static const char *mount_sub_state_to_string(Unit *u) {
10a94420
LP
1154 assert(u);
1155
a16e1123 1156 return mount_state_to_string(MOUNT(u)->state);
10a94420
LP
1157}
1158
44a6b1b6 1159_pure_ static bool mount_check_gc(Unit *u) {
701cc384
LP
1160 Mount *m = MOUNT(u);
1161
1162 assert(m);
1163
6b1dc2bd 1164 return m->from_proc_self_mountinfo;
701cc384
LP
1165}
1166
e537352b
LP
1167static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
1168 Mount *m = MOUNT(u);
9d2f5178 1169 MountResult f;
e537352b
LP
1170
1171 assert(m);
1172 assert(pid >= 0);
1173
8c47c732
LP
1174 if (pid != m->control_pid)
1175 return;
e537352b 1176
e537352b
LP
1177 m->control_pid = 0;
1178
96342de6 1179 if (is_clean_exit(code, status, NULL))
9d2f5178
LP
1180 f = MOUNT_SUCCESS;
1181 else if (code == CLD_EXITED)
1182 f = MOUNT_FAILURE_EXIT_CODE;
1183 else if (code == CLD_KILLED)
1184 f = MOUNT_FAILURE_SIGNAL;
1185 else if (code == CLD_DUMPED)
1186 f = MOUNT_FAILURE_CORE_DUMP;
1187 else
1188 assert_not_reached("Unknown code");
1189
1190 if (f != MOUNT_SUCCESS)
1191 m->result = f;
8c47c732 1192
a16e1123 1193 if (m->control_command) {
6ea832a2 1194 exec_status_exit(&m->control_command->exec_status, &m->exec_context, pid, code, status);
9d2f5178 1195
a16e1123
LP
1196 m->control_command = NULL;
1197 m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
1198 }
1199
79008bdd
LP
1200 log_unit_full(u->id,
1201 f == MOUNT_SUCCESS ? LOG_DEBUG : LOG_NOTICE,
66870f90
ZJS
1202 "%s mount process exited, code=%s status=%i",
1203 u->id, sigchld_code_to_string(code), status);
e537352b
LP
1204
1205 /* Note that mount(8) returning and the kernel sending us a
1206 * mount table change event might happen out-of-order. If an
1207 * operation succeed we assume the kernel will follow soon too
1208 * and already change into the resulting state. If it fails
1209 * we check if the kernel still knows about the mount. and
1210 * change state accordingly. */
1211
1212 switch (m->state) {
1213
1214 case MOUNT_MOUNTING:
1215 case MOUNT_MOUNTING_DONE:
1216 case MOUNT_MOUNTING_SIGKILL:
1217 case MOUNT_MOUNTING_SIGTERM:
e537352b 1218
9d2f5178
LP
1219 if (f == MOUNT_SUCCESS)
1220 mount_enter_mounted(m, f);
e537352b 1221 else if (m->from_proc_self_mountinfo)
9d2f5178 1222 mount_enter_mounted(m, f);
e537352b 1223 else
9d2f5178 1224 mount_enter_dead(m, f);
e537352b
LP
1225 break;
1226
e2f3b44c
LP
1227 case MOUNT_REMOUNTING:
1228 case MOUNT_REMOUNTING_SIGKILL:
1229 case MOUNT_REMOUNTING_SIGTERM:
1230
9d2f5178 1231 m->reload_result = f;
e2f3b44c 1232 if (m->from_proc_self_mountinfo)
9d2f5178 1233 mount_enter_mounted(m, MOUNT_SUCCESS);
e2f3b44c 1234 else
9d2f5178 1235 mount_enter_dead(m, MOUNT_SUCCESS);
e2f3b44c
LP
1236
1237 break;
1238
e537352b
LP
1239 case MOUNT_UNMOUNTING:
1240 case MOUNT_UNMOUNTING_SIGKILL:
1241 case MOUNT_UNMOUNTING_SIGTERM:
1242
7d54a03a
LP
1243 if (f == MOUNT_SUCCESS) {
1244
1245 if (m->from_proc_self_mountinfo) {
1246
1247 /* Still a mount point? If so, let's
1248 * try again. Most likely there were
1249 * multiple mount points stacked on
1250 * top of each other. Note that due to
1251 * the io event priority logic we can
1252 * be sure the new mountinfo is loaded
1253 * before we process the SIGCHLD for
1254 * the mount command. */
1255
1256 if (m->n_retry_umount < RETRY_UMOUNT_MAX) {
1257 log_unit_debug(u->id, "%s: mount still present, trying again.", u->id);
1258 m->n_retry_umount++;
1259 mount_enter_unmounting(m);
1260 } else {
1261 log_unit_debug(u->id, "%s: mount still present after %u attempts to unmount, giving up.", u->id, m->n_retry_umount);
1262 mount_enter_mounted(m, f);
1263 }
1264 } else
1265 mount_enter_dead(m, f);
1266
1267 } else if (m->from_proc_self_mountinfo)
9d2f5178 1268 mount_enter_mounted(m, f);
e537352b 1269 else
9d2f5178 1270 mount_enter_dead(m, f);
e537352b
LP
1271 break;
1272
1273 default:
1274 assert_not_reached("Uh, control process died at wrong time.");
1275 }
c4e2ceae
LP
1276
1277 /* Notify clients about changed exit status */
1278 unit_add_to_dbus_queue(u);
e537352b
LP
1279}
1280
718db961
LP
1281static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
1282 Mount *m = MOUNT(userdata);
e537352b
LP
1283
1284 assert(m);
718db961 1285 assert(m->timer_event_source == source);
e537352b
LP
1286
1287 switch (m->state) {
1288
1289 case MOUNT_MOUNTING:
1290 case MOUNT_MOUNTING_DONE:
79008bdd 1291 log_unit_warning(UNIT(m)->id,
718db961 1292 "%s mounting timed out. Stopping.", UNIT(m)->id);
9d2f5178 1293 mount_enter_signal(m, MOUNT_MOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
e537352b
LP
1294 break;
1295
1296 case MOUNT_REMOUNTING:
79008bdd 1297 log_unit_warning(UNIT(m)->id,
718db961 1298 "%s remounting timed out. Stopping.", UNIT(m)->id);
9d2f5178
LP
1299 m->reload_result = MOUNT_FAILURE_TIMEOUT;
1300 mount_enter_mounted(m, MOUNT_SUCCESS);
e537352b
LP
1301 break;
1302
1303 case MOUNT_UNMOUNTING:
79008bdd 1304 log_unit_warning(UNIT(m)->id,
718db961 1305 "%s unmounting timed out. Stopping.", UNIT(m)->id);
9d2f5178 1306 mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
e537352b
LP
1307 break;
1308
1309 case MOUNT_MOUNTING_SIGTERM:
4819ff03 1310 if (m->kill_context.send_sigkill) {
79008bdd 1311 log_unit_warning(UNIT(m)->id,
718db961 1312 "%s mounting timed out. Killing.", UNIT(m)->id);
9d2f5178 1313 mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
ba035df2 1314 } else {
79008bdd 1315 log_unit_warning(UNIT(m)->id,
66870f90 1316 "%s mounting timed out. Skipping SIGKILL. Ignoring.",
718db961 1317 UNIT(m)->id);
ba035df2
LP
1318
1319 if (m->from_proc_self_mountinfo)
9d2f5178 1320 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1321 else
9d2f5178 1322 mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1323 }
e537352b
LP
1324 break;
1325
1326 case MOUNT_REMOUNTING_SIGTERM:
4819ff03 1327 if (m->kill_context.send_sigkill) {
79008bdd 1328 log_unit_warning(UNIT(m)->id,
718db961 1329 "%s remounting timed out. Killing.", UNIT(m)->id);
9d2f5178 1330 mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
ba035df2 1331 } else {
79008bdd 1332 log_unit_warning(UNIT(m)->id,
66870f90 1333 "%s remounting timed out. Skipping SIGKILL. Ignoring.",
718db961 1334 UNIT(m)->id);
ba035df2
LP
1335
1336 if (m->from_proc_self_mountinfo)
9d2f5178 1337 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1338 else
9d2f5178 1339 mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1340 }
e537352b
LP
1341 break;
1342
1343 case MOUNT_UNMOUNTING_SIGTERM:
4819ff03 1344 if (m->kill_context.send_sigkill) {
79008bdd 1345 log_unit_warning(UNIT(m)->id,
718db961 1346 "%s unmounting timed out. Killing.", UNIT(m)->id);
9d2f5178 1347 mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
ba035df2 1348 } else {
79008bdd 1349 log_unit_warning(UNIT(m)->id,
66870f90 1350 "%s unmounting timed out. Skipping SIGKILL. Ignoring.",
718db961 1351 UNIT(m)->id);
ba035df2
LP
1352
1353 if (m->from_proc_self_mountinfo)
9d2f5178 1354 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1355 else
9d2f5178 1356 mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1357 }
e537352b
LP
1358 break;
1359
1360 case MOUNT_MOUNTING_SIGKILL:
1361 case MOUNT_REMOUNTING_SIGKILL:
1362 case MOUNT_UNMOUNTING_SIGKILL:
79008bdd 1363 log_unit_warning(UNIT(m)->id,
66870f90 1364 "%s mount process still around after SIGKILL. Ignoring.",
718db961 1365 UNIT(m)->id);
e537352b
LP
1366
1367 if (m->from_proc_self_mountinfo)
9d2f5178 1368 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
e537352b 1369 else
9d2f5178 1370 mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
e537352b
LP
1371 break;
1372
1373 default:
1374 assert_not_reached("Timeout at wrong time.");
1375 }
718db961
LP
1376
1377 return 0;
e537352b
LP
1378}
1379
1380static int mount_add_one(
1381 Manager *m,
1382 const char *what,
1383 const char *where,
1384 const char *options,
1385 const char *fstype,
e537352b 1386 bool set_flags) {
057d9ab8
LP
1387
1388 _cleanup_free_ char *e = NULL, *w = NULL, *o = NULL, *f = NULL;
b87705cd 1389 bool load_extras = false;
057d9ab8 1390 MountParameters *p;
ff5f34d0 1391 bool delete, changed = false;
057d9ab8
LP
1392 Unit *u;
1393 int r;
b08d03ff 1394
f50e0a01 1395 assert(m);
b08d03ff
LP
1396 assert(what);
1397 assert(where);
e537352b
LP
1398 assert(options);
1399 assert(fstype);
1400
e537352b
LP
1401 /* Ignore API mount points. They should never be referenced in
1402 * dependencies ever. */
33ff02c9 1403 if (mount_point_is_api(where) || mount_point_ignore(where))
57f2a956 1404 return 0;
b08d03ff 1405
8d567588
LP
1406 if (streq(fstype, "autofs"))
1407 return 0;
1408
4e85aff4
LP
1409 /* probably some kind of swap, ignore */
1410 if (!is_path(where))
b08d03ff
LP
1411 return 0;
1412
7d17cfbc
MS
1413 e = unit_name_from_path(where, ".mount");
1414 if (!e)
b08d03ff
LP
1415 return -ENOMEM;
1416
7d17cfbc
MS
1417 u = manager_get_unit(m, e);
1418 if (!u) {
b08d03ff
LP
1419 delete = true;
1420
7d17cfbc 1421 u = unit_new(m, sizeof(Mount));
057d9ab8 1422 if (!u)
b08d03ff 1423 return -ENOMEM;
b08d03ff
LP
1424
1425 r = unit_add_name(u, e);
b08d03ff
LP
1426 if (r < 0)
1427 goto fail;
1428
7d17cfbc
MS
1429 MOUNT(u)->where = strdup(where);
1430 if (!MOUNT(u)->where) {
07b0b134
ML
1431 r = -ENOMEM;
1432 goto fail;
1433 }
f50e0a01 1434
47a81ba2
UTL
1435 u->source_path = strdup("/proc/self/mountinfo");
1436 if (!u->source_path) {
1437 r = -ENOMEM;
1438 goto fail;
1439 }
1440
057d9ab8
LP
1441 if (m->running_as == SYSTEMD_SYSTEM) {
1442 const char* target;
1443
affc3d83 1444 target = mount_needs_network(options, fstype) ? SPECIAL_REMOTE_FS_TARGET : SPECIAL_LOCAL_FS_TARGET;
057d9ab8 1445 r = unit_add_dependency_by_name(u, UNIT_BEFORE, target, NULL, true);
602c0e74
LP
1446 if (r < 0)
1447 goto fail;
057d9ab8
LP
1448
1449 if (should_umount(MOUNT(u))) {
1450 r = unit_add_dependency_by_name(u, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
1451 if (r < 0)
1452 goto fail;
1453 }
602c0e74 1454 }
89b1d5e0 1455
f94ea366 1456 unit_add_to_load_queue(u);
ff5f34d0 1457 changed = true;
b08d03ff
LP
1458 } else {
1459 delete = false;
8eba616f 1460
bcbd5405
WW
1461 if (!MOUNT(u)->where) {
1462 MOUNT(u)->where = strdup(where);
1463 if (!MOUNT(u)->where) {
1464 r = -ENOMEM;
1465 goto fail;
1466 }
1467 }
1468
9d05dd2e
ZJS
1469 if (m->running_as == SYSTEMD_SYSTEM &&
1470 mount_needs_network(options, fstype)) {
a6d305f9
CL
1471 /* _netdev option may have shown up late, or on a
1472 * remount. Add remote-fs dependencies, even though
9d05dd2e
ZJS
1473 * local-fs ones may already be there. */
1474 unit_add_dependency_by_name(u, UNIT_BEFORE, SPECIAL_REMOTE_FS_TARGET, NULL, true);
1475 load_extras = true;
a6d305f9
CL
1476 }
1477
c2756a68 1478 if (u->load_state == UNIT_NOT_FOUND) {
8eba616f
MS
1479 u->load_state = UNIT_LOADED;
1480 u->load_error = 0;
b87705cd
LP
1481
1482 /* Load in the extras later on, after we
1483 * finished initialization of the unit */
1484 load_extras = true;
ff5f34d0 1485 changed = true;
8eba616f 1486 }
b08d03ff
LP
1487 }
1488
dd7a22a9
LP
1489 w = strdup(what);
1490 o = strdup(options);
1491 f = strdup(fstype);
1492 if (!w || !o || !f) {
e537352b
LP
1493 r = -ENOMEM;
1494 goto fail;
1495 }
1496
6b1dc2bd 1497 p = &MOUNT(u)->parameters_proc_self_mountinfo;
ff5f34d0
LP
1498
1499 changed = changed ||
1500 !streq_ptr(p->options, options) ||
1501 !streq_ptr(p->what, what) ||
1502 !streq_ptr(p->fstype, fstype);
1503
6b1dc2bd
LP
1504 if (set_flags) {
1505 MOUNT(u)->is_mounted = true;
1506 MOUNT(u)->just_mounted = !MOUNT(u)->from_proc_self_mountinfo;
ff5f34d0 1507 MOUNT(u)->just_changed = changed;
ef734fd6 1508 }
f50e0a01 1509
6b1dc2bd
LP
1510 MOUNT(u)->from_proc_self_mountinfo = true;
1511
4e85aff4
LP
1512 free(p->what);
1513 p->what = w;
057d9ab8 1514 w = NULL;
b08d03ff 1515
4e85aff4
LP
1516 free(p->options);
1517 p->options = o;
057d9ab8 1518 o = NULL;
e537352b 1519
4e85aff4
LP
1520 free(p->fstype);
1521 p->fstype = f;
057d9ab8 1522 f = NULL;
b08d03ff 1523
b87705cd
LP
1524 if (load_extras) {
1525 r = mount_add_extras(MOUNT(u));
1526 if (r < 0)
1527 goto fail;
1528 }
1529
ff5f34d0
LP
1530 if (changed)
1531 unit_add_to_dbus_queue(u);
c1e1601e 1532
b08d03ff
LP
1533 return 0;
1534
1535fail:
1536 if (delete && u)
1537 unit_free(u);
1538
4e85aff4 1539 return r;
b08d03ff
LP
1540}
1541
ef734fd6 1542static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
4e920142
ZJS
1543 _cleanup_(mnt_free_tablep) struct libmnt_table *tb = NULL;
1544 _cleanup_(mnt_free_iterp) struct libmnt_iter *itr = NULL;
8d3ae2bd 1545 struct libmnt_fs *fs;
60b912f6 1546 int r = 0;
b08d03ff
LP
1547
1548 assert(m);
1549
8d3ae2bd
CL
1550 tb = mnt_new_table();
1551 itr = mnt_new_iter(MNT_ITER_FORWARD);
1552 if (!tb || !itr)
1553 return log_oom();
b08d03ff 1554
5cca8def
ZJS
1555 r = mnt_table_parse_mtab(tb, NULL);
1556 if (r < 0)
8d3ae2bd 1557 return r;
e537352b 1558
5cca8def
ZJS
1559 r = 0;
1560 for (;;) {
8d3ae2bd
CL
1561 const char *device, *path, *options, *fstype;
1562 _cleanup_free_ const char *d = NULL, *p = NULL;
1563 int k;
b08d03ff 1564
5cca8def
ZJS
1565 k = mnt_table_next_fs(tb, itr, &fs);
1566 if (k == 1)
1567 break;
1568 else if (k < 0)
1569 return log_error_errno(k, "Failed to get next entry from /etc/fstab: %m");
1570
8d3ae2bd
CL
1571 device = mnt_fs_get_source(fs);
1572 path = mnt_fs_get_target(fs);
1573 options = mnt_fs_get_options(fs);
1574 fstype = mnt_fs_get_fstype(fs);
a2e0f3d3 1575
a57f7e2c
LP
1576 d = cunescape(device);
1577 p = cunescape(path);
1578 if (!d || !p)
1579 return log_oom();
b08d03ff 1580
8d3ae2bd 1581 k = mount_add_one(m, d, p, options, fstype, set_flags);
5cca8def 1582 if (r == 0 && k < 0)
60b912f6 1583 r = k;
b08d03ff
LP
1584 }
1585
e537352b
LP
1586 return r;
1587}
1588
1589static void mount_shutdown(Manager *m) {
1590 assert(m);
1591
718db961 1592 m->mount_event_source = sd_event_source_unref(m->mount_event_source);
befb6d54 1593 m->mount_utab_event_source = sd_event_source_unref(m->mount_utab_event_source);
718db961 1594
a16e1123 1595 if (m->proc_self_mountinfo) {
e537352b 1596 fclose(m->proc_self_mountinfo);
a16e1123
LP
1597 m->proc_self_mountinfo = NULL;
1598 }
befb6d54 1599 m->utab_inotify_fd = safe_close(m->utab_inotify_fd);
b08d03ff
LP
1600}
1601
68db7a3b
ZJS
1602static int mount_get_timeout(Unit *u, uint64_t *timeout) {
1603 Mount *m = MOUNT(u);
1604 int r;
1605
1606 if (!m->timer_event_source)
1607 return 0;
1608
1609 r = sd_event_source_get_time(m->timer_event_source, timeout);
1610 if (r < 0)
1611 return r;
1612
1613 return 1;
1614}
1615
b08d03ff
LP
1616static int mount_enumerate(Manager *m) {
1617 int r;
1618 assert(m);
1619
8d3ae2bd
CL
1620 mnt_init_debug(0);
1621
a16e1123 1622 if (!m->proc_self_mountinfo) {
e62d8c39
ZJS
1623 m->proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
1624 if (!m->proc_self_mountinfo)
a16e1123 1625 return -errno;
ef734fd6 1626
151b9b96 1627 r = sd_event_add_io(m->event, &m->mount_event_source, fileno(m->proc_self_mountinfo), EPOLLPRI, mount_dispatch_io, m);
718db961
LP
1628 if (r < 0)
1629 goto fail;
29083707
LP
1630
1631 /* Dispatch this before we dispatch SIGCHLD, so that
1632 * we always get the events from /proc/self/mountinfo
1633 * before the SIGCHLD of /bin/mount. */
1634 r = sd_event_source_set_priority(m->mount_event_source, -10);
1635 if (r < 0)
1636 goto fail;
a16e1123 1637 }
ef734fd6 1638
befb6d54
CL
1639 if (m->utab_inotify_fd < 0) {
1640 m->utab_inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
f7c1ad4f
LP
1641 if (m->utab_inotify_fd < 0) {
1642 r = -errno;
1643 goto fail;
1644 }
befb6d54 1645
90598531
ZJS
1646 (void) mkdir_p_label("/run/mount", 0755);
1647
befb6d54 1648 r = inotify_add_watch(m->utab_inotify_fd, "/run/mount", IN_MOVED_TO);
f7c1ad4f
LP
1649 if (r < 0) {
1650 r = -errno;
1651 goto fail;
1652 }
befb6d54
CL
1653
1654 r = sd_event_add_io(m->event, &m->mount_utab_event_source, m->utab_inotify_fd, EPOLLIN, mount_dispatch_io, m);
1655 if (r < 0)
1656 goto fail;
1657
1658 r = sd_event_source_set_priority(m->mount_utab_event_source, -10);
1659 if (r < 0)
1660 goto fail;
1661 }
1662
e62d8c39
ZJS
1663 r = mount_load_proc_self_mountinfo(m, false);
1664 if (r < 0)
b08d03ff
LP
1665 goto fail;
1666
1667 return 0;
1668
1669fail:
1670 mount_shutdown(m);
1671 return r;
5cb5a6ff
LP
1672}
1673
718db961
LP
1674static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
1675 Manager *m = userdata;
595ed347 1676 Unit *u;
ef734fd6
LP
1677 int r;
1678
1679 assert(m);
befb6d54 1680 assert(revents & (EPOLLPRI | EPOLLIN));
ef734fd6
LP
1681
1682 /* The manager calls this for every fd event happening on the
1683 * /proc/self/mountinfo file, which informs us about mounting
fddf1a31
ZJS
1684 * table changes, and for /run/mount events which we watch
1685 * for mount options. */
befb6d54
CL
1686
1687 if (fd == m->utab_inotify_fd) {
df63dda6 1688 bool rescan = false;
befb6d54 1689
b7307642
LP
1690 /* FIXME: We *really* need to replace this with
1691 * libmount's own API for this, we should not hardcode
1692 * internal behaviour of libmount here. */
1693
f7c1ad4f 1694 for (;;) {
0254e944 1695 union inotify_event_buffer buffer;
f7c1ad4f
LP
1696 struct inotify_event *e;
1697 ssize_t l;
1698
0254e944 1699 l = read(fd, &buffer, sizeof(buffer));
f7c1ad4f
LP
1700 if (l < 0) {
1701 if (errno == EAGAIN || errno == EINTR)
1702 break;
1703
1704 log_error_errno(errno, "Failed to read utab inotify: %m");
1705 break;
1706 }
1707
1708 FOREACH_INOTIFY_EVENT(e, buffer, l) {
1709 /* Only care about changes to utab,
1710 * but we have to monitor the
1711 * directory to reliably get
1712 * notifications about when utab is
1713 * replaced using rename(2) */
1714 if ((e->mask & IN_Q_OVERFLOW) || streq(e->name, "utab"))
df63dda6 1715 rescan = true;
befb6d54 1716 }
f7c1ad4f 1717 }
fddf1a31 1718
befb6d54
CL
1719 if (!rescan)
1720 return 0;
1721 }
ef734fd6 1722
4f0eedb7
ZJS
1723 r = mount_load_proc_self_mountinfo(m, true);
1724 if (r < 0) {
da927ba9 1725 log_error_errno(r, "Failed to reread /proc/self/mountinfo: %m");
e537352b
LP
1726
1727 /* Reset flags, just in case, for later calls */
595ed347
MS
1728 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) {
1729 Mount *mount = MOUNT(u);
e537352b
LP
1730
1731 mount->is_mounted = mount->just_mounted = mount->just_changed = false;
1732 }
1733
718db961 1734 return 0;
ef734fd6
LP
1735 }
1736
1737 manager_dispatch_load_queue(m);
1738
595ed347
MS
1739 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) {
1740 Mount *mount = MOUNT(u);
ef734fd6 1741
e537352b 1742 if (!mount->is_mounted) {
e537352b 1743
ef734fd6 1744 mount->from_proc_self_mountinfo = false;
e537352b
LP
1745
1746 switch (mount->state) {
1747
1748 case MOUNT_MOUNTED:
aef83136
LP
1749 /* This has just been unmounted by
1750 * somebody else, follow the state
1751 * change. */
9d2f5178 1752 mount_enter_dead(mount, MOUNT_SUCCESS);
e537352b
LP
1753 break;
1754
1755 default:
e537352b 1756 break;
e537352b
LP
1757 }
1758
1759 } else if (mount->just_mounted || mount->just_changed) {
1760
60b912f6 1761 /* New or changed mount entry */
e537352b
LP
1762
1763 switch (mount->state) {
1764
1765 case MOUNT_DEAD:
fdf20a31 1766 case MOUNT_FAILED:
aef83136
LP
1767 /* This has just been mounted by
1768 * somebody else, follow the state
1769 * change. */
9d2f5178 1770 mount_enter_mounted(mount, MOUNT_SUCCESS);
e537352b
LP
1771 break;
1772
1773 case MOUNT_MOUNTING:
5bcb0f2b 1774 mount_set_state(mount, MOUNT_MOUNTING_DONE);
e537352b
LP
1775 break;
1776
1777 default:
1778 /* Nothing really changed, but let's
1779 * issue an notification call
1780 * nonetheless, in case somebody is
1781 * waiting for this. (e.g. file system
1782 * ro/rw remounts.) */
1783 mount_set_state(mount, mount->state);
1784 break;
1785 }
1786 }
1787
1788 /* Reset the flags for later calls */
1789 mount->is_mounted = mount->just_mounted = mount->just_changed = false;
1790 }
718db961
LP
1791
1792 return 0;
e537352b
LP
1793}
1794
fdf20a31 1795static void mount_reset_failed(Unit *u) {
5632e374
LP
1796 Mount *m = MOUNT(u);
1797
1798 assert(m);
1799
fdf20a31 1800 if (m->state == MOUNT_FAILED)
5632e374
LP
1801 mount_set_state(m, MOUNT_DEAD);
1802
9d2f5178
LP
1803 m->result = MOUNT_SUCCESS;
1804 m->reload_result = MOUNT_SUCCESS;
5632e374
LP
1805}
1806
718db961 1807static int mount_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
814cc562 1808 return unit_kill_common(u, who, signo, -1, MOUNT(u)->control_pid, error);
8a0867d6
LP
1809}
1810
a16e1123
LP
1811static const char* const mount_state_table[_MOUNT_STATE_MAX] = {
1812 [MOUNT_DEAD] = "dead",
1813 [MOUNT_MOUNTING] = "mounting",
1814 [MOUNT_MOUNTING_DONE] = "mounting-done",
1815 [MOUNT_MOUNTED] = "mounted",
1816 [MOUNT_REMOUNTING] = "remounting",
1817 [MOUNT_UNMOUNTING] = "unmounting",
1818 [MOUNT_MOUNTING_SIGTERM] = "mounting-sigterm",
1819 [MOUNT_MOUNTING_SIGKILL] = "mounting-sigkill",
1820 [MOUNT_REMOUNTING_SIGTERM] = "remounting-sigterm",
1821 [MOUNT_REMOUNTING_SIGKILL] = "remounting-sigkill",
1822 [MOUNT_UNMOUNTING_SIGTERM] = "unmounting-sigterm",
1823 [MOUNT_UNMOUNTING_SIGKILL] = "unmounting-sigkill",
fdf20a31 1824 [MOUNT_FAILED] = "failed"
a16e1123
LP
1825};
1826
1827DEFINE_STRING_TABLE_LOOKUP(mount_state, MountState);
1828
1829static const char* const mount_exec_command_table[_MOUNT_EXEC_COMMAND_MAX] = {
1830 [MOUNT_EXEC_MOUNT] = "ExecMount",
1831 [MOUNT_EXEC_UNMOUNT] = "ExecUnmount",
1832 [MOUNT_EXEC_REMOUNT] = "ExecRemount",
1833};
1834
1835DEFINE_STRING_TABLE_LOOKUP(mount_exec_command, MountExecCommand);
1836
9d2f5178
LP
1837static const char* const mount_result_table[_MOUNT_RESULT_MAX] = {
1838 [MOUNT_SUCCESS] = "success",
1839 [MOUNT_FAILURE_RESOURCES] = "resources",
1840 [MOUNT_FAILURE_TIMEOUT] = "timeout",
1841 [MOUNT_FAILURE_EXIT_CODE] = "exit-code",
1842 [MOUNT_FAILURE_SIGNAL] = "signal",
1843 [MOUNT_FAILURE_CORE_DUMP] = "core-dump"
1844};
1845
1846DEFINE_STRING_TABLE_LOOKUP(mount_result, MountResult);
1847
87f0e418 1848const UnitVTable mount_vtable = {
7d17cfbc 1849 .object_size = sizeof(Mount),
718db961
LP
1850 .exec_context_offset = offsetof(Mount, exec_context),
1851 .cgroup_context_offset = offsetof(Mount, cgroup_context),
1852 .kill_context_offset = offsetof(Mount, kill_context),
613b411c 1853 .exec_runtime_offset = offsetof(Mount, exec_runtime),
3ef63c31 1854
f975e971
LP
1855 .sections =
1856 "Unit\0"
1857 "Mount\0"
1858 "Install\0",
4ad49000 1859 .private_section = "Mount",
71645aca 1860
e537352b 1861 .no_alias = true,
9e2f7c11 1862 .no_instances = true,
e537352b
LP
1863
1864 .init = mount_init,
1865 .load = mount_load,
034c6ed7 1866 .done = mount_done,
e537352b 1867
f50e0a01
LP
1868 .coldplug = mount_coldplug,
1869
034c6ed7 1870 .dump = mount_dump,
5cb5a6ff 1871
e537352b
LP
1872 .start = mount_start,
1873 .stop = mount_stop,
1874 .reload = mount_reload,
1875
8a0867d6
LP
1876 .kill = mount_kill,
1877
a16e1123
LP
1878 .serialize = mount_serialize,
1879 .deserialize_item = mount_deserialize_item,
1880
f50e0a01 1881 .active_state = mount_active_state,
10a94420 1882 .sub_state_to_string = mount_sub_state_to_string,
b08d03ff 1883
701cc384
LP
1884 .check_gc = mount_check_gc,
1885
e537352b 1886 .sigchld_event = mount_sigchld_event,
e537352b 1887
fdf20a31 1888 .reset_failed = mount_reset_failed,
5632e374 1889
c4e2ceae 1890 .bus_interface = "org.freedesktop.systemd1.Mount",
718db961 1891 .bus_vtable = bus_mount_vtable,
74c964d3
LP
1892 .bus_set_property = bus_mount_set_property,
1893 .bus_commit_properties = bus_mount_commit_properties,
4139c1b2 1894
68db7a3b
ZJS
1895 .get_timeout = mount_get_timeout,
1896
0e252f6b
TG
1897 .can_transient = true,
1898
f50e0a01 1899 .enumerate = mount_enumerate,
c6918296
MS
1900 .shutdown = mount_shutdown,
1901
1902 .status_message_formats = {
1903 .starting_stopping = {
1904 [0] = "Mounting %s...",
1905 [1] = "Unmounting %s...",
1906 },
1907 .finished_start_job = {
1908 [JOB_DONE] = "Mounted %s.",
1909 [JOB_FAILED] = "Failed to mount %s.",
1910 [JOB_DEPENDENCY] = "Dependency failed for %s.",
1911 [JOB_TIMEOUT] = "Timed out mounting %s.",
1912 },
1913 .finished_stop_job = {
1914 [JOB_DONE] = "Unmounted %s.",
1915 [JOB_FAILED] = "Failed unmounting %s.",
1916 [JOB_TIMEOUT] = "Timed out unmounting %s.",
1917 },
1918 },
5cb5a6ff 1919};