chiark / gitweb /
relicense to LGPLv2.1 (with exceptions)
[elogind.git] / src / core / automount.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23 #include <limits.h>
24 #include <sys/mount.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <sys/epoll.h>
28 #include <sys/stat.h>
29 #include <linux/auto_fs4.h>
30 #include <linux/auto_dev-ioctl.h>
31
32 #include "unit.h"
33 #include "automount.h"
34 #include "load-fragment.h"
35 #include "load-dropin.h"
36 #include "unit-name.h"
37 #include "dbus-automount.h"
38 #include "bus-errors.h"
39 #include "special.h"
40 #include "label.h"
41 #include "mkdir.h"
42
43 static const UnitActiveState state_translation_table[_AUTOMOUNT_STATE_MAX] = {
44         [AUTOMOUNT_DEAD] = UNIT_INACTIVE,
45         [AUTOMOUNT_WAITING] = UNIT_ACTIVE,
46         [AUTOMOUNT_RUNNING] = UNIT_ACTIVE,
47         [AUTOMOUNT_FAILED] = UNIT_FAILED
48 };
49
50 static int open_dev_autofs(Manager *m);
51
52 static void automount_init(Unit *u) {
53         Automount *a = AUTOMOUNT(u);
54
55         assert(u);
56         assert(u->load_state == UNIT_STUB);
57
58         a->pipe_watch.fd = a->pipe_fd = -1;
59         a->pipe_watch.type = WATCH_INVALID;
60
61         a->directory_mode = 0755;
62
63         UNIT(a)->ignore_on_isolate = true;
64 }
65
66 static void repeat_unmout(const char *path) {
67         assert(path);
68
69         for (;;) {
70                 /* If there are multiple mounts on a mount point, this
71                  * removes them all */
72
73                 if (umount2(path, MNT_DETACH) >= 0)
74                         continue;
75
76                 if (errno != EINVAL)
77                         log_error("Failed to unmount: %m");
78
79                 break;
80         }
81 }
82
83 static void unmount_autofs(Automount *a) {
84         assert(a);
85
86         if (a->pipe_fd < 0)
87                 return;
88
89         automount_send_ready(a, -EHOSTDOWN);
90
91         unit_unwatch_fd(UNIT(a), &a->pipe_watch);
92         close_nointr_nofail(a->pipe_fd);
93         a->pipe_fd = -1;
94
95         /* If we reload/reexecute things we keep the mount point
96          * around */
97         if (a->where &&
98             (UNIT(a)->manager->exit_code != MANAGER_RELOAD &&
99              UNIT(a)->manager->exit_code != MANAGER_REEXECUTE))
100                 repeat_unmout(a->where);
101 }
102
103 static void automount_done(Unit *u) {
104         Automount *a = AUTOMOUNT(u);
105
106         assert(a);
107
108         unmount_autofs(a);
109         unit_ref_unset(&a->mount);
110
111         free(a->where);
112         a->where = NULL;
113
114         set_free(a->tokens);
115         a->tokens = NULL;
116 }
117
118 int automount_add_one_mount_link(Automount *a, Mount *m) {
119         int r;
120
121         assert(a);
122         assert(m);
123
124         if (UNIT(a)->load_state != UNIT_LOADED ||
125             UNIT(m)->load_state != UNIT_LOADED)
126                 return 0;
127
128         if (!path_startswith(a->where, m->where))
129                 return 0;
130
131         if (path_equal(a->where, m->where))
132                 return 0;
133
134         if ((r = unit_add_two_dependencies(UNIT(a), UNIT_AFTER, UNIT_REQUIRES, UNIT(m), true)) < 0)
135                 return r;
136
137         return 0;
138 }
139
140 static int automount_add_mount_links(Automount *a) {
141         Unit *other;
142         int r;
143
144         assert(a);
145
146         LIST_FOREACH(units_by_type, other, UNIT(a)->manager->units_by_type[UNIT_MOUNT])
147                 if ((r = automount_add_one_mount_link(a, MOUNT(other))) < 0)
148                         return r;
149
150         return 0;
151 }
152
153 static int automount_add_default_dependencies(Automount *a) {
154         int r;
155
156         assert(a);
157
158         if (UNIT(a)->manager->running_as == MANAGER_SYSTEM) {
159
160                 if ((r = unit_add_dependency_by_name(UNIT(a), UNIT_BEFORE, SPECIAL_BASIC_TARGET, NULL, true)) < 0)
161                         return r;
162
163                 if ((r = unit_add_two_dependencies_by_name(UNIT(a), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, NULL, true)) < 0)
164                         return r;
165         }
166
167         return 0;
168 }
169
170 static int automount_verify(Automount *a) {
171         bool b;
172         char *e;
173         assert(a);
174
175         if (UNIT(a)->load_state != UNIT_LOADED)
176                 return 0;
177
178         if (path_equal(a->where, "/")) {
179                 log_error("Cannot have an automount unit for the root directory. Refusing.");
180                 return -EINVAL;
181         }
182
183         if (!(e = unit_name_from_path(a->where, ".automount")))
184                 return -ENOMEM;
185
186         b = unit_has_name(UNIT(a), e);
187         free(e);
188
189         if (!b) {
190                 log_error("%s's Where setting doesn't match unit name. Refusing.", UNIT(a)->id);
191                 return -EINVAL;
192         }
193
194         return 0;
195 }
196
197 static int automount_load(Unit *u) {
198         int r;
199         Automount *a = AUTOMOUNT(u);
200
201         assert(u);
202         assert(u->load_state == UNIT_STUB);
203
204         /* Load a .automount file */
205         if ((r = unit_load_fragment_and_dropin_optional(u)) < 0)
206                 return r;
207
208         if (u->load_state == UNIT_LOADED) {
209                 Unit *x;
210
211                 if (!a->where)
212                         if (!(a->where = unit_name_to_path(u->id)))
213                                 return -ENOMEM;
214
215                 path_kill_slashes(a->where);
216
217                 if ((r = automount_add_mount_links(a)) < 0)
218                         return r;
219
220                 r = unit_load_related_unit(u, ".mount", &x);
221                 if (r < 0)
222                         return r;
223
224                 unit_ref_set(&a->mount, x);
225
226                 r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, UNIT_DEREF(a->mount), true);
227                 if (r < 0)
228                         return r;
229
230                 if (UNIT(a)->default_dependencies)
231                         if ((r = automount_add_default_dependencies(a)) < 0)
232                                 return r;
233         }
234
235         return automount_verify(a);
236 }
237
238 static void automount_set_state(Automount *a, AutomountState state) {
239         AutomountState old_state;
240         assert(a);
241
242         old_state = a->state;
243         a->state = state;
244
245         if (state != AUTOMOUNT_WAITING &&
246             state != AUTOMOUNT_RUNNING)
247                 unmount_autofs(a);
248
249         if (state != old_state)
250                 log_debug("%s changed %s -> %s",
251                           UNIT(a)->id,
252                           automount_state_to_string(old_state),
253                           automount_state_to_string(state));
254
255         unit_notify(UNIT(a), state_translation_table[old_state], state_translation_table[state], true);
256 }
257
258 static int automount_coldplug(Unit *u) {
259         Automount *a = AUTOMOUNT(u);
260         int r;
261
262         assert(a);
263         assert(a->state == AUTOMOUNT_DEAD);
264
265         if (a->deserialized_state != a->state) {
266
267                 if ((r = open_dev_autofs(u->manager)) < 0)
268                         return r;
269
270                 if (a->deserialized_state == AUTOMOUNT_WAITING ||
271                     a->deserialized_state == AUTOMOUNT_RUNNING) {
272
273                         assert(a->pipe_fd >= 0);
274
275                         if ((r = unit_watch_fd(UNIT(a), a->pipe_fd, EPOLLIN, &a->pipe_watch)) < 0)
276                                 return r;
277                 }
278
279                 automount_set_state(a, a->deserialized_state);
280         }
281
282         return 0;
283 }
284
285 static void automount_dump(Unit *u, FILE *f, const char *prefix) {
286         Automount *a = AUTOMOUNT(u);
287
288         assert(a);
289
290         fprintf(f,
291                 "%sAutomount State: %s\n"
292                 "%sResult: %s\n"
293                 "%sWhere: %s\n"
294                 "%sDirectoryMode: %04o\n",
295                 prefix, automount_state_to_string(a->state),
296                 prefix, automount_result_to_string(a->result),
297                 prefix, a->where,
298                 prefix, a->directory_mode);
299 }
300
301 static void automount_enter_dead(Automount *a, AutomountResult f) {
302         assert(a);
303
304         if (f != AUTOMOUNT_SUCCESS)
305                 a->result = f;
306
307         automount_set_state(a, a->result != AUTOMOUNT_SUCCESS ? AUTOMOUNT_FAILED : AUTOMOUNT_DEAD);
308 }
309
310 static int open_dev_autofs(Manager *m) {
311         struct autofs_dev_ioctl param;
312
313         assert(m);
314
315         if (m->dev_autofs_fd >= 0)
316                 return m->dev_autofs_fd;
317
318         label_fix("/dev/autofs", false);
319
320         if ((m->dev_autofs_fd = open("/dev/autofs", O_CLOEXEC|O_RDONLY)) < 0) {
321                 log_error("Failed to open /dev/autofs: %s", strerror(errno));
322                 return -errno;
323         }
324
325         init_autofs_dev_ioctl(&param);
326         if (ioctl(m->dev_autofs_fd, AUTOFS_DEV_IOCTL_VERSION, &param) < 0) {
327                 close_nointr_nofail(m->dev_autofs_fd);
328                 m->dev_autofs_fd = -1;
329                 return -errno;
330         }
331
332         log_debug("Autofs kernel version %i.%i", param.ver_major, param.ver_minor);
333
334         return m->dev_autofs_fd;
335 }
336
337 static int open_ioctl_fd(int dev_autofs_fd, const char *where, dev_t devid) {
338         struct autofs_dev_ioctl *param;
339         size_t l;
340         int r;
341
342         assert(dev_autofs_fd >= 0);
343         assert(where);
344
345         l = sizeof(struct autofs_dev_ioctl) + strlen(where) + 1;
346
347         if (!(param = malloc(l)))
348                 return -ENOMEM;
349
350         init_autofs_dev_ioctl(param);
351         param->size = l;
352         param->ioctlfd = -1;
353         param->openmount.devid = devid;
354         strcpy(param->path, where);
355
356         if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_OPENMOUNT, param) < 0) {
357                 r = -errno;
358                 goto finish;
359         }
360
361         if (param->ioctlfd < 0) {
362                 r = -EIO;
363                 goto finish;
364         }
365
366         fd_cloexec(param->ioctlfd, true);
367         r = param->ioctlfd;
368
369 finish:
370         free(param);
371         return r;
372 }
373
374 static int autofs_protocol(int dev_autofs_fd, int ioctl_fd) {
375         uint32_t major, minor;
376         struct autofs_dev_ioctl param;
377
378         assert(dev_autofs_fd >= 0);
379         assert(ioctl_fd >= 0);
380
381         init_autofs_dev_ioctl(&param);
382         param.ioctlfd = ioctl_fd;
383
384         if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_PROTOVER, &param) < 0)
385                 return -errno;
386
387         major = param.protover.version;
388
389         init_autofs_dev_ioctl(&param);
390         param.ioctlfd = ioctl_fd;
391
392         if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_PROTOSUBVER, &param) < 0)
393                 return -errno;
394
395         minor = param.protosubver.sub_version;
396
397         log_debug("Autofs protocol version %i.%i", major, minor);
398         return 0;
399 }
400
401 static int autofs_set_timeout(int dev_autofs_fd, int ioctl_fd, time_t sec) {
402         struct autofs_dev_ioctl param;
403
404         assert(dev_autofs_fd >= 0);
405         assert(ioctl_fd >= 0);
406
407         init_autofs_dev_ioctl(&param);
408         param.ioctlfd = ioctl_fd;
409         param.timeout.timeout = sec;
410
411         if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_TIMEOUT, &param) < 0)
412                 return -errno;
413
414         return 0;
415 }
416
417 static int autofs_send_ready(int dev_autofs_fd, int ioctl_fd, uint32_t token, int status) {
418         struct autofs_dev_ioctl param;
419
420         assert(dev_autofs_fd >= 0);
421         assert(ioctl_fd >= 0);
422
423         init_autofs_dev_ioctl(&param);
424         param.ioctlfd = ioctl_fd;
425
426         if (status) {
427                 param.fail.token = token;
428                 param.fail.status = status;
429         } else
430                 param.ready.token = token;
431
432         if (ioctl(dev_autofs_fd, status ? AUTOFS_DEV_IOCTL_FAIL : AUTOFS_DEV_IOCTL_READY, &param) < 0)
433                 return -errno;
434
435         return 0;
436 }
437
438 int automount_send_ready(Automount *a, int status) {
439         int ioctl_fd, r;
440         unsigned token;
441
442         assert(a);
443         assert(status <= 0);
444
445         if (set_isempty(a->tokens))
446                 return 0;
447
448         if ((ioctl_fd = open_ioctl_fd(UNIT(a)->manager->dev_autofs_fd, a->where, a->dev_id)) < 0) {
449                 r = ioctl_fd;
450                 goto fail;
451         }
452
453         if (status)
454                 log_debug("Sending failure: %s", strerror(-status));
455         else
456                 log_debug("Sending success.");
457
458         r = 0;
459
460         /* Autofs thankfully does not hand out 0 as a token */
461         while ((token = PTR_TO_UINT(set_steal_first(a->tokens)))) {
462                 int k;
463
464                 /* Autofs fun fact II:
465                  *
466                  * if you pass a positive status code here, the kernel will
467                  * freeze! Yay! */
468
469                 if ((k = autofs_send_ready(UNIT(a)->manager->dev_autofs_fd,
470                                            ioctl_fd,
471                                            token,
472                                            status)) < 0)
473                         r = k;
474         }
475
476 fail:
477         if (ioctl_fd >= 0)
478                 close_nointr_nofail(ioctl_fd);
479
480         return r;
481 }
482
483 static void automount_enter_waiting(Automount *a) {
484         int p[2] = { -1, -1 };
485         char name[32], options[128];
486         bool mounted = false;
487         int r, ioctl_fd = -1, dev_autofs_fd;
488         struct stat st;
489
490         assert(a);
491         assert(a->pipe_fd < 0);
492         assert(a->where);
493
494         if (a->tokens)
495                 set_clear(a->tokens);
496
497         if ((dev_autofs_fd = open_dev_autofs(UNIT(a)->manager)) < 0) {
498                 r = dev_autofs_fd;
499                 goto fail;
500         }
501
502         /* We knowingly ignore the results of this call */
503         mkdir_p(a->where, 0555);
504
505         if (pipe2(p, O_NONBLOCK|O_CLOEXEC) < 0) {
506                 r = -errno;
507                 goto fail;
508         }
509
510         snprintf(options, sizeof(options), "fd=%i,pgrp=%u,minproto=5,maxproto=5,direct", p[1], (unsigned) getpgrp());
511         char_array_0(options);
512
513         snprintf(name, sizeof(name), "systemd-%u", (unsigned) getpid());
514         char_array_0(name);
515
516         if (mount(name, a->where, "autofs", 0, options) < 0) {
517                 r = -errno;
518                 goto fail;
519         }
520
521         mounted = true;
522
523         close_nointr_nofail(p[1]);
524         p[1] = -1;
525
526         if (stat(a->where, &st) < 0) {
527                 r = -errno;
528                 goto fail;
529         }
530
531         if ((ioctl_fd = open_ioctl_fd(dev_autofs_fd, a->where, st.st_dev)) < 0) {
532                 r = ioctl_fd;
533                 goto fail;
534         }
535
536         if ((r = autofs_protocol(dev_autofs_fd, ioctl_fd)) < 0)
537                 goto fail;
538
539         if ((r = autofs_set_timeout(dev_autofs_fd, ioctl_fd, 300)) < 0)
540                 goto fail;
541
542         /* Autofs fun fact:
543          *
544          * Unless we close the ioctl fd here, for some weird reason
545          * the direct mount will not receive events from the
546          * kernel. */
547
548         close_nointr_nofail(ioctl_fd);
549         ioctl_fd = -1;
550
551         if ((r = unit_watch_fd(UNIT(a), p[0], EPOLLIN, &a->pipe_watch)) < 0)
552                 goto fail;
553
554         a->pipe_fd = p[0];
555         a->dev_id = st.st_dev;
556
557         automount_set_state(a, AUTOMOUNT_WAITING);
558
559         return;
560
561 fail:
562         assert_se(close_pipe(p) == 0);
563
564         if (ioctl_fd >= 0)
565                 close_nointr_nofail(ioctl_fd);
566
567         if (mounted)
568                 repeat_unmout(a->where);
569
570         log_error("Failed to initialize automounter: %s", strerror(-r));
571         automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
572 }
573
574 static void automount_enter_runnning(Automount *a) {
575         int r;
576         struct stat st;
577         DBusError error;
578
579         assert(a);
580         assert(UNIT_DEREF(a->mount));
581
582         dbus_error_init(&error);
583
584         /* We don't take mount requests anymore if we are supposed to
585          * shut down anyway */
586         if (unit_pending_inactive(UNIT(a))) {
587                 log_debug("Suppressing automount request on %s since unit stop is scheduled.", UNIT(a)->id);
588                 automount_send_ready(a, -EHOSTDOWN);
589                 return;
590         }
591
592         mkdir_p(a->where, a->directory_mode);
593
594         /* Before we do anything, let's see if somebody is playing games with us? */
595         if (lstat(a->where, &st) < 0) {
596                 log_warning("%s failed to stat automount point: %m", UNIT(a)->id);
597                 goto fail;
598         }
599
600         if (!S_ISDIR(st.st_mode) || st.st_dev != a->dev_id)
601                 log_info("%s's automount point already active?", UNIT(a)->id);
602         else if ((r = manager_add_job(UNIT(a)->manager, JOB_START, UNIT_DEREF(a->mount), JOB_REPLACE, true, &error, NULL)) < 0) {
603                 log_warning("%s failed to queue mount startup job: %s", UNIT(a)->id, bus_error(&error, r));
604                 goto fail;
605         }
606
607         automount_set_state(a, AUTOMOUNT_RUNNING);
608         return;
609
610 fail:
611         automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
612         dbus_error_free(&error);
613 }
614
615 static int automount_start(Unit *u) {
616         Automount *a = AUTOMOUNT(u);
617
618         assert(a);
619
620         assert(a->state == AUTOMOUNT_DEAD || a->state == AUTOMOUNT_FAILED);
621
622         if (path_is_mount_point(a->where, false)) {
623                 log_error("Path %s is already a mount point, refusing start for %s", a->where, u->id);
624                 return -EEXIST;
625         }
626
627         if (UNIT_DEREF(a->mount)->load_state != UNIT_LOADED)
628                 return -ENOENT;
629
630         a->result = AUTOMOUNT_SUCCESS;
631         automount_enter_waiting(a);
632         return 0;
633 }
634
635 static int automount_stop(Unit *u) {
636         Automount *a = AUTOMOUNT(u);
637
638         assert(a);
639
640         assert(a->state == AUTOMOUNT_WAITING || a->state == AUTOMOUNT_RUNNING);
641
642         automount_enter_dead(a, AUTOMOUNT_SUCCESS);
643         return 0;
644 }
645
646 static int automount_serialize(Unit *u, FILE *f, FDSet *fds) {
647         Automount *a = AUTOMOUNT(u);
648         void *p;
649         Iterator i;
650
651         assert(a);
652         assert(f);
653         assert(fds);
654
655         unit_serialize_item(u, f, "state", automount_state_to_string(a->state));
656         unit_serialize_item(u, f, "result", automount_result_to_string(a->result));
657         unit_serialize_item_format(u, f, "dev-id", "%u", (unsigned) a->dev_id);
658
659         SET_FOREACH(p, a->tokens, i)
660                 unit_serialize_item_format(u, f, "token", "%u", PTR_TO_UINT(p));
661
662         if (a->pipe_fd >= 0) {
663                 int copy;
664
665                 if ((copy = fdset_put_dup(fds, a->pipe_fd)) < 0)
666                         return copy;
667
668                 unit_serialize_item_format(u, f, "pipe-fd", "%i", copy);
669         }
670
671         return 0;
672 }
673
674 static int automount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
675         Automount *a = AUTOMOUNT(u);
676         int r;
677
678         assert(a);
679         assert(fds);
680
681         if (streq(key, "state")) {
682                 AutomountState state;
683
684                 if ((state = automount_state_from_string(value)) < 0)
685                         log_debug("Failed to parse state value %s", value);
686                 else
687                         a->deserialized_state = state;
688         } else if (streq(key, "result")) {
689                 AutomountResult f;
690
691                 f = automount_result_from_string(value);
692                 if (f < 0)
693                         log_debug("Failed to parse result value %s", value);
694                 else if (f != AUTOMOUNT_SUCCESS)
695                         a->result = f;
696
697         } else if (streq(key, "dev-id")) {
698                 unsigned d;
699
700                 if (safe_atou(value, &d) < 0)
701                         log_debug("Failed to parse dev-id value %s", value);
702                 else
703                         a->dev_id = (unsigned) d;
704         } else if (streq(key, "token")) {
705                 unsigned token;
706
707                 if (safe_atou(value, &token) < 0)
708                         log_debug("Failed to parse token value %s", value);
709                 else {
710                         if (!a->tokens)
711                                 if (!(a->tokens = set_new(trivial_hash_func, trivial_compare_func)))
712                                         return -ENOMEM;
713
714                         if ((r = set_put(a->tokens, UINT_TO_PTR(token))) < 0)
715                                 return r;
716                 }
717         } else if (streq(key, "pipe-fd")) {
718                 int fd;
719
720                 if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
721                         log_debug("Failed to parse pipe-fd value %s", value);
722                 else {
723                         if (a->pipe_fd >= 0)
724                                 close_nointr_nofail(a->pipe_fd);
725
726                         a->pipe_fd = fdset_remove(fds, fd);
727                 }
728         } else
729                 log_debug("Unknown serialization key '%s'", key);
730
731         return 0;
732 }
733
734 static UnitActiveState automount_active_state(Unit *u) {
735         assert(u);
736
737         return state_translation_table[AUTOMOUNT(u)->state];
738 }
739
740 static const char *automount_sub_state_to_string(Unit *u) {
741         assert(u);
742
743         return automount_state_to_string(AUTOMOUNT(u)->state);
744 }
745
746 static bool automount_check_gc(Unit *u) {
747         Automount *a = AUTOMOUNT(u);
748
749         assert(a);
750
751         if (!UNIT_DEREF(a->mount))
752                 return false;
753
754         return UNIT_VTABLE(UNIT_DEREF(a->mount))->check_gc(UNIT_DEREF(a->mount));
755 }
756
757 static void automount_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
758         Automount *a = AUTOMOUNT(u);
759         union autofs_v5_packet_union packet;
760         ssize_t l;
761         int r;
762
763         assert(a);
764         assert(fd == a->pipe_fd);
765
766         if (events != EPOLLIN) {
767                 log_error("Got invalid poll event on pipe.");
768                 goto fail;
769         }
770
771         if ((l = loop_read(a->pipe_fd, &packet, sizeof(packet), true)) != sizeof(packet)) {
772                 log_error("Invalid read from pipe: %s", l < 0 ? strerror(-l) : "short read");
773                 goto fail;
774         }
775
776         switch (packet.hdr.type) {
777
778         case autofs_ptype_missing_direct:
779
780                 if (packet.v5_packet.pid > 0) {
781                         char *p = NULL;
782
783                         get_process_comm(packet.v5_packet.pid, &p);
784                         log_debug("Got direct mount request for %s, triggered by %lu (%s)", packet.v5_packet.name, (unsigned long) packet.v5_packet.pid, strna(p));
785                         free(p);
786
787                 } else
788                         log_debug("Got direct mount request for %s", packet.v5_packet.name);
789
790                 if (!a->tokens)
791                         if (!(a->tokens = set_new(trivial_hash_func, trivial_compare_func))) {
792                                 log_error("Failed to allocate token set.");
793                                 goto fail;
794                         }
795
796                 if ((r = set_put(a->tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token))) < 0) {
797                         log_error("Failed to remember token: %s", strerror(-r));
798                         goto fail;
799                 }
800
801                 automount_enter_runnning(a);
802                 break;
803
804         default:
805                 log_error("Received unknown automount request %i", packet.hdr.type);
806                 break;
807         }
808
809         return;
810
811 fail:
812         automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
813 }
814
815 static void automount_shutdown(Manager *m) {
816         assert(m);
817
818         if (m->dev_autofs_fd >= 0)
819                 close_nointr_nofail(m->dev_autofs_fd);
820 }
821
822 static void automount_reset_failed(Unit *u) {
823         Automount *a = AUTOMOUNT(u);
824
825         assert(a);
826
827         if (a->state == AUTOMOUNT_FAILED)
828                 automount_set_state(a, AUTOMOUNT_DEAD);
829
830         a->result = AUTOMOUNT_SUCCESS;
831 }
832
833 static const char* const automount_state_table[_AUTOMOUNT_STATE_MAX] = {
834         [AUTOMOUNT_DEAD] = "dead",
835         [AUTOMOUNT_WAITING] = "waiting",
836         [AUTOMOUNT_RUNNING] = "running",
837         [AUTOMOUNT_FAILED] = "failed"
838 };
839
840 DEFINE_STRING_TABLE_LOOKUP(automount_state, AutomountState);
841
842 static const char* const automount_result_table[_AUTOMOUNT_RESULT_MAX] = {
843         [AUTOMOUNT_SUCCESS] = "success",
844         [AUTOMOUNT_FAILURE_RESOURCES] = "resources"
845 };
846
847 DEFINE_STRING_TABLE_LOOKUP(automount_result, AutomountResult);
848
849 const UnitVTable automount_vtable = {
850         .suffix = ".automount",
851         .object_size = sizeof(Automount),
852         .sections =
853                 "Unit\0"
854                 "Automount\0"
855                 "Install\0",
856
857         .no_alias = true,
858         .no_instances = true,
859
860         .init = automount_init,
861         .load = automount_load,
862         .done = automount_done,
863
864         .coldplug = automount_coldplug,
865
866         .dump = automount_dump,
867
868         .start = automount_start,
869         .stop = automount_stop,
870
871         .serialize = automount_serialize,
872         .deserialize_item = automount_deserialize_item,
873
874         .active_state = automount_active_state,
875         .sub_state_to_string = automount_sub_state_to_string,
876
877         .check_gc = automount_check_gc,
878
879         .fd_event = automount_fd_event,
880
881         .reset_failed = automount_reset_failed,
882
883         .bus_interface = "org.freedesktop.systemd1.Automount",
884         .bus_message_handler = bus_automount_message_handler,
885         .bus_invalidating_properties = bus_automount_invalidating_properties,
886
887         .shutdown = automount_shutdown
888 };