| File: | build-scan/../src/core/automount.c |
| Warning: | line 678, column 24 Potential leak of memory pointed to by 'data' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | |||
| 2 | ||||
| 3 | #include <errno(*__errno_location ()).h> | |||
| 4 | #include <fcntl.h> | |||
| 5 | #include <limits.h> | |||
| 6 | #include <linux1/auto_dev-ioctl.h> | |||
| 7 | #include <linux1/auto_fs4.h> | |||
| 8 | #include <sys/epoll.h> | |||
| 9 | #include <sys/mount.h> | |||
| 10 | #include <sys/stat.h> | |||
| 11 | #include <unistd.h> | |||
| 12 | ||||
| 13 | #include "alloc-util.h" | |||
| 14 | #include "async.h" | |||
| 15 | #include "automount.h" | |||
| 16 | #include "bus-error.h" | |||
| 17 | #include "bus-util.h" | |||
| 18 | #include "dbus-automount.h" | |||
| 19 | #include "fd-util.h" | |||
| 20 | #include "format-util.h" | |||
| 21 | #include "io-util.h" | |||
| 22 | #include "label.h" | |||
| 23 | #include "mkdir.h" | |||
| 24 | #include "mount-util.h" | |||
| 25 | #include "mount.h" | |||
| 26 | #include "parse-util.h" | |||
| 27 | #include "path-util.h" | |||
| 28 | #include "process-util.h" | |||
| 29 | #include "special.h" | |||
| 30 | #include "stdio-util.h" | |||
| 31 | #include "string-table.h" | |||
| 32 | #include "string-util.h" | |||
| 33 | #include "unit-name.h" | |||
| 34 | #include "unit.h" | |||
| 35 | ||||
| 36 | static const UnitActiveState state_translation_table[_AUTOMOUNT_STATE_MAX] = { | |||
| 37 | [AUTOMOUNT_DEAD] = UNIT_INACTIVE, | |||
| 38 | [AUTOMOUNT_WAITING] = UNIT_ACTIVE, | |||
| 39 | [AUTOMOUNT_RUNNING] = UNIT_ACTIVE, | |||
| 40 | [AUTOMOUNT_FAILED] = UNIT_FAILED | |||
| 41 | }; | |||
| 42 | ||||
| 43 | struct expire_data { | |||
| 44 | int dev_autofs_fd; | |||
| 45 | int ioctl_fd; | |||
| 46 | }; | |||
| 47 | ||||
| 48 | static inline void expire_data_free(struct expire_data *data) { | |||
| 49 | if (!data) | |||
| 50 | return; | |||
| 51 | ||||
| 52 | safe_close(data->dev_autofs_fd); | |||
| 53 | safe_close(data->ioctl_fd); | |||
| 54 | free(data); | |||
| 55 | } | |||
| 56 | ||||
| 57 | DEFINE_TRIVIAL_CLEANUP_FUNC(struct expire_data*, expire_data_free)static inline void expire_data_freep(struct expire_data* *p) { if (*p) expire_data_free(*p); }; | |||
| 58 | ||||
| 59 | static int open_dev_autofs(Manager *m); | |||
| 60 | static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata); | |||
| 61 | static int automount_start_expire(Automount *a); | |||
| 62 | static void automount_stop_expire(Automount *a); | |||
| 63 | static int automount_send_ready(Automount *a, Set *tokens, int status); | |||
| 64 | ||||
| 65 | static void automount_init(Unit *u) { | |||
| 66 | Automount *a = AUTOMOUNT(u); | |||
| 67 | ||||
| 68 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/core/automount.c", 68, __PRETTY_FUNCTION__ ); } while (0); | |||
| 69 | assert(u->load_state == UNIT_STUB)do { if ((__builtin_expect(!!(!(u->load_state == UNIT_STUB )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("u->load_state == UNIT_STUB" ), "../src/core/automount.c", 69, __PRETTY_FUNCTION__); } while (0); | |||
| 70 | ||||
| 71 | a->pipe_fd = -1; | |||
| 72 | a->directory_mode = 0755; | |||
| 73 | UNIT(a)({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->ignore_on_isolate = true1; | |||
| 74 | } | |||
| 75 | ||||
| 76 | static void unmount_autofs(Automount *a) { | |||
| 77 | int r; | |||
| 78 | ||||
| 79 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/core/automount.c", 79, __PRETTY_FUNCTION__ ); } while (0); | |||
| 80 | ||||
| 81 | if (a->pipe_fd < 0) | |||
| 82 | return; | |||
| 83 | ||||
| 84 | a->pipe_event_source = sd_event_source_unref(a->pipe_event_source); | |||
| 85 | a->pipe_fd = safe_close(a->pipe_fd); | |||
| 86 | ||||
| 87 | /* If we reload/reexecute things we keep the mount point around */ | |||
| 88 | if (!IN_SET(UNIT(a)->manager->exit_code, MANAGER_RELOAD, MANAGER_REEXECUTE)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){MANAGER_RELOAD, MANAGER_REEXECUTE})/sizeof (int)]; switch(({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? & (_u_)->meta : ((void*)0); _w_; })->manager->exit_code ) { case MANAGER_RELOAD: case MANAGER_REEXECUTE: _found = 1; break ; default: break; } _found; })) { | |||
| 89 | ||||
| 90 | automount_send_ready(a, a->tokens, -EHOSTDOWN112); | |||
| 91 | automount_send_ready(a, a->expire_tokens, -EHOSTDOWN112); | |||
| 92 | ||||
| 93 | if (a->where) { | |||
| 94 | r = repeat_unmount(a->where, MNT_DETACHMNT_DETACH); | |||
| 95 | if (r < 0) | |||
| 96 | log_error_errno(r, "Failed to unmount: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/core/automount.c", 96, __func__, "Failed to unmount: %m" ) : -abs(_e); }); | |||
| 97 | } | |||
| 98 | } | |||
| 99 | } | |||
| 100 | ||||
| 101 | static void automount_done(Unit *u) { | |||
| 102 | Automount *a = AUTOMOUNT(u); | |||
| 103 | ||||
| 104 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/core/automount.c", 104, __PRETTY_FUNCTION__ ); } while (0); | |||
| 105 | ||||
| 106 | unmount_autofs(a); | |||
| 107 | ||||
| 108 | a->where = mfree(a->where); | |||
| 109 | ||||
| 110 | a->tokens = set_free(a->tokens); | |||
| 111 | a->expire_tokens = set_free(a->expire_tokens); | |||
| 112 | ||||
| 113 | a->expire_event_source = sd_event_source_unref(a->expire_event_source); | |||
| 114 | } | |||
| 115 | ||||
| 116 | static int automount_add_trigger_dependencies(Automount *a) { | |||
| 117 | Unit *x; | |||
| 118 | int r; | |||
| 119 | ||||
| 120 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/core/automount.c", 120, __PRETTY_FUNCTION__ ); } while (0); | |||
| 121 | ||||
| 122 | r = unit_load_related_unit(UNIT(a)({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), ".mount", &x); | |||
| 123 | if (r < 0) | |||
| 124 | return r; | |||
| 125 | ||||
| 126 | return unit_add_two_dependencies(UNIT(a)({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), UNIT_BEFORE, UNIT_TRIGGERS, x, true1, UNIT_DEPENDENCY_IMPLICIT); | |||
| 127 | } | |||
| 128 | ||||
| 129 | static int automount_add_mount_dependencies(Automount *a) { | |||
| 130 | _cleanup_free___attribute__((cleanup(freep))) char *parent = NULL((void*)0); | |||
| 131 | ||||
| 132 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/core/automount.c", 132, __PRETTY_FUNCTION__ ); } while (0); | |||
| 133 | ||||
| 134 | parent = dirname_malloc(a->where); | |||
| 135 | if (!parent) | |||
| 136 | return -ENOMEM12; | |||
| 137 | ||||
| 138 | return unit_require_mounts_for(UNIT(a)({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), parent, UNIT_DEPENDENCY_IMPLICIT); | |||
| 139 | } | |||
| 140 | ||||
| 141 | static int automount_add_default_dependencies(Automount *a) { | |||
| 142 | int r; | |||
| 143 | ||||
| 144 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/core/automount.c", 144, __PRETTY_FUNCTION__ ); } while (0); | |||
| 145 | ||||
| 146 | if (!UNIT(a)({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->default_dependencies) | |||
| 147 | return 0; | |||
| 148 | ||||
| 149 | if (!MANAGER_IS_SYSTEM(UNIT(a)->manager)((({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager)->unit_file_scope == UNIT_FILE_SYSTEM )) | |||
| 150 | return 0; | |||
| 151 | ||||
| 152 | r = unit_add_two_dependencies_by_name(UNIT(a)({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET"umount.target", NULL((void*)0), true1, UNIT_DEPENDENCY_DEFAULT); | |||
| 153 | if (r < 0) | |||
| 154 | return r; | |||
| 155 | ||||
| 156 | return 0; | |||
| 157 | } | |||
| 158 | ||||
| 159 | static int automount_verify(Automount *a) { | |||
| 160 | _cleanup_free___attribute__((cleanup(freep))) char *e = NULL((void*)0); | |||
| 161 | int r; | |||
| 162 | ||||
| 163 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/core/automount.c", 163, __PRETTY_FUNCTION__ ); } while (0); | |||
| 164 | ||||
| 165 | if (UNIT(a)({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->load_state != UNIT_LOADED) | |||
| 166 | return 0; | |||
| 167 | ||||
| 168 | if (path_equal(a->where, "/")) { | |||
| 169 | log_unit_error(UNIT(a), "Cannot have an automount unit for the root directory. Refusing.")({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/automount.c", 169, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Cannot have an automount unit for the root directory. Refusing." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), 0, "../src/core/automount.c", 169, __func__, "Cannot have an automount unit for the root directory. Refusing." ); }); | |||
| 170 | return -ENOEXEC8; | |||
| 171 | } | |||
| 172 | ||||
| 173 | r = unit_name_from_path(a->where, ".automount", &e); | |||
| 174 | if (r < 0) | |||
| 175 | return log_unit_error_errno(UNIT(a), r, "Failed to generate unit name from path: %m")({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, r, "../src/core/automount.c", 175, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to generate unit name from path: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/core/automount.c", 175, __func__, "Failed to generate unit name from path: %m" ); }); | |||
| 176 | ||||
| 177 | if (!unit_has_name(UNIT(a)({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), e)) { | |||
| 178 | log_unit_error(UNIT(a), "Where= setting doesn't match unit name. Refusing.")({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/automount.c", 178, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Where= setting doesn't match unit name. Refusing." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), 0, "../src/core/automount.c", 178, __func__, "Where= setting doesn't match unit name. Refusing." ); }); | |||
| 179 | return -ENOEXEC8; | |||
| 180 | } | |||
| 181 | ||||
| 182 | return 0; | |||
| 183 | } | |||
| 184 | ||||
| 185 | static int automount_set_where(Automount *a) { | |||
| 186 | int r; | |||
| 187 | ||||
| 188 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/core/automount.c", 188, __PRETTY_FUNCTION__ ); } while (0); | |||
| 189 | ||||
| 190 | if (a->where) | |||
| 191 | return 0; | |||
| 192 | ||||
| 193 | r = unit_name_to_path(UNIT(a)({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->id, &a->where); | |||
| 194 | if (r < 0) | |||
| 195 | return r; | |||
| 196 | ||||
| 197 | path_simplify(a->where, false0); | |||
| 198 | return 1; | |||
| 199 | } | |||
| 200 | ||||
| 201 | static int automount_load(Unit *u) { | |||
| 202 | Automount *a = AUTOMOUNT(u); | |||
| 203 | int r; | |||
| 204 | ||||
| 205 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/core/automount.c", 205, __PRETTY_FUNCTION__ ); } while (0); | |||
| 206 | assert(u->load_state == UNIT_STUB)do { if ((__builtin_expect(!!(!(u->load_state == UNIT_STUB )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("u->load_state == UNIT_STUB" ), "../src/core/automount.c", 206, __PRETTY_FUNCTION__); } while (0); | |||
| 207 | ||||
| 208 | /* Load a .automount file */ | |||
| 209 | r = unit_load_fragment_and_dropin(u); | |||
| 210 | if (r < 0) | |||
| 211 | return r; | |||
| 212 | ||||
| 213 | if (u->load_state == UNIT_LOADED) { | |||
| 214 | r = automount_set_where(a); | |||
| 215 | if (r < 0) | |||
| 216 | return r; | |||
| 217 | ||||
| 218 | r = automount_add_trigger_dependencies(a); | |||
| 219 | if (r < 0) | |||
| 220 | return r; | |||
| 221 | ||||
| 222 | r = automount_add_mount_dependencies(a); | |||
| 223 | if (r < 0) | |||
| 224 | return r; | |||
| 225 | ||||
| 226 | r = automount_add_default_dependencies(a); | |||
| 227 | if (r < 0) | |||
| 228 | return r; | |||
| 229 | } | |||
| 230 | ||||
| 231 | return automount_verify(a); | |||
| 232 | } | |||
| 233 | ||||
| 234 | static void automount_set_state(Automount *a, AutomountState state) { | |||
| 235 | AutomountState old_state; | |||
| 236 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/core/automount.c", 236, __PRETTY_FUNCTION__ ); } while (0); | |||
| 237 | ||||
| 238 | old_state = a->state; | |||
| 239 | a->state = state; | |||
| 240 | ||||
| 241 | if (state != AUTOMOUNT_RUNNING) | |||
| 242 | automount_stop_expire(a); | |||
| 243 | ||||
| 244 | if (!IN_SET(state, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING})/sizeof (int)]; switch(state) { case AUTOMOUNT_WAITING: case AUTOMOUNT_RUNNING : _found = 1; break; default: break; } _found; })) | |||
| 245 | unmount_autofs(a); | |||
| 246 | ||||
| 247 | if (state != old_state) | |||
| 248 | log_unit_debug(UNIT(a), "Changed %s -> %s", automount_state_to_string(old_state), automount_state_to_string(state))({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/automount.c", 248, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Changed %s -> %s", automount_state_to_string (old_state), automount_state_to_string(state)) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/automount.c" , 248, __func__, "Changed %s -> %s", automount_state_to_string (old_state), automount_state_to_string(state)); }); | |||
| 249 | ||||
| 250 | unit_notify(UNIT(a)({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), state_translation_table[old_state], state_translation_table[state], 0); | |||
| 251 | } | |||
| 252 | ||||
| 253 | static int automount_coldplug(Unit *u) { | |||
| 254 | Automount *a = AUTOMOUNT(u); | |||
| 255 | int r; | |||
| 256 | ||||
| 257 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/core/automount.c", 257, __PRETTY_FUNCTION__ ); } while (0); | |||
| 258 | assert(a->state == AUTOMOUNT_DEAD)do { if ((__builtin_expect(!!(!(a->state == AUTOMOUNT_DEAD )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("a->state == AUTOMOUNT_DEAD" ), "../src/core/automount.c", 258, __PRETTY_FUNCTION__); } while (0); | |||
| 259 | ||||
| 260 | if (a->deserialized_state == a->state) | |||
| 261 | return 0; | |||
| 262 | ||||
| 263 | if (IN_SET(a->deserialized_state, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING})/sizeof (int)]; switch(a->deserialized_state) { case AUTOMOUNT_WAITING : case AUTOMOUNT_RUNNING: _found = 1; break; default: break; } _found; })) { | |||
| 264 | ||||
| 265 | r = automount_set_where(a); | |||
| 266 | if (r < 0) | |||
| 267 | return r; | |||
| 268 | ||||
| 269 | r = open_dev_autofs(u->manager); | |||
| 270 | if (r < 0) | |||
| 271 | return r; | |||
| 272 | ||||
| 273 | assert(a->pipe_fd >= 0)do { if ((__builtin_expect(!!(!(a->pipe_fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a->pipe_fd >= 0"), "../src/core/automount.c" , 273, __PRETTY_FUNCTION__); } while (0); | |||
| 274 | ||||
| 275 | r = sd_event_add_io(u->manager->event, &a->pipe_event_source, a->pipe_fd, EPOLLINEPOLLIN, automount_dispatch_io, u); | |||
| 276 | if (r < 0) | |||
| 277 | return r; | |||
| 278 | ||||
| 279 | (void) sd_event_source_set_description(a->pipe_event_source, "automount-io"); | |||
| 280 | if (a->deserialized_state == AUTOMOUNT_RUNNING) { | |||
| 281 | r = automount_start_expire(a); | |||
| 282 | if (r < 0) | |||
| 283 | log_unit_warning_errno(UNIT(a), r, "Failed to start expiration timer, ignoring: %m")({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/automount.c", 283, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to start expiration timer, ignoring: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/core/automount.c", 283, __func__, "Failed to start expiration timer, ignoring: %m" ); }); | |||
| 284 | } | |||
| 285 | ||||
| 286 | automount_set_state(a, a->deserialized_state); | |||
| 287 | } | |||
| 288 | ||||
| 289 | return 0; | |||
| 290 | } | |||
| 291 | ||||
| 292 | static void automount_dump(Unit *u, FILE *f, const char *prefix) { | |||
| 293 | char time_string[FORMAT_TIMESPAN_MAX64]; | |||
| 294 | Automount *a = AUTOMOUNT(u); | |||
| 295 | ||||
| 296 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/core/automount.c", 296, __PRETTY_FUNCTION__ ); } while (0); | |||
| 297 | ||||
| 298 | fprintf(f, | |||
| 299 | "%sAutomount State: %s\n" | |||
| 300 | "%sResult: %s\n" | |||
| 301 | "%sWhere: %s\n" | |||
| 302 | "%sDirectoryMode: %04o\n" | |||
| 303 | "%sTimeoutIdleUSec: %s\n", | |||
| 304 | prefix, automount_state_to_string(a->state), | |||
| 305 | prefix, automount_result_to_string(a->result), | |||
| 306 | prefix, a->where, | |||
| 307 | prefix, a->directory_mode, | |||
| 308 | prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX64, a->timeout_idle_usec, USEC_PER_SEC((usec_t) 1000000ULL))); | |||
| 309 | } | |||
| 310 | ||||
| 311 | static void automount_enter_dead(Automount *a, AutomountResult f) { | |||
| 312 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/core/automount.c", 312, __PRETTY_FUNCTION__ ); } while (0); | |||
| 313 | ||||
| 314 | if (a->result == AUTOMOUNT_SUCCESS) | |||
| 315 | a->result = f; | |||
| 316 | ||||
| 317 | if (a->result == AUTOMOUNT_SUCCESS) | |||
| 318 | unit_log_success(UNIT(a)({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); | |||
| 319 | else | |||
| 320 | unit_log_failure(UNIT(a)({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), automount_result_to_string(a->result)); | |||
| 321 | ||||
| 322 | automount_set_state(a, a->result != AUTOMOUNT_SUCCESS ? AUTOMOUNT_FAILED : AUTOMOUNT_DEAD); | |||
| 323 | } | |||
| 324 | ||||
| 325 | static int open_dev_autofs(Manager *m) { | |||
| 326 | struct autofs_dev_ioctl param; | |||
| 327 | ||||
| 328 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/core/automount.c", 328, __PRETTY_FUNCTION__ ); } while (0); | |||
| 329 | ||||
| 330 | if (m->dev_autofs_fd >= 0) | |||
| 331 | return m->dev_autofs_fd; | |||
| 332 | ||||
| 333 | (void) label_fix("/dev/autofs", 0); | |||
| 334 | ||||
| 335 | m->dev_autofs_fd = open("/dev/autofs", O_CLOEXEC02000000|O_RDONLY00); | |||
| 336 | if (m->dev_autofs_fd < 0) | |||
| 337 | return log_error_errno(errno, "Failed to open /dev/autofs: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/core/automount.c", 337, __func__ , "Failed to open /dev/autofs: %m") : -abs(_e); }); | |||
| 338 | ||||
| 339 | init_autofs_dev_ioctl(¶m); | |||
| 340 | if (ioctl(m->dev_autofs_fd, AUTOFS_DEV_IOCTL_VERSION(((2U|1U) << (((0 +8)+8)+14)) | (((0x93)) << (0 + 8)) | (((AUTOFS_DEV_IOCTL_VERSION_CMD)) << 0) | ((((sizeof (struct autofs_dev_ioctl)))) << ((0 +8)+8))), ¶m) < 0) { | |||
| 341 | m->dev_autofs_fd = safe_close(m->dev_autofs_fd); | |||
| 342 | return -errno(*__errno_location ()); | |||
| 343 | } | |||
| 344 | ||||
| 345 | log_debug("Autofs kernel version %i.%i", param.ver_major, param.ver_minor)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/core/automount.c", 345, __func__, "Autofs kernel version %i.%i" , param.ver_major, param.ver_minor) : -abs(_e); }); | |||
| 346 | ||||
| 347 | return m->dev_autofs_fd; | |||
| 348 | } | |||
| 349 | ||||
| 350 | static int open_ioctl_fd(int dev_autofs_fd, const char *where, dev_t devid) { | |||
| 351 | struct autofs_dev_ioctl *param; | |||
| 352 | size_t l; | |||
| 353 | ||||
| 354 | assert(dev_autofs_fd >= 0)do { if ((__builtin_expect(!!(!(dev_autofs_fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("dev_autofs_fd >= 0"), "../src/core/automount.c" , 354, __PRETTY_FUNCTION__); } while (0); | |||
| 355 | assert(where)do { if ((__builtin_expect(!!(!(where)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("where"), "../src/core/automount.c", 355 , __PRETTY_FUNCTION__); } while (0); | |||
| 356 | ||||
| 357 | l = sizeof(struct autofs_dev_ioctl) + strlen(where) + 1; | |||
| 358 | param = alloca(l)__builtin_alloca (l); | |||
| 359 | ||||
| 360 | init_autofs_dev_ioctl(param); | |||
| 361 | param->size = l; | |||
| 362 | param->ioctlfd = -1; | |||
| 363 | param->openmount.devid = devid; | |||
| 364 | strcpy(param->path, where); | |||
| 365 | ||||
| 366 | if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_OPENMOUNT(((2U|1U) << (((0 +8)+8)+14)) | (((0x93)) << (0 + 8)) | (((AUTOFS_DEV_IOCTL_OPENMOUNT_CMD)) << 0) | ((((sizeof (struct autofs_dev_ioctl)))) << ((0 +8)+8))), param) < 0) | |||
| 367 | return -errno(*__errno_location ()); | |||
| 368 | ||||
| 369 | if (param->ioctlfd < 0) | |||
| 370 | return -EIO5; | |||
| 371 | ||||
| 372 | (void) fd_cloexec(param->ioctlfd, true1); | |||
| 373 | return param->ioctlfd; | |||
| 374 | } | |||
| 375 | ||||
| 376 | static int autofs_protocol(int dev_autofs_fd, int ioctl_fd) { | |||
| 377 | uint32_t major, minor; | |||
| 378 | struct autofs_dev_ioctl param; | |||
| 379 | ||||
| 380 | assert(dev_autofs_fd >= 0)do { if ((__builtin_expect(!!(!(dev_autofs_fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("dev_autofs_fd >= 0"), "../src/core/automount.c" , 380, __PRETTY_FUNCTION__); } while (0); | |||
| 381 | assert(ioctl_fd >= 0)do { if ((__builtin_expect(!!(!(ioctl_fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ioctl_fd >= 0"), "../src/core/automount.c" , 381, __PRETTY_FUNCTION__); } while (0); | |||
| 382 | ||||
| 383 | init_autofs_dev_ioctl(¶m); | |||
| 384 | param.ioctlfd = ioctl_fd; | |||
| 385 | ||||
| 386 | if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_PROTOVER(((2U|1U) << (((0 +8)+8)+14)) | (((0x93)) << (0 + 8)) | (((AUTOFS_DEV_IOCTL_PROTOVER_CMD)) << 0) | ((((sizeof (struct autofs_dev_ioctl)))) << ((0 +8)+8))), ¶m) < 0) | |||
| 387 | return -errno(*__errno_location ()); | |||
| 388 | ||||
| 389 | major = param.protover.version; | |||
| 390 | ||||
| 391 | init_autofs_dev_ioctl(¶m); | |||
| 392 | param.ioctlfd = ioctl_fd; | |||
| 393 | ||||
| 394 | if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_PROTOSUBVER(((2U|1U) << (((0 +8)+8)+14)) | (((0x93)) << (0 + 8)) | (((AUTOFS_DEV_IOCTL_PROTOSUBVER_CMD)) << 0) | ((( (sizeof(struct autofs_dev_ioctl)))) << ((0 +8)+8))), ¶m) < 0) | |||
| 395 | return -errno(*__errno_location ()); | |||
| 396 | ||||
| 397 | minor = param.protosubver.sub_version; | |||
| 398 | ||||
| 399 | log_debug("Autofs protocol version %i.%i", major, minor)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/core/automount.c", 399, __func__, "Autofs protocol version %i.%i" , major, minor) : -abs(_e); }); | |||
| 400 | return 0; | |||
| 401 | } | |||
| 402 | ||||
| 403 | static int autofs_set_timeout(int dev_autofs_fd, int ioctl_fd, usec_t usec) { | |||
| 404 | struct autofs_dev_ioctl param; | |||
| 405 | ||||
| 406 | assert(dev_autofs_fd >= 0)do { if ((__builtin_expect(!!(!(dev_autofs_fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("dev_autofs_fd >= 0"), "../src/core/automount.c" , 406, __PRETTY_FUNCTION__); } while (0); | |||
| 407 | assert(ioctl_fd >= 0)do { if ((__builtin_expect(!!(!(ioctl_fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ioctl_fd >= 0"), "../src/core/automount.c" , 407, __PRETTY_FUNCTION__); } while (0); | |||
| 408 | ||||
| 409 | init_autofs_dev_ioctl(¶m); | |||
| 410 | param.ioctlfd = ioctl_fd; | |||
| 411 | ||||
| 412 | if (usec == USEC_INFINITY((usec_t) -1)) | |||
| 413 | param.timeout.timeout = 0; | |||
| 414 | else | |||
| 415 | /* Convert to seconds, rounding up. */ | |||
| 416 | param.timeout.timeout = DIV_ROUND_UP(usec, USEC_PER_SEC)({ const typeof((usec)) __unique_prefix_X23 = ((usec)); const typeof((((usec_t) 1000000ULL))) __unique_prefix_Y24 = ((((usec_t ) 1000000ULL))); (__unique_prefix_X23 / __unique_prefix_Y24 + !!(__unique_prefix_X23 % __unique_prefix_Y24)); }); | |||
| 417 | ||||
| 418 | if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_TIMEOUT(((2U|1U) << (((0 +8)+8)+14)) | (((0x93)) << (0 + 8)) | (((AUTOFS_DEV_IOCTL_TIMEOUT_CMD)) << 0) | ((((sizeof (struct autofs_dev_ioctl)))) << ((0 +8)+8))), ¶m) < 0) | |||
| 419 | return -errno(*__errno_location ()); | |||
| 420 | ||||
| 421 | return 0; | |||
| 422 | } | |||
| 423 | ||||
| 424 | static int autofs_send_ready(int dev_autofs_fd, int ioctl_fd, uint32_t token, int status) { | |||
| 425 | struct autofs_dev_ioctl param; | |||
| 426 | ||||
| 427 | assert(dev_autofs_fd >= 0)do { if ((__builtin_expect(!!(!(dev_autofs_fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("dev_autofs_fd >= 0"), "../src/core/automount.c" , 427, __PRETTY_FUNCTION__); } while (0); | |||
| 428 | assert(ioctl_fd >= 0)do { if ((__builtin_expect(!!(!(ioctl_fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ioctl_fd >= 0"), "../src/core/automount.c" , 428, __PRETTY_FUNCTION__); } while (0); | |||
| 429 | ||||
| 430 | init_autofs_dev_ioctl(¶m); | |||
| 431 | param.ioctlfd = ioctl_fd; | |||
| 432 | ||||
| 433 | if (status != 0) { | |||
| 434 | param.fail.token = token; | |||
| 435 | param.fail.status = status; | |||
| 436 | } else | |||
| 437 | param.ready.token = token; | |||
| 438 | ||||
| 439 | if (ioctl(dev_autofs_fd, status ? AUTOFS_DEV_IOCTL_FAIL(((2U|1U) << (((0 +8)+8)+14)) | (((0x93)) << (0 + 8)) | (((AUTOFS_DEV_IOCTL_FAIL_CMD)) << 0) | ((((sizeof (struct autofs_dev_ioctl)))) << ((0 +8)+8))) : AUTOFS_DEV_IOCTL_READY(((2U|1U) << (((0 +8)+8)+14)) | (((0x93)) << (0 + 8)) | (((AUTOFS_DEV_IOCTL_READY_CMD)) << 0) | ((((sizeof (struct autofs_dev_ioctl)))) << ((0 +8)+8))), ¶m) < 0) | |||
| 440 | return -errno(*__errno_location ()); | |||
| 441 | ||||
| 442 | return 0; | |||
| 443 | } | |||
| 444 | ||||
| 445 | static int automount_send_ready(Automount *a, Set *tokens, int status) { | |||
| 446 | _cleanup_close___attribute__((cleanup(closep))) int ioctl_fd = -1; | |||
| 447 | unsigned token; | |||
| 448 | int r; | |||
| 449 | ||||
| 450 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/core/automount.c", 450, __PRETTY_FUNCTION__ ); } while (0); | |||
| 451 | assert(status <= 0)do { if ((__builtin_expect(!!(!(status <= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("status <= 0"), "../src/core/automount.c" , 451, __PRETTY_FUNCTION__); } while (0); | |||
| 452 | ||||
| 453 | if (set_isempty(tokens)) | |||
| 454 | return 0; | |||
| 455 | ||||
| 456 | ioctl_fd = open_ioctl_fd(UNIT(a)({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager->dev_autofs_fd, a->where, a->dev_id); | |||
| 457 | if (ioctl_fd < 0) | |||
| 458 | return ioctl_fd; | |||
| 459 | ||||
| 460 | if (status != 0) | |||
| 461 | log_unit_debug_errno(UNIT(a), status, "Sending failure: %m")({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, status, "../src/core/automount.c", 461, __func__, _u-> manager->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Sending failure: %m") : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), status, "../src/core/automount.c" , 461, __func__, "Sending failure: %m"); }); | |||
| 462 | else | |||
| 463 | log_unit_debug(UNIT(a), "Sending success.")({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/automount.c", 463, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Sending success.") : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/automount.c" , 463, __func__, "Sending success."); }); | |||
| 464 | ||||
| 465 | r = 0; | |||
| 466 | ||||
| 467 | /* Autofs thankfully does not hand out 0 as a token */ | |||
| 468 | while ((token = PTR_TO_UINT(set_steal_first(tokens))((unsigned int) ((uintptr_t) (set_steal_first(tokens)))))) { | |||
| 469 | int k; | |||
| 470 | ||||
| 471 | /* Autofs fun fact: | |||
| 472 | * | |||
| 473 | * if you pass a positive status code here, kernels | |||
| 474 | * prior to 4.12 will freeze! Yay! */ | |||
| 475 | ||||
| 476 | k = autofs_send_ready(UNIT(a)({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager->dev_autofs_fd, | |||
| 477 | ioctl_fd, | |||
| 478 | token, | |||
| 479 | status); | |||
| 480 | if (k < 0) | |||
| 481 | r = k; | |||
| 482 | } | |||
| 483 | ||||
| 484 | return r; | |||
| 485 | } | |||
| 486 | ||||
| 487 | static void automount_trigger_notify(Unit *u, Unit *other) { | |||
| 488 | Automount *a = AUTOMOUNT(u); | |||
| 489 | int r; | |||
| 490 | ||||
| 491 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/core/automount.c", 491, __PRETTY_FUNCTION__ ); } while (0); | |||
| 492 | assert(other)do { if ((__builtin_expect(!!(!(other)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("other"), "../src/core/automount.c", 492 , __PRETTY_FUNCTION__); } while (0); | |||
| 493 | ||||
| 494 | /* Filter out invocations with bogus state */ | |||
| 495 | if (other->load_state != UNIT_LOADED || other->type != UNIT_MOUNT) | |||
| 496 | return; | |||
| 497 | ||||
| 498 | /* Don't propagate state changes from the mount if we are already down */ | |||
| 499 | if (!IN_SET(a->state, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING})/sizeof (int)]; switch(a->state) { case AUTOMOUNT_WAITING: case AUTOMOUNT_RUNNING : _found = 1; break; default: break; } _found; })) | |||
| 500 | return; | |||
| 501 | ||||
| 502 | /* Propagate start limit hit state */ | |||
| 503 | if (other->start_limit_hit) { | |||
| 504 | automount_enter_dead(a, AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT); | |||
| 505 | return; | |||
| 506 | } | |||
| 507 | ||||
| 508 | /* Don't propagate anything if there's still a job queued */ | |||
| 509 | if (other->job) | |||
| 510 | return; | |||
| 511 | ||||
| 512 | /* The mount is successfully established */ | |||
| 513 | if (IN_SET(MOUNT(other)->state, MOUNT_MOUNTED, MOUNT_REMOUNTING)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){MOUNT_MOUNTED, MOUNT_REMOUNTING})/sizeof (int)]; switch(MOUNT(other)->state) { case MOUNT_MOUNTED: case MOUNT_REMOUNTING: _found = 1; break; default: break; } _found ; })) { | |||
| 514 | (void) automount_send_ready(a, a->tokens, 0); | |||
| 515 | ||||
| 516 | r = automount_start_expire(a); | |||
| 517 | if (r < 0) | |||
| 518 | log_unit_warning_errno(UNIT(a), r, "Failed to start expiration timer, ignoring: %m")({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/automount.c", 518, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to start expiration timer, ignoring: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/core/automount.c", 518, __func__, "Failed to start expiration timer, ignoring: %m" ); }); | |||
| 519 | ||||
| 520 | automount_set_state(a, AUTOMOUNT_RUNNING); | |||
| 521 | } | |||
| 522 | ||||
| 523 | if (IN_SET(MOUNT(other)->state,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){MOUNT_MOUNTING, MOUNT_MOUNTING_DONE, MOUNT_MOUNTED , MOUNT_REMOUNTING, MOUNT_REMOUNTING_SIGTERM, MOUNT_REMOUNTING_SIGKILL , MOUNT_UNMOUNTING_SIGTERM, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILED })/sizeof(int)]; switch(MOUNT(other)->state) { case MOUNT_MOUNTING : case MOUNT_MOUNTING_DONE: case MOUNT_MOUNTED: case MOUNT_REMOUNTING : case MOUNT_REMOUNTING_SIGTERM: case MOUNT_REMOUNTING_SIGKILL : case MOUNT_UNMOUNTING_SIGTERM: case MOUNT_UNMOUNTING_SIGKILL : case MOUNT_FAILED: _found = 1; break; default: break; } _found ; }) | |||
| 524 | MOUNT_MOUNTING, MOUNT_MOUNTING_DONE,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){MOUNT_MOUNTING, MOUNT_MOUNTING_DONE, MOUNT_MOUNTED , MOUNT_REMOUNTING, MOUNT_REMOUNTING_SIGTERM, MOUNT_REMOUNTING_SIGKILL , MOUNT_UNMOUNTING_SIGTERM, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILED })/sizeof(int)]; switch(MOUNT(other)->state) { case MOUNT_MOUNTING : case MOUNT_MOUNTING_DONE: case MOUNT_MOUNTED: case MOUNT_REMOUNTING : case MOUNT_REMOUNTING_SIGTERM: case MOUNT_REMOUNTING_SIGKILL : case MOUNT_UNMOUNTING_SIGTERM: case MOUNT_UNMOUNTING_SIGKILL : case MOUNT_FAILED: _found = 1; break; default: break; } _found ; }) | |||
| 525 | MOUNT_MOUNTED, MOUNT_REMOUNTING,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){MOUNT_MOUNTING, MOUNT_MOUNTING_DONE, MOUNT_MOUNTED , MOUNT_REMOUNTING, MOUNT_REMOUNTING_SIGTERM, MOUNT_REMOUNTING_SIGKILL , MOUNT_UNMOUNTING_SIGTERM, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILED })/sizeof(int)]; switch(MOUNT(other)->state) { case MOUNT_MOUNTING : case MOUNT_MOUNTING_DONE: case MOUNT_MOUNTED: case MOUNT_REMOUNTING : case MOUNT_REMOUNTING_SIGTERM: case MOUNT_REMOUNTING_SIGKILL : case MOUNT_UNMOUNTING_SIGTERM: case MOUNT_UNMOUNTING_SIGKILL : case MOUNT_FAILED: _found = 1; break; default: break; } _found ; }) | |||
| 526 | MOUNT_REMOUNTING_SIGTERM, MOUNT_REMOUNTING_SIGKILL,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){MOUNT_MOUNTING, MOUNT_MOUNTING_DONE, MOUNT_MOUNTED , MOUNT_REMOUNTING, MOUNT_REMOUNTING_SIGTERM, MOUNT_REMOUNTING_SIGKILL , MOUNT_UNMOUNTING_SIGTERM, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILED })/sizeof(int)]; switch(MOUNT(other)->state) { case MOUNT_MOUNTING : case MOUNT_MOUNTING_DONE: case MOUNT_MOUNTED: case MOUNT_REMOUNTING : case MOUNT_REMOUNTING_SIGTERM: case MOUNT_REMOUNTING_SIGKILL : case MOUNT_UNMOUNTING_SIGTERM: case MOUNT_UNMOUNTING_SIGKILL : case MOUNT_FAILED: _found = 1; break; default: break; } _found ; }) | |||
| 527 | MOUNT_UNMOUNTING_SIGTERM, MOUNT_UNMOUNTING_SIGKILL,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){MOUNT_MOUNTING, MOUNT_MOUNTING_DONE, MOUNT_MOUNTED , MOUNT_REMOUNTING, MOUNT_REMOUNTING_SIGTERM, MOUNT_REMOUNTING_SIGKILL , MOUNT_UNMOUNTING_SIGTERM, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILED })/sizeof(int)]; switch(MOUNT(other)->state) { case MOUNT_MOUNTING : case MOUNT_MOUNTING_DONE: case MOUNT_MOUNTED: case MOUNT_REMOUNTING : case MOUNT_REMOUNTING_SIGTERM: case MOUNT_REMOUNTING_SIGKILL : case MOUNT_UNMOUNTING_SIGTERM: case MOUNT_UNMOUNTING_SIGKILL : case MOUNT_FAILED: _found = 1; break; default: break; } _found ; }) | |||
| 528 | MOUNT_FAILED)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){MOUNT_MOUNTING, MOUNT_MOUNTING_DONE, MOUNT_MOUNTED , MOUNT_REMOUNTING, MOUNT_REMOUNTING_SIGTERM, MOUNT_REMOUNTING_SIGKILL , MOUNT_UNMOUNTING_SIGTERM, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILED })/sizeof(int)]; switch(MOUNT(other)->state) { case MOUNT_MOUNTING : case MOUNT_MOUNTING_DONE: case MOUNT_MOUNTED: case MOUNT_REMOUNTING : case MOUNT_REMOUNTING_SIGTERM: case MOUNT_REMOUNTING_SIGKILL : case MOUNT_UNMOUNTING_SIGTERM: case MOUNT_UNMOUNTING_SIGKILL : case MOUNT_FAILED: _found = 1; break; default: break; } _found ; })) { | |||
| 529 | ||||
| 530 | (void) automount_send_ready(a, a->expire_tokens, -ENODEV19); | |||
| 531 | } | |||
| 532 | ||||
| 533 | if (MOUNT(other)->state == MOUNT_DEAD) | |||
| 534 | (void) automount_send_ready(a, a->expire_tokens, 0); | |||
| 535 | ||||
| 536 | /* The mount is in some unhappy state now, let's unfreeze any waiting clients */ | |||
| 537 | if (IN_SET(MOUNT(other)->state,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){MOUNT_DEAD, MOUNT_UNMOUNTING, MOUNT_REMOUNTING_SIGTERM , MOUNT_REMOUNTING_SIGKILL, MOUNT_UNMOUNTING_SIGTERM, MOUNT_UNMOUNTING_SIGKILL , MOUNT_FAILED})/sizeof(int)]; switch(MOUNT(other)->state) { case MOUNT_DEAD: case MOUNT_UNMOUNTING: case MOUNT_REMOUNTING_SIGTERM : case MOUNT_REMOUNTING_SIGKILL: case MOUNT_UNMOUNTING_SIGTERM : case MOUNT_UNMOUNTING_SIGKILL: case MOUNT_FAILED: _found = 1 ; break; default: break; } _found; }) | |||
| 538 | MOUNT_DEAD, MOUNT_UNMOUNTING,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){MOUNT_DEAD, MOUNT_UNMOUNTING, MOUNT_REMOUNTING_SIGTERM , MOUNT_REMOUNTING_SIGKILL, MOUNT_UNMOUNTING_SIGTERM, MOUNT_UNMOUNTING_SIGKILL , MOUNT_FAILED})/sizeof(int)]; switch(MOUNT(other)->state) { case MOUNT_DEAD: case MOUNT_UNMOUNTING: case MOUNT_REMOUNTING_SIGTERM : case MOUNT_REMOUNTING_SIGKILL: case MOUNT_UNMOUNTING_SIGTERM : case MOUNT_UNMOUNTING_SIGKILL: case MOUNT_FAILED: _found = 1 ; break; default: break; } _found; }) | |||
| 539 | MOUNT_REMOUNTING_SIGTERM, MOUNT_REMOUNTING_SIGKILL,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){MOUNT_DEAD, MOUNT_UNMOUNTING, MOUNT_REMOUNTING_SIGTERM , MOUNT_REMOUNTING_SIGKILL, MOUNT_UNMOUNTING_SIGTERM, MOUNT_UNMOUNTING_SIGKILL , MOUNT_FAILED})/sizeof(int)]; switch(MOUNT(other)->state) { case MOUNT_DEAD: case MOUNT_UNMOUNTING: case MOUNT_REMOUNTING_SIGTERM : case MOUNT_REMOUNTING_SIGKILL: case MOUNT_UNMOUNTING_SIGTERM : case MOUNT_UNMOUNTING_SIGKILL: case MOUNT_FAILED: _found = 1 ; break; default: break; } _found; }) | |||
| 540 | MOUNT_UNMOUNTING_SIGTERM, MOUNT_UNMOUNTING_SIGKILL,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){MOUNT_DEAD, MOUNT_UNMOUNTING, MOUNT_REMOUNTING_SIGTERM , MOUNT_REMOUNTING_SIGKILL, MOUNT_UNMOUNTING_SIGTERM, MOUNT_UNMOUNTING_SIGKILL , MOUNT_FAILED})/sizeof(int)]; switch(MOUNT(other)->state) { case MOUNT_DEAD: case MOUNT_UNMOUNTING: case MOUNT_REMOUNTING_SIGTERM : case MOUNT_REMOUNTING_SIGKILL: case MOUNT_UNMOUNTING_SIGTERM : case MOUNT_UNMOUNTING_SIGKILL: case MOUNT_FAILED: _found = 1 ; break; default: break; } _found; }) | |||
| 541 | MOUNT_FAILED)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){MOUNT_DEAD, MOUNT_UNMOUNTING, MOUNT_REMOUNTING_SIGTERM , MOUNT_REMOUNTING_SIGKILL, MOUNT_UNMOUNTING_SIGTERM, MOUNT_UNMOUNTING_SIGKILL , MOUNT_FAILED})/sizeof(int)]; switch(MOUNT(other)->state) { case MOUNT_DEAD: case MOUNT_UNMOUNTING: case MOUNT_REMOUNTING_SIGTERM : case MOUNT_REMOUNTING_SIGKILL: case MOUNT_UNMOUNTING_SIGTERM : case MOUNT_UNMOUNTING_SIGKILL: case MOUNT_FAILED: _found = 1 ; break; default: break; } _found; })) { | |||
| 542 | ||||
| 543 | (void) automount_send_ready(a, a->tokens, -ENODEV19); | |||
| 544 | ||||
| 545 | automount_set_state(a, AUTOMOUNT_WAITING); | |||
| 546 | } | |||
| 547 | } | |||
| 548 | ||||
| 549 | static void automount_enter_waiting(Automount *a) { | |||
| 550 | _cleanup_close___attribute__((cleanup(closep))) int ioctl_fd = -1; | |||
| 551 | int p[2] = { -1, -1 }; | |||
| 552 | char name[STRLEN("systemd-")(sizeof("""systemd-""") - 1) + DECIMAL_STR_MAX(pid_t)(2+(sizeof(pid_t) <= 1 ? 3 : sizeof(pid_t) <= 2 ? 5 : sizeof (pid_t) <= 4 ? 10 : sizeof(pid_t) <= 8 ? 20 : sizeof(int [-2*(sizeof(pid_t) > 8)]))) + 1]; | |||
| 553 | char options[STRLEN("fd=,pgrp=,minproto=5,maxproto=5,direct")(sizeof("""fd=,pgrp=,minproto=5,maxproto=5,direct""") - 1) | |||
| 554 | + DECIMAL_STR_MAX(int)(2+(sizeof(int) <= 1 ? 3 : sizeof(int) <= 2 ? 5 : sizeof (int) <= 4 ? 10 : sizeof(int) <= 8 ? 20 : sizeof(int[-2 *(sizeof(int) > 8)]))) + DECIMAL_STR_MAX(gid_t)(2+(sizeof(gid_t) <= 1 ? 3 : sizeof(gid_t) <= 2 ? 5 : sizeof (gid_t) <= 4 ? 10 : sizeof(gid_t) <= 8 ? 20 : sizeof(int [-2*(sizeof(gid_t) > 8)]))) + 1]; | |||
| 555 | bool_Bool mounted = false0; | |||
| 556 | int r, dev_autofs_fd; | |||
| 557 | struct stat st; | |||
| 558 | ||||
| 559 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/core/automount.c", 559, __PRETTY_FUNCTION__ ); } while (0); | |||
| 560 | assert(a->pipe_fd < 0)do { if ((__builtin_expect(!!(!(a->pipe_fd < 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a->pipe_fd < 0"), "../src/core/automount.c" , 560, __PRETTY_FUNCTION__); } while (0); | |||
| 561 | assert(a->where)do { if ((__builtin_expect(!!(!(a->where)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a->where"), "../src/core/automount.c" , 561, __PRETTY_FUNCTION__); } while (0); | |||
| 562 | ||||
| 563 | set_clear(a->tokens); | |||
| 564 | ||||
| 565 | r = unit_fail_if_noncanonical(UNIT(a)({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), a->where); | |||
| 566 | if (r < 0) | |||
| 567 | goto fail; | |||
| 568 | ||||
| 569 | (void) mkdir_p_label(a->where, 0555); | |||
| 570 | ||||
| 571 | unit_warn_if_dir_nonempty(UNIT(a)({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), a->where); | |||
| 572 | ||||
| 573 | dev_autofs_fd = open_dev_autofs(UNIT(a)({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager); | |||
| 574 | if (dev_autofs_fd < 0) { | |||
| 575 | r = dev_autofs_fd; | |||
| 576 | goto fail; | |||
| 577 | } | |||
| 578 | ||||
| 579 | if (pipe2(p, O_NONBLOCK04000|O_CLOEXEC02000000) < 0) { | |||
| 580 | r = -errno(*__errno_location ()); | |||
| 581 | goto fail; | |||
| 582 | } | |||
| 583 | ||||
| 584 | xsprintf(options, "fd=%i,pgrp="PID_FMT",minproto=5,maxproto=5,direct", p[1], getpgrp())do { if ((__builtin_expect(!!(!(((size_t) snprintf(options, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (options), typeof(&*(options))), sizeof(options)/sizeof(( options)[0]), ((void)0))), "fd=%i,pgrp=""%" "i"",minproto=5,maxproto=5,direct" , p[1], getpgrp()) < (__extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(options), typeof(& *(options))), sizeof(options)/sizeof((options)[0]), ((void)0) )))))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("xsprintf: " "options" "[] must be big enough"), "../src/core/automount.c" , 584, __PRETTY_FUNCTION__); } while (0); | |||
| 585 | xsprintf(name, "systemd-"PID_FMT, getpid_cached())do { if ((__builtin_expect(!!(!(((size_t) snprintf(name, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (name), typeof(&*(name))), sizeof(name)/sizeof((name)[0]) , ((void)0))), "systemd-""%" "i", getpid_cached()) < (__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (name), typeof(&*(name))), sizeof(name)/sizeof((name)[0]) , ((void)0))))))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("xsprintf: " "name" "[] must be big enough"), "../src/core/automount.c" , 585, __PRETTY_FUNCTION__); } while (0); | |||
| 586 | if (mount(name, a->where, "autofs", 0, options) < 0) { | |||
| 587 | r = -errno(*__errno_location ()); | |||
| 588 | goto fail; | |||
| 589 | } | |||
| 590 | ||||
| 591 | mounted = true1; | |||
| 592 | ||||
| 593 | p[1] = safe_close(p[1]); | |||
| 594 | ||||
| 595 | if (stat(a->where, &st) < 0) { | |||
| 596 | r = -errno(*__errno_location ()); | |||
| 597 | goto fail; | |||
| 598 | } | |||
| 599 | ||||
| 600 | ioctl_fd = open_ioctl_fd(dev_autofs_fd, a->where, st.st_dev); | |||
| 601 | if (ioctl_fd < 0) { | |||
| 602 | r = ioctl_fd; | |||
| 603 | goto fail; | |||
| 604 | } | |||
| 605 | ||||
| 606 | r = autofs_protocol(dev_autofs_fd, ioctl_fd); | |||
| 607 | if (r < 0) | |||
| 608 | goto fail; | |||
| 609 | ||||
| 610 | r = autofs_set_timeout(dev_autofs_fd, ioctl_fd, a->timeout_idle_usec); | |||
| 611 | if (r < 0) | |||
| 612 | goto fail; | |||
| 613 | ||||
| 614 | r = sd_event_add_io(UNIT(a)({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager->event, &a->pipe_event_source, p[0], EPOLLINEPOLLIN, automount_dispatch_io, a); | |||
| 615 | if (r < 0) | |||
| 616 | goto fail; | |||
| 617 | ||||
| 618 | (void) sd_event_source_set_description(a->pipe_event_source, "automount-io"); | |||
| 619 | ||||
| 620 | a->pipe_fd = p[0]; | |||
| 621 | a->dev_id = st.st_dev; | |||
| 622 | ||||
| 623 | automount_set_state(a, AUTOMOUNT_WAITING); | |||
| 624 | ||||
| 625 | return; | |||
| 626 | ||||
| 627 | fail: | |||
| 628 | log_unit_error_errno(UNIT(a), r, "Failed to initialize automounter: %m")({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, r, "../src/core/automount.c", 628, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to initialize automounter: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/core/automount.c", 628, __func__, "Failed to initialize automounter: %m" ); }); | |||
| 629 | ||||
| 630 | safe_close_pair(p); | |||
| 631 | ||||
| 632 | if (mounted) { | |||
| 633 | r = repeat_unmount(a->where, MNT_DETACHMNT_DETACH); | |||
| 634 | if (r < 0) | |||
| 635 | log_error_errno(r, "Failed to unmount, ignoring: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/core/automount.c", 635, __func__, "Failed to unmount, ignoring: %m" ) : -abs(_e); }); | |||
| 636 | } | |||
| 637 | ||||
| 638 | automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES); | |||
| 639 | } | |||
| 640 | ||||
| 641 | static void *expire_thread(void *p) { | |||
| 642 | struct autofs_dev_ioctl param; | |||
| 643 | _cleanup_(expire_data_freep)__attribute__((cleanup(expire_data_freep))) struct expire_data *data = (struct expire_data*)p; | |||
| 644 | int r; | |||
| 645 | ||||
| 646 | assert(data->dev_autofs_fd >= 0)do { if ((__builtin_expect(!!(!(data->dev_autofs_fd >= 0 )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("data->dev_autofs_fd >= 0" ), "../src/core/automount.c", 646, __PRETTY_FUNCTION__); } while (0); | |||
| 647 | assert(data->ioctl_fd >= 0)do { if ((__builtin_expect(!!(!(data->ioctl_fd >= 0)),0 ))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("data->ioctl_fd >= 0" ), "../src/core/automount.c", 647, __PRETTY_FUNCTION__); } while (0); | |||
| 648 | ||||
| 649 | init_autofs_dev_ioctl(¶m); | |||
| 650 | param.ioctlfd = data->ioctl_fd; | |||
| 651 | ||||
| 652 | do { | |||
| 653 | r = ioctl(data->dev_autofs_fd, AUTOFS_DEV_IOCTL_EXPIRE(((2U|1U) << (((0 +8)+8)+14)) | (((0x93)) << (0 + 8)) | (((AUTOFS_DEV_IOCTL_EXPIRE_CMD)) << 0) | ((((sizeof (struct autofs_dev_ioctl)))) << ((0 +8)+8))), ¶m); | |||
| 654 | } while (r >= 0); | |||
| 655 | ||||
| 656 | if (errno(*__errno_location ()) != EAGAIN11) | |||
| 657 | log_warning_errno(errno, "Failed to expire automount, ignoring: %m")({ int _level = ((4)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/core/automount.c", 657, __func__ , "Failed to expire automount, ignoring: %m") : -abs(_e); }); | |||
| 658 | ||||
| 659 | return NULL((void*)0); | |||
| 660 | } | |||
| 661 | ||||
| 662 | static int automount_dispatch_expire(sd_event_source *source, usec_t usec, void *userdata) { | |||
| 663 | Automount *a = AUTOMOUNT(userdata); | |||
| 664 | _cleanup_(expire_data_freep)__attribute__((cleanup(expire_data_freep))) struct expire_data *data = NULL((void*)0); | |||
| 665 | int r; | |||
| 666 | ||||
| 667 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/core/automount.c", 667, __PRETTY_FUNCTION__ ); } while (0); | |||
| ||||
| 668 | assert(source == a->expire_event_source)do { if ((__builtin_expect(!!(!(source == a->expire_event_source )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("source == a->expire_event_source" ), "../src/core/automount.c", 668, __PRETTY_FUNCTION__); } while (0); | |||
| 669 | ||||
| 670 | data = new0(struct expire_data, 1)((struct expire_data*) calloc((1), sizeof(struct expire_data) )); | |||
| 671 | if (!data) | |||
| 672 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/core/automount.c" , 672, __func__); | |||
| 673 | ||||
| 674 | data->ioctl_fd = -1; | |||
| 675 | ||||
| 676 | data->dev_autofs_fd = fcntl(UNIT(a)({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager->dev_autofs_fd, F_DUPFD_CLOEXEC1030, 3); | |||
| 677 | if (data->dev_autofs_fd < 0) | |||
| 678 | return log_unit_error_errno(UNIT(a), errno, "Failed to duplicate autofs fd: %m")({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, (*__errno_location ()), "../src/core/automount.c", 678, __func__ , _u->manager->unit_log_field, _u->id, _u->manager ->invocation_log_field, _u->invocation_id_string, "Failed to duplicate autofs fd: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), (*__errno_location ()), "../src/core/automount.c", 678, __func__ , "Failed to duplicate autofs fd: %m"); }); | |||
| ||||
| 679 | ||||
| 680 | data->ioctl_fd = open_ioctl_fd(UNIT(a)({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager->dev_autofs_fd, a->where, a->dev_id); | |||
| 681 | if (data->ioctl_fd < 0) | |||
| 682 | return log_unit_error_errno(UNIT(a), data->ioctl_fd, "Couldn't open autofs ioctl fd: %m")({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, data->ioctl_fd, "../src/core/automount.c", 682, __func__ , _u->manager->unit_log_field, _u->id, _u->manager ->invocation_log_field, _u->invocation_id_string, "Couldn't open autofs ioctl fd: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), data->ioctl_fd, "../src/core/automount.c", 682, __func__ , "Couldn't open autofs ioctl fd: %m"); }); | |||
| 683 | ||||
| 684 | r = asynchronous_job(expire_thread, data); | |||
| 685 | if (r < 0) | |||
| 686 | return log_unit_error_errno(UNIT(a), r, "Failed to start expire job: %m")({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, r, "../src/core/automount.c", 686, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to start expire job: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/core/automount.c", 686, __func__, "Failed to start expire job: %m" ); }); | |||
| 687 | ||||
| 688 | data = NULL((void*)0); | |||
| 689 | ||||
| 690 | return automount_start_expire(a); | |||
| 691 | } | |||
| 692 | ||||
| 693 | static int automount_start_expire(Automount *a) { | |||
| 694 | int r; | |||
| 695 | usec_t timeout; | |||
| 696 | ||||
| 697 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/core/automount.c", 697, __PRETTY_FUNCTION__ ); } while (0); | |||
| 698 | ||||
| 699 | if (a->timeout_idle_usec == 0) | |||
| 700 | return 0; | |||
| 701 | ||||
| 702 | timeout = now(CLOCK_MONOTONIC1) + MAX(a->timeout_idle_usec/3, USEC_PER_SEC)__extension__ ({ const typeof((a->timeout_idle_usec/3)) __unique_prefix_A25 = ((a->timeout_idle_usec/3)); const typeof((((usec_t) 1000000ULL ))) __unique_prefix_B26 = ((((usec_t) 1000000ULL))); __unique_prefix_A25 > __unique_prefix_B26 ? __unique_prefix_A25 : __unique_prefix_B26 ; }); | |||
| 703 | ||||
| 704 | if (a->expire_event_source) { | |||
| 705 | r = sd_event_source_set_time(a->expire_event_source, timeout); | |||
| 706 | if (r < 0) | |||
| 707 | return r; | |||
| 708 | ||||
| 709 | return sd_event_source_set_enabled(a->expire_event_source, SD_EVENT_ONESHOT); | |||
| 710 | } | |||
| 711 | ||||
| 712 | r = sd_event_add_time( | |||
| 713 | UNIT(a)({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager->event, | |||
| 714 | &a->expire_event_source, | |||
| 715 | CLOCK_MONOTONIC1, timeout, 0, | |||
| 716 | automount_dispatch_expire, a); | |||
| 717 | if (r < 0) | |||
| 718 | return r; | |||
| 719 | ||||
| 720 | (void) sd_event_source_set_description(a->expire_event_source, "automount-expire"); | |||
| 721 | ||||
| 722 | return 0; | |||
| 723 | } | |||
| 724 | ||||
| 725 | static void automount_stop_expire(Automount *a) { | |||
| 726 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/core/automount.c", 726, __PRETTY_FUNCTION__ ); } while (0); | |||
| 727 | ||||
| 728 | if (!a->expire_event_source) | |||
| 729 | return; | |||
| 730 | ||||
| 731 | (void) sd_event_source_set_enabled(a->expire_event_source, SD_EVENT_OFF); | |||
| 732 | } | |||
| 733 | ||||
| 734 | static void automount_enter_running(Automount *a) { | |||
| 735 | _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0}); | |||
| 736 | Unit *trigger; | |||
| 737 | struct stat st; | |||
| 738 | int r; | |||
| 739 | ||||
| 740 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/core/automount.c", 740, __PRETTY_FUNCTION__ ); } while (0); | |||
| 741 | ||||
| 742 | /* If the user masked our unit in the meantime, fail */ | |||
| 743 | if (UNIT(a)({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->load_state != UNIT_LOADED) { | |||
| 744 | log_unit_error(UNIT(a), "Suppressing automount event since unit is no longer loaded.")({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/automount.c", 744, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Suppressing automount event since unit is no longer loaded." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), 0, "../src/core/automount.c", 744, __func__, "Suppressing automount event since unit is no longer loaded." ); }); | |||
| 745 | goto fail; | |||
| 746 | } | |||
| 747 | ||||
| 748 | /* We don't take mount requests anymore if we are supposed to | |||
| 749 | * shut down anyway */ | |||
| 750 | if (unit_stop_pending(UNIT(a)({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }))) { | |||
| 751 | log_unit_debug(UNIT(a), "Suppressing automount request since unit stop is scheduled.")({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/automount.c", 751, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Suppressing automount request since unit stop is scheduled." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7 ))), 0, "../src/core/automount.c", 751, __func__, "Suppressing automount request since unit stop is scheduled." ); }); | |||
| 752 | automount_send_ready(a, a->tokens, -EHOSTDOWN112); | |||
| 753 | automount_send_ready(a, a->expire_tokens, -EHOSTDOWN112); | |||
| 754 | return; | |||
| 755 | } | |||
| 756 | ||||
| 757 | mkdir_p_label(a->where, a->directory_mode); | |||
| 758 | ||||
| 759 | /* Before we do anything, let's see if somebody is playing games with us? */ | |||
| 760 | if (lstat(a->where, &st) < 0) { | |||
| 761 | log_unit_warning_errno(UNIT(a), errno, "Failed to stat automount point: %m")({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, (*__errno_location ()), "../src/core/automount.c", 761, __func__ , _u->manager->unit_log_field, _u->id, _u->manager ->invocation_log_field, _u->invocation_id_string, "Failed to stat automount point: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), (*__errno_location ()), "../src/core/automount.c", 761, __func__ , "Failed to stat automount point: %m"); }); | |||
| 762 | goto fail; | |||
| 763 | } | |||
| 764 | ||||
| 765 | /* The mount unit may have been explicitly started before we got the | |||
| 766 | * autofs request. Ack it to unblock anything waiting on the mount point. */ | |||
| 767 | if (!S_ISDIR(st.st_mode)((((st.st_mode)) & 0170000) == (0040000)) || st.st_dev != a->dev_id) { | |||
| 768 | log_unit_info(UNIT(a), "Automount point already active?")({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (6, 0, "../src/core/automount.c", 768, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Automount point already active?" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((6 ))), 0, "../src/core/automount.c", 768, __func__, "Automount point already active?" ); }); | |||
| 769 | automount_send_ready(a, a->tokens, 0); | |||
| 770 | return; | |||
| 771 | } | |||
| 772 | ||||
| 773 | trigger = UNIT_TRIGGER(UNIT(a))((Unit*) hashmap_first_key((({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }))->dependencies [UNIT_TRIGGERS])); | |||
| 774 | if (!trigger) { | |||
| 775 | log_unit_error(UNIT(a), "Unit to trigger vanished.")({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/automount.c", 775, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Unit to trigger vanished.") : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3))) , 0, "../src/core/automount.c", 775, __func__, "Unit to trigger vanished." ); }); | |||
| 776 | goto fail; | |||
| 777 | } | |||
| 778 | ||||
| 779 | r = manager_add_job(UNIT(a)({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager, JOB_START, trigger, JOB_REPLACE, NULL((void*)0), &error, NULL((void*)0)); | |||
| 780 | if (r < 0) { | |||
| 781 | log_unit_warning(UNIT(a), "Failed to queue mount startup job: %s", bus_error_message(&error, r))({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/automount.c", 781, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to queue mount startup job: %s" , bus_error_message(&error, r)) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((4))), 0, "../src/core/automount.c", 781, __func__ , "Failed to queue mount startup job: %s", bus_error_message( &error, r)); }); | |||
| 782 | goto fail; | |||
| 783 | } | |||
| 784 | ||||
| 785 | automount_set_state(a, AUTOMOUNT_RUNNING); | |||
| 786 | return; | |||
| 787 | ||||
| 788 | fail: | |||
| 789 | automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES); | |||
| 790 | } | |||
| 791 | ||||
| 792 | static int automount_start(Unit *u) { | |||
| 793 | Automount *a = AUTOMOUNT(u); | |||
| 794 | Unit *trigger; | |||
| 795 | int r; | |||
| 796 | ||||
| 797 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/core/automount.c", 797, __PRETTY_FUNCTION__ ); } while (0); | |||
| 798 | assert(IN_SET(a->state, AUTOMOUNT_DEAD, AUTOMOUNT_FAILED))do { if ((__builtin_expect(!!(!(({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended[20 - sizeof((int[]){AUTOMOUNT_DEAD, AUTOMOUNT_FAILED})/sizeof(int )]; switch(a->state) { case AUTOMOUNT_DEAD: case AUTOMOUNT_FAILED : _found = 1; break; default: break; } _found; }))),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("IN_SET(a->state, AUTOMOUNT_DEAD, AUTOMOUNT_FAILED)" ), "../src/core/automount.c", 798, __PRETTY_FUNCTION__); } while (0); | |||
| 799 | ||||
| 800 | if (path_is_mount_point(a->where, NULL((void*)0), 0) > 0) { | |||
| 801 | log_unit_error(u, "Path %s is already a mount point, refusing start.", a->where)({ const Unit *_u = (u); _u ? log_object_internal(3, 0, "../src/core/automount.c" , 801, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Path %s is already a mount point, refusing start.", a-> where) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3))), 0, "../src/core/automount.c", 801, __func__, "Path %s is already a mount point, refusing start." , a->where); }); | |||
| 802 | return -EEXIST17; | |||
| 803 | } | |||
| 804 | ||||
| 805 | trigger = UNIT_TRIGGER(u)((Unit*) hashmap_first_key((u)->dependencies[UNIT_TRIGGERS ])); | |||
| 806 | if (!trigger || trigger->load_state != UNIT_LOADED) { | |||
| 807 | log_unit_error(u, "Refusing to start, unit to trigger not loaded.")({ const Unit *_u = (u); _u ? log_object_internal(3, 0, "../src/core/automount.c" , 807, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Refusing to start, unit to trigger not loaded.") : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((3))), 0, "../src/core/automount.c" , 807, __func__, "Refusing to start, unit to trigger not loaded." ); }); | |||
| 808 | return -ENOENT2; | |||
| 809 | } | |||
| 810 | ||||
| 811 | r = unit_start_limit_test(u); | |||
| 812 | if (r < 0) { | |||
| 813 | automount_enter_dead(a, AUTOMOUNT_FAILURE_START_LIMIT_HIT); | |||
| 814 | return r; | |||
| 815 | } | |||
| 816 | ||||
| 817 | r = unit_acquire_invocation_id(u); | |||
| 818 | if (r < 0) | |||
| 819 | return r; | |||
| 820 | ||||
| 821 | a->result = AUTOMOUNT_SUCCESS; | |||
| 822 | automount_enter_waiting(a); | |||
| 823 | return 1; | |||
| 824 | } | |||
| 825 | ||||
| 826 | static int automount_stop(Unit *u) { | |||
| 827 | Automount *a = AUTOMOUNT(u); | |||
| 828 | ||||
| 829 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/core/automount.c", 829, __PRETTY_FUNCTION__ ); } while (0); | |||
| 830 | assert(IN_SET(a->state, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING))do { if ((__builtin_expect(!!(!(({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended[20 - sizeof((int[]){AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING})/sizeof (int)]; switch(a->state) { case AUTOMOUNT_WAITING: case AUTOMOUNT_RUNNING : _found = 1; break; default: break; } _found; }))),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("IN_SET(a->state, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING)" ), "../src/core/automount.c", 830, __PRETTY_FUNCTION__); } while (0); | |||
| 831 | ||||
| 832 | automount_enter_dead(a, AUTOMOUNT_SUCCESS); | |||
| 833 | return 1; | |||
| 834 | } | |||
| 835 | ||||
| 836 | static int automount_serialize(Unit *u, FILE *f, FDSet *fds) { | |||
| 837 | Automount *a = AUTOMOUNT(u); | |||
| 838 | Iterator i; | |||
| 839 | void *p; | |||
| 840 | int r; | |||
| 841 | ||||
| 842 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/core/automount.c", 842, __PRETTY_FUNCTION__ ); } while (0); | |||
| 843 | assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("f"), "../src/core/automount.c", 843, __PRETTY_FUNCTION__ ); } while (0); | |||
| 844 | assert(fds)do { if ((__builtin_expect(!!(!(fds)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fds"), "../src/core/automount.c", 844, __PRETTY_FUNCTION__ ); } while (0); | |||
| 845 | ||||
| 846 | unit_serialize_item(u, f, "state", automount_state_to_string(a->state)); | |||
| 847 | unit_serialize_item(u, f, "result", automount_result_to_string(a->result)); | |||
| 848 | unit_serialize_item_format(u, f, "dev-id", "%u", (unsigned) a->dev_id); | |||
| 849 | ||||
| 850 | SET_FOREACH(p, a->tokens, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), . next_key = ((void*)0) }); set_iterate((a->tokens), &(i ), (void**)&(p)); ) | |||
| 851 | unit_serialize_item_format(u, f, "token", "%u", PTR_TO_UINT(p)((unsigned int) ((uintptr_t) (p)))); | |||
| 852 | SET_FOREACH(p, a->expire_tokens, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), . next_key = ((void*)0) }); set_iterate((a->expire_tokens), & (i), (void**)&(p)); ) | |||
| 853 | unit_serialize_item_format(u, f, "expire-token", "%u", PTR_TO_UINT(p)((unsigned int) ((uintptr_t) (p)))); | |||
| 854 | ||||
| 855 | r = unit_serialize_item_fd(u, f, fds, "pipe-fd", a->pipe_fd); | |||
| 856 | if (r < 0) | |||
| 857 | return r; | |||
| 858 | ||||
| 859 | return 0; | |||
| 860 | } | |||
| 861 | ||||
| 862 | static int automount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { | |||
| 863 | Automount *a = AUTOMOUNT(u); | |||
| 864 | int r; | |||
| 865 | ||||
| 866 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/core/automount.c", 866, __PRETTY_FUNCTION__ ); } while (0); | |||
| 867 | assert(fds)do { if ((__builtin_expect(!!(!(fds)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fds"), "../src/core/automount.c", 867, __PRETTY_FUNCTION__ ); } while (0); | |||
| 868 | ||||
| 869 | if (streq(key, "state")(strcmp((key),("state")) == 0)) { | |||
| 870 | AutomountState state; | |||
| 871 | ||||
| 872 | state = automount_state_from_string(value); | |||
| 873 | if (state < 0) | |||
| 874 | log_unit_debug(u, "Failed to parse state value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/automount.c" , 874, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse state value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/automount.c" , 874, __func__, "Failed to parse state value: %s", value); } ); | |||
| 875 | else | |||
| 876 | a->deserialized_state = state; | |||
| 877 | } else if (streq(key, "result")(strcmp((key),("result")) == 0)) { | |||
| 878 | AutomountResult f; | |||
| 879 | ||||
| 880 | f = automount_result_from_string(value); | |||
| 881 | if (f < 0) | |||
| 882 | log_unit_debug(u, "Failed to parse result value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/automount.c" , 882, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse result value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/automount.c" , 882, __func__, "Failed to parse result value: %s", value); } ); | |||
| 883 | else if (f != AUTOMOUNT_SUCCESS) | |||
| 884 | a->result = f; | |||
| 885 | ||||
| 886 | } else if (streq(key, "dev-id")(strcmp((key),("dev-id")) == 0)) { | |||
| 887 | unsigned d; | |||
| 888 | ||||
| 889 | if (safe_atou(value, &d) < 0) | |||
| 890 | log_unit_debug(u, "Failed to parse dev-id value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/automount.c" , 890, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse dev-id value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/automount.c" , 890, __func__, "Failed to parse dev-id value: %s", value); } ); | |||
| 891 | else | |||
| 892 | a->dev_id = (unsigned) d; | |||
| 893 | } else if (streq(key, "token")(strcmp((key),("token")) == 0)) { | |||
| 894 | unsigned token; | |||
| 895 | ||||
| 896 | if (safe_atou(value, &token) < 0) | |||
| 897 | log_unit_debug(u, "Failed to parse token value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/automount.c" , 897, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse token value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/automount.c" , 897, __func__, "Failed to parse token value: %s", value); } ); | |||
| 898 | else { | |||
| 899 | r = set_ensure_allocated(&a->tokens, NULL)internal_set_ensure_allocated(&a->tokens, ((void*)0) ); | |||
| 900 | if (r < 0) { | |||
| 901 | log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/core/automount.c" , 901, __func__); | |||
| 902 | return 0; | |||
| 903 | } | |||
| 904 | ||||
| 905 | r = set_put(a->tokens, UINT_TO_PTR(token)((void *) ((uintptr_t) (token)))); | |||
| 906 | if (r < 0) | |||
| 907 | log_unit_error_errno(u, r, "Failed to add token to set: %m")({ const Unit *_u = (u); _u ? log_object_internal(3, r, "../src/core/automount.c" , 907, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to add token to set: %m") : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((3))), r, "../src/core/automount.c", 907, __func__ , "Failed to add token to set: %m"); }); | |||
| 908 | } | |||
| 909 | } else if (streq(key, "expire-token")(strcmp((key),("expire-token")) == 0)) { | |||
| 910 | unsigned token; | |||
| 911 | ||||
| 912 | if (safe_atou(value, &token) < 0) | |||
| 913 | log_unit_debug(u, "Failed to parse token value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/automount.c" , 913, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse token value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/automount.c" , 913, __func__, "Failed to parse token value: %s", value); } ); | |||
| 914 | else { | |||
| 915 | r = set_ensure_allocated(&a->expire_tokens, NULL)internal_set_ensure_allocated(&a->expire_tokens, ((void *)0) ); | |||
| 916 | if (r < 0) { | |||
| 917 | log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/core/automount.c" , 917, __func__); | |||
| 918 | return 0; | |||
| 919 | } | |||
| 920 | ||||
| 921 | r = set_put(a->expire_tokens, UINT_TO_PTR(token)((void *) ((uintptr_t) (token)))); | |||
| 922 | if (r < 0) | |||
| 923 | log_unit_error_errno(u, r, "Failed to add expire token to set: %m")({ const Unit *_u = (u); _u ? log_object_internal(3, r, "../src/core/automount.c" , 923, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to add expire token to set: %m") : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((3))), r, "../src/core/automount.c" , 923, __func__, "Failed to add expire token to set: %m"); }); | |||
| 924 | } | |||
| 925 | } else if (streq(key, "pipe-fd")(strcmp((key),("pipe-fd")) == 0)) { | |||
| 926 | int fd; | |||
| 927 | ||||
| 928 | if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) | |||
| 929 | log_unit_debug(u, "Failed to parse pipe-fd value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/automount.c" , 929, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse pipe-fd value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/automount.c" , 929, __func__, "Failed to parse pipe-fd value: %s", value); }); | |||
| 930 | else { | |||
| 931 | safe_close(a->pipe_fd); | |||
| 932 | a->pipe_fd = fdset_remove(fds, fd); | |||
| 933 | } | |||
| 934 | } else | |||
| 935 | log_unit_debug(u, "Unknown serialization key: %s", key)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/automount.c" , 935, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Unknown serialization key: %s", key) : log_internal_realm( ((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/automount.c" , 935, __func__, "Unknown serialization key: %s", key); }); | |||
| 936 | ||||
| 937 | return 0; | |||
| 938 | } | |||
| 939 | ||||
| 940 | static UnitActiveState automount_active_state(Unit *u) { | |||
| 941 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/core/automount.c", 941, __PRETTY_FUNCTION__ ); } while (0); | |||
| 942 | ||||
| 943 | return state_translation_table[AUTOMOUNT(u)->state]; | |||
| 944 | } | |||
| 945 | ||||
| 946 | static const char *automount_sub_state_to_string(Unit *u) { | |||
| 947 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/core/automount.c", 947, __PRETTY_FUNCTION__ ); } while (0); | |||
| 948 | ||||
| 949 | return automount_state_to_string(AUTOMOUNT(u)->state); | |||
| 950 | } | |||
| 951 | ||||
| 952 | static bool_Bool automount_may_gc(Unit *u) { | |||
| 953 | Unit *t; | |||
| 954 | ||||
| 955 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/core/automount.c", 955, __PRETTY_FUNCTION__ ); } while (0); | |||
| 956 | ||||
| 957 | t = UNIT_TRIGGER(u)((Unit*) hashmap_first_key((u)->dependencies[UNIT_TRIGGERS ])); | |||
| 958 | if (!t) | |||
| 959 | return true1; | |||
| 960 | ||||
| 961 | return UNIT_VTABLE(t)unit_vtable[(t)->type]->may_gc(t); | |||
| 962 | } | |||
| 963 | ||||
| 964 | static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata) { | |||
| 965 | _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0}); | |||
| 966 | union autofs_v5_packet_union packet; | |||
| 967 | Automount *a = AUTOMOUNT(userdata); | |||
| 968 | Unit *trigger; | |||
| 969 | int r; | |||
| 970 | ||||
| 971 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/core/automount.c", 971, __PRETTY_FUNCTION__ ); } while (0); | |||
| 972 | assert(fd == a->pipe_fd)do { if ((__builtin_expect(!!(!(fd == a->pipe_fd)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fd == a->pipe_fd"), "../src/core/automount.c" , 972, __PRETTY_FUNCTION__); } while (0); | |||
| 973 | ||||
| 974 | if (events != EPOLLINEPOLLIN) { | |||
| 975 | log_unit_error(UNIT(a), "Got invalid poll event %"PRIu32" on pipe (fd=%d)", events, fd)({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/automount.c", 975, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Got invalid poll event %""u"" on pipe (fd=%d)" , events, fd) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3))), 0, "../src/core/automount.c", 975, __func__, "Got invalid poll event %" "u"" on pipe (fd=%d)", events, fd); }); | |||
| 976 | goto fail; | |||
| 977 | } | |||
| 978 | ||||
| 979 | r = loop_read_exact(a->pipe_fd, &packet, sizeof(packet), true1); | |||
| 980 | if (r < 0) { | |||
| 981 | log_unit_error_errno(UNIT(a), r, "Invalid read from pipe: %m")({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, r, "../src/core/automount.c", 981, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Invalid read from pipe: %m") : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3))) , r, "../src/core/automount.c", 981, __func__, "Invalid read from pipe: %m" ); }); | |||
| 982 | goto fail; | |||
| 983 | } | |||
| 984 | ||||
| 985 | switch (packet.hdr.type) { | |||
| 986 | ||||
| 987 | case autofs_ptype_missing_direct5: | |||
| 988 | ||||
| 989 | if (packet.v5_packet.pid > 0) { | |||
| 990 | _cleanup_free___attribute__((cleanup(freep))) char *p = NULL((void*)0); | |||
| 991 | ||||
| 992 | get_process_comm(packet.v5_packet.pid, &p); | |||
| 993 | log_unit_info(UNIT(a), "Got automount request for %s, triggered by %"PRIu32" (%s)", a->where, packet.v5_packet.pid, strna(p))({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (6, 0, "../src/core/automount.c", 993, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Got automount request for %s, triggered by %" "u"" (%s)", a->where, packet.v5_packet.pid, strna(p)) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((6))), 0, "../src/core/automount.c" , 993, __func__, "Got automount request for %s, triggered by %" "u"" (%s)", a->where, packet.v5_packet.pid, strna(p)); }); | |||
| 994 | } else | |||
| 995 | log_unit_debug(UNIT(a), "Got direct mount request on %s", a->where)({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/automount.c", 995, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Got direct mount request on %s" , a->where) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/automount.c", 995, __func__, "Got direct mount request on %s" , a->where); }); | |||
| 996 | ||||
| 997 | r = set_ensure_allocated(&a->tokens, NULL)internal_set_ensure_allocated(&a->tokens, ((void*)0) ); | |||
| 998 | if (r < 0) { | |||
| 999 | log_unit_error(UNIT(a), "Failed to allocate token set.")({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/automount.c", 999, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to allocate token set." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), 0, "../src/core/automount.c", 999, __func__, "Failed to allocate token set." ); }); | |||
| 1000 | goto fail; | |||
| 1001 | } | |||
| 1002 | ||||
| 1003 | r = set_put(a->tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token)((void *) ((uintptr_t) (packet.v5_packet.wait_queue_token)))); | |||
| 1004 | if (r < 0) { | |||
| 1005 | log_unit_error_errno(UNIT(a), r, "Failed to remember token: %m")({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, r, "../src/core/automount.c", 1005, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to remember token: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/core/automount.c", 1005, __func__, "Failed to remember token: %m" ); }); | |||
| 1006 | goto fail; | |||
| 1007 | } | |||
| 1008 | ||||
| 1009 | automount_enter_running(a); | |||
| 1010 | break; | |||
| 1011 | ||||
| 1012 | case autofs_ptype_expire_direct6: | |||
| 1013 | log_unit_debug(UNIT(a), "Got direct umount request on %s", a->where)({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/automount.c", 1013, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Got direct umount request on %s" , a->where) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/automount.c", 1013, __func__, "Got direct umount request on %s" , a->where); }); | |||
| 1014 | ||||
| 1015 | automount_stop_expire(a); | |||
| 1016 | ||||
| 1017 | r = set_ensure_allocated(&a->expire_tokens, NULL)internal_set_ensure_allocated(&a->expire_tokens, ((void *)0) ); | |||
| 1018 | if (r < 0) { | |||
| 1019 | log_unit_error(UNIT(a), "Failed to allocate token set.")({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/automount.c", 1019, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to allocate token set." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), 0, "../src/core/automount.c", 1019, __func__, "Failed to allocate token set." ); }); | |||
| 1020 | goto fail; | |||
| 1021 | } | |||
| 1022 | ||||
| 1023 | r = set_put(a->expire_tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token)((void *) ((uintptr_t) (packet.v5_packet.wait_queue_token)))); | |||
| 1024 | if (r < 0) { | |||
| 1025 | log_unit_error_errno(UNIT(a), r, "Failed to remember token: %m")({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, r, "../src/core/automount.c", 1025, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to remember token: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/core/automount.c", 1025, __func__, "Failed to remember token: %m" ); }); | |||
| 1026 | goto fail; | |||
| 1027 | } | |||
| 1028 | ||||
| 1029 | trigger = UNIT_TRIGGER(UNIT(a))((Unit*) hashmap_first_key((({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }))->dependencies [UNIT_TRIGGERS])); | |||
| 1030 | if (!trigger) { | |||
| 1031 | log_unit_error(UNIT(a), "Unit to trigger vanished.")({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/automount.c", 1031, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Unit to trigger vanished.") : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3))) , 0, "../src/core/automount.c", 1031, __func__, "Unit to trigger vanished." ); }); | |||
| 1032 | goto fail; | |||
| 1033 | } | |||
| 1034 | ||||
| 1035 | r = manager_add_job(UNIT(a)({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager, JOB_STOP, trigger, JOB_REPLACE, NULL((void*)0), &error, NULL((void*)0)); | |||
| 1036 | if (r < 0) { | |||
| 1037 | log_unit_warning(UNIT(a), "Failed to queue umount startup job: %s", bus_error_message(&error, r))({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/automount.c", 1037, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to queue umount startup job: %s" , bus_error_message(&error, r)) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((4))), 0, "../src/core/automount.c", 1037, __func__ , "Failed to queue umount startup job: %s", bus_error_message (&error, r)); }); | |||
| 1038 | goto fail; | |||
| 1039 | } | |||
| 1040 | break; | |||
| 1041 | ||||
| 1042 | default: | |||
| 1043 | log_unit_error(UNIT(a), "Received unknown automount request %i", packet.hdr.type)({ const Unit *_u = (({ typeof(a) _u_ = (a); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/automount.c", 1043, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Received unknown automount request %i" , packet.hdr.type) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3))), 0, "../src/core/automount.c", 1043, __func__, "Received unknown automount request %i" , packet.hdr.type); }); | |||
| 1044 | break; | |||
| 1045 | } | |||
| 1046 | ||||
| 1047 | return 0; | |||
| 1048 | ||||
| 1049 | fail: | |||
| 1050 | automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES); | |||
| 1051 | return 0; | |||
| 1052 | } | |||
| 1053 | ||||
| 1054 | static void automount_shutdown(Manager *m) { | |||
| 1055 | assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("m"), "../src/core/automount.c", 1055, __PRETTY_FUNCTION__ ); } while (0); | |||
| 1056 | ||||
| 1057 | m->dev_autofs_fd = safe_close(m->dev_autofs_fd); | |||
| 1058 | } | |||
| 1059 | ||||
| 1060 | static void automount_reset_failed(Unit *u) { | |||
| 1061 | Automount *a = AUTOMOUNT(u); | |||
| 1062 | ||||
| 1063 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/core/automount.c", 1063, __PRETTY_FUNCTION__ ); } while (0); | |||
| 1064 | ||||
| 1065 | if (a->state == AUTOMOUNT_FAILED) | |||
| 1066 | automount_set_state(a, AUTOMOUNT_DEAD); | |||
| 1067 | ||||
| 1068 | a->result = AUTOMOUNT_SUCCESS; | |||
| 1069 | } | |||
| 1070 | ||||
| 1071 | static bool_Bool automount_supported(void) { | |||
| 1072 | static int supported = -1; | |||
| 1073 | ||||
| 1074 | if (supported < 0) | |||
| 1075 | supported = access("/dev/autofs", F_OK0) >= 0; | |||
| 1076 | ||||
| 1077 | return supported; | |||
| 1078 | } | |||
| 1079 | ||||
| 1080 | static const char* const automount_result_table[_AUTOMOUNT_RESULT_MAX] = { | |||
| 1081 | [AUTOMOUNT_SUCCESS] = "success", | |||
| 1082 | [AUTOMOUNT_FAILURE_RESOURCES] = "resources", | |||
| 1083 | [AUTOMOUNT_FAILURE_START_LIMIT_HIT] = "start-limit-hit", | |||
| 1084 | [AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT] = "mount-start-limit-hit", | |||
| 1085 | }; | |||
| 1086 | ||||
| 1087 | DEFINE_STRING_TABLE_LOOKUP(automount_result, AutomountResult)const char *automount_result_to_string(AutomountResult i) { if (i < 0 || i >= (AutomountResult) __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(automount_result_table ), typeof(&*(automount_result_table))), sizeof(automount_result_table )/sizeof((automount_result_table)[0]), ((void)0)))) return (( void*)0); return automount_result_table[i]; } AutomountResult automount_result_from_string(const char *s) { return (AutomountResult ) string_table_lookup(automount_result_table, __extension__ ( __builtin_choose_expr( !__builtin_types_compatible_p(typeof(automount_result_table ), typeof(&*(automount_result_table))), sizeof(automount_result_table )/sizeof((automount_result_table)[0]), ((void)0))), s); }; | |||
| 1088 | ||||
| 1089 | const UnitVTable automount_vtable = { | |||
| 1090 | .object_size = sizeof(Automount), | |||
| 1091 | ||||
| 1092 | .sections = | |||
| 1093 | "Unit\0" | |||
| 1094 | "Automount\0" | |||
| 1095 | "Install\0", | |||
| 1096 | ||||
| 1097 | .init = automount_init, | |||
| 1098 | .load = automount_load, | |||
| 1099 | .done = automount_done, | |||
| 1100 | ||||
| 1101 | .coldplug = automount_coldplug, | |||
| 1102 | ||||
| 1103 | .dump = automount_dump, | |||
| 1104 | ||||
| 1105 | .start = automount_start, | |||
| 1106 | .stop = automount_stop, | |||
| 1107 | ||||
| 1108 | .serialize = automount_serialize, | |||
| 1109 | .deserialize_item = automount_deserialize_item, | |||
| 1110 | ||||
| 1111 | .active_state = automount_active_state, | |||
| 1112 | .sub_state_to_string = automount_sub_state_to_string, | |||
| 1113 | ||||
| 1114 | .may_gc = automount_may_gc, | |||
| 1115 | ||||
| 1116 | .trigger_notify = automount_trigger_notify, | |||
| 1117 | ||||
| 1118 | .reset_failed = automount_reset_failed, | |||
| 1119 | ||||
| 1120 | .bus_vtable = bus_automount_vtable, | |||
| 1121 | .bus_set_property = bus_automount_set_property, | |||
| 1122 | ||||
| 1123 | .can_transient = true1, | |||
| 1124 | ||||
| 1125 | .shutdown = automount_shutdown, | |||
| 1126 | .supported = automount_supported, | |||
| 1127 | ||||
| 1128 | .status_message_formats = { | |||
| 1129 | .finished_start_job = { | |||
| 1130 | [JOB_DONE] = "Set up automount %s.", | |||
| 1131 | [JOB_FAILED] = "Failed to set up automount %s.", | |||
| 1132 | }, | |||
| 1133 | .finished_stop_job = { | |||
| 1134 | [JOB_DONE] = "Unset automount %s.", | |||
| 1135 | [JOB_FAILED] = "Failed to unset automount %s.", | |||
| 1136 | }, | |||
| 1137 | }, | |||
| 1138 | }; |