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