From: Lennart Poettering Date: Thu, 22 Jun 2023 08:57:31 +0000 (+0200) Subject: automont: rework expiry to use subprocess rather than thread X-Git-Tag: v254-rc1~133^2~9 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f7bccef178943bb7507193db246887024a62a07f;p=thirdparty%2Fsystemd.git automont: rework expiry to use subprocess rather than thread One more step towards a thread-free PID1: let's do automount expiry in a subprocess rather than a thread. --- diff --git a/src/core/automount.c b/src/core/automount.c index 3254275d6b1..52fb4b6948c 100644 --- a/src/core/automount.c +++ b/src/core/automount.c @@ -44,22 +44,6 @@ static const UnitActiveState state_translation_table[_AUTOMOUNT_STATE_MAX] = { [AUTOMOUNT_FAILED] = UNIT_FAILED }; -struct expire_data { - int dev_autofs_fd; - int ioctl_fd; -}; - -static struct expire_data* expire_data_free(struct expire_data *data) { - if (!data) - return NULL; - - safe_close(data->dev_autofs_fd); - safe_close(data->ioctl_fd); - return mfree(data); -} - -DEFINE_TRIVIAL_CLEANUP_FUNC(struct expire_data*, expire_data_free); - static int open_dev_autofs(Manager *m); static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata); static int automount_start_expire(Automount *a); @@ -674,55 +658,57 @@ fail: automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES); } -static void *expire_thread(void *p) { - struct autofs_dev_ioctl param; - _cleanup_(expire_data_freep) struct expire_data *data = p; +static int asynchronous_expire(int dev_autofs_fd, int ioctl_fd) { int r; - assert(data->dev_autofs_fd >= 0); - assert(data->ioctl_fd >= 0); + assert(dev_autofs_fd >= 0); + assert(ioctl_fd >= 0); - init_autofs_dev_ioctl(¶m); - param.ioctlfd = data->ioctl_fd; + /* Issue AUTOFS_DEV_IOCTL_EXPIRE in subprocess, asynchronously. Note that we don't keep track of the + * child's PID, we are PID1/autoreaper after all, hence when it dies we'll automatically clean it up + * anyway. */ + + r = safe_fork_full("(sd-expire)", + /* stdio_fds= */ NULL, + (int[]) { dev_autofs_fd, ioctl_fd }, + /* n_except_fds= */ 2, + FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG, + /* pid= */ NULL); + if (r != 0) + return r; + + /* Child */ + for (;;) { + struct autofs_dev_ioctl param; + init_autofs_dev_ioctl(¶m); + param.ioctlfd = ioctl_fd; - do { - r = ioctl(data->dev_autofs_fd, AUTOFS_DEV_IOCTL_EXPIRE, ¶m); - } while (r >= 0); + if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_EXPIRE, ¶m) < 0) + break; + } if (errno != EAGAIN) log_warning_errno(errno, "Failed to expire automount, ignoring: %m"); - return NULL; + _exit(EXIT_SUCCESS); } static int automount_dispatch_expire(sd_event_source *source, usec_t usec, void *userdata) { + _cleanup_close_ int ioctl_fd = -EBADF; Automount *a = AUTOMOUNT(userdata); - _cleanup_(expire_data_freep) struct expire_data *data = NULL; int r; assert(a); assert(source == a->expire_event_source); - data = new0(struct expire_data, 1); - if (!data) - return log_oom(); - - data->ioctl_fd = -EBADF; - - data->dev_autofs_fd = fcntl(UNIT(a)->manager->dev_autofs_fd, F_DUPFD_CLOEXEC, 3); - if (data->dev_autofs_fd < 0) - return log_unit_error_errno(UNIT(a), errno, "Failed to duplicate autofs fd: %m"); - - data->ioctl_fd = open_ioctl_fd(UNIT(a)->manager->dev_autofs_fd, a->where, a->dev_id); - if (data->ioctl_fd < 0) - return log_unit_error_errno(UNIT(a), data->ioctl_fd, "Couldn't open autofs ioctl fd: %m"); + ioctl_fd = open_ioctl_fd(UNIT(a)->manager->dev_autofs_fd, a->where, a->dev_id); + if (ioctl_fd < 0) + return log_unit_error_errno(UNIT(a), ioctl_fd, "Couldn't open autofs ioctl fd: %m"); - r = asynchronous_job(expire_thread, data); + r = asynchronous_expire(UNIT(a)->manager->dev_autofs_fd, ioctl_fd); if (r < 0) return log_unit_error_errno(UNIT(a), r, "Failed to start expire job: %m"); - data = NULL; - return automount_start_expire(a); }