]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/mount.c
udev: Add builtin/rule to export evdev information as udev properties
[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 919 if (m->from_fragment) {
17a1c597
ZJS
920 _cleanup_free_ char *opts = NULL;
921
922 r = fstab_filter_options(m->parameters_fragment.options,
923 "nofail\0" "fail\0" "noauto\0" "auto\0", NULL, NULL, &opts);
924 if (r < 0)
925 goto fail;
926
e86b3761
ZJS
927 r = exec_command_set(m->control_command, "/bin/mount",
928 m->parameters_fragment.what, m->where, NULL);
929 if (r >= 0 && UNIT(m)->manager->running_as == SYSTEMD_SYSTEM)
930 r = exec_command_append(m->control_command, "-n", NULL);
931 if (r >= 0 && m->sloppy_options)
932 r = exec_command_append(m->control_command, "-s", NULL);
933 if (r >= 0 && m->parameters_fragment.fstype)
934 r = exec_command_append(m->control_command, "-t", m->parameters_fragment.fstype, NULL);
17a1c597
ZJS
935 if (r >= 0 && !strempty(opts))
936 r = exec_command_append(m->control_command, "-o", opts, NULL);
e86b3761 937 } else
e537352b
LP
938 r = -ENOENT;
939
940 if (r < 0)
941 goto fail;
942
a16e1123 943 mount_unwatch_control_pid(m);
5e94833f 944
257f1d8e
LP
945 r = mount_spawn(m, m->control_command, &m->control_pid);
946 if (r < 0)
e537352b
LP
947 goto fail;
948
949 mount_set_state(m, MOUNT_MOUNTING);
950
951 return;
952
953fail:
79008bdd 954 log_unit_warning(UNIT(m)->id,
66870f90
ZJS
955 "%s failed to run 'mount' task: %s",
956 UNIT(m)->id, strerror(-r));
9d2f5178 957 mount_enter_dead(m, MOUNT_FAILURE_RESOURCES);
e537352b
LP
958}
959
9d2f5178 960static void mount_enter_remounting(Mount *m) {
e537352b
LP
961 int r;
962
963 assert(m);
964
a16e1123
LP
965 m->control_command_id = MOUNT_EXEC_REMOUNT;
966 m->control_command = m->exec_command + MOUNT_EXEC_REMOUNT;
e537352b
LP
967
968 if (m->from_fragment) {
e537352b
LP
969 const char *o;
970
718db961
LP
971 if (m->parameters_fragment.options)
972 o = strappenda("remount,", m->parameters_fragment.options);
973 else
e537352b
LP
974 o = "remount";
975
e86b3761
ZJS
976 r = exec_command_set(m->control_command, "/bin/mount",
977 m->parameters_fragment.what, m->where,
978 "-o", o, NULL);
979 if (r >= 0 && UNIT(m)->manager->running_as == SYSTEMD_SYSTEM)
980 r = exec_command_append(m->control_command, "-n", NULL);
981 if (r >= 0 && m->sloppy_options)
982 r = exec_command_append(m->control_command, "-s", NULL);
983 if (r >= 0 && m->parameters_fragment.fstype)
984 r = exec_command_append(m->control_command, "-t", m->parameters_fragment.fstype, NULL);
6b1dc2bd 985 } else
e537352b
LP
986 r = -ENOENT;
987
60b912f6 988 if (r < 0)
e537352b 989 goto fail;
e537352b 990
a16e1123 991 mount_unwatch_control_pid(m);
5e94833f 992
718db961
LP
993 r = mount_spawn(m, m->control_command, &m->control_pid);
994 if (r < 0)
e537352b
LP
995 goto fail;
996
997 mount_set_state(m, MOUNT_REMOUNTING);
998
999 return;
1000
1001fail:
79008bdd 1002 log_unit_warning(UNIT(m)->id,
66870f90
ZJS
1003 "%s failed to run 'remount' task: %s",
1004 UNIT(m)->id, strerror(-r));
9d2f5178
LP
1005 m->reload_result = MOUNT_FAILURE_RESOURCES;
1006 mount_enter_mounted(m, MOUNT_SUCCESS);
e537352b
LP
1007}
1008
1009static int mount_start(Unit *u) {
1010 Mount *m = MOUNT(u);
1011
1012 assert(m);
1013
1014 /* We cannot fulfill this request right now, try again later
1015 * please! */
1016 if (m->state == MOUNT_UNMOUNTING ||
1017 m->state == MOUNT_UNMOUNTING_SIGTERM ||
60b912f6
LP
1018 m->state == MOUNT_UNMOUNTING_SIGKILL ||
1019 m->state == MOUNT_MOUNTING_SIGTERM ||
1020 m->state == MOUNT_MOUNTING_SIGKILL)
e537352b
LP
1021 return -EAGAIN;
1022
1023 /* Already on it! */
60b912f6 1024 if (m->state == MOUNT_MOUNTING)
e537352b
LP
1025 return 0;
1026
fdf20a31 1027 assert(m->state == MOUNT_DEAD || m->state == MOUNT_FAILED);
e537352b 1028
9d2f5178
LP
1029 m->result = MOUNT_SUCCESS;
1030 m->reload_result = MOUNT_SUCCESS;
1031
8d567588 1032 mount_enter_mounting(m);
e537352b
LP
1033 return 0;
1034}
1035
1036static int mount_stop(Unit *u) {
1037 Mount *m = MOUNT(u);
1038
1039 assert(m);
1040
e537352b
LP
1041 /* Already on it */
1042 if (m->state == MOUNT_UNMOUNTING ||
1043 m->state == MOUNT_UNMOUNTING_SIGKILL ||
60b912f6
LP
1044 m->state == MOUNT_UNMOUNTING_SIGTERM ||
1045 m->state == MOUNT_MOUNTING_SIGTERM ||
1046 m->state == MOUNT_MOUNTING_SIGKILL)
e537352b
LP
1047 return 0;
1048
3f6c78dc
LP
1049 assert(m->state == MOUNT_MOUNTING ||
1050 m->state == MOUNT_MOUNTING_DONE ||
1051 m->state == MOUNT_MOUNTED ||
3f6c78dc
LP
1052 m->state == MOUNT_REMOUNTING ||
1053 m->state == MOUNT_REMOUNTING_SIGTERM ||
1054 m->state == MOUNT_REMOUNTING_SIGKILL);
e537352b 1055
9d2f5178 1056 mount_enter_unmounting(m);
e537352b
LP
1057 return 0;
1058}
1059
1060static int mount_reload(Unit *u) {
1061 Mount *m = MOUNT(u);
1062
1063 assert(m);
1064
1065 if (m->state == MOUNT_MOUNTING_DONE)
1066 return -EAGAIN;
1067
1068 assert(m->state == MOUNT_MOUNTED);
1069
9d2f5178 1070 mount_enter_remounting(m);
e537352b
LP
1071 return 0;
1072}
1073
a16e1123
LP
1074static int mount_serialize(Unit *u, FILE *f, FDSet *fds) {
1075 Mount *m = MOUNT(u);
1076
1077 assert(m);
1078 assert(f);
1079 assert(fds);
1080
1081 unit_serialize_item(u, f, "state", mount_state_to_string(m->state));
9d2f5178
LP
1082 unit_serialize_item(u, f, "result", mount_result_to_string(m->result));
1083 unit_serialize_item(u, f, "reload-result", mount_result_to_string(m->reload_result));
a16e1123
LP
1084
1085 if (m->control_pid > 0)
ccd06097 1086 unit_serialize_item_format(u, f, "control-pid", PID_FMT, m->control_pid);
a16e1123
LP
1087
1088 if (m->control_command_id >= 0)
1089 unit_serialize_item(u, f, "control-command", mount_exec_command_to_string(m->control_command_id));
1090
1091 return 0;
1092}
1093
1094static int mount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
1095 Mount *m = MOUNT(u);
a16e1123
LP
1096
1097 assert(u);
1098 assert(key);
1099 assert(value);
1100 assert(fds);
1101
1102 if (streq(key, "state")) {
1103 MountState state;
1104
1105 if ((state = mount_state_from_string(value)) < 0)
79008bdd 1106 log_unit_debug(u->id, "Failed to parse state value %s", value);
a16e1123
LP
1107 else
1108 m->deserialized_state = state;
9d2f5178
LP
1109 } else if (streq(key, "result")) {
1110 MountResult f;
a16e1123 1111
9d2f5178
LP
1112 f = mount_result_from_string(value);
1113 if (f < 0)
79008bdd 1114 log_unit_debug(UNIT(m)->id,
66870f90 1115 "Failed to parse result value %s", value);
9d2f5178
LP
1116 else if (f != MOUNT_SUCCESS)
1117 m->result = f;
1118
1119 } else if (streq(key, "reload-result")) {
1120 MountResult f;
1121
1122 f = mount_result_from_string(value);
1123 if (f < 0)
79008bdd 1124 log_unit_debug(UNIT(m)->id,
66870f90 1125 "Failed to parse reload result value %s", value);
9d2f5178
LP
1126 else if (f != MOUNT_SUCCESS)
1127 m->reload_result = f;
a16e1123
LP
1128
1129 } else if (streq(key, "control-pid")) {
5925dd3c 1130 pid_t pid;
a16e1123 1131
e364ad06 1132 if (parse_pid(value, &pid) < 0)
79008bdd 1133 log_unit_debug(UNIT(m)->id,
66870f90 1134 "Failed to parse control-pid value %s", value);
a16e1123 1135 else
5925dd3c 1136 m->control_pid = pid;
a16e1123
LP
1137 } else if (streq(key, "control-command")) {
1138 MountExecCommand id;
1139
1140 if ((id = mount_exec_command_from_string(value)) < 0)
79008bdd 1141 log_unit_debug(UNIT(m)->id,
66870f90 1142 "Failed to parse exec-command value %s", value);
a16e1123
LP
1143 else {
1144 m->control_command_id = id;
1145 m->control_command = m->exec_command + id;
1146 }
a16e1123 1147 } else
79008bdd 1148 log_unit_debug(UNIT(m)->id,
66870f90 1149 "Unknown serialization key '%s'", key);
a16e1123
LP
1150
1151 return 0;
1152}
1153
44a6b1b6 1154_pure_ static UnitActiveState mount_active_state(Unit *u) {
e537352b
LP
1155 assert(u);
1156
1157 return state_translation_table[MOUNT(u)->state];
1158}
1159
44a6b1b6 1160_pure_ static const char *mount_sub_state_to_string(Unit *u) {
10a94420
LP
1161 assert(u);
1162
a16e1123 1163 return mount_state_to_string(MOUNT(u)->state);
10a94420
LP
1164}
1165
44a6b1b6 1166_pure_ static bool mount_check_gc(Unit *u) {
701cc384
LP
1167 Mount *m = MOUNT(u);
1168
1169 assert(m);
1170
6b1dc2bd 1171 return m->from_proc_self_mountinfo;
701cc384
LP
1172}
1173
e537352b
LP
1174static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
1175 Mount *m = MOUNT(u);
9d2f5178 1176 MountResult f;
e537352b
LP
1177
1178 assert(m);
1179 assert(pid >= 0);
1180
8c47c732
LP
1181 if (pid != m->control_pid)
1182 return;
e537352b 1183
e537352b
LP
1184 m->control_pid = 0;
1185
96342de6 1186 if (is_clean_exit(code, status, NULL))
9d2f5178
LP
1187 f = MOUNT_SUCCESS;
1188 else if (code == CLD_EXITED)
1189 f = MOUNT_FAILURE_EXIT_CODE;
1190 else if (code == CLD_KILLED)
1191 f = MOUNT_FAILURE_SIGNAL;
1192 else if (code == CLD_DUMPED)
1193 f = MOUNT_FAILURE_CORE_DUMP;
1194 else
1195 assert_not_reached("Unknown code");
1196
1197 if (f != MOUNT_SUCCESS)
1198 m->result = f;
8c47c732 1199
a16e1123 1200 if (m->control_command) {
6ea832a2 1201 exec_status_exit(&m->control_command->exec_status, &m->exec_context, pid, code, status);
9d2f5178 1202
a16e1123
LP
1203 m->control_command = NULL;
1204 m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
1205 }
1206
79008bdd
LP
1207 log_unit_full(u->id,
1208 f == MOUNT_SUCCESS ? LOG_DEBUG : LOG_NOTICE,
66870f90
ZJS
1209 "%s mount process exited, code=%s status=%i",
1210 u->id, sigchld_code_to_string(code), status);
e537352b
LP
1211
1212 /* Note that mount(8) returning and the kernel sending us a
1213 * mount table change event might happen out-of-order. If an
1214 * operation succeed we assume the kernel will follow soon too
1215 * and already change into the resulting state. If it fails
1216 * we check if the kernel still knows about the mount. and
1217 * change state accordingly. */
1218
1219 switch (m->state) {
1220
1221 case MOUNT_MOUNTING:
1222 case MOUNT_MOUNTING_DONE:
1223 case MOUNT_MOUNTING_SIGKILL:
1224 case MOUNT_MOUNTING_SIGTERM:
e537352b 1225
9d2f5178
LP
1226 if (f == MOUNT_SUCCESS)
1227 mount_enter_mounted(m, f);
e537352b 1228 else if (m->from_proc_self_mountinfo)
9d2f5178 1229 mount_enter_mounted(m, f);
e537352b 1230 else
9d2f5178 1231 mount_enter_dead(m, f);
e537352b
LP
1232 break;
1233
e2f3b44c
LP
1234 case MOUNT_REMOUNTING:
1235 case MOUNT_REMOUNTING_SIGKILL:
1236 case MOUNT_REMOUNTING_SIGTERM:
1237
9d2f5178 1238 m->reload_result = f;
e2f3b44c 1239 if (m->from_proc_self_mountinfo)
9d2f5178 1240 mount_enter_mounted(m, MOUNT_SUCCESS);
e2f3b44c 1241 else
9d2f5178 1242 mount_enter_dead(m, MOUNT_SUCCESS);
e2f3b44c
LP
1243
1244 break;
1245
e537352b
LP
1246 case MOUNT_UNMOUNTING:
1247 case MOUNT_UNMOUNTING_SIGKILL:
1248 case MOUNT_UNMOUNTING_SIGTERM:
1249
7d54a03a
LP
1250 if (f == MOUNT_SUCCESS) {
1251
1252 if (m->from_proc_self_mountinfo) {
1253
1254 /* Still a mount point? If so, let's
1255 * try again. Most likely there were
1256 * multiple mount points stacked on
1257 * top of each other. Note that due to
1258 * the io event priority logic we can
1259 * be sure the new mountinfo is loaded
1260 * before we process the SIGCHLD for
1261 * the mount command. */
1262
1263 if (m->n_retry_umount < RETRY_UMOUNT_MAX) {
1264 log_unit_debug(u->id, "%s: mount still present, trying again.", u->id);
1265 m->n_retry_umount++;
1266 mount_enter_unmounting(m);
1267 } else {
1268 log_unit_debug(u->id, "%s: mount still present after %u attempts to unmount, giving up.", u->id, m->n_retry_umount);
1269 mount_enter_mounted(m, f);
1270 }
1271 } else
1272 mount_enter_dead(m, f);
1273
1274 } else if (m->from_proc_self_mountinfo)
9d2f5178 1275 mount_enter_mounted(m, f);
e537352b 1276 else
9d2f5178 1277 mount_enter_dead(m, f);
e537352b
LP
1278 break;
1279
1280 default:
1281 assert_not_reached("Uh, control process died at wrong time.");
1282 }
c4e2ceae
LP
1283
1284 /* Notify clients about changed exit status */
1285 unit_add_to_dbus_queue(u);
e537352b
LP
1286}
1287
718db961
LP
1288static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
1289 Mount *m = MOUNT(userdata);
e537352b
LP
1290
1291 assert(m);
718db961 1292 assert(m->timer_event_source == source);
e537352b
LP
1293
1294 switch (m->state) {
1295
1296 case MOUNT_MOUNTING:
1297 case MOUNT_MOUNTING_DONE:
79008bdd 1298 log_unit_warning(UNIT(m)->id,
718db961 1299 "%s mounting timed out. Stopping.", UNIT(m)->id);
9d2f5178 1300 mount_enter_signal(m, MOUNT_MOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
e537352b
LP
1301 break;
1302
1303 case MOUNT_REMOUNTING:
79008bdd 1304 log_unit_warning(UNIT(m)->id,
718db961 1305 "%s remounting timed out. Stopping.", UNIT(m)->id);
9d2f5178
LP
1306 m->reload_result = MOUNT_FAILURE_TIMEOUT;
1307 mount_enter_mounted(m, MOUNT_SUCCESS);
e537352b
LP
1308 break;
1309
1310 case MOUNT_UNMOUNTING:
79008bdd 1311 log_unit_warning(UNIT(m)->id,
718db961 1312 "%s unmounting timed out. Stopping.", UNIT(m)->id);
9d2f5178 1313 mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
e537352b
LP
1314 break;
1315
1316 case MOUNT_MOUNTING_SIGTERM:
4819ff03 1317 if (m->kill_context.send_sigkill) {
79008bdd 1318 log_unit_warning(UNIT(m)->id,
718db961 1319 "%s mounting timed out. Killing.", UNIT(m)->id);
9d2f5178 1320 mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
ba035df2 1321 } else {
79008bdd 1322 log_unit_warning(UNIT(m)->id,
66870f90 1323 "%s mounting timed out. Skipping SIGKILL. Ignoring.",
718db961 1324 UNIT(m)->id);
ba035df2
LP
1325
1326 if (m->from_proc_self_mountinfo)
9d2f5178 1327 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1328 else
9d2f5178 1329 mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1330 }
e537352b
LP
1331 break;
1332
1333 case MOUNT_REMOUNTING_SIGTERM:
4819ff03 1334 if (m->kill_context.send_sigkill) {
79008bdd 1335 log_unit_warning(UNIT(m)->id,
718db961 1336 "%s remounting timed out. Killing.", UNIT(m)->id);
9d2f5178 1337 mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
ba035df2 1338 } else {
79008bdd 1339 log_unit_warning(UNIT(m)->id,
66870f90 1340 "%s remounting timed out. Skipping SIGKILL. Ignoring.",
718db961 1341 UNIT(m)->id);
ba035df2
LP
1342
1343 if (m->from_proc_self_mountinfo)
9d2f5178 1344 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1345 else
9d2f5178 1346 mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1347 }
e537352b
LP
1348 break;
1349
1350 case MOUNT_UNMOUNTING_SIGTERM:
4819ff03 1351 if (m->kill_context.send_sigkill) {
79008bdd 1352 log_unit_warning(UNIT(m)->id,
718db961 1353 "%s unmounting timed out. Killing.", UNIT(m)->id);
9d2f5178 1354 mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
ba035df2 1355 } else {
79008bdd 1356 log_unit_warning(UNIT(m)->id,
66870f90 1357 "%s unmounting timed out. Skipping SIGKILL. Ignoring.",
718db961 1358 UNIT(m)->id);
ba035df2
LP
1359
1360 if (m->from_proc_self_mountinfo)
9d2f5178 1361 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1362 else
9d2f5178 1363 mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1364 }
e537352b
LP
1365 break;
1366
1367 case MOUNT_MOUNTING_SIGKILL:
1368 case MOUNT_REMOUNTING_SIGKILL:
1369 case MOUNT_UNMOUNTING_SIGKILL:
79008bdd 1370 log_unit_warning(UNIT(m)->id,
66870f90 1371 "%s mount process still around after SIGKILL. Ignoring.",
718db961 1372 UNIT(m)->id);
e537352b
LP
1373
1374 if (m->from_proc_self_mountinfo)
9d2f5178 1375 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
e537352b 1376 else
9d2f5178 1377 mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
e537352b
LP
1378 break;
1379
1380 default:
1381 assert_not_reached("Timeout at wrong time.");
1382 }
718db961
LP
1383
1384 return 0;
e537352b
LP
1385}
1386
1387static int mount_add_one(
1388 Manager *m,
1389 const char *what,
1390 const char *where,
1391 const char *options,
1392 const char *fstype,
e537352b 1393 bool set_flags) {
057d9ab8
LP
1394
1395 _cleanup_free_ char *e = NULL, *w = NULL, *o = NULL, *f = NULL;
b87705cd 1396 bool load_extras = false;
057d9ab8 1397 MountParameters *p;
ff5f34d0 1398 bool delete, changed = false;
057d9ab8
LP
1399 Unit *u;
1400 int r;
b08d03ff 1401
f50e0a01 1402 assert(m);
b08d03ff
LP
1403 assert(what);
1404 assert(where);
e537352b
LP
1405 assert(options);
1406 assert(fstype);
1407
e537352b
LP
1408 /* Ignore API mount points. They should never be referenced in
1409 * dependencies ever. */
33ff02c9 1410 if (mount_point_is_api(where) || mount_point_ignore(where))
57f2a956 1411 return 0;
b08d03ff 1412
8d567588
LP
1413 if (streq(fstype, "autofs"))
1414 return 0;
1415
4e85aff4
LP
1416 /* probably some kind of swap, ignore */
1417 if (!is_path(where))
b08d03ff
LP
1418 return 0;
1419
7d17cfbc
MS
1420 e = unit_name_from_path(where, ".mount");
1421 if (!e)
b08d03ff
LP
1422 return -ENOMEM;
1423
7d17cfbc
MS
1424 u = manager_get_unit(m, e);
1425 if (!u) {
b08d03ff
LP
1426 delete = true;
1427
7d17cfbc 1428 u = unit_new(m, sizeof(Mount));
057d9ab8 1429 if (!u)
b08d03ff 1430 return -ENOMEM;
b08d03ff
LP
1431
1432 r = unit_add_name(u, e);
b08d03ff
LP
1433 if (r < 0)
1434 goto fail;
1435
7d17cfbc
MS
1436 MOUNT(u)->where = strdup(where);
1437 if (!MOUNT(u)->where) {
07b0b134
ML
1438 r = -ENOMEM;
1439 goto fail;
1440 }
f50e0a01 1441
47a81ba2
UTL
1442 u->source_path = strdup("/proc/self/mountinfo");
1443 if (!u->source_path) {
1444 r = -ENOMEM;
1445 goto fail;
1446 }
1447
057d9ab8
LP
1448 if (m->running_as == SYSTEMD_SYSTEM) {
1449 const char* target;
1450
affc3d83 1451 target = mount_needs_network(options, fstype) ? SPECIAL_REMOTE_FS_TARGET : SPECIAL_LOCAL_FS_TARGET;
057d9ab8 1452 r = unit_add_dependency_by_name(u, UNIT_BEFORE, target, NULL, true);
602c0e74
LP
1453 if (r < 0)
1454 goto fail;
057d9ab8
LP
1455
1456 if (should_umount(MOUNT(u))) {
1457 r = unit_add_dependency_by_name(u, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true);
1458 if (r < 0)
1459 goto fail;
1460 }
602c0e74 1461 }
89b1d5e0 1462
f94ea366 1463 unit_add_to_load_queue(u);
ff5f34d0 1464 changed = true;
b08d03ff
LP
1465 } else {
1466 delete = false;
8eba616f 1467
bcbd5405
WW
1468 if (!MOUNT(u)->where) {
1469 MOUNT(u)->where = strdup(where);
1470 if (!MOUNT(u)->where) {
1471 r = -ENOMEM;
1472 goto fail;
1473 }
1474 }
1475
9d05dd2e
ZJS
1476 if (m->running_as == SYSTEMD_SYSTEM &&
1477 mount_needs_network(options, fstype)) {
a6d305f9
CL
1478 /* _netdev option may have shown up late, or on a
1479 * remount. Add remote-fs dependencies, even though
9d05dd2e
ZJS
1480 * local-fs ones may already be there. */
1481 unit_add_dependency_by_name(u, UNIT_BEFORE, SPECIAL_REMOTE_FS_TARGET, NULL, true);
1482 load_extras = true;
a6d305f9
CL
1483 }
1484
c2756a68 1485 if (u->load_state == UNIT_NOT_FOUND) {
8eba616f
MS
1486 u->load_state = UNIT_LOADED;
1487 u->load_error = 0;
b87705cd
LP
1488
1489 /* Load in the extras later on, after we
1490 * finished initialization of the unit */
1491 load_extras = true;
ff5f34d0 1492 changed = true;
8eba616f 1493 }
b08d03ff
LP
1494 }
1495
dd7a22a9
LP
1496 w = strdup(what);
1497 o = strdup(options);
1498 f = strdup(fstype);
1499 if (!w || !o || !f) {
e537352b
LP
1500 r = -ENOMEM;
1501 goto fail;
1502 }
1503
6b1dc2bd 1504 p = &MOUNT(u)->parameters_proc_self_mountinfo;
ff5f34d0
LP
1505
1506 changed = changed ||
1507 !streq_ptr(p->options, options) ||
1508 !streq_ptr(p->what, what) ||
1509 !streq_ptr(p->fstype, fstype);
1510
6b1dc2bd
LP
1511 if (set_flags) {
1512 MOUNT(u)->is_mounted = true;
1513 MOUNT(u)->just_mounted = !MOUNT(u)->from_proc_self_mountinfo;
ff5f34d0 1514 MOUNT(u)->just_changed = changed;
ef734fd6 1515 }
f50e0a01 1516
6b1dc2bd
LP
1517 MOUNT(u)->from_proc_self_mountinfo = true;
1518
4e85aff4
LP
1519 free(p->what);
1520 p->what = w;
057d9ab8 1521 w = NULL;
b08d03ff 1522
4e85aff4
LP
1523 free(p->options);
1524 p->options = o;
057d9ab8 1525 o = NULL;
e537352b 1526
4e85aff4
LP
1527 free(p->fstype);
1528 p->fstype = f;
057d9ab8 1529 f = NULL;
b08d03ff 1530
b87705cd
LP
1531 if (load_extras) {
1532 r = mount_add_extras(MOUNT(u));
1533 if (r < 0)
1534 goto fail;
1535 }
1536
ff5f34d0
LP
1537 if (changed)
1538 unit_add_to_dbus_queue(u);
c1e1601e 1539
b08d03ff
LP
1540 return 0;
1541
1542fail:
1543 if (delete && u)
1544 unit_free(u);
1545
4e85aff4 1546 return r;
b08d03ff
LP
1547}
1548
ef734fd6 1549static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
4e920142
ZJS
1550 _cleanup_(mnt_free_tablep) struct libmnt_table *tb = NULL;
1551 _cleanup_(mnt_free_iterp) struct libmnt_iter *itr = NULL;
8d3ae2bd 1552 struct libmnt_fs *fs;
60b912f6 1553 int r = 0;
b08d03ff
LP
1554
1555 assert(m);
1556
8d3ae2bd
CL
1557 tb = mnt_new_table();
1558 itr = mnt_new_iter(MNT_ITER_FORWARD);
1559 if (!tb || !itr)
1560 return log_oom();
b08d03ff 1561
5cca8def
ZJS
1562 r = mnt_table_parse_mtab(tb, NULL);
1563 if (r < 0)
8d3ae2bd 1564 return r;
e537352b 1565
5cca8def
ZJS
1566 r = 0;
1567 for (;;) {
8d3ae2bd
CL
1568 const char *device, *path, *options, *fstype;
1569 _cleanup_free_ const char *d = NULL, *p = NULL;
1570 int k;
b08d03ff 1571
5cca8def
ZJS
1572 k = mnt_table_next_fs(tb, itr, &fs);
1573 if (k == 1)
1574 break;
1575 else if (k < 0)
1576 return log_error_errno(k, "Failed to get next entry from /etc/fstab: %m");
1577
8d3ae2bd
CL
1578 device = mnt_fs_get_source(fs);
1579 path = mnt_fs_get_target(fs);
1580 options = mnt_fs_get_options(fs);
1581 fstype = mnt_fs_get_fstype(fs);
a2e0f3d3 1582
a57f7e2c
LP
1583 d = cunescape(device);
1584 p = cunescape(path);
1585 if (!d || !p)
1586 return log_oom();
b08d03ff 1587
8d3ae2bd 1588 k = mount_add_one(m, d, p, options, fstype, set_flags);
5cca8def 1589 if (r == 0 && k < 0)
60b912f6 1590 r = k;
b08d03ff
LP
1591 }
1592
e537352b
LP
1593 return r;
1594}
1595
1596static void mount_shutdown(Manager *m) {
1597 assert(m);
1598
718db961 1599 m->mount_event_source = sd_event_source_unref(m->mount_event_source);
befb6d54 1600 m->mount_utab_event_source = sd_event_source_unref(m->mount_utab_event_source);
718db961 1601
a16e1123 1602 if (m->proc_self_mountinfo) {
e537352b 1603 fclose(m->proc_self_mountinfo);
a16e1123
LP
1604 m->proc_self_mountinfo = NULL;
1605 }
befb6d54 1606 m->utab_inotify_fd = safe_close(m->utab_inotify_fd);
b08d03ff
LP
1607}
1608
68db7a3b
ZJS
1609static int mount_get_timeout(Unit *u, uint64_t *timeout) {
1610 Mount *m = MOUNT(u);
1611 int r;
1612
1613 if (!m->timer_event_source)
1614 return 0;
1615
1616 r = sd_event_source_get_time(m->timer_event_source, timeout);
1617 if (r < 0)
1618 return r;
1619
1620 return 1;
1621}
1622
b08d03ff
LP
1623static int mount_enumerate(Manager *m) {
1624 int r;
1625 assert(m);
1626
8d3ae2bd
CL
1627 mnt_init_debug(0);
1628
a16e1123 1629 if (!m->proc_self_mountinfo) {
e62d8c39
ZJS
1630 m->proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
1631 if (!m->proc_self_mountinfo)
a16e1123 1632 return -errno;
ef734fd6 1633
151b9b96 1634 r = sd_event_add_io(m->event, &m->mount_event_source, fileno(m->proc_self_mountinfo), EPOLLPRI, mount_dispatch_io, m);
718db961
LP
1635 if (r < 0)
1636 goto fail;
29083707
LP
1637
1638 /* Dispatch this before we dispatch SIGCHLD, so that
1639 * we always get the events from /proc/self/mountinfo
1640 * before the SIGCHLD of /bin/mount. */
1641 r = sd_event_source_set_priority(m->mount_event_source, -10);
1642 if (r < 0)
1643 goto fail;
a16e1123 1644 }
ef734fd6 1645
befb6d54
CL
1646 if (m->utab_inotify_fd < 0) {
1647 m->utab_inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
f7c1ad4f
LP
1648 if (m->utab_inotify_fd < 0) {
1649 r = -errno;
1650 goto fail;
1651 }
befb6d54 1652
90598531
ZJS
1653 (void) mkdir_p_label("/run/mount", 0755);
1654
befb6d54 1655 r = inotify_add_watch(m->utab_inotify_fd, "/run/mount", IN_MOVED_TO);
f7c1ad4f
LP
1656 if (r < 0) {
1657 r = -errno;
1658 goto fail;
1659 }
befb6d54
CL
1660
1661 r = sd_event_add_io(m->event, &m->mount_utab_event_source, m->utab_inotify_fd, EPOLLIN, mount_dispatch_io, m);
1662 if (r < 0)
1663 goto fail;
1664
1665 r = sd_event_source_set_priority(m->mount_utab_event_source, -10);
1666 if (r < 0)
1667 goto fail;
1668 }
1669
e62d8c39
ZJS
1670 r = mount_load_proc_self_mountinfo(m, false);
1671 if (r < 0)
b08d03ff
LP
1672 goto fail;
1673
1674 return 0;
1675
1676fail:
1677 mount_shutdown(m);
1678 return r;
5cb5a6ff
LP
1679}
1680
718db961
LP
1681static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
1682 Manager *m = userdata;
595ed347 1683 Unit *u;
ef734fd6
LP
1684 int r;
1685
1686 assert(m);
befb6d54 1687 assert(revents & (EPOLLPRI | EPOLLIN));
ef734fd6
LP
1688
1689 /* The manager calls this for every fd event happening on the
1690 * /proc/self/mountinfo file, which informs us about mounting
fddf1a31
ZJS
1691 * table changes, and for /run/mount events which we watch
1692 * for mount options. */
befb6d54
CL
1693
1694 if (fd == m->utab_inotify_fd) {
df63dda6 1695 bool rescan = false;
befb6d54 1696
b7307642
LP
1697 /* FIXME: We *really* need to replace this with
1698 * libmount's own API for this, we should not hardcode
1699 * internal behaviour of libmount here. */
1700
f7c1ad4f 1701 for (;;) {
0254e944 1702 union inotify_event_buffer buffer;
f7c1ad4f
LP
1703 struct inotify_event *e;
1704 ssize_t l;
1705
0254e944 1706 l = read(fd, &buffer, sizeof(buffer));
f7c1ad4f
LP
1707 if (l < 0) {
1708 if (errno == EAGAIN || errno == EINTR)
1709 break;
1710
1711 log_error_errno(errno, "Failed to read utab inotify: %m");
1712 break;
1713 }
1714
1715 FOREACH_INOTIFY_EVENT(e, buffer, l) {
1716 /* Only care about changes to utab,
1717 * but we have to monitor the
1718 * directory to reliably get
1719 * notifications about when utab is
1720 * replaced using rename(2) */
1721 if ((e->mask & IN_Q_OVERFLOW) || streq(e->name, "utab"))
df63dda6 1722 rescan = true;
befb6d54 1723 }
f7c1ad4f 1724 }
fddf1a31 1725
befb6d54
CL
1726 if (!rescan)
1727 return 0;
1728 }
ef734fd6 1729
4f0eedb7
ZJS
1730 r = mount_load_proc_self_mountinfo(m, true);
1731 if (r < 0) {
da927ba9 1732 log_error_errno(r, "Failed to reread /proc/self/mountinfo: %m");
e537352b
LP
1733
1734 /* Reset flags, just in case, for later calls */
595ed347
MS
1735 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) {
1736 Mount *mount = MOUNT(u);
e537352b
LP
1737
1738 mount->is_mounted = mount->just_mounted = mount->just_changed = false;
1739 }
1740
718db961 1741 return 0;
ef734fd6
LP
1742 }
1743
1744 manager_dispatch_load_queue(m);
1745
595ed347
MS
1746 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) {
1747 Mount *mount = MOUNT(u);
ef734fd6 1748
e537352b 1749 if (!mount->is_mounted) {
e537352b 1750
ef734fd6 1751 mount->from_proc_self_mountinfo = false;
e537352b
LP
1752
1753 switch (mount->state) {
1754
1755 case MOUNT_MOUNTED:
aef83136
LP
1756 /* This has just been unmounted by
1757 * somebody else, follow the state
1758 * change. */
9d2f5178 1759 mount_enter_dead(mount, MOUNT_SUCCESS);
e537352b
LP
1760 break;
1761
1762 default:
e537352b 1763 break;
e537352b
LP
1764 }
1765
1766 } else if (mount->just_mounted || mount->just_changed) {
1767
60b912f6 1768 /* New or changed mount entry */
e537352b
LP
1769
1770 switch (mount->state) {
1771
1772 case MOUNT_DEAD:
fdf20a31 1773 case MOUNT_FAILED:
aef83136
LP
1774 /* This has just been mounted by
1775 * somebody else, follow the state
1776 * change. */
9d2f5178 1777 mount_enter_mounted(mount, MOUNT_SUCCESS);
e537352b
LP
1778 break;
1779
1780 case MOUNT_MOUNTING:
5bcb0f2b 1781 mount_set_state(mount, MOUNT_MOUNTING_DONE);
e537352b
LP
1782 break;
1783
1784 default:
1785 /* Nothing really changed, but let's
1786 * issue an notification call
1787 * nonetheless, in case somebody is
1788 * waiting for this. (e.g. file system
1789 * ro/rw remounts.) */
1790 mount_set_state(mount, mount->state);
1791 break;
1792 }
1793 }
1794
1795 /* Reset the flags for later calls */
1796 mount->is_mounted = mount->just_mounted = mount->just_changed = false;
1797 }
718db961
LP
1798
1799 return 0;
e537352b
LP
1800}
1801
fdf20a31 1802static void mount_reset_failed(Unit *u) {
5632e374
LP
1803 Mount *m = MOUNT(u);
1804
1805 assert(m);
1806
fdf20a31 1807 if (m->state == MOUNT_FAILED)
5632e374
LP
1808 mount_set_state(m, MOUNT_DEAD);
1809
9d2f5178
LP
1810 m->result = MOUNT_SUCCESS;
1811 m->reload_result = MOUNT_SUCCESS;
5632e374
LP
1812}
1813
718db961 1814static int mount_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
814cc562 1815 return unit_kill_common(u, who, signo, -1, MOUNT(u)->control_pid, error);
8a0867d6
LP
1816}
1817
a16e1123
LP
1818static const char* const mount_state_table[_MOUNT_STATE_MAX] = {
1819 [MOUNT_DEAD] = "dead",
1820 [MOUNT_MOUNTING] = "mounting",
1821 [MOUNT_MOUNTING_DONE] = "mounting-done",
1822 [MOUNT_MOUNTED] = "mounted",
1823 [MOUNT_REMOUNTING] = "remounting",
1824 [MOUNT_UNMOUNTING] = "unmounting",
1825 [MOUNT_MOUNTING_SIGTERM] = "mounting-sigterm",
1826 [MOUNT_MOUNTING_SIGKILL] = "mounting-sigkill",
1827 [MOUNT_REMOUNTING_SIGTERM] = "remounting-sigterm",
1828 [MOUNT_REMOUNTING_SIGKILL] = "remounting-sigkill",
1829 [MOUNT_UNMOUNTING_SIGTERM] = "unmounting-sigterm",
1830 [MOUNT_UNMOUNTING_SIGKILL] = "unmounting-sigkill",
fdf20a31 1831 [MOUNT_FAILED] = "failed"
a16e1123
LP
1832};
1833
1834DEFINE_STRING_TABLE_LOOKUP(mount_state, MountState);
1835
1836static const char* const mount_exec_command_table[_MOUNT_EXEC_COMMAND_MAX] = {
1837 [MOUNT_EXEC_MOUNT] = "ExecMount",
1838 [MOUNT_EXEC_UNMOUNT] = "ExecUnmount",
1839 [MOUNT_EXEC_REMOUNT] = "ExecRemount",
1840};
1841
1842DEFINE_STRING_TABLE_LOOKUP(mount_exec_command, MountExecCommand);
1843
9d2f5178
LP
1844static const char* const mount_result_table[_MOUNT_RESULT_MAX] = {
1845 [MOUNT_SUCCESS] = "success",
1846 [MOUNT_FAILURE_RESOURCES] = "resources",
1847 [MOUNT_FAILURE_TIMEOUT] = "timeout",
1848 [MOUNT_FAILURE_EXIT_CODE] = "exit-code",
1849 [MOUNT_FAILURE_SIGNAL] = "signal",
1850 [MOUNT_FAILURE_CORE_DUMP] = "core-dump"
1851};
1852
1853DEFINE_STRING_TABLE_LOOKUP(mount_result, MountResult);
1854
87f0e418 1855const UnitVTable mount_vtable = {
7d17cfbc 1856 .object_size = sizeof(Mount),
718db961
LP
1857 .exec_context_offset = offsetof(Mount, exec_context),
1858 .cgroup_context_offset = offsetof(Mount, cgroup_context),
1859 .kill_context_offset = offsetof(Mount, kill_context),
613b411c 1860 .exec_runtime_offset = offsetof(Mount, exec_runtime),
3ef63c31 1861
f975e971
LP
1862 .sections =
1863 "Unit\0"
1864 "Mount\0"
1865 "Install\0",
4ad49000 1866 .private_section = "Mount",
71645aca 1867
e537352b 1868 .no_alias = true,
9e2f7c11 1869 .no_instances = true,
e537352b
LP
1870
1871 .init = mount_init,
1872 .load = mount_load,
034c6ed7 1873 .done = mount_done,
e537352b 1874
f50e0a01
LP
1875 .coldplug = mount_coldplug,
1876
034c6ed7 1877 .dump = mount_dump,
5cb5a6ff 1878
e537352b
LP
1879 .start = mount_start,
1880 .stop = mount_stop,
1881 .reload = mount_reload,
1882
8a0867d6
LP
1883 .kill = mount_kill,
1884
a16e1123
LP
1885 .serialize = mount_serialize,
1886 .deserialize_item = mount_deserialize_item,
1887
f50e0a01 1888 .active_state = mount_active_state,
10a94420 1889 .sub_state_to_string = mount_sub_state_to_string,
b08d03ff 1890
701cc384
LP
1891 .check_gc = mount_check_gc,
1892
e537352b 1893 .sigchld_event = mount_sigchld_event,
e537352b 1894
fdf20a31 1895 .reset_failed = mount_reset_failed,
5632e374 1896
c4e2ceae 1897 .bus_interface = "org.freedesktop.systemd1.Mount",
718db961 1898 .bus_vtable = bus_mount_vtable,
74c964d3
LP
1899 .bus_set_property = bus_mount_set_property,
1900 .bus_commit_properties = bus_mount_commit_properties,
4139c1b2 1901
68db7a3b
ZJS
1902 .get_timeout = mount_get_timeout,
1903
0e252f6b
TG
1904 .can_transient = true,
1905
f50e0a01 1906 .enumerate = mount_enumerate,
c6918296
MS
1907 .shutdown = mount_shutdown,
1908
1909 .status_message_formats = {
1910 .starting_stopping = {
1911 [0] = "Mounting %s...",
1912 [1] = "Unmounting %s...",
1913 },
1914 .finished_start_job = {
1915 [JOB_DONE] = "Mounted %s.",
1916 [JOB_FAILED] = "Failed to mount %s.",
1917 [JOB_DEPENDENCY] = "Dependency failed for %s.",
1918 [JOB_TIMEOUT] = "Timed out mounting %s.",
1919 },
1920 .finished_stop_job = {
1921 [JOB_DONE] = "Unmounted %s.",
1922 [JOB_FAILED] = "Failed unmounting %s.",
1923 [JOB_TIMEOUT] = "Timed out unmounting %s.",
1924 },
1925 },
5cb5a6ff 1926};