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