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