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