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