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