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