autofs-5.1.9 - update per-mount expire timeout on readmap From: Ian Kent Ensure read map requests are propagated to child submounts and update the amd per-mount timeout. Also update the logging text to remove the use of the word dentry as it might not make sense to users. Signed-off-by: Ian Kent --- CHANGELOG | 1 daemon/master.c | 2 - daemon/state.c | 1 include/master.h | 1 include/mounts.h | 1 lib/mounts.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++ modules/parse_amd.c | 6 +-- 7 files changed, 130 insertions(+), 4 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 87bf6ebf2..f9432181f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -25,6 +25,7 @@ - fix lookup search type in umount_subtree_mounts(). - fix remount_active_mount() not remounting symlinks. - log when setting amd per-mount timeout. +- update per-mount expire timeout on readmap. 02/11/2023 autofs-5.1.9 - fix kernel mount status notification. diff --git a/daemon/master.c b/daemon/master.c index 6bf67552e..bd7b16f90 100644 --- a/daemon/master.c +++ b/daemon/master.c @@ -1388,7 +1388,7 @@ static int master_do_mount(struct master_mapent *entry) return 1; } -static void check_update_map_sources(struct master_mapent *entry, int readall) +void check_update_map_sources(struct master_mapent *entry, int readall) { struct map_source *source, *last; struct autofs_point *ap; diff --git a/daemon/state.c b/daemon/state.c index b7dfbc6da..4e26bc68f 100644 --- a/daemon/state.c +++ b/daemon/state.c @@ -432,6 +432,7 @@ static void *do_readmap(void *arg) time_t timeout = get_exp_timeout(ap, ap->entry->maps); ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO; ops->timeout(ap->logopt, ap->ioctlfd, NULL, timeout); + update_mounted_mounts_timeout(ap, ap->path); lookup_prune_cache(ap, now); status = lookup_ghost(ap); } else { diff --git a/include/master.h b/include/master.h index 38070bfc4..7b93c8e94 100644 --- a/include/master.h +++ b/include/master.h @@ -115,6 +115,7 @@ struct master *master_new(const char *, unsigned int, unsigned int); int master_read_master(struct master *, time_t); int master_notify_submount(struct autofs_point *, const char *path, enum states); void master_notify_state_change(struct master *, int); +void check_update_map_sources(struct master_mapent *, int); int master_mount_mounts(struct master *, time_t); int dump_map(struct master *, const char *, const char *); int master_show_mounts(struct master *); diff --git a/include/mounts.h b/include/mounts.h index 0c711ee83..8b3acac51 100644 --- a/include/mounts.h +++ b/include/mounts.h @@ -197,6 +197,7 @@ const char *mount_type_str(unsigned int); void set_exp_timeout(struct autofs_point *ap, struct map_source *source, time_t timeout); time_t get_exp_timeout(struct autofs_point *ap, struct map_source *source); void notify_mount_result(struct autofs_point *, const char *, time_t, const char *); +void update_mounted_mounts_timeout(struct autofs_point *, const char *); int try_remount(struct autofs_point *, struct mapent *, unsigned int); void set_indirect_mount_tree_catatonic(struct autofs_point *); void set_direct_mount_tree_catatonic(struct autofs_point *, struct mapent *); diff --git a/lib/mounts.c b/lib/mounts.c index b87e79a27..2c28a34b0 100644 --- a/lib/mounts.c +++ b/lib/mounts.c @@ -2605,6 +2605,128 @@ void notify_mount_result(struct autofs_point *ap, return; } +void update_mounted_mounts_timeout(struct autofs_point *ap, const char *path) +{ + struct ioctl_ops *ops = get_ioctl_ops(); + struct dirent **de; + char buf[PATH_MAX + 1]; + int n, size; + + n = scandir(path, &de, 0, alphasort); + if (n < 0) + return; + + size = sizeof(buf); + + while (n--) { + unsigned int mounted = 0; + struct mnt_list *mnt; + int ret; + + if (strcmp(de[n]->d_name, ".") == 0 || + strcmp(de[n]->d_name, "..") == 0) { + free(de[n]); + continue; + } + + ret = cat_path(buf, size, path, de[n]->d_name); + if (!ret) { + do { + free(de[n]); + } while (n--); + free(de); + return; + } + + ops->ismountpoint(ap->logopt, -1, buf, &mounted); + if (!mounted) { + struct dirent **de2; + int i, j; + + i = j = scandir(buf, &de2, 0, alphasort); + if (i < 0) { + free(de[n]); + continue; + } + while (i--) + free(de2[i]); + free(de2); + if (j <= 2) { + free(de[n]); + continue; + } + } + + /* For submounts we need to propogate the read map + * request. + */ + mnt = mnts_find_submount(buf); + if (mnt) { + check_update_map_sources(mnt->ap->entry, 1); + mnts_put_mount(mnt); + } + + mnt = mnts_find_amdmount(buf); + if (!mnt) { + free(de[n]); + continue; + } + + /* For amd type auto mounts the timeout is the per-mount + * timeout. + */ + if (mnt->amd_flags & AMD_MOUNT_TYPE_AUTO) + goto next; + + /* No per-mount timeout set? */ + if (!(mnt->amd_flags & AMD_MOUNT_OPT_MASK)) + goto next; + + /* The default in autofs is to always expire mounts according to + * a timeout set in the autofs mount super block information + * structure. But amd allows for differing expire timeouts on a + * per-mount basis. It also has (context sensitive) options "unmount" + * to say expire this mount and "nounmount" to say don't expire this + * mount. In amd mounts these options are set by default according + * to whether a mount should expire or not, for example a cd mount + * is set "nounmount". Setting defaults like this is not used in the + * autofs amd implementation because there's only one, little used, + * removable file system available. + * + * But the "nounmount" and "utimeout" options can be useful. + */ + if (mnt->amd_flags & AMD_MOUNT_OPT_NOUNMOUNT) { + if (mnt->amd_utimeout) + warn(ap->logopt, + "non-zero timeout set, possible conflicting options"); + + /* "nounmount" option, don't expire this mount. */ + if (ops) { + info(ap->logopt, + "set amd per-mount expire timeout to 0 for %s", + buf); + ops->timeout(ap->logopt, ap->ioctlfd, de[n]->d_name, 0); + } + } else if (mnt->amd_flags & AMD_MOUNT_OPT_UTIMEOUT) { + if (!mnt->amd_utimeout) + warn(ap->logopt, + "zero timeout set, possible conflicting options"); + + /* "utimeout" option, expire this mount according to a timeout. */ + if (ops) { + info(ap->logopt, + "set amd per-mount expire timeout to %d for %s", + mnt->amd_utimeout, buf); + ops->timeout(ap->logopt, ap->ioctlfd, de[n]->d_name, mnt->amd_utimeout); + } + } +next: + mnts_put_mount(mnt); + free(de[n]); + } + free(de); +} + static int do_remount_direct(struct autofs_point *ap, const unsigned int type, int fd, const char *path) { diff --git a/modules/parse_amd.c b/modules/parse_amd.c index bb32895e2..83e85f946 100644 --- a/modules/parse_amd.c +++ b/modules/parse_amd.c @@ -1765,7 +1765,7 @@ static int amd_mount(struct autofs_point *ap, const char *name, if (ops) { info(ap->logopt, "set amd per-mount expire timeout to 0 for %s", - name); + entry->path); ops->timeout(ap->logopt, ap->ioctlfd, name, 0); } } else if (per_mnt_flags & AMD_MOUNT_OPT_UTIMEOUT) { @@ -1776,8 +1776,8 @@ static int amd_mount(struct autofs_point *ap, const char *name, /* "utimeout" option, expire this mount according to a timeout. */ if (ops) { info(ap->logopt, - "set amd per-dentry expire timeout to %d for %s", - entry->utimeout, name); + "set amd per-mount expire timeout to %d for %s", + entry->utimeout, entry->path); ops->timeout(ap->logopt, ap->ioctlfd, name, entry->utimeout); } }