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