]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/mount.c
relicense to LGPLv2.1 (with exceptions)
[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>
5cb5a6ff 27
87f0e418 28#include "unit.h"
5cb5a6ff
LP
29#include "mount.h"
30#include "load-fragment.h"
5cb5a6ff 31#include "load-dropin.h"
b08d03ff 32#include "log.h"
e537352b 33#include "strv.h"
49e942b2 34#include "mkdir.h"
e537352b 35#include "mount-setup.h"
9e2f7c11 36#include "unit-name.h"
4139c1b2 37#include "dbus-mount.h"
514f4ef5 38#include "special.h"
8a0867d6 39#include "bus-errors.h"
9a57c629 40#include "exit-status.h"
f6a6225e 41#include "def.h"
5cb5a6ff 42
f50e0a01
LP
43static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = {
44 [MOUNT_DEAD] = UNIT_INACTIVE,
45 [MOUNT_MOUNTING] = UNIT_ACTIVATING,
e537352b 46 [MOUNT_MOUNTING_DONE] = UNIT_ACTIVE,
f50e0a01 47 [MOUNT_MOUNTED] = UNIT_ACTIVE,
032ff4af 48 [MOUNT_REMOUNTING] = UNIT_RELOADING,
f50e0a01 49 [MOUNT_UNMOUNTING] = UNIT_DEACTIVATING,
e537352b
LP
50 [MOUNT_MOUNTING_SIGTERM] = UNIT_DEACTIVATING,
51 [MOUNT_MOUNTING_SIGKILL] = UNIT_DEACTIVATING,
032ff4af
LP
52 [MOUNT_REMOUNTING_SIGTERM] = UNIT_RELOADING,
53 [MOUNT_REMOUNTING_SIGKILL] = UNIT_RELOADING,
e537352b
LP
54 [MOUNT_UNMOUNTING_SIGTERM] = UNIT_DEACTIVATING,
55 [MOUNT_UNMOUNTING_SIGKILL] = UNIT_DEACTIVATING,
fdf20a31 56 [MOUNT_FAILED] = UNIT_FAILED
f50e0a01 57};
5cb5a6ff 58
a16e1123
LP
59static void mount_init(Unit *u) {
60 Mount *m = MOUNT(u);
5cb5a6ff 61
a16e1123 62 assert(u);
ac155bb8 63 assert(u->load_state == UNIT_STUB);
a16e1123
LP
64
65 m->timeout_usec = DEFAULT_TIMEOUT_USEC;
3e5235b0
LP
66 m->directory_mode = 0755;
67
c3686083 68 exec_context_init(&m->exec_context);
d893269d
LP
69
70 /* The stdio/kmsg bridge socket is on /, in order to avoid a
71 * dep loop, don't use kmsg logging for -.mount */
f6cebb3b 72 if (!unit_has_name(u, "-.mount")) {
ac155bb8
MS
73 m->exec_context.std_output = u->manager->default_std_output;
74 m->exec_context.std_error = u->manager->default_std_error;
f6cebb3b 75 }
c3686083 76
a16e1123
LP
77 /* We need to make sure that /bin/mount is always called in
78 * the same process group as us, so that the autofs kernel
79 * side doesn't send us another mount request while we are
80 * already trying to comply its last one. */
74922904 81 m->exec_context.same_pgrp = true;
8d567588 82
a16e1123
LP
83 m->timer_watch.type = WATCH_INVALID;
84
85 m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
c8f4d764 86
1124fe6f 87 UNIT(m)->ignore_on_isolate = true;
8d567588
LP
88}
89
a16e1123 90static void mount_unwatch_control_pid(Mount *m) {
5e94833f
LP
91 assert(m);
92
93 if (m->control_pid <= 0)
94 return;
95
96 unit_unwatch_pid(UNIT(m), m->control_pid);
97 m->control_pid = 0;
98}
99
e537352b
LP
100static void mount_parameters_done(MountParameters *p) {
101 assert(p);
102
103 free(p->what);
104 free(p->options);
105 free(p->fstype);
106
107 p->what = p->options = p->fstype = NULL;
108}
109
87f0e418 110static void mount_done(Unit *u) {
ef734fd6 111 Mount *m = MOUNT(u);
034c6ed7 112
ef734fd6 113 assert(m);
034c6ed7 114
e537352b
LP
115 free(m->where);
116 m->where = NULL;
f50e0a01 117
e537352b
LP
118 mount_parameters_done(&m->parameters_etc_fstab);
119 mount_parameters_done(&m->parameters_proc_self_mountinfo);
120 mount_parameters_done(&m->parameters_fragment);
ef734fd6 121
e537352b
LP
122 exec_context_done(&m->exec_context);
123 exec_command_done_array(m->exec_command, _MOUNT_EXEC_COMMAND_MAX);
124 m->control_command = NULL;
f50e0a01 125
a16e1123 126 mount_unwatch_control_pid(m);
f50e0a01 127
e537352b 128 unit_unwatch_timer(u, &m->timer_watch);
f50e0a01
LP
129}
130
cb39ed3f
LP
131static MountParameters* get_mount_parameters_configured(Mount *m) {
132 assert(m);
133
134 if (m->from_fragment)
135 return &m->parameters_fragment;
136 else if (m->from_etc_fstab)
137 return &m->parameters_etc_fstab;
138
139 return NULL;
140}
141
142static MountParameters* get_mount_parameters(Mount *m) {
143 assert(m);
144
145 if (m->from_proc_self_mountinfo)
146 return &m->parameters_proc_self_mountinfo;
147
148 return get_mount_parameters_configured(m);
149}
150
6e2ef85b 151static int mount_add_mount_links(Mount *m) {
ac155bb8 152 Unit *other;
b08d03ff 153 int r;
5c78d8e2 154 MountParameters *pm;
b08d03ff 155
6e2ef85b 156 assert(m);
b08d03ff 157
cb39ed3f 158 pm = get_mount_parameters_configured(m);
5c78d8e2 159
6e2ef85b
LP
160 /* Adds in links to other mount points that might lie below or
161 * above us in the hierarchy */
e537352b 162
1124fe6f 163 LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_MOUNT]) {
595ed347 164 Mount *n = MOUNT(other);
5c78d8e2 165 MountParameters *pn;
07b0b134 166
6e2ef85b
LP
167 if (n == m)
168 continue;
b08d03ff 169
1124fe6f 170 if (UNIT(n)->load_state != UNIT_LOADED)
6e2ef85b 171 continue;
b08d03ff 172
cb39ed3f 173 pn = get_mount_parameters_configured(n);
5c78d8e2 174
6e2ef85b 175 if (path_startswith(m->where, n->where)) {
b08d03ff 176
6e2ef85b
LP
177 if ((r = unit_add_dependency(UNIT(m), UNIT_AFTER, UNIT(n), true)) < 0)
178 return r;
b08d03ff 179
cb39ed3f 180 if (pn)
6e2ef85b
LP
181 if ((r = unit_add_dependency(UNIT(m), UNIT_REQUIRES, UNIT(n), true)) < 0)
182 return r;
b08d03ff 183
6e2ef85b 184 } else if (path_startswith(n->where, m->where)) {
b08d03ff 185
5c78d8e2
LP
186 if ((r = unit_add_dependency(UNIT(n), UNIT_AFTER, UNIT(m), true)) < 0)
187 return r;
188
cb39ed3f 189 if (pm)
5c78d8e2
LP
190 if ((r = unit_add_dependency(UNIT(n), UNIT_REQUIRES, UNIT(m), true)) < 0)
191 return r;
192
9631c090 193 } else if (pm && pm->what && path_startswith(pm->what, n->where)) {
5c78d8e2
LP
194
195 if ((r = unit_add_dependency(UNIT(m), UNIT_AFTER, UNIT(n), true)) < 0)
6e2ef85b
LP
196 return r;
197
cb39ed3f
LP
198 if ((r = unit_add_dependency(UNIT(m), UNIT_REQUIRES, UNIT(n), true)) < 0)
199 return r;
5c78d8e2 200
9631c090 201 } else if (pn && pn->what && path_startswith(pn->what, m->where)) {
5c78d8e2
LP
202
203 if ((r = unit_add_dependency(UNIT(n), UNIT_AFTER, UNIT(m), true)) < 0)
204 return r;
205
cb39ed3f
LP
206 if ((r = unit_add_dependency(UNIT(n), UNIT_REQUIRES, UNIT(m), true)) < 0)
207 return r;
6e2ef85b
LP
208 }
209 }
b08d03ff
LP
210
211 return 0;
212}
213
6e2ef85b 214static int mount_add_swap_links(Mount *m) {
ac155bb8 215 Unit *other;
b08d03ff
LP
216 int r;
217
6e2ef85b 218 assert(m);
b08d03ff 219
1124fe6f 220 LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_SWAP])
595ed347 221 if ((r = swap_add_one_mount_link(SWAP(other), m)) < 0)
6e2ef85b 222 return r;
b08d03ff 223
6e2ef85b
LP
224 return 0;
225}
b08d03ff 226
01f78473 227static int mount_add_path_links(Mount *m) {
ac155bb8 228 Unit *other;
01f78473
LP
229 int r;
230
231 assert(m);
232
1124fe6f 233 LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_PATH])
595ed347 234 if ((r = path_add_one_mount_link(PATH(other), m)) < 0)
01f78473
LP
235 return r;
236
237 return 0;
238}
239
6e2ef85b 240static int mount_add_automount_links(Mount *m) {
ac155bb8 241 Unit *other;
6e2ef85b 242 int r;
e537352b 243
6e2ef85b 244 assert(m);
b08d03ff 245
1124fe6f 246 LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_AUTOMOUNT])
595ed347 247 if ((r = automount_add_one_mount_link(AUTOMOUNT(other), m)) < 0)
6e2ef85b 248 return r;
b08d03ff 249
6e2ef85b
LP
250 return 0;
251}
b08d03ff 252
6e2ef85b 253static int mount_add_socket_links(Mount *m) {
ac155bb8 254 Unit *other;
6e2ef85b 255 int r;
b08d03ff 256
6e2ef85b 257 assert(m);
b08d03ff 258
1124fe6f 259 LIST_FOREACH(units_by_type, other, UNIT(m)->manager->units_by_type[UNIT_SOCKET])
595ed347 260 if ((r = socket_add_one_mount_link(SOCKET(other), m)) < 0)
6e2ef85b 261 return r;
b08d03ff
LP
262
263 return 0;
264}
265
07b0b134 266static char* mount_test_option(const char *haystack, const char *needle) {
e537352b
LP
267 struct mntent me;
268
269 assert(needle);
270
271 /* Like glibc's hasmntopt(), but works on a string, not a
272 * struct mntent */
273
274 if (!haystack)
6a39419f 275 return NULL;
e537352b
LP
276
277 zero(me);
278 me.mnt_opts = (char*) haystack;
279
07b0b134 280 return hasmntopt(&me, needle);
e537352b
LP
281}
282
cb39ed3f
LP
283static bool mount_is_network(MountParameters *p) {
284 assert(p);
285
286 if (mount_test_option(p->options, "_netdev"))
287 return true;
288
289 if (p->fstype && fstype_is_network(p->fstype))
290 return true;
291
292 return false;
293}
294
295static bool mount_is_bind(MountParameters *p) {
296 assert(p);
297
298 if (mount_test_option(p->options, "bind"))
299 return true;
300
301 if (p->fstype && streq(p->fstype, "bind"))
302 return true;
303
304 return false;
305}
306
307static bool needs_quota(MountParameters *p) {
308 assert(p);
309
310 if (mount_is_network(p))
311 return false;
312
313 if (mount_is_bind(p))
314 return false;
315
316 return mount_test_option(p->options, "usrquota") ||
d3354f66
LP
317 mount_test_option(p->options, "grpquota") ||
318 mount_test_option(p->options, "quota") ||
319 mount_test_option(p->options, "usrjquota") ||
320 mount_test_option(p->options, "grpjquota");
cb39ed3f
LP
321}
322
155da457 323static int mount_add_fstab_links(Mount *m) {
db1355b1 324 const char *target, *after, *tu_wants = NULL;
e537352b 325 MountParameters *p;
a16e1123 326 Unit *tu;
e537352b 327 int r;
d9143006 328 bool noauto, nofail, handle, automount;
e537352b
LP
329
330 assert(m);
331
1124fe6f 332 if (UNIT(m)->manager->running_as != MANAGER_SYSTEM)
155da457
LP
333 return 0;
334
cb39ed3f 335 if (!(p = get_mount_parameters_configured(m)))
e537352b
LP
336 return 0;
337
155da457
LP
338 if (p != &m->parameters_etc_fstab)
339 return 0;
340
341 noauto = !!mount_test_option(p->options, "noauto");
d9143006 342 nofail = !!mount_test_option(p->options, "nofail");
155da457
LP
343 automount =
344 mount_test_option(p->options, "comment=systemd.automount") ||
345 mount_test_option(p->options, "x-systemd-automount");
d4a7e06d 346 handle =
155da457 347 automount ||
d4a7e06d
LP
348 mount_test_option(p->options, "comment=systemd.mount") ||
349 mount_test_option(p->options, "x-systemd-mount") ||
1124fe6f 350 UNIT(m)->manager->mount_auto;
e537352b 351
cb39ed3f 352 if (mount_is_network(p)) {
e537352b 353 target = SPECIAL_REMOTE_FS_TARGET;
db1355b1 354 after = tu_wants = SPECIAL_REMOTE_FS_PRE_TARGET;
21e557ed 355 } else {
e537352b 356 target = SPECIAL_LOCAL_FS_TARGET;
21e557ed
LP
357 after = SPECIAL_LOCAL_FS_PRE_TARGET;
358 }
e537352b 359
db1355b1
MS
360 r = manager_load_unit(UNIT(m)->manager, target, NULL, NULL, &tu);
361 if (r < 0)
e537352b
LP
362 return r;
363
db1355b1
MS
364 if (tu_wants) {
365 r = unit_add_dependency_by_name(tu, UNIT_WANTS, tu_wants, NULL, true);
366 if (r < 0)
a55da3cd 367 return r;
db1355b1 368 }
a55da3cd 369
db1355b1
MS
370 if (after) {
371 r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, NULL, true);
372 if (r < 0)
7fc2a89a 373 return r;
db1355b1 374 }
7fc2a89a 375
155da457 376 if (automount) {
a16e1123
LP
377 Unit *am;
378
379 if ((r = unit_load_related_unit(UNIT(m), ".automount", &am)) < 0)
9fcc065a 380 return r;
e537352b 381
155da457
LP
382 /* If auto is configured as well also pull in the
383 * mount right-away, but don't rely on it. */
384 if (!noauto) /* automount + auto */
385 if ((r = unit_add_dependency(tu, UNIT_WANTS, UNIT(m), true)) < 0)
386 return r;
387
388 /* Install automount unit */
389 if (!nofail) /* automount + fail */
ac155bb8 390 return unit_add_two_dependencies(tu, UNIT_AFTER, UNIT_REQUIRES, am, true);
155da457 391 else /* automount + nofail */
ac155bb8 392 return unit_add_two_dependencies(tu, UNIT_AFTER, UNIT_WANTS, am, true);
155da457
LP
393
394 } else if (handle && !noauto) {
a16e1123 395
81bf310e
LP
396 /* Automatically add mount points that aren't natively
397 * configured to local-fs.target */
a16e1123 398
155da457
LP
399 if (!nofail) /* auto + fail */
400 return unit_add_two_dependencies(tu, UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true);
401 else /* auto + nofail */
402 return unit_add_dependency(tu, UNIT_WANTS, UNIT(m), true);
a16e1123 403 }
155da457
LP
404
405 return 0;
e537352b
LP
406}
407
173a8d04
LP
408static int mount_add_device_links(Mount *m) {
409 MountParameters *p;
9fff8a1f 410 int r;
173a8d04
LP
411
412 assert(m);
413
cb39ed3f 414 if (!(p = get_mount_parameters_configured(m)))
173a8d04
LP
415 return 0;
416
9fff8a1f 417 if (!p->what)
173a8d04 418 return 0;
5c78d8e2 419
155da457
LP
420 if (!mount_is_bind(p) &&
421 !path_equal(m->where, "/") &&
422 p == &m->parameters_etc_fstab) {
9fff8a1f 423 bool nofail, noauto;
173a8d04 424
155da457 425 noauto = !!mount_test_option(p->options, "noauto");
9fff8a1f
LP
426 nofail = !!mount_test_option(p->options, "nofail");
427
428 if ((r = unit_add_node_link(UNIT(m), p->what,
429 !noauto && nofail &&
ac155bb8 430 UNIT(m)->manager->running_as == MANAGER_SYSTEM)) < 0)
9fff8a1f
LP
431 return r;
432 }
433
491ad5dc 434 if (p->passno > 0 &&
ff2e0f05 435 !mount_is_bind(p) &&
ac155bb8 436 UNIT(m)->manager->running_as == MANAGER_SYSTEM &&
b65a25f2 437 !path_equal(m->where, "/")) {
9fff8a1f
LP
438 char *name;
439 Unit *fsck;
440 /* Let's add in the fsck service */
173a8d04 441
a9e1f5ec 442 /* aka SPECIAL_FSCK_SERVICE */
9fff8a1f
LP
443 if (!(name = unit_name_from_path_instance("fsck", p->what, ".service")))
444 return -ENOMEM;
445
1124fe6f 446 if ((r = manager_load_unit_prepare(UNIT(m)->manager, name, NULL, NULL, &fsck)) < 0) {
9fff8a1f
LP
447 log_warning("Failed to prepare unit %s: %s", name, strerror(-r));
448 free(name);
449 return r;
450 }
451
452 free(name);
453
454 SERVICE(fsck)->fsck_passno = p->passno;
455
0355825f 456 if ((r = unit_add_two_dependencies(UNIT(m), UNIT_AFTER, UNIT_REQUIRES, fsck, true)) < 0)
9fff8a1f
LP
457 return r;
458 }
459
460 return 0;
173a8d04
LP
461}
462
2edd4434
LP
463static int mount_add_default_dependencies(Mount *m) {
464 int r;
9ddc4a26 465 MountParameters *p;
2edd4434
LP
466
467 assert(m);
468
1124fe6f 469 if (UNIT(m)->manager->running_as != MANAGER_SYSTEM)
9ddc4a26 470 return 0;
cb39ed3f 471
9ddc4a26
MS
472 p = get_mount_parameters_configured(m);
473 if (p && needs_quota(p)) {
474 if ((r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTACHECK_SERVICE, NULL, true)) < 0 ||
475 (r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTAON_SERVICE, NULL, true)) < 0)
476 return r;
477 }
2edd4434 478
9ddc4a26 479 if (!path_equal(m->where, "/"))
ead8e478 480 if ((r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true)) < 0)
75d287d3 481 return r;
2edd4434
LP
482
483 return 0;
484}
485
f4c05147 486static int mount_fix_timeouts(Mount *m) {
8024c3a7
LP
487 MountParameters *p;
488 const char *timeout = NULL;
489 Unit *other;
490 Iterator i;
491 usec_t u;
f4c05147
LP
492 char *t;
493 int r;
8024c3a7
LP
494
495 assert(m);
496
497 if (!(p = get_mount_parameters_configured(m)))
f4c05147 498 return 0;
8024c3a7
LP
499
500 /* Allow configuration how long we wait for a device that
501 * backs a mount point to show up. This is useful to support
502 * endless device timeouts for devices that show up only after
503 * user input, like crypto devices. */
504
505 if ((timeout = mount_test_option(p->options, "comment=systemd.device-timeout")))
506 timeout += 31;
507 else if ((timeout = mount_test_option(p->options, "x-systemd-device-timeout")))
508 timeout += 25;
509 else
f4c05147
LP
510 return 0;
511
512 t = strndup(timeout, strcspn(timeout, ",;" WHITESPACE));
513 if (!t)
514 return -ENOMEM;
8024c3a7 515
f4c05147
LP
516 r = parse_usec(t, &u);
517 free(t);
518
519 if (r < 0) {
8024c3a7 520 log_warning("Failed to parse timeout for %s, ignoring: %s", m->where, timeout);
f4c05147 521 return r;
8024c3a7
LP
522 }
523
1124fe6f 524 SET_FOREACH(other, UNIT(m)->dependencies[UNIT_AFTER], i) {
ac155bb8 525 if (other->type != UNIT_DEVICE)
8024c3a7
LP
526 continue;
527
ac155bb8 528 other->job_timeout = u;
8024c3a7 529 }
f4c05147
LP
530
531 return 0;
8024c3a7
LP
532}
533
8d567588
LP
534static int mount_verify(Mount *m) {
535 bool b;
536 char *e;
537 assert(m);
538
1124fe6f 539 if (UNIT(m)->load_state != UNIT_LOADED)
8d567588
LP
540 return 0;
541
8cbef760
LP
542 if (!m->from_etc_fstab && !m->from_fragment && !m->from_proc_self_mountinfo)
543 return -ENOENT;
544
a16e1123 545 if (!(e = unit_name_from_path(m->where, ".mount")))
8d567588
LP
546 return -ENOMEM;
547
548 b = unit_has_name(UNIT(m), e);
549 free(e);
550
551 if (!b) {
1124fe6f 552 log_error("%s's Where setting doesn't match unit name. Refusing.", UNIT(m)->id);
8d567588
LP
553 return -EINVAL;
554 }
555
33ff02c9
LP
556 if (mount_point_is_api(m->where) || mount_point_ignore(m->where)) {
557 log_error("Cannot create mount unit for API file system %s. Refusing.", m->where);
558 return -EINVAL;
559 }
560
1124fe6f
MS
561 if (UNIT(m)->fragment_path && !m->parameters_fragment.what) {
562 log_error("%s's What setting is missing. Refusing.", UNIT(m)->id);
4e85aff4
LP
563 return -EBADMSG;
564 }
565
2e22afe9 566 if (m->exec_context.pam_name && m->exec_context.kill_mode != KILL_CONTROL_GROUP) {
1124fe6f 567 log_error("%s has PAM enabled. Kill mode must be set to 'control-group'. Refusing.", UNIT(m)->id);
4d0e5dbd
LP
568 return -EINVAL;
569 }
570
8d567588
LP
571 return 0;
572}
573
e537352b
LP
574static int mount_load(Unit *u) {
575 Mount *m = MOUNT(u);
576 int r;
577
578 assert(u);
ac155bb8 579 assert(u->load_state == UNIT_STUB);
e537352b
LP
580
581 if ((r = unit_load_fragment_and_dropin_optional(u)) < 0)
582 return r;
583
584 /* This is a new unit? Then let's add in some extras */
ac155bb8 585 if (u->load_state == UNIT_LOADED) {
27abbe82
LP
586 if ((r = unit_add_exec_dependencies(u, &m->exec_context)) < 0)
587 return r;
588
1124fe6f 589 if (UNIT(m)->fragment_path)
4e85aff4 590 m->from_fragment = true;
da375869
MS
591 else if (m->from_etc_fstab)
592 /* We always add several default dependencies to fstab mounts,
593 * but we do not want the implicit complementing of Wants= with After=
594 * in the target unit that this mount unit will be hooked into. */
595 UNIT(m)->default_dependencies = false;
e537352b 596
a16e1123 597 if (!m->where)
ac155bb8 598 if (!(m->where = unit_name_to_path(u->id)))
a16e1123
LP
599 return -ENOMEM;
600
601 path_kill_slashes(m->where);
602
1124fe6f 603 if (!UNIT(m)->description)
4e85aff4
LP
604 if ((r = unit_set_description(u, m->where)) < 0)
605 return r;
e537352b 606
173a8d04
LP
607 if ((r = mount_add_device_links(m)) < 0)
608 return r;
6e2ef85b
LP
609
610 if ((r = mount_add_mount_links(m)) < 0)
611 return r;
612
613 if ((r = mount_add_socket_links(m)) < 0)
614 return r;
615
616 if ((r = mount_add_swap_links(m)) < 0)
e537352b
LP
617 return r;
618
01f78473
LP
619 if ((r = mount_add_path_links(m)) < 0)
620 return r;
621
6e2ef85b 622 if ((r = mount_add_automount_links(m)) < 0)
e537352b
LP
623 return r;
624
155da457 625 if ((r = mount_add_fstab_links(m)) < 0)
e537352b 626 return r;
4e67ddd6 627
da375869 628 if (UNIT(m)->default_dependencies || m->from_etc_fstab)
2edd4434 629 if ((r = mount_add_default_dependencies(m)) < 0)
4e67ddd6 630 return r;
8024c3a7 631
155da457
LP
632 if ((r = unit_add_default_cgroups(u)) < 0)
633 return r;
634
8024c3a7 635 mount_fix_timeouts(m);
e537352b
LP
636 }
637
8d567588 638 return mount_verify(m);
e537352b
LP
639}
640
a16e1123
LP
641static int mount_notify_automount(Mount *m, int status) {
642 Unit *p;
643 int r;
57020a3a 644 Iterator i;
a16e1123
LP
645
646 assert(m);
647
1124fe6f 648 SET_FOREACH(p, UNIT(m)->dependencies[UNIT_TRIGGERED_BY], i)
ac155bb8 649 if (p->type == UNIT_AUTOMOUNT) {
57020a3a
LP
650 r = automount_send_ready(AUTOMOUNT(p), status);
651 if (r < 0)
652 return r;
653 }
a16e1123 654
57020a3a 655 return 0;
a16e1123
LP
656}
657
e537352b
LP
658static void mount_set_state(Mount *m, MountState state) {
659 MountState old_state;
660 assert(m);
661
662 old_state = m->state;
663 m->state = state;
664
665 if (state != MOUNT_MOUNTING &&
666 state != MOUNT_MOUNTING_DONE &&
667 state != MOUNT_REMOUNTING &&
668 state != MOUNT_UNMOUNTING &&
669 state != MOUNT_MOUNTING_SIGTERM &&
670 state != MOUNT_MOUNTING_SIGKILL &&
671 state != MOUNT_UNMOUNTING_SIGTERM &&
672 state != MOUNT_UNMOUNTING_SIGKILL &&
673 state != MOUNT_REMOUNTING_SIGTERM &&
674 state != MOUNT_REMOUNTING_SIGKILL) {
675 unit_unwatch_timer(UNIT(m), &m->timer_watch);
a16e1123 676 mount_unwatch_control_pid(m);
e537352b 677 m->control_command = NULL;
a16e1123 678 m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
e537352b
LP
679 }
680
8d567588
LP
681 if (state == MOUNT_MOUNTED ||
682 state == MOUNT_REMOUNTING)
683 mount_notify_automount(m, 0);
684 else if (state == MOUNT_DEAD ||
685 state == MOUNT_UNMOUNTING ||
686 state == MOUNT_MOUNTING_SIGTERM ||
687 state == MOUNT_MOUNTING_SIGKILL ||
688 state == MOUNT_REMOUNTING_SIGTERM ||
689 state == MOUNT_REMOUNTING_SIGKILL ||
690 state == MOUNT_UNMOUNTING_SIGTERM ||
691 state == MOUNT_UNMOUNTING_SIGKILL ||
fdf20a31 692 state == MOUNT_FAILED)
8d567588
LP
693 mount_notify_automount(m, -ENODEV);
694
e537352b 695 if (state != old_state)
40d50879 696 log_debug("%s changed %s -> %s",
1124fe6f 697 UNIT(m)->id,
a16e1123
LP
698 mount_state_to_string(old_state),
699 mount_state_to_string(state));
e537352b 700
9d2f5178
LP
701 unit_notify(UNIT(m), state_translation_table[old_state], state_translation_table[state], m->reload_result == MOUNT_SUCCESS);
702 m->reload_result = MOUNT_SUCCESS;
e537352b
LP
703}
704
705static int mount_coldplug(Unit *u) {
706 Mount *m = MOUNT(u);
a16e1123
LP
707 MountState new_state = MOUNT_DEAD;
708 int r;
e537352b
LP
709
710 assert(m);
711 assert(m->state == MOUNT_DEAD);
712
a16e1123
LP
713 if (m->deserialized_state != m->state)
714 new_state = m->deserialized_state;
715 else if (m->from_proc_self_mountinfo)
716 new_state = MOUNT_MOUNTED;
e537352b 717
a16e1123 718 if (new_state != m->state) {
e537352b 719
a16e1123
LP
720 if (new_state == MOUNT_MOUNTING ||
721 new_state == MOUNT_MOUNTING_DONE ||
722 new_state == MOUNT_REMOUNTING ||
723 new_state == MOUNT_UNMOUNTING ||
724 new_state == MOUNT_MOUNTING_SIGTERM ||
725 new_state == MOUNT_MOUNTING_SIGKILL ||
726 new_state == MOUNT_UNMOUNTING_SIGTERM ||
727 new_state == MOUNT_UNMOUNTING_SIGKILL ||
728 new_state == MOUNT_REMOUNTING_SIGTERM ||
729 new_state == MOUNT_REMOUNTING_SIGKILL) {
e537352b 730
a16e1123
LP
731 if (m->control_pid <= 0)
732 return -EBADMSG;
e537352b 733
a16e1123
LP
734 if ((r = unit_watch_pid(UNIT(m), m->control_pid)) < 0)
735 return r;
e537352b 736
a16e1123
LP
737 if ((r = unit_watch_timer(UNIT(m), m->timeout_usec, &m->timer_watch)) < 0)
738 return r;
739 }
e537352b 740
a16e1123
LP
741 mount_set_state(m, new_state);
742 }
e537352b
LP
743
744 return 0;
e537352b
LP
745}
746
747static void mount_dump(Unit *u, FILE *f, const char *prefix) {
748 Mount *m = MOUNT(u);
749 MountParameters *p;
750
751 assert(m);
752 assert(f);
753
cb39ed3f 754 p = get_mount_parameters(m);
e537352b
LP
755
756 fprintf(f,
757 "%sMount State: %s\n"
81a5c6d0 758 "%sResult: %s\n"
e537352b
LP
759 "%sWhere: %s\n"
760 "%sWhat: %s\n"
761 "%sFile System Type: %s\n"
762 "%sOptions: %s\n"
763 "%sFrom /etc/fstab: %s\n"
764 "%sFrom /proc/self/mountinfo: %s\n"
765 "%sFrom fragment: %s\n"
3e5235b0 766 "%sDirectoryMode: %04o\n",
a16e1123 767 prefix, mount_state_to_string(m->state),
81a5c6d0 768 prefix, mount_result_to_string(m->result),
e537352b
LP
769 prefix, m->where,
770 prefix, strna(p->what),
771 prefix, strna(p->fstype),
772 prefix, strna(p->options),
773 prefix, yes_no(m->from_etc_fstab),
774 prefix, yes_no(m->from_proc_self_mountinfo),
775 prefix, yes_no(m->from_fragment),
3e5235b0 776 prefix, m->directory_mode);
e537352b
LP
777
778 if (m->control_pid > 0)
779 fprintf(f,
bb00e604
LP
780 "%sControl PID: %lu\n",
781 prefix, (unsigned long) m->control_pid);
e537352b
LP
782
783 exec_context_dump(&m->exec_context, f, prefix);
784}
785
a16e1123
LP
786static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
787 pid_t pid;
788 int r;
789
790 assert(m);
791 assert(c);
792 assert(_pid);
793
794 if ((r = unit_watch_timer(UNIT(m), m->timeout_usec, &m->timer_watch)) < 0)
795 goto fail;
796
797 if ((r = exec_spawn(c,
798 NULL,
799 &m->exec_context,
800 NULL, 0,
1124fe6f 801 UNIT(m)->manager->environment,
a16e1123
LP
802 true,
803 true,
1e3ad081 804 true,
1124fe6f
MS
805 UNIT(m)->manager->confirm_spawn,
806 UNIT(m)->cgroup_bondings,
807 UNIT(m)->cgroup_attributes,
a16e1123
LP
808 &pid)) < 0)
809 goto fail;
810
811 if ((r = unit_watch_pid(UNIT(m), pid)) < 0)
812 /* FIXME: we need to do something here */
813 goto fail;
814
815 *_pid = pid;
816
817 return 0;
818
819fail:
820 unit_unwatch_timer(UNIT(m), &m->timer_watch);
821
822 return r;
823}
824
9d2f5178 825static void mount_enter_dead(Mount *m, MountResult f) {
e537352b
LP
826 assert(m);
827
9d2f5178
LP
828 if (f != MOUNT_SUCCESS)
829 m->result = f;
e537352b 830
9d2f5178 831 mount_set_state(m, m->result != MOUNT_SUCCESS ? MOUNT_FAILED : MOUNT_DEAD);
e537352b
LP
832}
833
9d2f5178 834static void mount_enter_mounted(Mount *m, MountResult f) {
80876c20
LP
835 assert(m);
836
9d2f5178
LP
837 if (f != MOUNT_SUCCESS)
838 m->result = f;
80876c20
LP
839
840 mount_set_state(m, MOUNT_MOUNTED);
841}
842
9d2f5178 843static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
e537352b 844 int r;
ca949c9d
LP
845 Set *pid_set = NULL;
846 bool wait_for_exit = false;
e537352b
LP
847
848 assert(m);
849
9d2f5178
LP
850 if (f != MOUNT_SUCCESS)
851 m->result = f;
e537352b 852
2e22afe9 853 if (m->exec_context.kill_mode != KILL_NONE) {
80876c20
LP
854 int sig = (state == MOUNT_MOUNTING_SIGTERM ||
855 state == MOUNT_UNMOUNTING_SIGTERM ||
2e22afe9 856 state == MOUNT_REMOUNTING_SIGTERM) ? m->exec_context.kill_signal : SIGKILL;
e537352b 857
ca949c9d 858 if (m->control_pid > 0) {
cd25cce9 859 if (kill_and_sigcont(m->control_pid, sig) < 0 && errno != ESRCH)
e537352b 860
ca949c9d
LP
861 log_warning("Failed to kill control process %li: %m", (long) m->control_pid);
862 else
863 wait_for_exit = true;
e537352b
LP
864 }
865
ca949c9d 866 if (m->exec_context.kill_mode == KILL_CONTROL_GROUP) {
2e22afe9 867
ca949c9d
LP
868 if (!(pid_set = set_new(trivial_hash_func, trivial_compare_func))) {
869 r = -ENOMEM;
e537352b
LP
870 goto fail;
871 }
ca949c9d
LP
872
873 /* Exclude the control pid from being killed via the cgroup */
874 if (m->control_pid > 0)
875 if ((r = set_put(pid_set, LONG_TO_PTR(m->control_pid))) < 0)
876 goto fail;
877
1124fe6f 878 if ((r = cgroup_bonding_kill_list(UNIT(m)->cgroup_bondings, sig, true, pid_set)) < 0) {
ca949c9d
LP
879 if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
880 log_warning("Failed to kill control group: %s", strerror(-r));
881 } else if (r > 0)
882 wait_for_exit = true;
883
884 set_free(pid_set);
da19d5c1 885 pid_set = NULL;
ca949c9d 886 }
e537352b
LP
887 }
888
ca949c9d 889 if (wait_for_exit) {
80876c20
LP
890 if ((r = unit_watch_timer(UNIT(m), m->timeout_usec, &m->timer_watch)) < 0)
891 goto fail;
e537352b 892
80876c20
LP
893 mount_set_state(m, state);
894 } else if (state == MOUNT_REMOUNTING_SIGTERM || state == MOUNT_REMOUNTING_SIGKILL)
9d2f5178 895 mount_enter_mounted(m, MOUNT_SUCCESS);
80876c20 896 else
9d2f5178 897 mount_enter_dead(m, MOUNT_SUCCESS);
e537352b
LP
898
899 return;
900
901fail:
1124fe6f 902 log_warning("%s failed to kill processes: %s", UNIT(m)->id, strerror(-r));
e537352b 903
80876c20 904 if (state == MOUNT_REMOUNTING_SIGTERM || state == MOUNT_REMOUNTING_SIGKILL)
9d2f5178 905 mount_enter_mounted(m, MOUNT_FAILURE_RESOURCES);
80876c20 906 else
9d2f5178 907 mount_enter_dead(m, MOUNT_FAILURE_RESOURCES);
ca949c9d
LP
908
909 if (pid_set)
910 set_free(pid_set);
e537352b
LP
911}
912
9d2f5178 913static void mount_enter_unmounting(Mount *m) {
e537352b
LP
914 int r;
915
916 assert(m);
917
a16e1123
LP
918 m->control_command_id = MOUNT_EXEC_UNMOUNT;
919 m->control_command = m->exec_command + MOUNT_EXEC_UNMOUNT;
e537352b
LP
920
921 if ((r = exec_command_set(
a16e1123 922 m->control_command,
e537352b
LP
923 "/bin/umount",
924 m->where,
925 NULL)) < 0)
926 goto fail;
927
a16e1123 928 mount_unwatch_control_pid(m);
5e94833f 929
a16e1123 930 if ((r = mount_spawn(m, m->control_command, &m->control_pid)) < 0)
e537352b
LP
931 goto fail;
932
933 mount_set_state(m, MOUNT_UNMOUNTING);
934
935 return;
936
937fail:
1124fe6f 938 log_warning("%s failed to run 'umount' task: %s", UNIT(m)->id, strerror(-r));
9d2f5178 939 mount_enter_mounted(m, MOUNT_FAILURE_RESOURCES);
e537352b
LP
940}
941
8d567588 942static void mount_enter_mounting(Mount *m) {
e537352b 943 int r;
cb39ed3f 944 MountParameters *p;
e537352b
LP
945
946 assert(m);
947
a16e1123
LP
948 m->control_command_id = MOUNT_EXEC_MOUNT;
949 m->control_command = m->exec_command + MOUNT_EXEC_MOUNT;
e537352b 950
3e5235b0
LP
951 mkdir_p(m->where, m->directory_mode);
952
cb39ed3f
LP
953 /* Create the source directory for bind-mounts if needed */
954 p = get_mount_parameters_configured(m);
955 if (p && mount_is_bind(p))
956 mkdir_p(p->what, m->directory_mode);
2b583ce6 957
e537352b
LP
958 if (m->from_fragment)
959 r = exec_command_set(
a16e1123 960 m->control_command,
e537352b
LP
961 "/bin/mount",
962 m->parameters_fragment.what,
963 m->where,
40b8a332 964 "-t", m->parameters_fragment.fstype ? m->parameters_fragment.fstype : "auto",
8d567588 965 m->parameters_fragment.options ? "-o" : NULL, m->parameters_fragment.options,
e537352b
LP
966 NULL);
967 else if (m->from_etc_fstab)
968 r = exec_command_set(
a16e1123 969 m->control_command,
e537352b
LP
970 "/bin/mount",
971 m->where,
972 NULL);
973 else
974 r = -ENOENT;
975
976 if (r < 0)
977 goto fail;
978
a16e1123 979 mount_unwatch_control_pid(m);
5e94833f 980
a16e1123 981 if ((r = mount_spawn(m, m->control_command, &m->control_pid)) < 0)
e537352b
LP
982 goto fail;
983
984 mount_set_state(m, MOUNT_MOUNTING);
985
986 return;
987
988fail:
1124fe6f 989 log_warning("%s failed to run 'mount' task: %s", UNIT(m)->id, strerror(-r));
9d2f5178 990 mount_enter_dead(m, MOUNT_FAILURE_RESOURCES);
e537352b
LP
991}
992
8d567588 993static void mount_enter_mounting_done(Mount *m) {
e537352b
LP
994 assert(m);
995
e537352b
LP
996 mount_set_state(m, MOUNT_MOUNTING_DONE);
997}
998
9d2f5178 999static void mount_enter_remounting(Mount *m) {
e537352b
LP
1000 int r;
1001
1002 assert(m);
1003
a16e1123
LP
1004 m->control_command_id = MOUNT_EXEC_REMOUNT;
1005 m->control_command = m->exec_command + MOUNT_EXEC_REMOUNT;
e537352b
LP
1006
1007 if (m->from_fragment) {
1008 char *buf = NULL;
1009 const char *o;
1010
1011 if (m->parameters_fragment.options) {
1012 if (!(buf = strappend("remount,", m->parameters_fragment.options))) {
1013 r = -ENOMEM;
1014 goto fail;
1015 }
1016
1017 o = buf;
1018 } else
1019 o = "remount";
1020
1021 r = exec_command_set(
a16e1123 1022 m->control_command,
e537352b
LP
1023 "/bin/mount",
1024 m->parameters_fragment.what,
1025 m->where,
40b8a332 1026 "-t", m->parameters_fragment.fstype ? m->parameters_fragment.fstype : "auto",
e537352b
LP
1027 "-o", o,
1028 NULL);
1029
1030 free(buf);
1031 } else if (m->from_etc_fstab)
1032 r = exec_command_set(
a16e1123 1033 m->control_command,
e537352b
LP
1034 "/bin/mount",
1035 m->where,
1036 "-o", "remount",
1037 NULL);
1038 else
1039 r = -ENOENT;
1040
60b912f6 1041 if (r < 0)
e537352b 1042 goto fail;
e537352b 1043
a16e1123 1044 mount_unwatch_control_pid(m);
5e94833f 1045
a16e1123 1046 if ((r = mount_spawn(m, m->control_command, &m->control_pid)) < 0)
e537352b
LP
1047 goto fail;
1048
1049 mount_set_state(m, MOUNT_REMOUNTING);
1050
1051 return;
1052
1053fail:
1124fe6f 1054 log_warning("%s failed to run 'remount' task: %s", UNIT(m)->id, strerror(-r));
9d2f5178
LP
1055 m->reload_result = MOUNT_FAILURE_RESOURCES;
1056 mount_enter_mounted(m, MOUNT_SUCCESS);
e537352b
LP
1057}
1058
1059static int mount_start(Unit *u) {
1060 Mount *m = MOUNT(u);
1061
1062 assert(m);
1063
1064 /* We cannot fulfill this request right now, try again later
1065 * please! */
1066 if (m->state == MOUNT_UNMOUNTING ||
1067 m->state == MOUNT_UNMOUNTING_SIGTERM ||
60b912f6
LP
1068 m->state == MOUNT_UNMOUNTING_SIGKILL ||
1069 m->state == MOUNT_MOUNTING_SIGTERM ||
1070 m->state == MOUNT_MOUNTING_SIGKILL)
e537352b
LP
1071 return -EAGAIN;
1072
1073 /* Already on it! */
60b912f6 1074 if (m->state == MOUNT_MOUNTING)
e537352b
LP
1075 return 0;
1076
fdf20a31 1077 assert(m->state == MOUNT_DEAD || m->state == MOUNT_FAILED);
e537352b 1078
9d2f5178
LP
1079 m->result = MOUNT_SUCCESS;
1080 m->reload_result = MOUNT_SUCCESS;
1081
8d567588 1082 mount_enter_mounting(m);
e537352b
LP
1083 return 0;
1084}
1085
1086static int mount_stop(Unit *u) {
1087 Mount *m = MOUNT(u);
1088
1089 assert(m);
1090
e537352b
LP
1091 /* Already on it */
1092 if (m->state == MOUNT_UNMOUNTING ||
1093 m->state == MOUNT_UNMOUNTING_SIGKILL ||
60b912f6
LP
1094 m->state == MOUNT_UNMOUNTING_SIGTERM ||
1095 m->state == MOUNT_MOUNTING_SIGTERM ||
1096 m->state == MOUNT_MOUNTING_SIGKILL)
e537352b
LP
1097 return 0;
1098
3f6c78dc
LP
1099 assert(m->state == MOUNT_MOUNTING ||
1100 m->state == MOUNT_MOUNTING_DONE ||
1101 m->state == MOUNT_MOUNTED ||
3f6c78dc
LP
1102 m->state == MOUNT_REMOUNTING ||
1103 m->state == MOUNT_REMOUNTING_SIGTERM ||
1104 m->state == MOUNT_REMOUNTING_SIGKILL);
e537352b 1105
9d2f5178 1106 mount_enter_unmounting(m);
e537352b
LP
1107 return 0;
1108}
1109
1110static int mount_reload(Unit *u) {
1111 Mount *m = MOUNT(u);
1112
1113 assert(m);
1114
1115 if (m->state == MOUNT_MOUNTING_DONE)
1116 return -EAGAIN;
1117
1118 assert(m->state == MOUNT_MOUNTED);
1119
9d2f5178 1120 mount_enter_remounting(m);
e537352b
LP
1121 return 0;
1122}
1123
a16e1123
LP
1124static int mount_serialize(Unit *u, FILE *f, FDSet *fds) {
1125 Mount *m = MOUNT(u);
1126
1127 assert(m);
1128 assert(f);
1129 assert(fds);
1130
1131 unit_serialize_item(u, f, "state", mount_state_to_string(m->state));
9d2f5178
LP
1132 unit_serialize_item(u, f, "result", mount_result_to_string(m->result));
1133 unit_serialize_item(u, f, "reload-result", mount_result_to_string(m->reload_result));
a16e1123
LP
1134
1135 if (m->control_pid > 0)
5925dd3c 1136 unit_serialize_item_format(u, f, "control-pid", "%lu", (unsigned long) m->control_pid);
a16e1123
LP
1137
1138 if (m->control_command_id >= 0)
1139 unit_serialize_item(u, f, "control-command", mount_exec_command_to_string(m->control_command_id));
1140
1141 return 0;
1142}
1143
1144static int mount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
1145 Mount *m = MOUNT(u);
a16e1123
LP
1146
1147 assert(u);
1148 assert(key);
1149 assert(value);
1150 assert(fds);
1151
1152 if (streq(key, "state")) {
1153 MountState state;
1154
1155 if ((state = mount_state_from_string(value)) < 0)
1156 log_debug("Failed to parse state value %s", value);
1157 else
1158 m->deserialized_state = state;
9d2f5178
LP
1159 } else if (streq(key, "result")) {
1160 MountResult f;
a16e1123 1161
9d2f5178
LP
1162 f = mount_result_from_string(value);
1163 if (f < 0)
1164 log_debug("Failed to parse result value %s", value);
1165 else if (f != MOUNT_SUCCESS)
1166 m->result = f;
1167
1168 } else if (streq(key, "reload-result")) {
1169 MountResult f;
1170
1171 f = mount_result_from_string(value);
1172 if (f < 0)
1173 log_debug("Failed to parse reload result value %s", value);
1174 else if (f != MOUNT_SUCCESS)
1175 m->reload_result = f;
a16e1123
LP
1176
1177 } else if (streq(key, "control-pid")) {
5925dd3c 1178 pid_t pid;
a16e1123 1179
e364ad06 1180 if (parse_pid(value, &pid) < 0)
a16e1123
LP
1181 log_debug("Failed to parse control-pid value %s", value);
1182 else
5925dd3c 1183 m->control_pid = pid;
a16e1123
LP
1184 } else if (streq(key, "control-command")) {
1185 MountExecCommand id;
1186
1187 if ((id = mount_exec_command_from_string(value)) < 0)
1188 log_debug("Failed to parse exec-command value %s", value);
1189 else {
1190 m->control_command_id = id;
1191 m->control_command = m->exec_command + id;
1192 }
1193
1194 } else
1195 log_debug("Unknown serialization key '%s'", key);
1196
1197 return 0;
1198}
1199
e537352b
LP
1200static UnitActiveState mount_active_state(Unit *u) {
1201 assert(u);
1202
1203 return state_translation_table[MOUNT(u)->state];
1204}
1205
10a94420
LP
1206static const char *mount_sub_state_to_string(Unit *u) {
1207 assert(u);
1208
a16e1123 1209 return mount_state_to_string(MOUNT(u)->state);
10a94420
LP
1210}
1211
701cc384
LP
1212static bool mount_check_gc(Unit *u) {
1213 Mount *m = MOUNT(u);
1214
1215 assert(m);
1216
1217 return m->from_etc_fstab || m->from_proc_self_mountinfo;
1218}
1219
e537352b
LP
1220static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
1221 Mount *m = MOUNT(u);
9d2f5178 1222 MountResult f;
e537352b
LP
1223
1224 assert(m);
1225 assert(pid >= 0);
1226
8c47c732
LP
1227 if (pid != m->control_pid)
1228 return;
e537352b 1229
e537352b
LP
1230 m->control_pid = 0;
1231
9d2f5178
LP
1232 if (is_clean_exit(code, status))
1233 f = MOUNT_SUCCESS;
1234 else if (code == CLD_EXITED)
1235 f = MOUNT_FAILURE_EXIT_CODE;
1236 else if (code == CLD_KILLED)
1237 f = MOUNT_FAILURE_SIGNAL;
1238 else if (code == CLD_DUMPED)
1239 f = MOUNT_FAILURE_CORE_DUMP;
1240 else
1241 assert_not_reached("Unknown code");
1242
1243 if (f != MOUNT_SUCCESS)
1244 m->result = f;
8c47c732 1245
a16e1123 1246 if (m->control_command) {
6ea832a2 1247 exec_status_exit(&m->control_command->exec_status, &m->exec_context, pid, code, status);
9d2f5178 1248
a16e1123
LP
1249 m->control_command = NULL;
1250 m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
1251 }
1252
9d2f5178 1253 log_full(f == MOUNT_SUCCESS ? LOG_DEBUG : LOG_NOTICE,
ac155bb8 1254 "%s mount process exited, code=%s status=%i", u->id, sigchld_code_to_string(code), status);
e537352b
LP
1255
1256 /* Note that mount(8) returning and the kernel sending us a
1257 * mount table change event might happen out-of-order. If an
1258 * operation succeed we assume the kernel will follow soon too
1259 * and already change into the resulting state. If it fails
1260 * we check if the kernel still knows about the mount. and
1261 * change state accordingly. */
1262
1263 switch (m->state) {
1264
1265 case MOUNT_MOUNTING:
1266 case MOUNT_MOUNTING_DONE:
1267 case MOUNT_MOUNTING_SIGKILL:
1268 case MOUNT_MOUNTING_SIGTERM:
e537352b 1269
9d2f5178
LP
1270 if (f == MOUNT_SUCCESS)
1271 mount_enter_mounted(m, f);
e537352b 1272 else if (m->from_proc_self_mountinfo)
9d2f5178 1273 mount_enter_mounted(m, f);
e537352b 1274 else
9d2f5178 1275 mount_enter_dead(m, f);
e537352b
LP
1276 break;
1277
e2f3b44c
LP
1278 case MOUNT_REMOUNTING:
1279 case MOUNT_REMOUNTING_SIGKILL:
1280 case MOUNT_REMOUNTING_SIGTERM:
1281
9d2f5178 1282 m->reload_result = f;
e2f3b44c 1283 if (m->from_proc_self_mountinfo)
9d2f5178 1284 mount_enter_mounted(m, MOUNT_SUCCESS);
e2f3b44c 1285 else
9d2f5178 1286 mount_enter_dead(m, MOUNT_SUCCESS);
e2f3b44c
LP
1287
1288 break;
1289
e537352b
LP
1290 case MOUNT_UNMOUNTING:
1291 case MOUNT_UNMOUNTING_SIGKILL:
1292 case MOUNT_UNMOUNTING_SIGTERM:
1293
9d2f5178
LP
1294 if (f == MOUNT_SUCCESS)
1295 mount_enter_dead(m, f);
e537352b 1296 else if (m->from_proc_self_mountinfo)
9d2f5178 1297 mount_enter_mounted(m, f);
e537352b 1298 else
9d2f5178 1299 mount_enter_dead(m, f);
e537352b
LP
1300 break;
1301
1302 default:
1303 assert_not_reached("Uh, control process died at wrong time.");
1304 }
c4e2ceae
LP
1305
1306 /* Notify clients about changed exit status */
1307 unit_add_to_dbus_queue(u);
e537352b
LP
1308}
1309
1310static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
1311 Mount *m = MOUNT(u);
1312
1313 assert(m);
1314 assert(elapsed == 1);
1315 assert(w == &m->timer_watch);
1316
1317 switch (m->state) {
1318
1319 case MOUNT_MOUNTING:
1320 case MOUNT_MOUNTING_DONE:
ac155bb8 1321 log_warning("%s mounting timed out. Stopping.", u->id);
9d2f5178 1322 mount_enter_signal(m, MOUNT_MOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
e537352b
LP
1323 break;
1324
1325 case MOUNT_REMOUNTING:
ac155bb8 1326 log_warning("%s remounting timed out. Stopping.", u->id);
9d2f5178
LP
1327 m->reload_result = MOUNT_FAILURE_TIMEOUT;
1328 mount_enter_mounted(m, MOUNT_SUCCESS);
e537352b
LP
1329 break;
1330
1331 case MOUNT_UNMOUNTING:
ac155bb8 1332 log_warning("%s unmounting timed out. Stopping.", u->id);
9d2f5178 1333 mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
e537352b
LP
1334 break;
1335
1336 case MOUNT_MOUNTING_SIGTERM:
ba035df2 1337 if (m->exec_context.send_sigkill) {
ac155bb8 1338 log_warning("%s mounting timed out. Killing.", u->id);
9d2f5178 1339 mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
ba035df2 1340 } else {
ac155bb8 1341 log_warning("%s mounting timed out. Skipping SIGKILL. Ignoring.", u->id);
ba035df2
LP
1342
1343 if (m->from_proc_self_mountinfo)
9d2f5178 1344 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1345 else
9d2f5178 1346 mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1347 }
e537352b
LP
1348 break;
1349
1350 case MOUNT_REMOUNTING_SIGTERM:
ba035df2 1351 if (m->exec_context.send_sigkill) {
ac155bb8 1352 log_warning("%s remounting timed out. Killing.", u->id);
9d2f5178 1353 mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
ba035df2 1354 } else {
ac155bb8 1355 log_warning("%s remounting timed out. Skipping SIGKILL. Ignoring.", u->id);
ba035df2
LP
1356
1357 if (m->from_proc_self_mountinfo)
9d2f5178 1358 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1359 else
9d2f5178 1360 mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1361 }
e537352b
LP
1362 break;
1363
1364 case MOUNT_UNMOUNTING_SIGTERM:
ba035df2 1365 if (m->exec_context.send_sigkill) {
ac155bb8 1366 log_warning("%s unmounting timed out. Killing.", u->id);
9d2f5178 1367 mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
ba035df2 1368 } else {
ac155bb8 1369 log_warning("%s unmounting timed out. Skipping SIGKILL. Ignoring.", u->id);
ba035df2
LP
1370
1371 if (m->from_proc_self_mountinfo)
9d2f5178 1372 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1373 else
9d2f5178 1374 mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
ba035df2 1375 }
e537352b
LP
1376 break;
1377
1378 case MOUNT_MOUNTING_SIGKILL:
1379 case MOUNT_REMOUNTING_SIGKILL:
1380 case MOUNT_UNMOUNTING_SIGKILL:
ac155bb8 1381 log_warning("%s mount process still around after SIGKILL. Ignoring.", u->id);
e537352b
LP
1382
1383 if (m->from_proc_self_mountinfo)
9d2f5178 1384 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
e537352b 1385 else
9d2f5178 1386 mount_enter_dead(m, MOUNT_FAILURE_TIMEOUT);
e537352b
LP
1387 break;
1388
1389 default:
1390 assert_not_reached("Timeout at wrong time.");
1391 }
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,
9fff8a1f 1400 int passno,
e537352b
LP
1401 bool from_proc_self_mountinfo,
1402 bool set_flags) {
b08d03ff
LP
1403 int r;
1404 Unit *u;
1405 bool delete;
e537352b 1406 char *e, *w = NULL, *o = NULL, *f = NULL;
4e85aff4 1407 MountParameters *p;
b08d03ff 1408
f50e0a01 1409 assert(m);
b08d03ff
LP
1410 assert(what);
1411 assert(where);
e537352b
LP
1412 assert(options);
1413 assert(fstype);
1414
1415 assert(!set_flags || from_proc_self_mountinfo);
1416
1417 /* Ignore API mount points. They should never be referenced in
1418 * dependencies ever. */
33ff02c9 1419 if (mount_point_is_api(where) || mount_point_ignore(where))
57f2a956 1420 return 0;
b08d03ff 1421
8d567588
LP
1422 if (streq(fstype, "autofs"))
1423 return 0;
1424
4e85aff4
LP
1425 /* probably some kind of swap, ignore */
1426 if (!is_path(where))
b08d03ff
LP
1427 return 0;
1428
7d17cfbc
MS
1429 e = unit_name_from_path(where, ".mount");
1430 if (!e)
b08d03ff
LP
1431 return -ENOMEM;
1432
7d17cfbc
MS
1433 u = manager_get_unit(m, e);
1434 if (!u) {
b08d03ff
LP
1435 delete = true;
1436
7d17cfbc
MS
1437 u = unit_new(m, sizeof(Mount));
1438 if (!u) {
b08d03ff
LP
1439 free(e);
1440 return -ENOMEM;
1441 }
1442
1443 r = unit_add_name(u, e);
1444 free(e);
1445
1446 if (r < 0)
1447 goto fail;
1448
7d17cfbc
MS
1449 MOUNT(u)->where = strdup(where);
1450 if (!MOUNT(u)->where) {
07b0b134
ML
1451 r = -ENOMEM;
1452 goto fail;
1453 }
f50e0a01 1454
f94ea366 1455 unit_add_to_load_queue(u);
b08d03ff
LP
1456 } else {
1457 delete = false;
1458 free(e);
1459 }
1460
e537352b
LP
1461 if (!(w = strdup(what)) ||
1462 !(o = strdup(options)) ||
1463 !(f = strdup(fstype))) {
1464 r = -ENOMEM;
1465 goto fail;
1466 }
1467
1468 if (from_proc_self_mountinfo) {
4e85aff4 1469 p = &MOUNT(u)->parameters_proc_self_mountinfo;
e537352b
LP
1470
1471 if (set_flags) {
1472 MOUNT(u)->is_mounted = true;
1473 MOUNT(u)->just_mounted = !MOUNT(u)->from_proc_self_mountinfo;
4e85aff4 1474 MOUNT(u)->just_changed = !streq_ptr(p->options, o);
e537352b 1475 }
ef734fd6 1476
f50e0a01 1477 MOUNT(u)->from_proc_self_mountinfo = true;
ef734fd6 1478 } else {
4e85aff4 1479 p = &MOUNT(u)->parameters_etc_fstab;
f50e0a01 1480 MOUNT(u)->from_etc_fstab = true;
ef734fd6 1481 }
f50e0a01 1482
4e85aff4
LP
1483 free(p->what);
1484 p->what = w;
b08d03ff 1485
4e85aff4
LP
1486 free(p->options);
1487 p->options = o;
e537352b 1488
4e85aff4
LP
1489 free(p->fstype);
1490 p->fstype = f;
b08d03ff 1491
9fff8a1f
LP
1492 p->passno = passno;
1493
c1e1601e
LP
1494 unit_add_to_dbus_queue(u);
1495
b08d03ff
LP
1496 return 0;
1497
1498fail:
e537352b
LP
1499 free(w);
1500 free(o);
1501 free(f);
1502
b08d03ff
LP
1503 if (delete && u)
1504 unit_free(u);
1505
4e85aff4 1506 return r;
b08d03ff
LP
1507}
1508
07b0b134
ML
1509static int mount_find_pri(char *options) {
1510 char *end, *pri;
1511 unsigned long r;
1512
3a34ae3a 1513 if (!(pri = mount_test_option(options, "pri")))
07b0b134
ML
1514 return 0;
1515
1516 pri += 4;
1517
1518 errno = 0;
1519 r = strtoul(pri, &end, 10);
1520
1521 if (errno != 0)
1522 return -errno;
1523
1524 if (end == pri || (*end != ',' && *end != 0))
1525 return -EINVAL;
1526
1527 return (int) r;
1528}
1529
e537352b 1530static int mount_load_etc_fstab(Manager *m) {
b08d03ff 1531 FILE *f;
60b912f6 1532 int r = 0;
b08d03ff
LP
1533 struct mntent* me;
1534
1535 assert(m);
1536
1537 errno = 0;
1538 if (!(f = setmntent("/etc/fstab", "r")))
1539 return -errno;
1540
1541 while ((me = getmntent(f))) {
1542 char *where, *what;
60b912f6 1543 int k;
b08d03ff
LP
1544
1545 if (!(what = fstab_node_to_udev_node(me->mnt_fsname))) {
1546 r = -ENOMEM;
1547 goto finish;
1548 }
1549
1550 if (!(where = strdup(me->mnt_dir))) {
1551 free(what);
1552 r = -ENOMEM;
1553 goto finish;
1554 }
1555
1556 if (what[0] == '/')
1557 path_kill_slashes(what);
1558
1559 if (where[0] == '/')
1560 path_kill_slashes(where);
1561
07b0b134
ML
1562 if (streq(me->mnt_type, "swap")) {
1563 int pri;
1564
1565 if ((pri = mount_find_pri(me->mnt_opts)) < 0)
60b912f6 1566 k = pri;
07b0b134 1567 else
60b912f6 1568 k = swap_add_one(m,
07b0b134 1569 what,
60b912f6 1570 NULL,
07b0b134 1571 pri,
155da457 1572 !!mount_test_option(me->mnt_opts, "noauto"),
173a8d04 1573 !!mount_test_option(me->mnt_opts, "nofail"),
4e85aff4 1574 !!mount_test_option(me->mnt_opts, "comment=systemd.swapon"),
07b0b134
ML
1575 false);
1576 } else
9fff8a1f 1577 k = mount_add_one(m, what, where, me->mnt_opts, me->mnt_type, me->mnt_passno, false, false);
07b0b134 1578
b08d03ff
LP
1579 free(what);
1580 free(where);
1581
85eda572 1582 if (k < 0)
60b912f6 1583 r = k;
b08d03ff
LP
1584 }
1585
b08d03ff
LP
1586finish:
1587
1588 endmntent(f);
1589 return r;
1590}
1591
ef734fd6 1592static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
60b912f6 1593 int r = 0;
1ddff895 1594 unsigned i;
a2e0f3d3 1595 char *device, *path, *options, *options2, *fstype, *d, *p, *o;
b08d03ff
LP
1596
1597 assert(m);
1598
ef734fd6 1599 rewind(m->proc_self_mountinfo);
b08d03ff 1600
1ddff895 1601 for (i = 1;; i++) {
b08d03ff 1602 int k;
e537352b 1603
a2e0f3d3 1604 device = path = options = options2 = fstype = d = p = o = NULL;
b08d03ff 1605
ef734fd6 1606 if ((k = fscanf(m->proc_self_mountinfo,
b08d03ff
LP
1607 "%*s " /* (1) mount id */
1608 "%*s " /* (2) parent id */
1609 "%*s " /* (3) major:minor */
1610 "%*s " /* (4) root */
1611 "%ms " /* (5) mount point */
e537352b 1612 "%ms" /* (6) mount options */
b08d03ff 1613 "%*[^-]" /* (7) optional fields */
c899f8c6 1614 "- " /* (8) separator */
e537352b 1615 "%ms " /* (9) file system type */
ef734fd6 1616 "%ms" /* (10) mount source */
a2e0f3d3 1617 "%ms" /* (11) mount options 2 */
ef734fd6 1618 "%*[^\n]", /* some rubbish at the end */
b08d03ff 1619 &path,
e537352b
LP
1620 &options,
1621 &fstype,
a2e0f3d3
LP
1622 &device,
1623 &options2)) != 5) {
b08d03ff 1624
ef734fd6
LP
1625 if (k == EOF)
1626 break;
b08d03ff 1627
1ddff895
FF
1628 log_warning("Failed to parse /proc/self/mountinfo:%u.", i);
1629 goto clean_up;
b08d03ff
LP
1630 }
1631
a2e0f3d3
LP
1632 if (asprintf(&o, "%s,%s", options, options2) < 0) {
1633 r = -ENOMEM;
1634 goto finish;
1635 }
1636
e537352b
LP
1637 if (!(d = cunescape(device)) ||
1638 !(p = cunescape(path))) {
1639 r = -ENOMEM;
1640 goto finish;
b08d03ff 1641 }
b08d03ff 1642
9fff8a1f 1643 if ((k = mount_add_one(m, d, p, o, fstype, 0, true, set_flags)) < 0)
60b912f6 1644 r = k;
b08d03ff 1645
1ddff895 1646clean_up:
e537352b
LP
1647 free(device);
1648 free(path);
1649 free(options);
a2e0f3d3 1650 free(options2);
e537352b 1651 free(fstype);
b08d03ff
LP
1652 free(d);
1653 free(p);
a2e0f3d3 1654 free(o);
b08d03ff
LP
1655 }
1656
e537352b
LP
1657finish:
1658 free(device);
1659 free(path);
1660 free(options);
a2e0f3d3 1661 free(options2);
e537352b
LP
1662 free(fstype);
1663 free(d);
1664 free(p);
a2e0f3d3 1665 free(o);
e537352b
LP
1666
1667 return r;
1668}
1669
1670static void mount_shutdown(Manager *m) {
1671 assert(m);
1672
a16e1123 1673 if (m->proc_self_mountinfo) {
e537352b 1674 fclose(m->proc_self_mountinfo);
a16e1123
LP
1675 m->proc_self_mountinfo = NULL;
1676 }
b08d03ff
LP
1677}
1678
1679static int mount_enumerate(Manager *m) {
1680 int r;
ef734fd6 1681 struct epoll_event ev;
b08d03ff
LP
1682 assert(m);
1683
a16e1123
LP
1684 if (!m->proc_self_mountinfo) {
1685 if (!(m->proc_self_mountinfo = fopen("/proc/self/mountinfo", "re")))
1686 return -errno;
ef734fd6 1687
a16e1123
LP
1688 m->mount_watch.type = WATCH_MOUNT;
1689 m->mount_watch.fd = fileno(m->proc_self_mountinfo);
ef734fd6 1690
a16e1123 1691 zero(ev);
4e434314 1692 ev.events = EPOLLPRI;
a16e1123 1693 ev.data.ptr = &m->mount_watch;
ef734fd6 1694
a16e1123
LP
1695 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->mount_watch.fd, &ev) < 0)
1696 return -errno;
1697 }
ef734fd6 1698
e537352b 1699 if ((r = mount_load_etc_fstab(m)) < 0)
b08d03ff
LP
1700 goto fail;
1701
ef734fd6 1702 if ((r = mount_load_proc_self_mountinfo(m, false)) < 0)
b08d03ff
LP
1703 goto fail;
1704
1705 return 0;
1706
1707fail:
1708 mount_shutdown(m);
1709 return r;
5cb5a6ff
LP
1710}
1711
ef734fd6 1712void mount_fd_event(Manager *m, int events) {
595ed347 1713 Unit *u;
ef734fd6
LP
1714 int r;
1715
1716 assert(m);
4e434314 1717 assert(events & EPOLLPRI);
ef734fd6
LP
1718
1719 /* The manager calls this for every fd event happening on the
1720 * /proc/self/mountinfo file, which informs us about mounting
1721 * table changes */
1722
1723 if ((r = mount_load_proc_self_mountinfo(m, true)) < 0) {
e364ad06 1724 log_error("Failed to reread /proc/self/mountinfo: %s", strerror(-r));
e537352b
LP
1725
1726 /* Reset flags, just in case, for later calls */
595ed347
MS
1727 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) {
1728 Mount *mount = MOUNT(u);
e537352b
LP
1729
1730 mount->is_mounted = mount->just_mounted = mount->just_changed = false;
1731 }
1732
ef734fd6
LP
1733 return;
1734 }
1735
1736 manager_dispatch_load_queue(m);
1737
595ed347
MS
1738 LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) {
1739 Mount *mount = MOUNT(u);
ef734fd6 1740
e537352b
LP
1741 if (!mount->is_mounted) {
1742 /* This has just been unmounted. */
1743
ef734fd6 1744 mount->from_proc_self_mountinfo = false;
e537352b
LP
1745
1746 switch (mount->state) {
1747
1748 case MOUNT_MOUNTED:
9d2f5178 1749 mount_enter_dead(mount, MOUNT_SUCCESS);
e537352b
LP
1750 break;
1751
1752 default:
1753 mount_set_state(mount, mount->state);
1754 break;
1755
1756 }
1757
1758 } else if (mount->just_mounted || mount->just_changed) {
1759
60b912f6 1760 /* New or changed mount entry */
e537352b
LP
1761
1762 switch (mount->state) {
1763
1764 case MOUNT_DEAD:
fdf20a31 1765 case MOUNT_FAILED:
9d2f5178 1766 mount_enter_mounted(mount, MOUNT_SUCCESS);
e537352b
LP
1767 break;
1768
1769 case MOUNT_MOUNTING:
8d567588 1770 mount_enter_mounting_done(mount);
e537352b
LP
1771 break;
1772
1773 default:
1774 /* Nothing really changed, but let's
1775 * issue an notification call
1776 * nonetheless, in case somebody is
1777 * waiting for this. (e.g. file system
1778 * ro/rw remounts.) */
1779 mount_set_state(mount, mount->state);
1780 break;
1781 }
1782 }
1783
1784 /* Reset the flags for later calls */
1785 mount->is_mounted = mount->just_mounted = mount->just_changed = false;
1786 }
1787}
1788
fdf20a31 1789static void mount_reset_failed(Unit *u) {
5632e374
LP
1790 Mount *m = MOUNT(u);
1791
1792 assert(m);
1793
fdf20a31 1794 if (m->state == MOUNT_FAILED)
5632e374
LP
1795 mount_set_state(m, MOUNT_DEAD);
1796
9d2f5178
LP
1797 m->result = MOUNT_SUCCESS;
1798 m->reload_result = MOUNT_SUCCESS;
5632e374
LP
1799}
1800
8a0867d6
LP
1801static int mount_kill(Unit *u, KillWho who, KillMode mode, int signo, DBusError *error) {
1802 Mount *m = MOUNT(u);
1803 int r = 0;
1804 Set *pid_set = NULL;
1805
1806 assert(m);
1807
1808 if (who == KILL_MAIN) {
1809 dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "Mount units have no main processes");
a17204af 1810 return -ESRCH;
8a0867d6
LP
1811 }
1812
1813 if (m->control_pid <= 0 && who == KILL_CONTROL) {
1814 dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
a17204af 1815 return -ESRCH;
8a0867d6
LP
1816 }
1817
3611581e
LP
1818 if (who == KILL_CONTROL || who == KILL_ALL)
1819 if (m->control_pid > 0)
1820 if (kill(m->control_pid, signo) < 0)
1821 r = -errno;
8a0867d6 1822
3611581e 1823 if (who == KILL_ALL && mode == KILL_CONTROL_GROUP) {
8a0867d6
LP
1824 int q;
1825
1826 if (!(pid_set = set_new(trivial_hash_func, trivial_compare_func)))
1827 return -ENOMEM;
1828
1829 /* Exclude the control pid from being killed via the cgroup */
1830 if (m->control_pid > 0)
1831 if ((q = set_put(pid_set, LONG_TO_PTR(m->control_pid))) < 0) {
1832 r = q;
1833 goto finish;
1834 }
1835
1124fe6f 1836 if ((q = cgroup_bonding_kill_list(UNIT(m)->cgroup_bondings, signo, false, pid_set)) < 0)
3611581e 1837 if (q != -EAGAIN && q != -ESRCH && q != -ENOENT)
8a0867d6
LP
1838 r = q;
1839 }
1840
1841finish:
1842 if (pid_set)
1843 set_free(pid_set);
1844
1845 return r;
1846}
1847
a16e1123
LP
1848static const char* const mount_state_table[_MOUNT_STATE_MAX] = {
1849 [MOUNT_DEAD] = "dead",
1850 [MOUNT_MOUNTING] = "mounting",
1851 [MOUNT_MOUNTING_DONE] = "mounting-done",
1852 [MOUNT_MOUNTED] = "mounted",
1853 [MOUNT_REMOUNTING] = "remounting",
1854 [MOUNT_UNMOUNTING] = "unmounting",
1855 [MOUNT_MOUNTING_SIGTERM] = "mounting-sigterm",
1856 [MOUNT_MOUNTING_SIGKILL] = "mounting-sigkill",
1857 [MOUNT_REMOUNTING_SIGTERM] = "remounting-sigterm",
1858 [MOUNT_REMOUNTING_SIGKILL] = "remounting-sigkill",
1859 [MOUNT_UNMOUNTING_SIGTERM] = "unmounting-sigterm",
1860 [MOUNT_UNMOUNTING_SIGKILL] = "unmounting-sigkill",
fdf20a31 1861 [MOUNT_FAILED] = "failed"
a16e1123
LP
1862};
1863
1864DEFINE_STRING_TABLE_LOOKUP(mount_state, MountState);
1865
1866static const char* const mount_exec_command_table[_MOUNT_EXEC_COMMAND_MAX] = {
1867 [MOUNT_EXEC_MOUNT] = "ExecMount",
1868 [MOUNT_EXEC_UNMOUNT] = "ExecUnmount",
1869 [MOUNT_EXEC_REMOUNT] = "ExecRemount",
1870};
1871
1872DEFINE_STRING_TABLE_LOOKUP(mount_exec_command, MountExecCommand);
1873
9d2f5178
LP
1874static const char* const mount_result_table[_MOUNT_RESULT_MAX] = {
1875 [MOUNT_SUCCESS] = "success",
1876 [MOUNT_FAILURE_RESOURCES] = "resources",
1877 [MOUNT_FAILURE_TIMEOUT] = "timeout",
1878 [MOUNT_FAILURE_EXIT_CODE] = "exit-code",
1879 [MOUNT_FAILURE_SIGNAL] = "signal",
1880 [MOUNT_FAILURE_CORE_DUMP] = "core-dump"
1881};
1882
1883DEFINE_STRING_TABLE_LOOKUP(mount_result, MountResult);
1884
87f0e418 1885const UnitVTable mount_vtable = {
5cb5a6ff 1886 .suffix = ".mount",
7d17cfbc 1887 .object_size = sizeof(Mount),
f975e971
LP
1888 .sections =
1889 "Unit\0"
1890 "Mount\0"
1891 "Install\0",
5cb5a6ff 1892
e537352b 1893 .no_alias = true,
9e2f7c11 1894 .no_instances = true,
9e58ff9c 1895 .show_status = true,
e537352b
LP
1896
1897 .init = mount_init,
1898 .load = mount_load,
034c6ed7 1899 .done = mount_done,
e537352b 1900
f50e0a01
LP
1901 .coldplug = mount_coldplug,
1902
034c6ed7 1903 .dump = mount_dump,
5cb5a6ff 1904
e537352b
LP
1905 .start = mount_start,
1906 .stop = mount_stop,
1907 .reload = mount_reload,
1908
8a0867d6
LP
1909 .kill = mount_kill,
1910
a16e1123
LP
1911 .serialize = mount_serialize,
1912 .deserialize_item = mount_deserialize_item,
1913
f50e0a01 1914 .active_state = mount_active_state,
10a94420 1915 .sub_state_to_string = mount_sub_state_to_string,
b08d03ff 1916
701cc384
LP
1917 .check_gc = mount_check_gc,
1918
e537352b
LP
1919 .sigchld_event = mount_sigchld_event,
1920 .timer_event = mount_timer_event,
1921
fdf20a31 1922 .reset_failed = mount_reset_failed,
5632e374 1923
c4e2ceae 1924 .bus_interface = "org.freedesktop.systemd1.Mount",
4139c1b2 1925 .bus_message_handler = bus_mount_message_handler,
c4e2ceae 1926 .bus_invalidating_properties = bus_mount_invalidating_properties,
4139c1b2 1927
f50e0a01
LP
1928 .enumerate = mount_enumerate,
1929 .shutdown = mount_shutdown
5cb5a6ff 1930};