chiark / gitweb /
cgroup: add cgroup_bonding_to_string() call
[elogind.git] / automount.c
1 /*-*- Mode: C; c-basic-offset: 8 -*-*/
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 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
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
38 static const UnitActiveState state_translation_table[_AUTOMOUNT_STATE_MAX] = {
39         [AUTOMOUNT_DEAD] = UNIT_INACTIVE,
40         [AUTOMOUNT_WAITING] = UNIT_ACTIVE,
41         [AUTOMOUNT_RUNNING] = UNIT_ACTIVE,
42         [AUTOMOUNT_MAINTAINANCE] = UNIT_INACTIVE,
43 };
44
45 static const char* const state_string_table[_AUTOMOUNT_STATE_MAX] = {
46         [AUTOMOUNT_DEAD] = "dead",
47         [AUTOMOUNT_WAITING] = "waiting",
48         [AUTOMOUNT_RUNNING] = "running",
49         [AUTOMOUNT_MAINTAINANCE] = "maintainance"
50 };
51
52 static char *automount_name_from_where(const char *where) {
53         assert(where);
54
55         if (streq(where, "/"))
56                 return strdup("-.automount");
57
58         return unit_name_build_escape(where+1, NULL, ".automount");
59 }
60
61 static void automount_init(Unit *u) {
62         Automount *a = AUTOMOUNT(u);
63
64         assert(u);
65         assert(u->meta.load_state == UNIT_STUB);
66
67         a->pipe_watch.fd = a->pipe_fd = -1;
68 }
69
70 static void repeat_unmout(const char *path) {
71         assert(path);
72
73         for (;;) {
74
75                 if (umount2(path, MNT_DETACH) >= 0)
76                         continue;
77
78                 if (errno != EINVAL)
79                         log_error("Failed to unmount: %m");
80
81                 break;
82         }
83 }
84
85 static void unmount_autofs(Automount *a) {
86         assert(a);
87
88         if (a->pipe_fd < 0)
89                 return;
90
91         automount_send_ready(a, -EHOSTDOWN);
92
93         unit_unwatch_fd(UNIT(a), &a->pipe_watch);
94         close_nointr_nofail(a->pipe_fd);
95         a->pipe_fd = -1;
96
97         repeat_unmout(a->where);
98 }
99
100 static void automount_done(Unit *u) {
101         Automount *a = AUTOMOUNT(u);
102
103         assert(a);
104
105         unmount_autofs(a);
106         a->mount = NULL;
107
108         if (a->tokens) {
109                 set_free(a->tokens);
110                 a->tokens = NULL;
111         }
112 }
113
114 static int automount_verify(Automount *a) {
115         bool b;
116         char *e;
117         assert(a);
118
119         if (UNIT(a)->meta.load_state != UNIT_LOADED)
120                 return 0;
121
122         if (!a->where) {
123                 log_error("%s lacks Where setting. Refusing.", UNIT(a)->meta.id);
124                 return -EINVAL;
125         }
126
127         path_kill_slashes(a->where);
128
129         if (!(e = automount_name_from_where(a->where)))
130                 return -ENOMEM;
131
132         b = unit_has_name(UNIT(a), e);
133         free(e);
134
135         if (!b) {
136                 log_error("%s's Where setting doesn't match unit name. Refusing.", UNIT(a)->meta.id);
137                 return -EINVAL;
138         }
139
140         return 0;
141 }
142
143 static int automount_load(Unit *u) {
144         int r;
145         Automount *a = AUTOMOUNT(u);
146
147         assert(u);
148         assert(u->meta.load_state == UNIT_STUB);
149
150         /* Load a .automount file */
151         if ((r = unit_load_fragment_and_dropin_optional(u)) < 0)
152                 return r;
153
154         if (u->meta.load_state == UNIT_LOADED) {
155
156                 if ((r = unit_load_related_unit(u, ".mount", (Unit**) &a->mount)) < 0)
157                         return r;
158
159                 if ((r = unit_add_dependency(u, UNIT_BEFORE, UNIT(a->mount))) < 0)
160                         return r;
161         }
162
163         return automount_verify(a);
164 }
165
166 static void automount_set_state(Automount *a, AutomountState state) {
167         AutomountState old_state;
168         assert(a);
169
170         old_state = a->state;
171         a->state = state;
172
173         if (state != AUTOMOUNT_WAITING &&
174             state != AUTOMOUNT_RUNNING)
175                 unmount_autofs(a);
176
177         if (state != old_state)
178                 log_debug("%s changed %s → %s", UNIT(a)->meta.id, state_string_table[old_state], state_string_table[state]);
179
180         unit_notify(UNIT(a), state_translation_table[old_state], state_translation_table[state]);
181 }
182
183 static void automount_dump(Unit *u, FILE *f, const char *prefix) {
184         Automount *s = AUTOMOUNT(u);
185
186         assert(s);
187
188         fprintf(f,
189                 "%sAutomount State: %s\n",
190                 prefix, state_string_table[s->state]);
191 }
192
193 static void automount_enter_dead(Automount *a, bool success) {
194         assert(a);
195
196         if (!success)
197                 a->failure = true;
198
199         automount_set_state(a, a->failure ? AUTOMOUNT_MAINTAINANCE : AUTOMOUNT_DEAD);
200 }
201
202 static int open_dev_autofs(Manager *m) {
203         struct autofs_dev_ioctl param;
204
205         assert(m);
206
207         if (m->dev_autofs_fd >= 0)
208                 return m->dev_autofs_fd;
209
210         if ((m->dev_autofs_fd = open("/dev/autofs", O_RDONLY)) < 0) {
211                 log_error("Failed to open /dev/autofs: %s", strerror(errno));
212                 return -errno;
213         }
214
215         init_autofs_dev_ioctl(&param);
216         if (ioctl(m->dev_autofs_fd, AUTOFS_DEV_IOCTL_VERSION, &param) < 0) {
217                 close_nointr_nofail(m->dev_autofs_fd);
218                 m->dev_autofs_fd = -1;
219                 return -errno;
220         }
221
222         log_debug("Autofs kernel version %i.%i", param.ver_major, param.ver_minor);
223
224         return m->dev_autofs_fd;
225 }
226
227 static int open_ioctl_fd(int dev_autofs_fd, const char *where, dev_t devid) {
228         struct autofs_dev_ioctl *param;
229         size_t l;
230         int r;
231
232         assert(dev_autofs_fd >= 0);
233         assert(where);
234
235         l = sizeof(struct autofs_dev_ioctl) + strlen(where) + 1;
236
237         if (!(param = malloc(l)))
238                 return -ENOMEM;
239
240         init_autofs_dev_ioctl(param);
241         param->size = l;
242         param->ioctlfd = -1;
243         param->openmount.devid = devid;
244         strcpy(param->path, where);
245
246         if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_OPENMOUNT, param) < 0) {
247                 r = -errno;
248                 goto finish;
249         }
250
251         if (param->ioctlfd < 0) {
252                 r = -EIO;
253                 goto finish;
254         }
255
256         r = param->ioctlfd;
257
258 finish:
259         free(param);
260         return r;
261 }
262
263 static int autofs_protocol(int dev_autofs_fd, int ioctl_fd) {
264         uint32_t major, minor;
265         struct autofs_dev_ioctl param;
266
267         assert(dev_autofs_fd >= 0);
268         assert(ioctl_fd >= 0);
269
270         init_autofs_dev_ioctl(&param);
271         param.ioctlfd = ioctl_fd;
272
273         if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_PROTOVER, &param) < 0)
274                 return -errno;
275
276         major = param.protover.version;
277
278         init_autofs_dev_ioctl(&param);
279         param.ioctlfd = ioctl_fd;
280
281         if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_PROTOSUBVER, &param) < 0)
282                 return -errno;
283
284         minor = param.protosubver.sub_version;
285
286         log_debug("Autofs protocol version %i.%i", major, minor);
287         return 0;
288 }
289
290 static int autofs_set_timeout(int dev_autofs_fd, int ioctl_fd, time_t sec) {
291         struct autofs_dev_ioctl param;
292
293         assert(dev_autofs_fd >= 0);
294         assert(ioctl_fd >= 0);
295
296         init_autofs_dev_ioctl(&param);
297         param.ioctlfd = ioctl_fd;
298         param.timeout.timeout = sec;
299
300         if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_TIMEOUT, &param) < 0)
301                 return -errno;
302
303         return 0;
304 }
305
306 static int autofs_send_ready(int dev_autofs_fd, int ioctl_fd, uint32_t token, int status) {
307         struct autofs_dev_ioctl param;
308
309         assert(dev_autofs_fd >= 0);
310         assert(ioctl_fd >= 0);
311
312         init_autofs_dev_ioctl(&param);
313         param.ioctlfd = ioctl_fd;
314
315         if (status) {
316                 param.fail.token = token;
317                 param.fail.status = status;
318         } else
319                 param.ready.token = token;
320
321         if (ioctl(dev_autofs_fd, status ? AUTOFS_DEV_IOCTL_FAIL : AUTOFS_DEV_IOCTL_READY, &param) < 0)
322                 return -errno;
323
324         return 0;
325 }
326
327 int automount_send_ready(Automount *a, int status) {
328         int ioctl_fd, r;
329         unsigned token;
330
331         assert(a);
332         assert(status <= 0);
333
334         if (set_isempty(a->tokens))
335                 return 0;
336
337         if ((ioctl_fd = open_ioctl_fd(UNIT(a)->meta.manager->dev_autofs_fd, a->where, a->dev_id)) < 0) {
338                 r = ioctl_fd;
339                 goto fail;
340         }
341
342         if (status)
343                 log_debug("Sending failure: %s", strerror(-status));
344         else
345                 log_debug("Sending success.");
346
347         /* Autofs thankfully does not hand out 0 as a token */
348         while ((token = PTR_TO_UINT(set_steal_first(a->tokens)))) {
349                 int k;
350
351                 /* Autofs fun fact II:
352                  *
353                  * if you pass a positive status code here, the kernel will
354                  * freeze! Yay! */
355
356                 if ((k = autofs_send_ready(UNIT(a)->meta.manager->dev_autofs_fd,
357                                            ioctl_fd,
358                                            token,
359                                            status)) < 0)
360                         r = k;
361         }
362
363         r = 0;
364
365 fail:
366         if (ioctl_fd >= 0)
367                 close_nointr_nofail(ioctl_fd);
368
369         return r;
370 }
371
372 static void automount_enter_waiting(Automount *a) {
373         int p[2] = { -1, -1 };
374         char name[32], options[128];
375         bool mounted = false;
376         int r, ioctl_fd = -1, dev_autofs_fd;
377         struct stat st;
378
379         assert(a);
380         assert(a->pipe_fd < 0);
381         assert(a->where);
382
383         if (a->tokens)
384                 set_clear(a->tokens);
385         else if (!(a->tokens = set_new(trivial_hash_func, trivial_compare_func))) {
386                 r = -ENOMEM;
387                 goto fail;
388         }
389
390         if ((dev_autofs_fd = open_dev_autofs(UNIT(a)->meta.manager)) < 0) {
391                 r = dev_autofs_fd;
392                 goto fail;
393         }
394
395         /* We knowingly ignore the results of this call */
396         mkdir_p(a->where, 0555);
397
398         if (pipe2(p, O_NONBLOCK) < 0) {
399                 r = -errno;
400                 goto fail;
401         }
402
403         snprintf(options, sizeof(options), "fd=%i,pgrp=%u,minproto=5,maxproto=5,direct", p[1], (unsigned) getpgrp());
404         char_array_0(options);
405
406         snprintf(name, sizeof(name), "systemd-%u", (unsigned) getpid());
407         char_array_0(name);
408
409         if (mount(name, a->where, "autofs", 0, options) < 0) {
410                 r = -errno;
411                 goto fail;
412         }
413
414         mounted = true;
415
416         close_nointr_nofail(p[1]);
417         p[1] = -1;
418
419         if (stat(a->where, &st) < 0) {
420                 r = -errno;
421                 goto fail;
422         }
423
424         if ((ioctl_fd = open_ioctl_fd(dev_autofs_fd, a->where, st.st_dev)) < 0) {
425                 r = ioctl_fd;
426                 goto fail;
427         }
428
429         if ((r = autofs_protocol(dev_autofs_fd, ioctl_fd)) < 0)
430                 goto fail;
431
432         if ((r = autofs_set_timeout(dev_autofs_fd, ioctl_fd, 300)) < 0)
433                 goto fail;
434
435         /* Autofs fun fact:
436          *
437          * Unless we close the ioctl fd here, for some weird reason
438          * the direct mount will not receive events from the
439          * kernel. */
440
441         close_nointr_nofail(ioctl_fd);
442         ioctl_fd = -1;
443
444         if ((r = unit_watch_fd(UNIT(a), p[0], EPOLLIN, &a->pipe_watch)) < 0)
445                 goto fail;
446
447         a->pipe_fd = p[0];
448         a->dev_id = st.st_dev;
449
450         automount_set_state(a, AUTOMOUNT_WAITING);
451
452         return;
453
454 fail:
455         assert_se(close_pipe(p) == 0);
456
457         if (ioctl_fd >= 0)
458                 close_nointr_nofail(ioctl_fd);
459
460         if (mounted)
461                 repeat_unmout(a->where);
462
463         log_error("Failed to initialize automounter: %s", strerror(-r));
464         automount_enter_dead(a, false);
465 }
466
467 static void automount_enter_runnning(Automount *a) {
468         int r;
469         struct stat st;
470
471         assert(a);
472         assert(a->mount);
473
474         /* Before we do anything, let's see if somebody is playing games with us? */
475
476         if (stat(a->where, &st) < 0) {
477                 log_warning("%s failed stat automount point: %m", a->meta.id);
478                 goto fail;
479         }
480
481         if (!S_ISDIR(st.st_mode) || st.st_dev != a->dev_id)
482                 log_info("%s's automount point already active?", a->meta.id);
483         else if ((r = manager_add_job(UNIT(a)->meta.manager, JOB_START, UNIT(a->mount), JOB_REPLACE, true, NULL)) < 0) {
484                 log_warning("%s failed to queue mount startup job: %s", a->meta.id, strerror(-r));
485                 goto fail;
486         }
487
488         automount_set_state(a, AUTOMOUNT_RUNNING);
489         return;
490
491 fail:
492         automount_enter_dead(a, false);
493 }
494
495 static int automount_start(Unit *u) {
496         Automount *a = AUTOMOUNT(u);
497
498         assert(a);
499
500         if (path_is_mount_point(a->where)) {
501                 log_error("Path %s is already a mount point, refusing start for %s", a->where, u->meta.id);
502                 return -EEXIST;
503         }
504
505         assert(a->state == AUTOMOUNT_DEAD || a->state == AUTOMOUNT_MAINTAINANCE);
506
507         a->failure = false;
508         automount_enter_waiting(a);
509         return 0;
510 }
511
512 static int automount_stop(Unit *u) {
513         Automount *a = AUTOMOUNT(u);
514
515         assert(a);
516
517         assert(a->state == AUTOMOUNT_WAITING || a->state == AUTOMOUNT_RUNNING);
518
519         automount_enter_dead(a, true);
520         return 0;
521 }
522
523 static UnitActiveState automount_active_state(Unit *u) {
524
525         return state_translation_table[AUTOMOUNT(u)->state];
526 }
527
528 static const char *automount_sub_state_to_string(Unit *u) {
529         assert(u);
530
531         return state_string_table[AUTOMOUNT(u)->state];
532 }
533
534 static void automount_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
535         union autofs_v5_packet_union packet;
536         ssize_t l;
537         int r;
538
539         Automount *a = AUTOMOUNT(u);
540
541         assert(a);
542         assert(fd == a->pipe_fd);
543
544         if (events != EPOLLIN) {
545                 log_error("Got invalid poll event on pipe.");
546                 goto fail;
547         }
548
549         if ((l = loop_read(a->pipe_fd, &packet, sizeof(packet))) != sizeof(packet)) {
550                 log_error("Invalid read from pipe: %s", l < 0 ? strerror(-l) : "short read");
551                 goto fail;
552         }
553
554         switch (packet.hdr.type) {
555
556         case autofs_ptype_missing_direct:
557                 log_debug("Got direct mount request for %s", packet.v5_packet.name);
558
559                 if ((r = set_put(a->tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token))) < 0) {
560                         log_error("Failed to remember token: %s", strerror(-r));
561                         goto fail;
562                 }
563
564                 automount_enter_runnning(a);
565                 break;
566
567         default:
568                 log_error("Received unknown automount request %i", packet.hdr.type);
569                 break;
570         }
571
572         return;
573
574 fail:
575         automount_enter_dead(a, false);
576 }
577
578 static void automount_shutdown(Manager *m) {
579         assert(m);
580
581         if (m->dev_autofs_fd >= 0)
582                 close_nointr_nofail(m->dev_autofs_fd);
583 }
584
585 const UnitVTable automount_vtable = {
586         .suffix = ".automount",
587
588         .no_alias = true,
589         .no_instances = true,
590
591         .init = automount_init,
592         .load = automount_load,
593         .done = automount_done,
594
595         .dump = automount_dump,
596
597         .start = automount_start,
598         .stop = automount_stop,
599
600         .active_state = automount_active_state,
601         .sub_state_to_string = automount_sub_state_to_string,
602
603         .fd_event = automount_fd_event,
604
605         .shutdown = automount_shutdown
606 };