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