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