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