From cc58c12fcac0c08bb1183d20587ce08af8d76a2d Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Tue, 3 Jul 2012 11:51:28 +0800 Subject: [PATCH] - sync up with upstream patches. --- ...unction-to-delete-offset-cache-entry.patch | 84 +++ ...add-hup-signal-handling-to-hosts-map.patch | 498 +++++++++++++++++ ...update-of-multi-mount-offset-entries.patch | 104 ++++ ...f-mtab-is-a-link-to-proc-self-mounts.patch | 70 +++ ...t-retry-ldap-connect-if-not-required.patch | 65 +++ ...ate-parent-options-for-included-maps.patch | 158 ++++++ ....6-fix-device-ioctl-alloc-path-check.patch | 37 ++ ...fix-LDAP-result-leaks-on-error-paths.patch | 33 ++ ...l-verion-check-of-version-components.patch | 94 ++++ autofs-5.0.6-fix-nfs4-contacts-portmap.patch | 52 ++ ...offset-mount-point-directory-removal.patch | 167 ++++++ autofs-5.0.6-fix-remount-deadlock.patch | 136 +++++ autofs-5.0.6-fix-remount-of-multi-mount.patch | 49 ++ autofs-5.0.6-fix-sss-map-age.patch | 34 ++ ...umount-recovery-of-busy-direct-mount.patch | 66 +++ ...make-autofs-wait-longer-for-shutdown.patch | 78 +++ autofs-5.0.6-move-timeout-to-map_source.patch | 529 ++++++++++++++++++ ...s-5.0.6-refactor-lookup-hosts-module.patch | 248 ++++++++ ...remove-cache-update-from-parse_mount.patch | 47 ++ ...move-mount-code-and-configure-option.patch | 421 ++++++++++++++ ...port-map-not-read-when-debug-logging.patch | 99 ++++ ...meout-function-to-not-return-timeout.patch | 171 ++++++ 22 files changed, 3240 insertions(+) create mode 100644 autofs-5.0.6-add-function-to-delete-offset-cache-entry.patch create mode 100644 autofs-5.0.6-add-hup-signal-handling-to-hosts-map.patch create mode 100644 autofs-5.0.6-allow-update-of-multi-mount-offset-entries.patch create mode 100644 autofs-5.0.6-check-if-mtab-is-a-link-to-proc-self-mounts.patch create mode 100644 autofs-5.0.6-dont-retry-ldap-connect-if-not-required.patch create mode 100644 autofs-5.0.6-duplicate-parent-options-for-included-maps.patch create mode 100644 autofs-5.0.6-fix-device-ioctl-alloc-path-check.patch create mode 100644 autofs-5.0.6-fix-fix-LDAP-result-leaks-on-error-paths.patch create mode 100644 autofs-5.0.6-fix-kernel-verion-check-of-version-components.patch create mode 100644 autofs-5.0.6-fix-nfs4-contacts-portmap.patch create mode 100644 autofs-5.0.6-fix-offset-mount-point-directory-removal.patch create mode 100644 autofs-5.0.6-fix-remount-deadlock.patch create mode 100644 autofs-5.0.6-fix-remount-of-multi-mount.patch create mode 100644 autofs-5.0.6-fix-sss-map-age.patch create mode 100644 autofs-5.0.6-fix-umount-recovery-of-busy-direct-mount.patch create mode 100644 autofs-5.0.6-make-autofs-wait-longer-for-shutdown.patch create mode 100644 autofs-5.0.6-move-timeout-to-map_source.patch create mode 100644 autofs-5.0.6-refactor-lookup-hosts-module.patch create mode 100644 autofs-5.0.6-remove-cache-update-from-parse_mount.patch create mode 100644 autofs-5.0.6-remove-move-mount-code-and-configure-option.patch create mode 100644 autofs-5.0.6-report-map-not-read-when-debug-logging.patch create mode 100644 autofs-5.0.6-update-timeout-function-to-not-return-timeout.patch diff --git a/autofs-5.0.6-add-function-to-delete-offset-cache-entry.patch b/autofs-5.0.6-add-function-to-delete-offset-cache-entry.patch new file mode 100644 index 0000000..977bb11 --- /dev/null +++ b/autofs-5.0.6-add-function-to-delete-offset-cache-entry.patch @@ -0,0 +1,84 @@ +autofs-5.0.6 - add function to delete offset cache entry + +From: Ian Kent + +Currently only the entire expanded list of offset cache entries may be +removed from the cache. In order to be able to update already expanded +multi map offset entries we need to be able to delete them. +--- + + include/automount.h | 1 + + lib/cache.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 48 insertions(+), 0 deletions(-) + + +diff --git a/include/automount.h b/include/automount.h +index e1246e3..40c1975 100644 +--- a/include/automount.h ++++ b/include/automount.h +@@ -192,6 +192,7 @@ int cache_add_offset(struct mapent_cache *mc, const char *mkey, const char *key, + int cache_set_parents(struct mapent *mm); + int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key, const char *mapent, time_t age); + int cache_delete(struct mapent_cache *mc, const char *key); ++int cache_delete_offset(struct mapent_cache *mc, const char *key); + void cache_multi_readlock(struct mapent *me); + void cache_multi_writelock(struct mapent *me); + void cache_multi_unlock(struct mapent *me); +diff --git a/lib/cache.c b/lib/cache.c +index 3464e7d..1489273 100644 +--- a/lib/cache.c ++++ b/lib/cache.c +@@ -771,6 +771,53 @@ int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key + return ret; + } + ++/* cache_multi_lock of the multi mount owner must be held by caller */ ++int cache_delete_offset(struct mapent_cache *mc, const char *key) ++{ ++ u_int32_t hashval = hash(key, mc->size); ++ struct mapent *me = NULL, *pred; ++ int status; ++ ++ me = mc->hash[hashval]; ++ if (!me) ++ return CHE_FAIL; ++ ++ if (strcmp(key, me->key) == 0) { ++ if (me->multi && me->multi == me) ++ return CHE_FAIL; ++ mc->hash[hashval] = me->next; ++ goto delete; ++ } ++ ++ while (me->next != NULL) { ++ pred = me; ++ me = me->next; ++ if (strcmp(key, me->key) == 0) { ++ if (me->multi && me->multi == me) ++ return CHE_FAIL; ++ pred->next = me->next; ++ goto delete; ++ } ++ } ++ ++ return CHE_FAIL; ++ ++delete: ++ status = pthread_rwlock_destroy(&me->multi_rwlock); ++ if (status) ++ fatal(status); ++ list_del(&me->multi_list); ++ ino_index_lock(mc); ++ list_del(&me->ino_index); ++ ino_index_unlock(mc); ++ free(me->key); ++ if (me->mapent) ++ free(me->mapent); ++ free(me); ++ ++ return CHE_OK; ++} ++ + /* cache must be write locked by caller */ + int cache_delete(struct mapent_cache *mc, const char *key) + { diff --git a/autofs-5.0.6-add-hup-signal-handling-to-hosts-map.patch b/autofs-5.0.6-add-hup-signal-handling-to-hosts-map.patch new file mode 100644 index 0000000..491612c --- /dev/null +++ b/autofs-5.0.6-add-hup-signal-handling-to-hosts-map.patch @@ -0,0 +1,498 @@ +autofs-5.0.6 - add hup signal handling to hosts map + +From: Ian Kent + +Add HUP signal handling to the internal hosts lookup module. +--- + + CHANGELOG | 1 + daemon/direct.c | 4 - + include/mounts.h | 1 + lib/mounts.c | 162 ++++++++++++++++++++++++++++++++++++++++++++++++- + man/auto.master.5.in | 5 + + man/autofs.5 | 8 +- + modules/lookup_hosts.c | 97 ++++++++++++++++++++++++----- + modules/parse_sun.c | 9 ++ + 8 files changed, 262 insertions(+), 25 deletions(-) + + +--- autofs-5.0.6.orig/CHANGELOG ++++ autofs-5.0.6/CHANGELOG +@@ -57,6 +57,7 @@ + - fix offset mount point directory removal. + - fix remount of multi mount. + - fix devce ioctl alloc path check. ++- add hup signal handling to hosts map. + + 28/06/2011 autofs-5.0.6 + ----------------------- +--- autofs-5.0.6.orig/daemon/direct.c ++++ autofs-5.0.6/daemon/direct.c +@@ -654,7 +654,9 @@ int mount_autofs_offset(struct autofs_po + ret = try_remount(ap, me, t_offset); + if (ret == 1) + return MOUNT_OFFSET_OK; +- return MOUNT_OFFSET_FAIL; ++ /* Offset mount not found, fall thru and try to mount it */ ++ if (!(ret == -1 && errno == ENOENT)) ++ return MOUNT_OFFSET_FAIL; + } else { + /* + if (is_mounted(_PROC_MOUNTS, me->key, MNTS_AUTOFS)) { +--- autofs-5.0.6.orig/include/mounts.h ++++ autofs-5.0.6/include/mounts.h +@@ -112,5 +112,6 @@ int try_remount(struct autofs_point *, s + int umount_ent(struct autofs_point *, const char *); + int mount_multi_triggers(struct autofs_point *, struct mapent *, const char *, unsigned int, const char *); + int umount_multi_triggers(struct autofs_point *, struct mapent *, char *, const char *); ++int clean_stale_multi_triggers(struct autofs_point *, struct mapent *, char *, const char *); + + #endif +--- autofs-5.0.6.orig/lib/mounts.c ++++ autofs-5.0.6/lib/mounts.c +@@ -1436,6 +1436,7 @@ static int remount_active_mount(struct a + + /* Re-reading the map, set timeout and return */ + if (ap->state == ST_READMAP) { ++ debug(ap->logopt, "already mounted, update timeout"); + ops->timeout(ap->logopt, fd, timeout); + ops->close(ap->logopt, fd); + return REMOUNT_READ_MAP; +@@ -1550,7 +1551,9 @@ int try_remount(struct autofs_point *ap, + * record that in the mount point struct. Otherwise we're + * re-reading the map. + */ +- if (ret == REMOUNT_SUCCESS || ret == REMOUNT_READ_MAP) { ++ if (ret == REMOUNT_READ_MAP) ++ return 1; ++ else if (ret == REMOUNT_SUCCESS) { + if (fd != -1) { + if (type == t_indirect) + ap->ioctlfd = fd; +@@ -1781,5 +1784,162 @@ int umount_multi_triggers(struct autofs_ + } + + return left; ++} ++ ++int clean_stale_multi_triggers(struct autofs_point *ap, ++ struct mapent *me, char *top, const char *base) ++{ ++ char *root; ++ char mm_top[PATH_MAX + 1]; ++ char path[PATH_MAX + 1]; ++ char buf[MAX_ERR_BUF]; ++ char *offset; ++ struct mapent *oe; ++ struct list_head *mm_root, *pos; ++ const char o_root[] = "/"; ++ const char *mm_base; ++ int left, start; ++ time_t age; ++ ++ if (top) ++ root = top; ++ else { ++ if (!strchr(me->multi->key, '/')) ++ /* Indirect multi-mount root */ ++ /* sprintf okay - if it's mounted, it's ++ * PATH_MAX or less bytes */ ++ sprintf(mm_top, "%s/%s", ap->path, me->multi->key); ++ else ++ strcpy(mm_top, me->multi->key); ++ root = mm_top; ++ } ++ ++ left = 0; ++ start = strlen(root); ++ ++ mm_root = &me->multi->multi_list; ++ ++ if (!base) ++ mm_base = o_root; ++ else ++ mm_base = base; ++ ++ pos = NULL; ++ offset = path; ++ age = me->multi->age; ++ ++ while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) { ++ char *oe_base; ++ char *key; ++ int ret; ++ ++ oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list); ++ /* root offset is a special case */ ++ if (!oe || !oe->mapent || (strlen(oe->key) - start) == 1) ++ continue; ++ ++ /* Check for and umount stale subtree offsets */ ++ oe_base = oe->key + strlen(root); ++ ret = clean_stale_multi_triggers(ap, oe, root, oe_base); ++ left =+ ret; ++ if (ret) ++ continue; ++ ++ if (oe->age == age) ++ continue; ++ ++ /* ++ * If an offset that has an active mount has been removed ++ * from the multi-mount we don't want to attempt to trigger ++ * mounts for it. Obviously this is because it has been ++ * removed, but less obvious is the potential strange ++ * behaviour that can result if we do try and mount it ++ * again after it's been expired. For example, if an NFS ++ * file system is no longer exported and is later umounted ++ * it can be mounted again without any error message but ++ * shows as an empty directory. That's going to confuse ++ * people for sure. ++ * ++ * If the mount cannot be umounted (the process is now ++ * using a stale mount) the offset needs to be invalidated ++ * so no further mounts will be attempted but the offset ++ * cache entry must remain so expires can continue to ++ * attempt to umount it. If the mount can be umounted and ++ * the offset is removed, at least for NFS we will get ++ * ESTALE errors when attempting list the directory. ++ */ ++ if (oe->ioctlfd != -1 || ++ is_mounted(_PROC_MOUNTS, oe->key, MNTS_REAL)) { ++ if (umount_ent(ap, oe->key)) { ++ debug(ap->logopt, ++ "offset %s has active mount, invalidate", ++ oe->key); ++ if (oe->mapent) { ++ free(oe->mapent); ++ oe->mapent = NULL; ++ } ++ left++; ++ continue; ++ } ++ } ++ ++ key = strdup(oe->key); ++ if (!key) { ++ char *estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ error(ap->logopt, "malloc: %s", estr); ++ left++; ++ continue; ++ } ++ ++ debug(ap->logopt, "umount offset %s", oe->key); ++ ++ if (umount_autofs_offset(ap, oe)) { ++ warn(ap->logopt, "failed to umount offset %s", key); ++ left++; ++ } else { ++ struct stat st; ++ ++ /* Mount point not ours to delete ? */ ++ if (!(oe->flags & MOUNT_FLAG_DIR_CREATED)) { ++ debug(ap->logopt, "delete offset key %s", key); ++ if (cache_delete_offset(oe->mc, key) == CHE_FAIL) ++ error(ap->logopt, ++ "failed to delete offset key %s", key); ++ free(key); ++ continue; ++ } ++ ++ /* ++ * An error due to partial directory removal is ++ * ok so only try and remount the offset if the ++ * actual mount point still exists. ++ */ ++ ret = rmdir_path(ap, oe->key, ap->dev); ++ if (ret == -1 && !stat(oe->key, &st)) { ++ ret = do_mount_autofs_offset(ap, oe, root, offset); ++ if (ret) { ++ left++; ++ free(key); ++ continue; ++ } ++ /* ++ * Fall through if the trigger can't be mounted ++ * again, since there is no offset there can't ++ * be any mount requests so remove the map ++ * entry from the cache. There's now a dead ++ * offset mount, but what else can we do .... ++ */ ++ } ++ ++ debug(ap->logopt, "delete offset key %s", key); ++ ++ if (cache_delete_offset(oe->mc, key) == CHE_FAIL) ++ error(ap->logopt, ++ "failed to delete offset key %s", key); ++ } ++ free(key); ++ } ++ ++ return left; + } + +--- autofs-5.0.6.orig/man/auto.master.5.in ++++ autofs-5.0.6/man/auto.master.5.in +@@ -220,7 +220,10 @@ set default log level "none", "verbose" + .SH BUILTIN MAP -hosts + If "-hosts" is given as the map then accessing a key under the mount point + which corresponds to a hostname will allow access to the exports of that +-host. ++host. The hosts map cannot be dynamically updated and requires a HUP signal ++to be sent to the daemon for it to check hosts for an update. Due to possible ++hierarchic dependencies within a mount tree, it might not be completely ++updated during the HUP signal processing. + .P + For example, with an entry in the master map of + .nh +--- autofs-5.0.6.orig/man/autofs.5 ++++ autofs-5.0.6/man/autofs.5 +@@ -13,10 +13,10 @@ These maps describe how file systems bel + map format; if another map format is specified (e.g. \fBhesiod\fP), + this documentation does not apply. + +-Indirect maps can be changed on the fly and the automouter will recognize +-those changes on the next operation it performs on that map. Direct maps +-require a HUP signal be sent to the daemon to refresh their contents as does +-the master map. ++Indirect maps, except for the internal hosts map, can be changed on the fly ++and the automouter will recognize those changes on the next operation it ++performs on that map. Direct maps require a HUP signal be sent to the ++daemon to refresh their contents as does the master map. + .SH "FORMAT" + This is a description of the text file format. Other methods of specifying + these files may exist. All empty lines or lines beginning with # are +--- autofs-5.0.6.orig/modules/lookup_hosts.c ++++ autofs-5.0.6/modules/lookup_hosts.c +@@ -80,10 +80,11 @@ int lookup_read_master(struct master *ma + + static char *get_exports(struct autofs_point *ap, const char *host) + { +- char *mapent = NULL; ++ char buf[MAX_ERR_BUF]; ++ char *mapent; + exports exp; + +- debug(ap->logopt, MODPREFIX "fetchng export list for %s", name); ++ debug(ap->logopt, MODPREFIX "fetchng export list for %s", host); + + exp = rpc_get_exports(host, 10, 0, RPC_CLOSE_NOLINGER); + +@@ -92,20 +93,20 @@ static char *get_exports(struct autofs_p + if (mapent) { + int len = strlen(mapent) + 1; + +- len += strlen(name) + 2*(strlen(exp->ex_dir) + 2) + 3; ++ len += strlen(host) + 2*(strlen(exp->ex_dir) + 2) + 3; + mapent = realloc(mapent, len); + if (!mapent) { + char *estr; + estr = strerror_r(errno, buf, MAX_ERR_BUF); + error(ap->logopt, MODPREFIX "malloc: %s", estr); + rpc_exports_free(exp); +- return NSS_STATUS_UNAVAIL; ++ return NULL; + } + strcat(mapent, " \""); + strcat(mapent, exp->ex_dir); + strcat(mapent, "\""); + } else { +- int len = 2*(strlen(exp->ex_dir) + 2) + strlen(name) + 3; ++ int len = 2*(strlen(exp->ex_dir) + 2) + strlen(host) + 3; + + mapent = malloc(len); + if (!mapent) { +@@ -113,14 +114,14 @@ static char *get_exports(struct autofs_p + estr = strerror_r(errno, buf, MAX_ERR_BUF); + error(ap->logopt, MODPREFIX "malloc: %s", estr); + rpc_exports_free(exp); +- return NSS_STATUS_UNAVAIL; ++ return NULL; + } + strcpy(mapent, "\""); + strcat(mapent, exp->ex_dir); + strcat(mapent, "\""); + } + strcat(mapent, " \""); +- strcat(mapent, name); ++ strcat(mapent, host); + strcat(mapent, ":"); + strcat(mapent, exp->ex_dir); + strcat(mapent, "\""); +@@ -130,14 +131,14 @@ static char *get_exports(struct autofs_p + rpc_exports_free(exp); + + if (!mapent) +- error(ap->logopt, "exports lookup failed for %s", name); ++ error(ap->logopt, MODPREFIX "exports lookup failed for %s", host); + + return mapent; + } + +-static int do_parse_mount(struct autofs_point *ap, ++static int do_parse_mount(struct autofs_point *ap, struct map_source *source, + const char *name, int name_len, char *mapent, +- void *context) ++ struct lookup_context *ctxt) + { + int ret; + +@@ -166,8 +167,68 @@ static int do_parse_mount(struct autofs_ + return NSS_STATUS_SUCCESS; + } + ++static int update_hosts_mounts(struct autofs_point *ap, ++ struct map_source *source, time_t age, ++ struct lookup_context *ctxt) ++{ ++ struct mapent_cache *mc; ++ struct mapent *me; ++ char *mapent; ++ int ret; ++ ++ mc = source->mc; ++ ++ pthread_cleanup_push(cache_lock_cleanup, mc); ++ cache_writelock(mc); ++ me = cache_lookup_first(mc); ++ while (me) { ++ /* Hosts map entry not yet expanded or already expired */ ++ if (!me->multi) ++ goto next; ++ ++ debug(ap->logopt, MODPREFIX "get list of exports for %s", me->key); ++ ++ mapent = get_exports(ap, me->key); ++ if (mapent) { ++ cache_update(mc, source, me->key, mapent, age); ++ free(mapent); ++ } ++next: ++ me = cache_lookup_next(mc, me); ++ } ++ pthread_cleanup_pop(1); ++ ++ pthread_cleanup_push(cache_lock_cleanup, mc); ++ cache_readlock(mc); ++ me = cache_lookup_first(mc); ++ while (me) { ++ /* ++ * Hosts map entry not yet expanded, already expired ++ * or not the base of the tree ++ */ ++ if (!me->multi || me->multi != me) ++ goto cont; ++ ++ debug(ap->logopt, MODPREFIX ++ "attempt to update exports for exports for %s", me->key); ++ ++ master_source_current_wait(ap->entry); ++ ap->entry->current = source; ++ ap->flags |= MOUNT_FLAG_REMOUNT; ++ ret = ctxt->parse->parse_mount(ap, me->key, strlen(me->key), ++ me->mapent, ctxt->parse->context); ++ ap->flags &= ~MOUNT_FLAG_REMOUNT; ++cont: ++ me = cache_lookup_next(mc, me); ++ } ++ pthread_cleanup_pop(1); ++ ++ return NSS_STATUS_SUCCESS; ++} ++ + int lookup_read_map(struct autofs_point *ap, time_t age, void *context) + { ++ struct lookup_context *ctxt = (struct lookup_context *) context; + struct map_source *source; + struct mapent_cache *mc; + struct hostent *host; +@@ -177,18 +238,23 @@ int lookup_read_map(struct autofs_point + ap->entry->current = NULL; + master_source_current_signal(ap->entry); + ++ mc = source->mc; ++ ++ debug(ap->logopt, MODPREFIX "read hosts map"); ++ + /* + * If we don't need to create directories then there's no use + * reading the map. We always need to read the whole map for + * direct mounts in order to mount the triggers. + */ + if (!(ap->flags & MOUNT_FLAG_GHOST) && ap->type != LKP_DIRECT) { +- debug(ap->logopt, "map read not needed, so not done"); ++ debug(ap->logopt, MODPREFIX ++ "map not browsable, update existing host entries only"); ++ update_hosts_mounts(ap, source, age, ctxt); ++ source->age = age; + return NSS_STATUS_SUCCESS; + } + +- mc = source->mc; +- + status = pthread_mutex_lock(&hostent_mutex); + if (status) { + error(ap->logopt, MODPREFIX "failed to lock hostent mutex"); +@@ -209,6 +275,7 @@ int lookup_read_map(struct autofs_point + if (status) + error(ap->logopt, MODPREFIX "failed to unlock hostent mutex"); + ++ update_hosts_mounts(ap, source, age, ctxt); + source->age = age; + + return NSS_STATUS_SUCCESS; +@@ -220,11 +287,9 @@ int lookup_mount(struct autofs_point *ap + struct map_source *source; + struct mapent_cache *mc; + struct mapent *me; +- char buf[MAX_ERR_BUF]; + char *mapent = NULL; + int mapent_len; + time_t now = time(NULL); +- exports exp; + int ret; + + source = ap->entry->current; +@@ -320,7 +385,7 @@ done: + cache_unlock(mc); + } + +- ret = do_parse_mount(ap, name, name_len, mapent, ctxt->parse->context); ++ ret = do_parse_mount(ap, source, name, name_len, mapent, ctxt); + + free(mapent); + +--- autofs-5.0.6.orig/modules/parse_sun.c ++++ autofs-5.0.6/modules/parse_sun.c +@@ -1355,7 +1355,7 @@ int parse_mount(struct autofs_point *ap, + if (check_is_multi(p)) { + char *m_root = NULL; + int m_root_len; +- time_t age = time(NULL); ++ time_t age; + int l; + + /* If name starts with "/" it's a direct mount */ +@@ -1399,6 +1399,8 @@ int parse_mount(struct autofs_point *ap, + return 1; + } + ++ age = me->age; ++ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state); + cache_multi_writelock(me); + /* It's a multi-mount; deal with it */ +@@ -1472,8 +1474,11 @@ int parse_mount(struct autofs_point *ap, + + /* + * We've got the ordered list of multi-mount entries so go +- * through and set the parent entry of each ++ * through and remove any stale entries if this is the top ++ * of the multi-mount and set the parent entry of each. + */ ++ if (me == me->multi) ++ clean_stale_multi_triggers(ap, me, NULL, NULL); + cache_set_parents(me); + + rv = mount_subtree(ap, me, name, NULL, options, ctxt); diff --git a/autofs-5.0.6-allow-update-of-multi-mount-offset-entries.patch b/autofs-5.0.6-allow-update-of-multi-mount-offset-entries.patch new file mode 100644 index 0000000..99841a1 --- /dev/null +++ b/autofs-5.0.6-allow-update-of-multi-mount-offset-entries.patch @@ -0,0 +1,104 @@ +autofs-5.0.6 - allow update of multi mount offset entries + +From: Ian Kent + +Currently multi mount offsets can only be added or all offsets owned by +an entry deleted at once. In order to be able to update multi mount map +entries we need to be able to update offset entries of an already expanded +multi map cache entry. +--- + + include/automount.h | 2 +- + lib/cache.c | 4 ++-- + modules/parse_sun.c | 20 ++++++++++---------- + 3 files changed, 13 insertions(+), 13 deletions(-) + + +diff --git a/include/automount.h b/include/automount.h +index 40c1975..561fcc2 100644 +--- a/include/automount.h ++++ b/include/automount.h +@@ -188,7 +188,7 @@ struct mapent *cache_lookup_distinct(struct mapent_cache *mc, const char *key); + struct mapent *cache_lookup_offset(const char *prefix, const char *offset, int start, struct list_head *head); + struct mapent *cache_partial_match(struct mapent_cache *mc, const char *prefix); + int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, const char *mapent, time_t age); +-int cache_add_offset(struct mapent_cache *mc, const char *mkey, const char *key, const char *mapent, time_t age); ++int cache_update_offset(struct mapent_cache *mc, const char *mkey, const char *key, const char *mapent, time_t age); + int cache_set_parents(struct mapent *mm); + int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key, const char *mapent, time_t age); + int cache_delete(struct mapent_cache *mc, const char *key); +diff --git a/lib/cache.c b/lib/cache.c +index 1489273..9179ad5 100644 +--- a/lib/cache.c ++++ b/lib/cache.c +@@ -647,7 +647,7 @@ static void cache_add_ordered_offset(struct mapent *me, struct list_head *head) + } + + /* cache must be write locked by caller */ +-int cache_add_offset(struct mapent_cache *mc, const char *mkey, const char *key, const char *mapent, time_t age) ++int cache_update_offset(struct mapent_cache *mc, const char *mkey, const char *key, const char *mapent, time_t age) + { + unsigned logopt = mc->ap ? mc->ap->logopt : master_get_logopt(); + struct mapent *me, *owner; +@@ -659,7 +659,7 @@ int cache_add_offset(struct mapent_cache *mc, const char *mkey, const char *key, + + me = cache_lookup_distinct(mc, key); + if (me && me->age == age) { +- if (me != owner) ++ if (me->multi != owner) + return CHE_DUPLICATE; + } + +diff --git a/modules/parse_sun.c b/modules/parse_sun.c +index c4decbc..5be7345 100644 +--- a/modules/parse_sun.c ++++ b/modules/parse_sun.c +@@ -781,10 +781,10 @@ static int check_is_multi(const char *mapent) + } + + static int +-add_offset_entry(struct autofs_point *ap, const char *name, +- const char *m_root, int m_root_len, +- const char *path, const char *myoptions, const char *loc, +- time_t age) ++update_offset_entry(struct autofs_point *ap, const char *name, ++ const char *m_root, int m_root_len, ++ const char *path, const char *myoptions, const char *loc, ++ time_t age) + { + struct map_source *source; + struct mapent_cache *mc; +@@ -838,17 +838,17 @@ add_offset_entry(struct autofs_point *ap, const char *name, + } else + strcpy(m_mapent, loc); + +- ret = cache_add_offset(mc, name, m_key, m_mapent, age); ++ ret = cache_update_offset(mc, name, m_key, m_mapent, age); + if (ret == CHE_DUPLICATE) + warn(ap->logopt, MODPREFIX + "syntax error or duplicate offset %s -> %s", path, loc); + else if (ret == CHE_FAIL) + debug(ap->logopt, MODPREFIX +- "failed to add multi-mount offset %s -> %s", path, m_mapent); ++ "failed to update multi-mount offset %s -> %s", path, m_mapent); + else { + ret = CHE_OK; + debug(ap->logopt, MODPREFIX +- "added multi-mount offset %s -> %s", path, m_mapent); ++ "updated multi-mount offset %s -> %s", path, m_mapent); + } + + return ret; +@@ -1448,9 +1448,9 @@ int parse_mount(struct autofs_point *ap, const char *name, + master_source_current_wait(ap->entry); + ap->entry->current = source; + +- status = add_offset_entry(ap, name, +- m_root, m_root_len, +- path, myoptions, loc, age); ++ status = update_offset_entry(ap, name, ++ m_root, m_root_len, ++ path, myoptions, loc, age); + + if (status != CHE_OK) { + warn(ap->logopt, MODPREFIX "error adding multi-mount"); diff --git a/autofs-5.0.6-check-if-mtab-is-a-link-to-proc-self-mounts.patch b/autofs-5.0.6-check-if-mtab-is-a-link-to-proc-self-mounts.patch new file mode 100644 index 0000000..a8bef3b --- /dev/null +++ b/autofs-5.0.6-check-if-mtab-is-a-link-to-proc-self-mounts.patch @@ -0,0 +1,70 @@ +autofs-5.0.6 - check if /etc/mtab is a link to /proc/self/mounts + +From: Leonardo Chiquitto + +Check if /etc/mtab is a link to /proc/self/mounts + +Some distributions link /etc/mtab to /proc/self/mounts instead +of /proc/mounts. +--- + + CHANGELOG | 1 + + daemon/spawn.c | 9 ++++++--- + include/automount.h | 3 ++- + 3 files changed, 9 insertions(+), 4 deletions(-) + + +--- autofs-5.0.6.orig/CHANGELOG ++++ autofs-5.0.6/CHANGELOG +@@ -48,6 +48,7 @@ + - move timeout to map_source (allow per direct map timeout). + - fix kernel verion check of version components. + - dont retry ldap connect if not required. ++- check if /etc/mtab is a link to /proc/self/mounts. + + 28/06/2011 autofs-5.0.6 + ----------------------- +--- autofs-5.0.6.orig/daemon/spawn.c ++++ autofs-5.0.6/daemon/spawn.c +@@ -336,7 +336,8 @@ int spawn_mount(unsigned logopt, ...) + ret = readlink(_PATH_MOUNTED, buf, PATH_MAX); + if (ret != -1) { + buf[ret] = '\0'; +- if (!strcmp(buf, _PROC_MOUNTS)) { ++ if (!strcmp(buf, _PROC_MOUNTS) || ++ !strcmp(buf, _PROC_SELF_MOUNTS)) { + debug(logopt, + "mtab link detected, passing -n to mount"); + argc++; +@@ -467,7 +468,8 @@ int spawn_bind_mount(unsigned logopt, .. + ret = readlink(_PATH_MOUNTED, buf, PATH_MAX); + if (ret != -1) { + buf[ret] = '\0'; +- if (!strcmp(buf, _PROC_MOUNTS)) { ++ if (!strcmp(buf, _PROC_MOUNTS) || ++ !strcmp(buf, _PROC_SELF_MOUNTS)) { + debug(logopt, + "mtab link detected, passing -n to mount"); + argc++; +@@ -569,7 +571,8 @@ int spawn_umount(unsigned logopt, ...) + ret = readlink(_PATH_MOUNTED, buf, PATH_MAX); + if (ret != -1) { + buf[ret] = '\0'; +- if (!strcmp(buf, _PROC_MOUNTS)) { ++ if (!strcmp(buf, _PROC_MOUNTS) || ++ !strcmp(buf, _PROC_SELF_MOUNTS)) { + debug(logopt, + "mtab link detected, passing -n to mount"); + argc++; +--- autofs-5.0.6.orig/include/automount.h ++++ autofs-5.0.6/include/automount.h +@@ -84,7 +84,8 @@ int load_autofs4_module(void); + #define MTAB_NOTUPDATED 0x1000 /* mtab succeded but not updated */ + #define NOT_MOUNTED 0x0100 /* path notmounted */ + #define MNT_FORCE_FAIL -1 +-#define _PROC_MOUNTS "/proc/mounts" ++#define _PROC_MOUNTS "/proc/mounts" ++#define _PROC_SELF_MOUNTS "/proc/self/mounts" + + /* Constants for lookup modules */ + diff --git a/autofs-5.0.6-dont-retry-ldap-connect-if-not-required.patch b/autofs-5.0.6-dont-retry-ldap-connect-if-not-required.patch new file mode 100644 index 0000000..a611b83 --- /dev/null +++ b/autofs-5.0.6-dont-retry-ldap-connect-if-not-required.patch @@ -0,0 +1,65 @@ +autofs-5.0.6 - dont retry ldap connect if not required + +From: Ian Kent + +When using LDAP and the server is not available autofs retries the +connection when it fails in case the SASL credentail has expired. +But this is done even when not using SASL, so change it check if +SASL authentication is required. +--- + + CHANGELOG | 1 + + include/lookup_ldap.h | 1 + + modules/lookup_ldap.c | 6 +++--- + 3 files changed, 5 insertions(+), 3 deletions(-) + + +--- autofs-5.0.6.orig/CHANGELOG ++++ autofs-5.0.6/CHANGELOG +@@ -47,6 +47,7 @@ + - update ->timeout() function to not return timeout. + - move timeout to map_source (allow per direct map timeout). + - fix kernel verion check of version components. ++- dont retry ldap connect if not required. + + 28/06/2011 autofs-5.0.6 + ----------------------- +--- autofs-5.0.6.orig/include/lookup_ldap.h ++++ autofs-5.0.6/include/lookup_ldap.h +@@ -104,6 +104,7 @@ struct lookup_context { + #define LDAP_AUTH_NOTREQUIRED 0x0001 + #define LDAP_AUTH_REQUIRED 0x0002 + #define LDAP_AUTH_AUTODETECT 0x0004 ++#define LDAP_NEED_AUTH (LDAP_AUTH_REQUIRED|LDAP_AUTH_AUTODETECT) + #endif + + #define LDAP_AUTH_USESIMPLE 0x0008 +--- autofs-5.0.6.orig/modules/lookup_ldap.c ++++ autofs-5.0.6/modules/lookup_ldap.c +@@ -511,7 +511,7 @@ static int do_bind(unsigned logopt, LDAP + debug(logopt, MODPREFIX "auth_required: %d, sasl_mech %s", + ctxt->auth_required, ctxt->sasl_mech); + +- if (ctxt->auth_required & (LDAP_AUTH_REQUIRED|LDAP_AUTH_AUTODETECT)) { ++ if (ctxt->auth_required & LDAP_NEED_AUTH) { + rv = autofs_sasl_bind(logopt, ldap, ctxt); + debug(logopt, MODPREFIX "autofs_sasl_bind returned %d", rv); + } else { +@@ -731,7 +731,7 @@ static LDAP *do_reconnect(unsigned logop + ldap = do_connect(logopt, ctxt->server, ctxt); + #ifdef WITH_SASL + /* Dispose of the sasl authentication connection and try again. */ +- if (!ldap) { ++ if (!ldap && ctxt->auth_required & LDAP_NEED_AUTH) { + autofs_sasl_dispose(ctxt); + ldap = connect_to_server(logopt, ctxt->server, ctxt); + } +@@ -767,7 +767,7 @@ static LDAP *do_reconnect(unsigned logop + * Dispose of the sasl authentication connection and try the + * current server again before trying other servers in the list. + */ +- if (!ldap) { ++ if (!ldap && ctxt->auth_required & LDAP_NEED_AUTH) { + autofs_sasl_dispose(ctxt); + ldap = connect_to_server(logopt, ctxt->uri->uri, ctxt); + } diff --git a/autofs-5.0.6-duplicate-parent-options-for-included-maps.patch b/autofs-5.0.6-duplicate-parent-options-for-included-maps.patch new file mode 100644 index 0000000..a38c509 --- /dev/null +++ b/autofs-5.0.6-duplicate-parent-options-for-included-maps.patch @@ -0,0 +1,158 @@ +autofs-5.0.6 - duplicate parent options for included maps + +From: Ian Kent + +Included maps should inherite mount options from their parent mount. +--- + + CHANGELOG | 1 + modules/lookup_file.c | 61 +++++++++++++++++++++++++++++++++++++++++++------- + 2 files changed, 54 insertions(+), 8 deletions(-) + + +--- autofs-5.0.6.orig/CHANGELOG ++++ autofs-5.0.6/CHANGELOG +@@ -43,6 +43,7 @@ + - fix initialization in rpc create_client(). + - fix libtirpc name clash. + - report map not read when debug logging. ++- duplicate parent options for included maps. + + 28/06/2011 autofs-5.0.6 + ----------------------- +--- autofs-5.0.6.orig/modules/lookup_file.c ++++ autofs-5.0.6/modules/lookup_file.c +@@ -41,9 +41,10 @@ typedef enum { + typedef enum { got_nothing, got_star, got_real, got_plus } FOUND_STATE; + typedef enum { esc_none, esc_char, esc_val, esc_all } ESCAPES; + +- + struct lookup_context { + const char *mapname; ++ int opts_argc; ++ const char **opts_argv; + struct parse_mod *parse; + }; + +@@ -88,8 +89,20 @@ int lookup_init(const char *mapfmt, int + if (!mapfmt) + mapfmt = MAPFMT_DEFAULT; + +- ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1); ++ argc--; ++ argv++; ++ ++ ctxt->opts_argv = copy_argv(argc, (const char **) argv); ++ if (ctxt->opts_argv == NULL) { ++ free(ctxt); ++ warn(LOGOPT_NONE, MODPREFIX "failed to duplicate options"); ++ return 1; ++ } ++ ctxt->opts_argc = argc; ++ ++ ctxt->parse = open_parse(mapfmt, MODPREFIX, argc, argv); + if (!ctxt->parse) { ++ free_argv(ctxt->opts_argc, ctxt->opts_argv); + free(ctxt); + logmsg(MODPREFIX "failed to open parse context"); + return 1; +@@ -512,12 +525,15 @@ static int check_self_include(const char + } + + static struct map_source * +-prepare_plus_include(struct autofs_point *ap, time_t age, char *key, unsigned int inc) ++prepare_plus_include(struct autofs_point *ap, ++ time_t age, char *key, unsigned int inc, ++ struct lookup_context *ctxt) + { + struct map_source *current; + struct map_source *source; + struct map_type_info *info; + const char *argv[2]; ++ char **tmp_argv, **tmp_opts; + int argc; + char *buf; + +@@ -551,9 +567,35 @@ prepare_plus_include(struct autofs_point + argv[0] = info->map; + argv[1] = NULL; + ++ tmp_argv = (char **) copy_argv(argc, argv); ++ if (!tmp_argv) { ++ error(ap->logopt, MODPREFIX "failed to allocate args vector"); ++ free_map_type_info(info); ++ free(buf); ++ return NULL; ++ } ++ ++ tmp_opts = (char **) copy_argv(ctxt->opts_argc, ctxt->opts_argv); ++ if (!tmp_opts) { ++ error(ap->logopt, MODPREFIX "failed to allocate options args vector"); ++ free_argv(argc, (const char **) tmp_argv); ++ free_map_type_info(info); ++ free(buf); ++ return NULL; ++ } ++ ++ tmp_argv = append_argv(argc, tmp_argv, ctxt->opts_argc, tmp_opts); ++ if (!tmp_argv) { ++ error(ap->logopt, MODPREFIX "failed to append options vector"); ++ free_map_type_info(info); ++ free(buf); ++ return NULL; ++ } ++ argc += ctxt->opts_argc; ++ + source = master_find_source_instance(current, + info->type, info->format, +- argc, argv); ++ argc, (const char **) tmp_argv); + if (source) { + /* + * Make sure included map age is in sync with its owner +@@ -563,15 +605,17 @@ prepare_plus_include(struct autofs_point + source->stale = 1; + } else { + source = master_add_source_instance(current, +- info->type, info->format, +- age, argc, argv); ++ info->type, info->format, age, ++ argc, (const char **) tmp_argv); + if (!source) { ++ free_argv(argc, (const char **) tmp_argv); + free_map_type_info(info); + free(buf); + error(ap->logopt, "failed to add included map instance"); + return NULL; + } + } ++ free_argv(argc, (const char **) tmp_argv); + + source->depth = current->depth + 1; + if (inc) +@@ -645,7 +689,7 @@ int lookup_read_map(struct autofs_point + master_source_current_wait(ap->entry); + ap->entry->current = source; + +- inc_source = prepare_plus_include(ap, age, key, inc); ++ inc_source = prepare_plus_include(ap, age, key, inc, ctxt); + if (!inc_source) { + debug(ap->logopt, + "failed to select included map %s", key); +@@ -729,7 +773,7 @@ static int lookup_one(struct autofs_poin + master_source_current_wait(ap->entry); + ap->entry->current = source; + +- inc_source = prepare_plus_include(ap, age, mkey, inc); ++ inc_source = prepare_plus_include(ap, age, mkey, inc, ctxt); + if (!inc_source) { + debug(ap->logopt, + MODPREFIX +@@ -1096,6 +1140,7 @@ int lookup_done(void *context) + { + struct lookup_context *ctxt = (struct lookup_context *) context; + int rv = close_parse(ctxt->parse); ++ free_argv(ctxt->opts_argc, ctxt->opts_argv); + free(ctxt); + return rv; + } diff --git a/autofs-5.0.6-fix-device-ioctl-alloc-path-check.patch b/autofs-5.0.6-fix-device-ioctl-alloc-path-check.patch new file mode 100644 index 0000000..42e70de --- /dev/null +++ b/autofs-5.0.6-fix-device-ioctl-alloc-path-check.patch @@ -0,0 +1,37 @@ +autofs-5.0.6 - fix devce ioctl alloc path check + +From: Ian Kent + +The errno error should be set in alloc_dev_ioctl_path() if the passed +in path in NULL. +--- + + CHANGELOG | 1 + + lib/dev-ioctl-lib.c | 4 +++- + 2 files changed, 4 insertions(+), 1 deletion(-) + + +--- autofs-5.0.6.orig/CHANGELOG ++++ autofs-5.0.6/CHANGELOG +@@ -56,6 +56,7 @@ + - fix umount recovery of busy direct mount. + - fix offset mount point directory removal. + - fix remount of multi mount. ++- fix devce ioctl alloc path check. + + 28/06/2011 autofs-5.0.6 + ----------------------- +--- autofs-5.0.6.orig/lib/dev-ioctl-lib.c ++++ autofs-5.0.6/lib/dev-ioctl-lib.c +@@ -270,8 +270,10 @@ static struct autofs_dev_ioctl *alloc_de + struct autofs_dev_ioctl *ioctl; + size_t size, p_len; + +- if (!path) ++ if (!path) { ++ errno = EINVAL; + return NULL; ++ } + + p_len = strlen(path); + size = sizeof(struct autofs_dev_ioctl) + p_len + 1; diff --git a/autofs-5.0.6-fix-fix-LDAP-result-leaks-on-error-paths.patch b/autofs-5.0.6-fix-fix-LDAP-result-leaks-on-error-paths.patch new file mode 100644 index 0000000..cf0b069 --- /dev/null +++ b/autofs-5.0.6-fix-fix-LDAP-result-leaks-on-error-paths.patch @@ -0,0 +1,33 @@ +autofs-5.0.6 - fix fix LDAP result leaks on error paths + +From: Ian Kent + +The previous patch with which ensured that the result struture returned +from ldap_search_s(3) was freed could sometimes lead to a segmentation +fault because the local variable used was not initialized before use. +--- + + modules/lookup_ldap.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + + +--- autofs-5.0.6.orig/modules/lookup_ldap.c ++++ autofs-5.0.6/modules/lookup_ldap.c +@@ -1521,7 +1521,7 @@ int lookup_read_master(struct master *ma + char buf[MAX_ERR_BUF]; + char parse_buf[PARSE_MAX_BUF]; + char *query; +- LDAPMessage *result, *e; ++ LDAPMessage *result = NULL, *e; + char *class, *info, *entry; + char **keyValue = NULL; + char **values = NULL; +@@ -2467,7 +2467,7 @@ static int lookup_one(struct autofs_poin + char buf[MAX_ERR_BUF]; + time_t age = time(NULL); + char *query; +- LDAPMessage *result, *e; ++ LDAPMessage *result = NULL, *e; + char *class, *info, *entry; + char *enc_key1, *enc_key2; + int enc_len1 = 0, enc_len2 = 0; diff --git a/autofs-5.0.6-fix-kernel-verion-check-of-version-components.patch b/autofs-5.0.6-fix-kernel-verion-check-of-version-components.patch new file mode 100644 index 0000000..cc7ad24 --- /dev/null +++ b/autofs-5.0.6-fix-kernel-verion-check-of-version-components.patch @@ -0,0 +1,94 @@ +autofs-5.0.6 - fix kernel verion check of version components + +From: Ian Kent + +Oops, not following the ball. + +The kernel may have (or will have at times) a two digit version number. +Fix the version check function to allow for this. +--- + + CHANGELOG | 1 + + include/mounts.h | 15 +-------------- + lib/mounts.c | 29 +++++++++++++++++++++++++++++ + 3 files changed, 31 insertions(+), 14 deletions(-) + + +--- autofs-5.0.6.orig/CHANGELOG ++++ autofs-5.0.6/CHANGELOG +@@ -46,6 +46,7 @@ + - duplicate parent options for included maps. + - update ->timeout() function to not return timeout. + - move timeout to map_source (allow per direct map timeout). ++- fix kernel verion check of version components. + + 28/06/2011 autofs-5.0.6 + ----------------------- +--- autofs-5.0.6.orig/include/mounts.h ++++ autofs-5.0.6/include/mounts.h +@@ -75,26 +75,13 @@ struct mnt_list { + struct list_head ordered; + }; + +-static inline unsigned int linux_version_code(void) +-{ +- struct utsname my_utsname; +- unsigned int p, q, r; +- char *save; +- +- if (uname(&my_utsname)) +- return 0; +- +- p = (unsigned int) atoi(strtok_r(my_utsname.release, ".", &save)); +- q = (unsigned int) atoi(strtok_r(NULL, ".", &save)); +- r = (unsigned int) atoi(strtok_r(NULL, ".", &save)); +- return KERNEL_VERSION(p, q, r); +-} + + struct nfs_mount_vers { + unsigned int major; + unsigned int minor; + unsigned int fix; + }; ++unsigned int linux_version_code(void); + int check_nfs_mount_version(struct nfs_mount_vers *, struct nfs_mount_vers *); + extern unsigned int nfs_mount_uses_string_options; + +--- autofs-5.0.6.orig/lib/mounts.c ++++ autofs-5.0.6/lib/mounts.c +@@ -46,6 +46,35 @@ static const char mnt_name_template[] + static struct kernel_mod_version kver = {0, 0}; + static const char kver_options_template[] = "fd=%d,pgrp=%u,minproto=3,maxproto=5"; + ++unsigned int linux_version_code(void) ++{ ++ struct utsname my_utsname; ++ unsigned int p, q, r; ++ char *tmp, *save; ++ ++ if (uname(&my_utsname)) ++ return 0; ++ ++ p = q = r = 0; ++ ++ tmp = strtok_r(my_utsname.release, ".", &save); ++ if (!tmp) ++ return 0; ++ p = (unsigned int ) atoi(tmp); ++ ++ tmp = strtok_r(NULL, ".", &save); ++ if (!tmp) ++ return KERNEL_VERSION(p, 0, 0); ++ q = (unsigned int) atoi(tmp); ++ ++ tmp = strtok_r(NULL, ".", &save); ++ if (!tmp) ++ return KERNEL_VERSION(p, q, 0); ++ r = (unsigned int) atoi(tmp); ++ ++ return KERNEL_VERSION(p, q, r); ++} ++ + unsigned int query_kproto_ver(void) + { + struct ioctl_ops *ops = get_ioctl_ops(); diff --git a/autofs-5.0.6-fix-nfs4-contacts-portmap.patch b/autofs-5.0.6-fix-nfs4-contacts-portmap.patch new file mode 100644 index 0000000..57b1ae7 --- /dev/null +++ b/autofs-5.0.6-fix-nfs4-contacts-portmap.patch @@ -0,0 +1,52 @@ +autofs-5.0.6 - fix nfs4 contacts portmap + +From: Ian Kent + +When an fstype of nfs4 is specified probing the server for availability +should not need to contact the portmapper, it should use either the port +specified by the port= option or use port 2049. + +However, in function modules/replicated.c:get_nfs_info() a check for the +port= option, and subsequent portmap lookup when not it's not present, is +done before the check for whether nfsv3 is to be checked at all. + +Oops! +--- + + CHANGELOG | 1 + + modules/replicated.c | 6 +++--- + 2 files changed, 4 insertions(+), 3 deletions(-) + + +--- autofs-5.0.6.orig/CHANGELOG ++++ autofs-5.0.6/CHANGELOG +@@ -49,6 +49,7 @@ + - fix kernel verion check of version components. + - dont retry ldap connect if not required. + - check if /etc/mtab is a link to /proc/self/mounts. ++- fix nfs4 contacts portmap. + + 28/06/2011 autofs-5.0.6 + ----------------------- +--- autofs-5.0.6.orig/modules/replicated.c ++++ autofs-5.0.6/modules/replicated.c +@@ -589,6 +589,9 @@ static unsigned int get_nfs_info(unsigne + } + + v3_ver: ++ if (!(version & NFS3_REQUESTED)) ++ goto v2_ver; ++ + if (!have_port_opt) { + status = rpc_portmap_getclient(pm_info, + host->name, host->addr, host->addr_len, +@@ -600,9 +603,6 @@ v3_ver: + goto done_ver; + } + +- if (!(version & NFS3_REQUESTED)) +- goto v2_ver; +- + if (have_port_opt) { + if (!(rpc_info->port = get_port_option(options))) + goto done_ver; diff --git a/autofs-5.0.6-fix-offset-mount-point-directory-removal.patch b/autofs-5.0.6-fix-offset-mount-point-directory-removal.patch new file mode 100644 index 0000000..0bf8c92 --- /dev/null +++ b/autofs-5.0.6-fix-offset-mount-point-directory-removal.patch @@ -0,0 +1,167 @@ +autofs-5.0.6 - fix offset mount point directory removal + +From: Ian Kent + +Attempting to remove the last component of a multi-mount offset mount +point is incorrect. The removal and attempted recovery is better +handled in the calling function. +--- + + CHANGELOG | 1 + daemon/direct.c | 7 ---- + lib/mounts.c | 82 ++++++++++++++++++++++++++++++++------------------------ + 3 files changed, 49 insertions(+), 41 deletions(-) + + +--- autofs-5.0.6.orig/CHANGELOG ++++ autofs-5.0.6/CHANGELOG +@@ -54,6 +54,7 @@ + - fix sss map age not updated. + - fix remount deadlock. + - fix umount recovery of busy direct mount. ++- fix offset mount point directory removal. + + 28/06/2011 autofs-5.0.6 + ----------------------- +--- autofs-5.0.6.orig/daemon/direct.c ++++ autofs-5.0.6/daemon/direct.c +@@ -633,13 +633,6 @@ force_umount: + } else + info(ap->logopt, "umounted offset mount %s", me->key); + +- if (!rv && me->flags & MOUNT_FLAG_DIR_CREATED) { +- if (rmdir(me->key) == -1) { +- char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- warn(ap->logopt, "failed to remove dir %s: %s", +- me->key, estr); +- } +- } + return rv; + } + +--- autofs-5.0.6.orig/lib/mounts.c ++++ autofs-5.0.6/lib/mounts.c +@@ -1605,6 +1605,33 @@ int umount_ent(struct autofs_point *ap, + return rv; + } + ++static int do_mount_autofs_offset(struct autofs_point *ap, ++ struct mapent *oe, const char *root, ++ char *offset) ++ ++{ ++ int mounted = 0; ++ int ret; ++ ++ debug(ap->logopt, "mount offset %s at %s", oe->key, root); ++ ++ ret = mount_autofs_offset(ap, oe, root, offset); ++ if (ret >= MOUNT_OFFSET_OK) ++ mounted++; ++ else { ++ if (ret != MOUNT_OFFSET_IGNORE) ++ warn(ap->logopt, "failed to mount offset"); ++ else { ++ debug(ap->logopt, "ignoring \"nohide\" trigger %s", ++ oe->key); ++ free(oe->mapent); ++ oe->mapent = NULL; ++ } ++ } ++ ++ return mounted; ++} ++ + int mount_multi_triggers(struct autofs_point *ap, struct mapent *me, + const char *root, unsigned int start, const char *base) + { +@@ -1613,8 +1640,7 @@ int mount_multi_triggers(struct autofs_p + struct mapent *oe; + struct list_head *pos = NULL; + unsigned int fs_path_len; +- unsigned int mounted; +- int ret; ++ int mounted; + + fs_path_len = start + strlen(base); + if (fs_path_len > PATH_MAX) +@@ -1634,22 +1660,7 @@ int mount_multi_triggers(struct autofs_p + if (!oe || !oe->mapent) + goto cont; + +- debug(ap->logopt, "mount offset %s at %s", oe->key, root); +- +- ret = mount_autofs_offset(ap, oe, root, offset); +- if (ret >= MOUNT_OFFSET_OK) +- mounted++; +- else { +- if (ret != MOUNT_OFFSET_IGNORE) +- warn(ap->logopt, "failed to mount offset"); +- else { +- debug(ap->logopt, +- "ignoring \"nohide\" trigger %s", +- oe->key); +- free(oe->mapent); +- oe->mapent = NULL; +- } +- } ++ mounted += do_mount_autofs_offset(ap, oe, root, offset); + cont: + offset = cache_get_offset(base, + offset, start, &me->multi_list, &pos); +@@ -1681,7 +1692,6 @@ int umount_multi_triggers(struct autofs_ + pos = NULL; + offset = path; + +- /* Make sure "none" of the offsets have an active mount. */ + while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) { + char *oe_base; + +@@ -1700,28 +1710,32 @@ int umount_multi_triggers(struct autofs_ + if (oe->ioctlfd != -1 || + is_mounted(_PROC_MOUNTS, oe->key, MNTS_REAL)) { + left++; +- break; +- } +- } +- +- if (left) +- return left; +- +- pos = NULL; +- offset = path; +- +- /* Make sure "none" of the offsets have an active mount. */ +- while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) { +- oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list); +- /* root offset is a special case */ +- if (!oe || !oe->mapent || (strlen(oe->key) - start) == 1) + continue; ++ } + + debug(ap->logopt, "umount offset %s", oe->key); + + if (umount_autofs_offset(ap, oe)) { + warn(ap->logopt, "failed to umount offset"); + left++; ++ } else { ++ struct stat st; ++ int ret; ++ ++ if (!(oe->flags & MOUNT_FLAG_DIR_CREATED)) ++ continue; ++ ++ /* ++ * An error due to partial directory removal is ++ * ok so only try and remount the offset if the ++ * actual mount point still exists. ++ */ ++ ret = rmdir_path(ap, oe->key, ap->dev); ++ if (ret == -1 && !stat(oe->key, &st)) { ++ ret = do_mount_autofs_offset(ap, oe, root, offset); ++ if (ret) ++ left++; ++ } + } + } + diff --git a/autofs-5.0.6-fix-remount-deadlock.patch b/autofs-5.0.6-fix-remount-deadlock.patch new file mode 100644 index 0000000..31a92ed --- /dev/null +++ b/autofs-5.0.6-fix-remount-deadlock.patch @@ -0,0 +1,136 @@ +autofs-5.0.6 - fix remount deadlock + +From: Ian Kent + +When reconstructing the mount tree upon restart a writelock to the map +entry cache cannot be taken when parsing a direct map entry because a +readlock is already held higher up in the call tree. + +In the place this is done it isn't be necessary to alter the direct map +entries in the cache. Also, it shouldn't be necessary to delete existing +multi-mount cache entries to avoid a duplicate multi-mount entry error +return. The check for a duplicate can be done in the cache handling +functions. +--- + + CHANGELOG | 1 + lib/cache.c | 8 ++++-- + modules/parse_sun.c | 60 ++++++++++++++++++++++++++-------------------------- + 3 files changed, 36 insertions(+), 33 deletions(-) + + +--- autofs-5.0.6.orig/CHANGELOG ++++ autofs-5.0.6/CHANGELOG +@@ -52,6 +52,7 @@ + - fix nfs4 contacts portmap. + - make autofs wait longer for shutdown completion. + - fix sss map age not updated. ++- fix remount deadlock. + + 28/06/2011 autofs-5.0.6 + ----------------------- +--- autofs-5.0.6.orig/lib/cache.c ++++ autofs-5.0.6/lib/cache.c +@@ -658,10 +658,12 @@ int cache_add_offset(struct mapent_cache + return CHE_FAIL; + + me = cache_lookup_distinct(mc, key); +- if (me && me != owner) +- return CHE_DUPLICATE; ++ if (me && me->age == age) { ++ if (me != owner) ++ return CHE_DUPLICATE; ++ } + +- ret = cache_add(mc, owner->source, key, mapent, age); ++ ret = cache_update(mc, owner->source, key, mapent, age); + if (ret == CHE_FAIL) { + warn(logopt, "failed to add key %s to cache", key); + return CHE_FAIL; +--- autofs-5.0.6.orig/modules/parse_sun.c ++++ autofs-5.0.6/modules/parse_sun.c +@@ -843,12 +843,17 @@ add_offset_entry(struct autofs_point *ap + strcpy(m_mapent, loc); + + ret = cache_add_offset(mc, name, m_key, m_mapent, age); +- if (ret == CHE_OK) ++ if (ret == CHE_DUPLICATE) ++ warn(ap->logopt, MODPREFIX ++ "syntax error or duplicate offset %s -> %s", path, loc); ++ else if (ret == CHE_FAIL) ++ debug(ap->logopt, MODPREFIX ++ "failed to add multi-mount offset %s -> %s", path, m_mapent); ++ else { ++ ret = CHE_OK; + debug(ap->logopt, MODPREFIX + "added multi-mount offset %s -> %s", path, m_mapent); +- else +- warn(ap->logopt, MODPREFIX +- "syntax error or duplicate offset %s -> %s", path, loc); ++ } + + return ret; + } +@@ -1410,7 +1415,7 @@ int parse_mount(struct autofs_point *ap, + char buf[MAX_ERR_BUF]; + struct map_source *source; + struct mapent_cache *mc; +- struct mapent *me = NULL; ++ struct mapent *me; + char *pmapent, *options; + const char *p; + int mapent_len, rv = 0; +@@ -1561,33 +1566,28 @@ int parse_mount(struct autofs_point *ap, + strcat(m_root, name); + } + +- cache_writelock(mc); +- me = cache_lookup_distinct(mc, name); +- if (!me) { +- int ret; +- /* +- * Not in the cache, perhaps it's a program map +- * or one that doesn't support enumeration +- */ +- ret = cache_add(mc, source, name, mapent, time(NULL)); +- if (ret == CHE_FAIL) { +- cache_unlock(mc); +- free(options); +- return 1; ++ /* ++ * Can't take the write lock for direct mount entries here ++ * but they should always be present in the map entry cache. ++ */ ++ if (ap->type == LKP_INDIRECT) { ++ cache_writelock(mc); ++ me = cache_lookup_distinct(mc, name); ++ if (!me) { ++ int ret; ++ /* ++ * Not in the cache, perhaps it's a program map ++ * or one that doesn't support enumeration. ++ */ ++ ret = cache_add(mc, source, name, mapent, age); ++ if (ret == CHE_FAIL) { ++ cache_unlock(mc); ++ free(options); ++ return 1; ++ } + } +- } else { +- /* +- * If the entry exists it must not have any existing +- * multi-mount subordinate entries since we are +- * mounting this afresh. We need to do this to allow +- * us to fail on the check for duplicate offsets in +- * we don't know when submounts go away. +- */ +- cache_multi_writelock(me); +- cache_delete_offset_list(mc, name); +- cache_multi_unlock(me); ++ cache_unlock(mc); + } +- cache_unlock(mc); + + cache_readlock(mc); + me = cache_lookup_distinct(mc, name); diff --git a/autofs-5.0.6-fix-remount-of-multi-mount.patch b/autofs-5.0.6-fix-remount-of-multi-mount.patch new file mode 100644 index 0000000..59dd7f7 --- /dev/null +++ b/autofs-5.0.6-fix-remount-of-multi-mount.patch @@ -0,0 +1,49 @@ +autofs-5.0.6 - fix remount of multi mount + +From: Ian Kent + +Went accessing a multi-mount only the the offsets that need to be mounted +are mounted. But when re-mounting multi-mounts during a restart we need to +also traverse into existing mounts and re-connect to triggers mounted within +them. +--- + + CHANGELOG | 1 + + lib/mounts.c | 15 +++++++++++++++ + 2 files changed, 16 insertions(+) + + +--- autofs-5.0.6.orig/CHANGELOG ++++ autofs-5.0.6/CHANGELOG +@@ -55,6 +55,7 @@ + - fix remount deadlock. + - fix umount recovery of busy direct mount. + - fix offset mount point directory removal. ++- fix remount of multi mount. + + 28/06/2011 autofs-5.0.6 + ----------------------- +--- autofs-5.0.6.orig/lib/mounts.c ++++ autofs-5.0.6/lib/mounts.c +@@ -1661,6 +1661,21 @@ int mount_multi_triggers(struct autofs_p + goto cont; + + mounted += do_mount_autofs_offset(ap, oe, root, offset); ++ ++ /* ++ * If re-constructing a multi-mount it's necessary to walk ++ * into nested mounts, unlike the usual "mount only what's ++ * needed as you go" behavior. ++ */ ++ if (ap->state == ST_READMAP && ap->flags & MOUNT_FLAG_REMOUNT) { ++ if (oe->ioctlfd != -1 || ++ is_mounted(_PROC_MOUNTS, oe->key, MNTS_REAL)) { ++ char oe_root[PATH_MAX + 1]; ++ strcpy(oe_root, root); ++ strcat(oe_root, offset); ++ mount_multi_triggers(ap, oe, oe_root, strlen(oe_root), base); ++ } ++ } + cont: + offset = cache_get_offset(base, + offset, start, &me->multi_list, &pos); diff --git a/autofs-5.0.6-fix-sss-map-age.patch b/autofs-5.0.6-fix-sss-map-age.patch new file mode 100644 index 0000000..f30aa1b --- /dev/null +++ b/autofs-5.0.6-fix-sss-map-age.patch @@ -0,0 +1,34 @@ +autofs-5.0.6 - fix sss map age not updated + +From: Ian Kent + +The map source age field should be updated when the map is read for +map entry cache cleanup. +--- + + CHANGELOG | 1 + + modules/lookup_sss.c | 2 ++ + 2 files changed, 3 insertions(+) + + +--- autofs-5.0.6.orig/CHANGELOG ++++ autofs-5.0.6/CHANGELOG +@@ -51,6 +51,7 @@ + - check if /etc/mtab is a link to /proc/self/mounts. + - fix nfs4 contacts portmap. + - make autofs wait longer for shutdown completion. ++- fix sss map age not updated. + + 28/06/2011 autofs-5.0.6 + ----------------------- +--- autofs-5.0.6.orig/modules/lookup_sss.c ++++ autofs-5.0.6/modules/lookup_sss.c +@@ -362,6 +362,8 @@ int lookup_read_map(struct autofs_point + + endautomntent(ap->logopt, ctxt, &sss_ctxt); + ++ source->age = age; ++ + return NSS_STATUS_SUCCESS; + } + diff --git a/autofs-5.0.6-fix-umount-recovery-of-busy-direct-mount.patch b/autofs-5.0.6-fix-umount-recovery-of-busy-direct-mount.patch new file mode 100644 index 0000000..bc2bf42 --- /dev/null +++ b/autofs-5.0.6-fix-umount-recovery-of-busy-direct-mount.patch @@ -0,0 +1,66 @@ +autofs-5.0.6 - fix umount recovery of busy direct mount + +From: Ian Kent + +Reported by Leonardo Chiquitto (along with a problem analysis that lead +to the resolution). Thanks for the effort Leonardo. + +When umounting direct mounts at exit, if any are busy and contain offset +trigger mounts automount will try and re-mount them when the umount fails +so they can be used to re-construct the mount tree at restart. But this +fails because the kernel communication pipe, which is used as a parameter +when mounting the offsets, has already been closed. To fix this all we +need do is delay closing the kernel pipe file handle until after the +direct mounts have been umounted since this doesn't affect the in use +status of the mounts. +--- + + CHANGELOG | 1 + + daemon/direct.c | 18 +++++++++--------- + 2 files changed, 10 insertions(+), 9 deletions(-) + + +--- autofs-5.0.6.orig/CHANGELOG ++++ autofs-5.0.6/CHANGELOG +@@ -53,6 +53,7 @@ + - make autofs wait longer for shutdown completion. + - fix sss map age not updated. + - fix remount deadlock. ++- fix umount recovery of busy direct mount. + + 28/06/2011 autofs-5.0.6 + ----------------------- +--- autofs-5.0.6.orig/daemon/direct.c ++++ autofs-5.0.6/daemon/direct.c +@@ -193,15 +193,6 @@ int umount_autofs_direct(struct autofs_p + struct mnt_list *mnts; + struct mapent *me, *ne; + +- close(ap->state_pipe[0]); +- close(ap->state_pipe[1]); +- if (ap->pipefd >= 0) +- close(ap->pipefd); +- if (ap->kpipefd >= 0) { +- close(ap->kpipefd); +- ap->kpipefd = -1; +- } +- + mnts = tree_make_mnt_tree(_PROC_MOUNTS, "/"); + pthread_cleanup_push(mnts_cleanup, mnts); + nc = ap->entry->master->nc; +@@ -231,6 +222,15 @@ int umount_autofs_direct(struct autofs_p + pthread_cleanup_pop(1); + pthread_cleanup_pop(1); + ++ close(ap->state_pipe[0]); ++ close(ap->state_pipe[1]); ++ if (ap->pipefd >= 0) ++ close(ap->pipefd); ++ if (ap->kpipefd >= 0) { ++ close(ap->kpipefd); ++ ap->kpipefd = -1; ++ } ++ + return 0; + } + diff --git a/autofs-5.0.6-make-autofs-wait-longer-for-shutdown.patch b/autofs-5.0.6-make-autofs-wait-longer-for-shutdown.patch new file mode 100644 index 0000000..9917f67 --- /dev/null +++ b/autofs-5.0.6-make-autofs-wait-longer-for-shutdown.patch @@ -0,0 +1,78 @@ +autofs-5.0.6 - make autofs wait longer for shutdown + +From: Ian Kent + +After signaling the automount daemon to shutdown the autofs init script +doesn't wait long enough for the daemon to exit. This can be a problem +if there are a large number of mounts or if servers are slow to respond. +--- + + CHANGELOG | 1 + + redhat/autofs.init.in | 5 ++++- + samples/autofs.service.in | 1 + + samples/rc.autofs.in | 5 ++++- + 4 files changed, 10 insertions(+), 2 deletions(-) + + +--- autofs-5.0.6.orig/CHANGELOG ++++ autofs-5.0.6/CHANGELOG +@@ -50,6 +50,7 @@ + - dont retry ldap connect if not required. + - check if /etc/mtab is a link to /proc/self/mounts. + - fix nfs4 contacts portmap. ++- make autofs wait longer for shutdown completion. + + 28/06/2011 autofs-5.0.6 + ----------------------- +--- autofs-5.0.6.orig/redhat/autofs.init.in ++++ autofs-5.0.6/redhat/autofs.init.in +@@ -108,7 +108,7 @@ function stop() { + while [ -n "`pidof $prog`" -a $count -lt 15 ] ; do + killproc $prog -TERM >& /dev/null + RETVAL=$? +- [ $RETVAL = 0 -a -z "`pidof $prog`" ] || sleep 3 ++ [ $RETVAL = 0 -a -z "`pidof $prog`" ] || sleep 20 + count=`expr $count + 1` + done + if [ $RETVAL -eq 0 ]; then +@@ -129,6 +129,9 @@ function restart() { + status autofs > /dev/null 2>&1 + if [ $? -eq 0 ]; then + stop ++ while [ -n "`pidof $prog`" ] ; do ++ sleep 5 ++ done + fi + start + } +--- autofs-5.0.6.orig/samples/autofs.service.in ++++ autofs-5.0.6/samples/autofs.service.in +@@ -8,6 +8,7 @@ PIDFile=@@autofspiddir@@/autofs.pid + EnvironmentFile=-@@autofsconfdir@@/autofs + ExecStart=@@sbindir@@/automount ${OPTIONS} --pid-file @@autofspiddir@@/autofs.pid + ExecReload=/usr/bin/kill -HUP $MAINPID ++TimeoutSec=180 + + [Install] + WantedBy=multi-user.target +--- autofs-5.0.6.orig/samples/rc.autofs.in ++++ autofs-5.0.6/samples/rc.autofs.in +@@ -91,7 +91,7 @@ function stop() { + while [ -n "`pidof $prog`" -a $count -lt 15 ] ; do + killall -TERM $prog >& /dev/null + RETVAL=$? +- [ $RETVAL = 0 -a -z "`pidof $prog`" ] || sleep 3 ++ [ $RETVAL = 0 -a -z "`pidof $prog`" ] || sleep 20 + count=`expr $count + 1` + done + if [ -z "`pidof $prog`" ] ; then +@@ -104,6 +104,9 @@ function stop() { + + function restart() { + stop ++ while [ -n "`pidof $prog`" ] ; do ++ sleep 5 ++ done + start + } + diff --git a/autofs-5.0.6-move-timeout-to-map_source.patch b/autofs-5.0.6-move-timeout-to-map_source.patch new file mode 100644 index 0000000..6e181c3 --- /dev/null +++ b/autofs-5.0.6-move-timeout-to-map_source.patch @@ -0,0 +1,529 @@ +autofs-5.0.6 - move timeout to map_source + +From: Ian Kent + +Move the map entry timeout field from "struct autofs_point" to +"struct map_source". + +The result of this change is that an individual timeout may be +set for each direct map master map entry. +--- + + CHANGELOG | 1 + + daemon/automount.c | 2 +- + daemon/direct.c | 32 +++++++++++++++++++++----------- + daemon/indirect.c | 7 +++---- + daemon/lookup.c | 2 ++ + daemon/state.c | 18 +++++++++++++++++- + include/automount.h | 5 +++-- + include/master.h | 3 ++- + include/mounts.h | 2 +- + lib/master.c | 9 ++++----- + lib/master_parse.y | 32 +++++++++++++------------------- + lib/mounts.c | 37 ++++++++++++++++++------------------- + modules/mount_autofs.c | 5 +++-- + 13 files changed, 89 insertions(+), 66 deletions(-) + + +--- autofs-5.0.6.orig/CHANGELOG ++++ autofs-5.0.6/CHANGELOG +@@ -45,6 +45,7 @@ + - report map not read when debug logging. + - duplicate parent options for included maps. + - update ->timeout() function to not return timeout. ++- move timeout to map_source (allow per direct map timeout). + + 28/06/2011 autofs-5.0.6 + ----------------------- +--- autofs-5.0.6.orig/daemon/automount.c ++++ autofs-5.0.6/daemon/automount.c +@@ -1585,7 +1585,7 @@ void *handle_mounts(void *arg) + + /* We often start several automounters at the same time. Add some + randomness so we don't all expire at the same time. */ +- if (!ap->submount && ap->exp_timeout) ++ if (!ap->submount && ap->exp_runfreq) + alarm_add(ap, ap->exp_runfreq + rand() % ap->exp_runfreq); + + pthread_setcancelstate(cancel_state, NULL); +--- autofs-5.0.6.orig/daemon/direct.c ++++ autofs-5.0.6/daemon/direct.c +@@ -286,7 +286,7 @@ static int unlink_active_mounts(struct a + + if (tree_get_mnt_list(mnts, &list, me->key, 1)) { + if (ap->state == ST_READMAP) { +- time_t tout = ap->exp_timeout; ++ time_t tout = me->source->exp_timeout; + int save_ioctlfd, ioctlfd; + + save_ioctlfd = ioctlfd = me->ioctlfd; +@@ -321,18 +321,26 @@ static int unlink_active_mounts(struct a + return 1; + } + +-int do_mount_autofs_direct(struct autofs_point *ap, struct mnt_list *mnts, struct mapent *me) ++int do_mount_autofs_direct(struct autofs_point *ap, ++ struct mnt_list *mnts, struct mapent *me, ++ time_t timeout) + { + const char *str_direct = mount_type_str(t_direct); + struct ioctl_ops *ops = get_ioctl_ops(); + struct mnt_params *mp; +- time_t timeout = ap->exp_timeout; + struct stat st; + int status, ret, ioctlfd; + const char *map_name; ++ time_t runfreq; + +- /* Calculate the timeouts */ +- ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO; ++ if (timeout) { ++ /* Calculate the expire run frequency */ ++ runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO; ++ if (ap->exp_runfreq) ++ ap->exp_runfreq = min(ap->exp_runfreq, runfreq); ++ else ++ ap->exp_runfreq = runfreq; ++ } + + if (ops->version && !do_force_unlink) { + ap->flags |= MOUNT_FLAG_REMOUNT; +@@ -425,7 +433,7 @@ int do_mount_autofs_direct(struct autofs + } + + ops->timeout(ap->logopt, ioctlfd, timeout); +- notify_mount_result(ap, me->key, str_direct); ++ notify_mount_result(ap, me->key, timeout, str_direct); + cache_set_ino_index(me->mc, me->key, st.st_dev, st.st_ino); + ops->close(ap->logopt, ioctlfd); + +@@ -473,6 +481,7 @@ int mount_autofs_direct(struct autofs_po + pthread_cleanup_push(cache_lock_cleanup, nc); + map = ap->entry->maps; + while (map) { ++ time_t timeout; + /* + * Only consider map sources that have been read since + * the map entry was last updated. +@@ -483,6 +492,7 @@ int mount_autofs_direct(struct autofs_po + } + + mc = map->mc; ++ timeout = map->exp_timeout; + cache_readlock(mc); + pthread_cleanup_push(cache_lock_cleanup, mc); + me = cache_enumerate(mc, NULL); +@@ -491,7 +501,7 @@ int mount_autofs_direct(struct autofs_po + if (ne) { + if (map->master_line < ne->age) { + /* TODO: check return, locking me */ +- do_mount_autofs_direct(ap, mnts, me); ++ do_mount_autofs_direct(ap, mnts, me, timeout); + } + me = cache_enumerate(mc, me); + continue; +@@ -508,7 +518,7 @@ int mount_autofs_direct(struct autofs_po + } + + /* TODO: check return, locking me */ +- do_mount_autofs_direct(ap, mnts, me); ++ do_mount_autofs_direct(ap, mnts, me, timeout); + + me = cache_enumerate(mc, me); + } +@@ -639,7 +649,7 @@ int mount_autofs_offset(struct autofs_po + struct ioctl_ops *ops = get_ioctl_ops(); + char buf[MAX_ERR_BUF]; + struct mnt_params *mp; +- time_t timeout = ap->exp_timeout; ++ time_t timeout = me->source->exp_timeout; + struct stat st; + int ioctlfd, status, ret; + const char *hosts_map_name = "-hosts"; +@@ -774,9 +784,9 @@ int mount_autofs_offset(struct autofs_po + ops->timeout(ap->logopt, ioctlfd, timeout); + cache_set_ino_index(me->mc, me->key, st.st_dev, st.st_ino); + if (ap->logopt & LOGOPT_DEBUG) +- notify_mount_result(ap, mountpoint, str_offset); ++ notify_mount_result(ap, mountpoint, timeout, str_offset); + else +- notify_mount_result(ap, me->key, str_offset); ++ notify_mount_result(ap, me->key, timeout, str_offset); + ops->close(ap->logopt, ioctlfd); + + debug(ap->logopt, "mounted trigger %s at %s", me->key, mountpoint); +--- autofs-5.0.6.orig/daemon/indirect.c ++++ autofs-5.0.6/daemon/indirect.c +@@ -87,7 +87,7 @@ static int do_mount_autofs_indirect(stru + { + const char *str_indirect = mount_type_str(t_indirect); + struct ioctl_ops *ops = get_ioctl_ops(); +- time_t timeout = ap->exp_timeout; ++ time_t timeout = ap->entry->maps->exp_timeout; + char *options = NULL; + const char *hosts_map_name = "-hosts"; + const char *map_name = hosts_map_name; +@@ -170,13 +170,12 @@ static int do_mount_autofs_indirect(stru + } + + ap->dev = st.st_dev; /* Device number for mount point checks */ +- ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO; + + ops->timeout(ap->logopt, ap->ioctlfd, timeout); + if (ap->logopt & LOGOPT_DEBUG) +- notify_mount_result(ap, root, str_indirect); ++ notify_mount_result(ap, root, timeout, str_indirect); + else +- notify_mount_result(ap, ap->path, str_indirect); ++ notify_mount_result(ap, ap->path, timeout, str_indirect); + + return 0; + +--- autofs-5.0.6.orig/daemon/lookup.c ++++ autofs-5.0.6/daemon/lookup.c +@@ -413,6 +413,7 @@ static enum nsswitch_status read_map_sou + tmap.lookup = map->lookup; + tmap.mc = map->mc; + tmap.instance = map->instance; ++ tmap.exp_timeout = map->exp_timeout; + tmap.recurse = map->recurse; + tmap.depth = map->depth; + tmap.stale = map->stale; +@@ -770,6 +771,7 @@ static enum nsswitch_status lookup_map_n + tmap.format = map->format; + tmap.mc = map->mc; + tmap.instance = map->instance; ++ tmap.exp_timeout = map->exp_timeout; + tmap.recurse = map->recurse; + tmap.depth = map->depth; + tmap.argc = 0; +--- autofs-5.0.6.orig/daemon/state.c ++++ autofs-5.0.6/daemon/state.c +@@ -400,6 +400,9 @@ static void do_readmap_mount(struct auto + } + if (valid) { + struct mapent_cache *vmc = valid->mc; ++ struct ioctl_ops *ops = get_ioctl_ops(); ++ time_t runfreq; ++ + cache_unlock(vmc); + debug(ap->logopt, + "updating cache entry for valid direct trigger %s", +@@ -412,13 +415,22 @@ static void do_readmap_mount(struct auto + /* Set device and inode number of the new mapent */ + cache_set_ino_index(vmc, me->key, me->dev, me->ino); + cache_unlock(vmc); ++ /* Set timeout and calculate the expire run frequency */ ++ ops->timeout(ap->logopt, valid->ioctlfd, map->exp_timeout); ++ if (map->exp_timeout) { ++ runfreq = (map->exp_timeout + CHECK_RATIO - 1) / CHECK_RATIO; ++ if (ap->exp_runfreq) ++ ap->exp_runfreq = min(ap->exp_runfreq, runfreq); ++ else ++ ap->exp_runfreq = runfreq; ++ } + } else if (!tree_is_mounted(mnts, me->key, MNTS_REAL)) + do_umount_autofs_direct(ap, mnts, me); + else + debug(ap->logopt, + "%s is mounted", me->key); + } else +- do_mount_autofs_direct(ap, mnts, me); ++ do_mount_autofs_direct(ap, mnts, me, map->exp_timeout); + + return; + } +@@ -466,6 +478,10 @@ static void *do_readmap(void *arg) + pthread_cleanup_pop(1); + + if (ap->type == LKP_INDIRECT) { ++ struct ioctl_ops *ops = get_ioctl_ops(); ++ time_t timeout = ap->entry->maps->exp_timeout; ++ ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO; ++ ops->timeout(ap->logopt, ap->ioctlfd, timeout); + lookup_prune_cache(ap, now); + status = lookup_ghost(ap, ap->path); + } else { +--- autofs-5.0.6.orig/include/automount.h ++++ autofs-5.0.6/include/automount.h +@@ -114,6 +114,8 @@ int load_autofs4_module(void); + #define DB(x) do { } while(0) + #endif + ++#define min(a, b) (a <= b ? a : b) ++ + /* Forward declaraion */ + struct autofs_point; + +@@ -461,7 +463,6 @@ struct autofs_point { + dev_t dev; /* "Device" number assigned by kernel */ + struct master_mapent *entry; /* Master map entry for this mount */ + unsigned int type; /* Type of map direct or indirect */ +- time_t exp_timeout; /* Timeout for expiring mounts */ + time_t exp_runfreq; /* Frequency for polling for timeouts */ + time_t negative_timeout; /* timeout in secs for failed mounts */ + unsigned int flags; /* autofs mount flags */ +@@ -495,7 +496,7 @@ void *expire_proc_indirect(void *); + void *expire_proc_direct(void *); + int expire_offsets_direct(struct autofs_point *ap, struct mapent *me, int now); + int mount_autofs_indirect(struct autofs_point *ap, const char *root); +-int do_mount_autofs_direct(struct autofs_point *ap, struct mnt_list *mnts, struct mapent *me); ++int do_mount_autofs_direct(struct autofs_point *ap, struct mnt_list *mnts, struct mapent *me, time_t timeout); + int mount_autofs_direct(struct autofs_point *ap); + int mount_autofs_offset(struct autofs_point *ap, struct mapent *me, const char *root, const char *offset); + void submount_signal_parent(struct autofs_point *ap, unsigned int success); +--- autofs-5.0.6.orig/include/master.h ++++ autofs-5.0.6/include/master.h +@@ -23,6 +23,7 @@ + struct map_source { + char *type; + char *format; ++ time_t exp_timeout; /* Timeout for expiring mounts */ + time_t age; + unsigned int master_line; + struct mapent_cache *mc; +@@ -78,7 +79,7 @@ void master_mutex_unlock(void); + void master_mutex_lock_cleanup(void *); + void master_set_default_timeout(void); + void master_set_default_ghost_mode(void); +-int master_add_autofs_point(struct master_mapent *, time_t, unsigned, unsigned, unsigned, int); ++int master_add_autofs_point(struct master_mapent *, unsigned, unsigned, unsigned, int); + void master_free_autofs_point(struct autofs_point *); + struct map_source * + master_add_map_source(struct master_mapent *, char *, char *, time_t, int, const char **); +--- autofs-5.0.6.orig/include/mounts.h ++++ autofs-5.0.6/include/mounts.h +@@ -120,7 +120,7 @@ int tree_find_mnt_ents(struct mnt_list * + int tree_is_mounted(struct mnt_list *mnts, const char *path, unsigned int type); + void set_tsd_user_vars(unsigned int, uid_t, gid_t); + const char *mount_type_str(unsigned int); +-void notify_mount_result(struct autofs_point *, const char *, const char *); ++void notify_mount_result(struct autofs_point *, const char *, time_t, const char *); + int try_remount(struct autofs_point *, struct mapent *, unsigned int); + int umount_ent(struct autofs_point *, const char *); + int mount_multi_triggers(struct autofs_point *, struct mapent *, const char *, unsigned int, const char *); +--- autofs-5.0.6.orig/lib/master.c ++++ autofs-5.0.6/lib/master.c +@@ -65,9 +65,8 @@ void master_mutex_lock_cleanup(void *arg + return; + } + +-int master_add_autofs_point(struct master_mapent *entry, time_t timeout, +- unsigned logopt, unsigned nobind, unsigned ghost, +- int submount) ++int master_add_autofs_point(struct master_mapent *entry, unsigned logopt, ++ unsigned nobind, unsigned ghost, int submount) + { + struct autofs_point *ap; + int status; +@@ -91,7 +90,6 @@ int master_add_autofs_point(struct maste + ap->entry = entry; + ap->exp_thread = 0; + ap->readmap_thread = 0; +- ap->exp_timeout = timeout; + /* + * Program command line option overrides config. + * We can't use 0 negative timeout so use default. +@@ -100,7 +98,7 @@ int master_add_autofs_point(struct maste + ap->negative_timeout = defaults_get_negative_timeout(); + else + ap->negative_timeout = global_negative_timeout; +- ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO; ++ ap->exp_runfreq = 0; + ap->flags = 0; + if (ghost) + ap->flags = MOUNT_FLAG_GHOST; +@@ -437,6 +435,7 @@ master_add_source_instance(struct map_so + new->age = age; + new->master_line = 0; + new->mc = source->mc; ++ new->exp_timeout = source->exp_timeout; + new->stale = 1; + + tmpargv = copy_argv(argc, argv); +--- autofs-5.0.6.orig/lib/master_parse.y ++++ autofs-5.0.6/lib/master_parse.y +@@ -765,9 +765,6 @@ int master_parse_entry(const char *buffe + logopt |= (verbose ? LOGOPT_VERBOSE : 0); + } + +- if (timeout < 0) +- timeout = default_timeout; +- + new = NULL; + entry = master_find_mapent(master, path); + if (!entry) { +@@ -789,8 +786,19 @@ int master_parse_entry(const char *buffe + } + } + ++ if (timeout < 0) { ++ /* ++ * If no timeout is given get the timout from first ++ * map (if it exists). ++ */ ++ if (entry->maps) ++ timeout = entry->maps->exp_timeout; ++ else ++ timeout = default_timeout; ++ } ++ + if (!entry->ap) { +- ret = master_add_autofs_point(entry, timeout, logopt, nobind, ghost, 0); ++ ret = master_add_autofs_point(entry, logopt, nobind, ghost, 0); + if (!ret) { + error(m_logopt, "failed to add autofs_point"); + if (new) +@@ -798,20 +806,6 @@ int master_parse_entry(const char *buffe + local_free_vars(); + return 0; + } +- } else { +- struct ioctl_ops *ops = get_ioctl_ops(); +- struct autofs_point *ap = entry->ap; +- +- /* +- * Second and subsequent instances of a mount point +- * use the ghost, log and timeout of the first +- */ +- if (entry->age < age) { +- ap->exp_timeout = timeout; +- ap->exp_runfreq = (ap->exp_timeout + CHECK_RATIO - 1) / CHECK_RATIO; +- if (ap->ioctlfd != -1 && ap->type == LKP_INDIRECT) +- ops->timeout(ap->logopt, ap->ioctlfd, timeout); +- } + } + if (random_selection) + entry->ap->flags |= MOUNT_FLAG_RANDOM_SELECT; +@@ -838,7 +832,7 @@ int master_parse_entry(const char *buffe + local_free_vars(); + return 0; + } +- ++ source->exp_timeout = timeout; + source->master_line = lineno; + + entry->age = age; +--- autofs-5.0.6.orig/lib/mounts.c ++++ autofs-5.0.6/lib/mounts.c +@@ -1268,13 +1268,12 @@ const char *mount_type_str(const unsigne + } + + void notify_mount_result(struct autofs_point *ap, +- const char *path, const char *type) ++ const char *path, time_t timeout, const char *type) + { +- if (ap->exp_timeout) ++ if (timeout) + info(ap->logopt, + "mounted %s on %s with timeout %u, freq %u seconds", +- type, path, +- (unsigned int) ap->exp_timeout, ++ type, path, (unsigned int) timeout, + (unsigned int) ap->exp_runfreq); + else + info(ap->logopt, +@@ -1382,16 +1381,14 @@ static int do_remount_indirect(struct au + } + + static int remount_active_mount(struct autofs_point *ap, +- struct mapent_cache *mc, +- const char *path, dev_t devid, +- const unsigned int type, +- int *ioctlfd) ++ struct mapent *me, const char *path, dev_t devid, ++ const unsigned int type, int *ioctlfd) + { + struct ioctl_ops *ops = get_ioctl_ops(); +- time_t timeout = ap->exp_timeout; + const char *str_type = mount_type_str(type); + char buf[MAX_ERR_BUF]; + unsigned int mounted; ++ time_t timeout; + struct stat st; + int fd; + +@@ -1401,6 +1398,12 @@ static int remount_active_mount(struct a + ops->open(ap->logopt, &fd, devid, path); + if (fd == -1) + return REMOUNT_OPEN_FAIL; ++ else { ++ if (type == t_indirect || type == t_offset) ++ timeout = ap->entry->maps->exp_timeout; ++ else ++ timeout = me->source->exp_timeout; ++ } + + /* Re-reading the map, set timeout and return */ + if (ap->state == ST_READMAP) { +@@ -1434,11 +1437,11 @@ static int remount_active_mount(struct a + ops->close(ap->logopt, fd); + return REMOUNT_STAT_FAIL; + } +- if (mc) +- cache_set_ino_index(mc, path, st.st_dev, st.st_ino); ++ if (type != t_indirect) ++ cache_set_ino_index(me->mc, path, st.st_dev, st.st_ino); + else + ap->dev = st.st_dev; +- notify_mount_result(ap, path, str_type); ++ notify_mount_result(ap, path, timeout, str_type); + + *ioctlfd = fd; + +@@ -1481,24 +1484,20 @@ static int remount_active_mount(struct a + int try_remount(struct autofs_point *ap, struct mapent *me, unsigned int type) + { + struct ioctl_ops *ops = get_ioctl_ops(); +- struct mapent_cache *mc; + const char *path; + int ret, fd; + dev_t devid; + +- if (type == t_indirect) { +- mc = NULL; ++ if (type == t_indirect) + path = ap->path; +- } else { +- mc = me->mc; ++ else + path = me->key; +- } + + ret = ops->mount_device(ap->logopt, path, type, &devid); + if (ret == -1 || ret == 0) + return -1; + +- ret = remount_active_mount(ap, mc, path, devid, type, &fd); ++ ret = remount_active_mount(ap, me, path, devid, type, &fd); + + /* + * The directory must exist since we found a device +--- autofs-5.0.6.orig/modules/mount_autofs.c ++++ autofs-5.0.6/modules/mount_autofs.c +@@ -51,7 +51,7 @@ int mount_mount(struct autofs_point *ap, + int argc, status; + int nobind = ap->flags & MOUNT_FLAG_NOBIND; + int ghost = ap->flags & MOUNT_FLAG_GHOST; +- time_t timeout = ap->exp_timeout; ++ time_t timeout = ap->entry->maps->exp_timeout; + unsigned logopt = ap->logopt; + struct map_type_info *info; + struct master *master; +@@ -149,7 +149,7 @@ int mount_mount(struct autofs_point *ap, + return 1; + } + +- ret = master_add_autofs_point(entry, timeout, logopt, nobind, ghost, 1); ++ ret = master_add_autofs_point(entry, logopt, nobind, ghost, 1); + if (!ret) { + error(ap->logopt, + MODPREFIX "failed to add autofs_point to entry"); +@@ -203,6 +203,7 @@ int mount_mount(struct autofs_point *ap, + return 1; + } + free_map_type_info(info); ++ source->exp_timeout = timeout; + + mounts_mutex_lock(ap); + diff --git a/autofs-5.0.6-refactor-lookup-hosts-module.patch b/autofs-5.0.6-refactor-lookup-hosts-module.patch new file mode 100644 index 0000000..ecc18be --- /dev/null +++ b/autofs-5.0.6-refactor-lookup-hosts-module.patch @@ -0,0 +1,248 @@ +autofs-5.0.6 - refactor hosts lookup module + +From: Ian Kent + +Simplify lookup hosts lookup_mount() function. +--- + + modules/lookup_hosts.c | 206 ++++++++++++++++++++++++------------------------- + 1 file changed, 101 insertions(+), 105 deletions(-) + + +--- autofs-5.0.6.orig/modules/lookup_hosts.c ++++ autofs-5.0.6/modules/lookup_hosts.c +@@ -78,6 +78,94 @@ int lookup_read_master(struct master *ma + return NSS_STATUS_UNKNOWN; + } + ++static char *get_exports(struct autofs_point *ap, const char *host) ++{ ++ char *mapent = NULL; ++ exports exp; ++ ++ debug(ap->logopt, MODPREFIX "fetchng export list for %s", name); ++ ++ exp = rpc_get_exports(host, 10, 0, RPC_CLOSE_NOLINGER); ++ ++ mapent = NULL; ++ while (exp) { ++ if (mapent) { ++ int len = strlen(mapent) + 1; ++ ++ len += strlen(name) + 2*(strlen(exp->ex_dir) + 2) + 3; ++ mapent = realloc(mapent, len); ++ if (!mapent) { ++ char *estr; ++ estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ error(ap->logopt, MODPREFIX "malloc: %s", estr); ++ rpc_exports_free(exp); ++ return NSS_STATUS_UNAVAIL; ++ } ++ strcat(mapent, " \""); ++ strcat(mapent, exp->ex_dir); ++ strcat(mapent, "\""); ++ } else { ++ int len = 2*(strlen(exp->ex_dir) + 2) + strlen(name) + 3; ++ ++ mapent = malloc(len); ++ if (!mapent) { ++ char *estr; ++ estr = strerror_r(errno, buf, MAX_ERR_BUF); ++ error(ap->logopt, MODPREFIX "malloc: %s", estr); ++ rpc_exports_free(exp); ++ return NSS_STATUS_UNAVAIL; ++ } ++ strcpy(mapent, "\""); ++ strcat(mapent, exp->ex_dir); ++ strcat(mapent, "\""); ++ } ++ strcat(mapent, " \""); ++ strcat(mapent, name); ++ strcat(mapent, ":"); ++ strcat(mapent, exp->ex_dir); ++ strcat(mapent, "\""); ++ ++ exp = exp->ex_next; ++ } ++ rpc_exports_free(exp); ++ ++ if (!mapent) ++ error(ap->logopt, "exports lookup failed for %s", name); ++ ++ return mapent; ++} ++ ++static int do_parse_mount(struct autofs_point *ap, ++ const char *name, int name_len, char *mapent, ++ void *context) ++{ ++ int ret; ++ ++ master_source_current_wait(ap->entry); ++ ap->entry->current = source; ++ ++ ret = ctxt->parse->parse_mount(ap, name, name_len, ++ mapent, ctxt->parse->context); ++ if (ret) { ++ time_t now = time(NULL); ++ struct mapent_cache *mc = source->mc; ++ struct mapent *me; ++ int rv = CHE_OK; ++ ++ cache_writelock(mc); ++ me = cache_lookup_distinct(mc, name); ++ if (!me) ++ rv = cache_update(mc, source, name, NULL, now); ++ if (rv != CHE_FAIL) { ++ me = cache_lookup_distinct(mc, name); ++ me->status = now + ap->negative_timeout; ++ } ++ cache_unlock(mc); ++ return NSS_STATUS_TRYAGAIN; ++ } ++ return NSS_STATUS_SUCCESS; ++} ++ + int lookup_read_map(struct autofs_point *ap, time_t age, void *context) + { + struct map_source *source; +@@ -209,126 +297,34 @@ int lookup_mount(struct autofs_point *ap + if (*name == '/') { + pthread_cleanup_push(cache_lock_cleanup, mc); + mapent_len = strlen(me->mapent); +- mapent = alloca(mapent_len + 1); ++ mapent = malloc(mapent_len + 1); + if (mapent) + strcpy(mapent, me->mapent); + pthread_cleanup_pop(0); + } + cache_unlock(mc); + +- if (mapent) { +- master_source_current_wait(ap->entry); +- ap->entry->current = source; +- +- debug(ap->logopt, MODPREFIX "%s -> %s", name, me->mapent); +- +- ret = ctxt->parse->parse_mount(ap, name, name_len, +- mapent, ctxt->parse->context); +- +- if (ret) { +- time_t now = time(NULL); +- int rv = CHE_OK; +- +- cache_writelock(mc); +- me = cache_lookup_distinct(mc, name); +- if (!me) +- rv = cache_update(mc, source, name, NULL, now); +- if (rv != CHE_FAIL) { +- me = cache_lookup_distinct(mc, name); +- me->status = now + ap->negative_timeout; +- } +- cache_unlock(mc); +- return NSS_STATUS_TRYAGAIN; +- } +- return NSS_STATUS_SUCCESS; +- } + done: +- /* +- * Otherwise we need to get the exports list and add update +- * the cache. +- */ +- debug(ap->logopt, MODPREFIX "fetchng export list for %s", name); +- +- exp = rpc_get_exports(name, 10, 0, RPC_CLOSE_NOLINGER); +- +- mapent = NULL; +- while (exp) { +- if (mapent) { +- int len = strlen(mapent) + 1; +- +- len += strlen(name) + 2*(strlen(exp->ex_dir) + 2) + 3; +- mapent = realloc(mapent, len); +- if (!mapent) { +- char *estr; +- estr = strerror_r(errno, buf, MAX_ERR_BUF); +- logerr(MODPREFIX "malloc: %s", estr); +- rpc_exports_free(exp); +- return NSS_STATUS_UNAVAIL; +- } +- strcat(mapent, " \""); +- strcat(mapent, exp->ex_dir); +- strcat(mapent, "\""); +- } else { +- int len = 2*(strlen(exp->ex_dir) + 2) + strlen(name) + 3; +- +- mapent = malloc(len); +- if (!mapent) { +- char *estr; +- estr = strerror_r(errno, buf, MAX_ERR_BUF); +- logerr(MODPREFIX "malloc: %s", estr); +- rpc_exports_free(exp); +- return NSS_STATUS_UNAVAIL; +- } +- strcpy(mapent, "\""); +- strcat(mapent, exp->ex_dir); +- strcat(mapent, "\""); +- } +- strcat(mapent, " \""); +- strcat(mapent, name); +- strcat(mapent, ":"); +- strcat(mapent, exp->ex_dir); +- strcat(mapent, "\""); +- +- exp = exp->ex_next; +- } +- rpc_exports_free(exp); +- +- /* Exports lookup failed so we're outa here */ +- if (!mapent) { +- error(ap->logopt, "exports lookup failed for %s", name); +- return NSS_STATUS_UNAVAIL; +- } +- + debug(ap->logopt, MODPREFIX "%s -> %s", name, mapent); + +- cache_writelock(mc); +- cache_update(mc, source, name, mapent, now); +- cache_unlock(mc); +- +- master_source_current_wait(ap->entry); +- ap->entry->current = source; +- +- ret = ctxt->parse->parse_mount(ap, name, name_len, +- mapent, ctxt->parse->context); +- free(mapent); ++ if (!mapent) { ++ /* We need to get the exports list and update the cache. */ ++ mapent = get_exports(ap, name); + +- if (ret) { +- time_t now = time(NULL); +- int rv = CHE_OK; ++ /* Exports lookup failed so we're outa here */ ++ if (!mapent) ++ return NSS_STATUS_UNAVAIL; + + cache_writelock(mc); +- me = cache_lookup_distinct(mc, name); +- if (!me) +- rv = cache_update(mc, source, name, NULL, now); +- if (rv != CHE_FAIL) { +- me = cache_lookup_distinct(mc, name); +- me->status = now + ap->negative_timeout; +- } ++ cache_update(mc, source, name, mapent, now); + cache_unlock(mc); +- return NSS_STATUS_TRYAGAIN; + } + +- return NSS_STATUS_SUCCESS; ++ ret = do_parse_mount(ap, name, name_len, mapent, ctxt->parse->context); ++ ++ free(mapent); ++ ++ return ret; + } + + int lookup_done(void *context) diff --git a/autofs-5.0.6-remove-cache-update-from-parse_mount.patch b/autofs-5.0.6-remove-cache-update-from-parse_mount.patch new file mode 100644 index 0000000..3024b84 --- /dev/null +++ b/autofs-5.0.6-remove-cache-update-from-parse_mount.patch @@ -0,0 +1,47 @@ +autofs-5.0.6 - remove cache update from parse_mount() + +From: Ian Kent + +I'm not sure why I added this update in the parse sun module. + +The lookup modules have the job of updating the map entry cache and +I can't see why an entry would be missing since the parse function +is called following the entry lookup (which does the update). +--- + + modules/parse_sun.c | 23 ----------------------- + 1 file changed, 23 deletions(-) + + +--- autofs-5.0.6.orig/modules/parse_sun.c ++++ autofs-5.0.6/modules/parse_sun.c +@@ -1383,29 +1383,6 @@ int parse_mount(struct autofs_point *ap, + strcat(m_root, name); + } + +- /* +- * Can't take the write lock for direct mount entries here +- * but they should always be present in the map entry cache. +- */ +- if (ap->type == LKP_INDIRECT) { +- cache_writelock(mc); +- me = cache_lookup_distinct(mc, name); +- if (!me) { +- int ret; +- /* +- * Not in the cache, perhaps it's a program map +- * or one that doesn't support enumeration. +- */ +- ret = cache_add(mc, source, name, mapent, age); +- if (ret == CHE_FAIL) { +- cache_unlock(mc); +- free(options); +- return 1; +- } +- } +- cache_unlock(mc); +- } +- + cache_readlock(mc); + me = cache_lookup_distinct(mc, name); + if (me) { diff --git a/autofs-5.0.6-remove-move-mount-code-and-configure-option.patch b/autofs-5.0.6-remove-move-mount-code-and-configure-option.patch new file mode 100644 index 0000000..16113b2 --- /dev/null +++ b/autofs-5.0.6-remove-move-mount-code-and-configure-option.patch @@ -0,0 +1,421 @@ +autofs-5.0.6 - remove move mount code and configure option + +From: Ian Kent + +The code to construct a multi-mount tree in a temporary location and then +move it into place is obsolete when using a kernel which includes the +vfs-automount infrastructure. + +It is incompatible with systemd and cannot be used if systemd is being used. + +So it's being removed. +--- + + autofs.spec | 2 + configure | 18 ---- + configure.in | 10 -- + daemon/automount.c | 5 - + include/config.h.in | 3 + modules/parse_sun.c | 195 +--------------------------------------------------- + 6 files changed, 7 insertions(+), 226 deletions(-) + + +--- autofs-5.0.6.orig/autofs.spec ++++ autofs-5.0.6/autofs.spec +@@ -74,7 +74,7 @@ echo %{version}-%{release} > .version + %endif + + %build +-CFLAGS="$RPM_OPT_FLAGS -Wall" ./configure --libdir=%{_libdir} --disable-mount-locking --enable-ignore-busy --with-libtirpc --disable-mount-move %{?systemd_configure_arg:} ++CFLAGS="$RPM_OPT_FLAGS -Wall" ./configure --libdir=%{_libdir} --disable-mount-locking --enable-ignore-busy --with-libtirpc %{?systemd_configure_arg:} + CFLAGS="$RPM_OPT_FLAGS -Wall" make initdir=/etc/rc.d/init.d DONTSTRIP=1 + + %install +--- autofs-5.0.6.orig/configure ++++ autofs-5.0.6/configure +@@ -719,7 +719,6 @@ with_openldap + with_sasl + enable_ext_env + enable_mount_locking +-enable_mount_move + enable_forced_shutdown + enable_ignore_busy + ' +@@ -1343,7 +1342,6 @@ Optional Features: + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --disable-ext-env disable search in environment for substitution variable + --disable-mount-locking disable use of locking when spawning mount command +- --disable-mount-move disable use of mount move when when preparing tree of mounts + --enable-force-shutdown enable USR1 signal to force unlink umount of any + busy mounts during shutdown + --enable-ignore-busy enable exit without umounting busy mounts during +@@ -5447,22 +5445,6 @@ $as_echo "#define ENABLE_MOUNT_LOCKING 1 + + fi + +-# +-# Disable use of mount move +-# +-# Check whether --enable-mount-move was given. +-if test "${enable_mount_move+set}" = set; then : +- enableval=$enable_mount_move; +-else +- enableval=yes +-fi +- +-if test x$enable_mount_move = xyes -o x$enableval = xyes; then +- +-$as_echo "#define ENABLE_MOUNT_MOVE 1" >>confdefs.h +- +-fi +- + # + # Enable forced shutdown on USR1 signal (unlink umounts all mounts). + # +--- autofs-5.0.6.orig/configure.in ++++ autofs-5.0.6/configure.in +@@ -338,16 +338,6 @@ if test x$enable_mount_locking = xyes -o + fi + + # +-# Disable use of mount move +-# +-AC_ARG_ENABLE(mount-move, +-[ --disable-mount-move disable use of mount move when when preparing tree of mounts],, +- enableval=yes) +-if test x$enable_mount_move = xyes -o x$enableval = xyes; then +- AC_DEFINE(ENABLE_MOUNT_MOVE, 1, [Disable use of mount move when preparing tree of mounts]) +-fi +- +-# + # Enable forced shutdown on USR1 signal (unlink umounts all mounts). + # + AC_ARG_ENABLE(forced-shutdown, +--- autofs-5.0.6.orig/daemon/automount.c ++++ autofs-5.0.6/daemon/automount.c +@@ -1748,11 +1748,6 @@ static void show_build_info(void) + count = 22; + #endif + +-#ifndef ENABLE_MOUNT_MOVE +- printf("DISABLE_MOUNT_MOVE "); +- count = count + 19; +-#endif +- + #ifdef ENABLE_FORCED_SHUTDOWN + printf("ENABLE_FORCED_SHUTDOWN "); + count = count + 23; +--- autofs-5.0.6.orig/include/config.h.in ++++ autofs-5.0.6/include/config.h.in +@@ -12,9 +12,6 @@ + /* Disable use of locking when spawning mount command */ + #undef ENABLE_MOUNT_LOCKING + +-/* Disable use of mount move when preparing tree of mounts */ +-#undef ENABLE_MOUNT_MOVE +- + /* define if you have E2FSCK */ + #undef HAVE_E2FSCK + +--- autofs-5.0.6.orig/modules/parse_sun.c ++++ autofs-5.0.6/modules/parse_sun.c +@@ -37,10 +37,6 @@ + + #define MODPREFIX "parse(sun): " + +-#define MOUNT_MOVE_NONE 0x00 +-#define MOUNT_MOVE_AUTOFS 0x01 +-#define MOUNT_MOVE_OTHER 0x02 +- + int parse_version = AUTOFS_PARSE_VERSION; /* Required by protocol */ + + static struct mount_mod *mount_nfs = NULL; +@@ -1047,86 +1043,6 @@ static int parse_mapent(const char *ent, + return (p - ent); + } + +-#ifdef ENABLE_MOUNT_MOVE +-static int move_mount(struct autofs_point *ap, +- const char *mm_tmp_root, const char *mm_root, +- unsigned int move) +-{ +- char buf[MAX_ERR_BUF]; +- int err; +- +- if (move == MOUNT_MOVE_NONE) +- return 1; +- +- err = mkdir_path(mm_root, 0555); +- if (err < 0 && errno != EEXIST) { +- error(ap->logopt, +- "failed to create move target mount point %s", mm_root); +- return 0; +- } +- +- if (move == MOUNT_MOVE_AUTOFS) +- err = mount(mm_tmp_root, mm_root, NULL, MS_MOVE, NULL); +- else +- err = spawn_mount(ap->logopt, +- "--move", mm_tmp_root, mm_root, NULL); +- if (err) { +- char *estr = strerror_r(errno, buf, MAX_ERR_BUF); +- error(ap->logopt, +- "failed to move mount from %s to %s: %s", +- mm_tmp_root, mm_root, estr); +- return 0; +- } +- +- debug(ap->logopt, +- "moved mount tree from %s to %s", mm_tmp_root, mm_root); +- +- return 1; +-} +-#endif +- +-static void cleanup_multi_root(struct autofs_point *ap, const char *root, +- const char *path, unsigned int move) +-{ +- if (move == MOUNT_MOVE_NONE) +- return; +- +- if (move == MOUNT_MOVE_OTHER) +- spawn_umount(ap->logopt, root, NULL); +- else { +- struct ioctl_ops *ops = get_ioctl_ops(); +- struct autofs_point *submount; +- +- mounts_mutex_lock(ap); +- submount = __master_find_submount(ap, path); +- if (!submount) { +- mounts_mutex_unlock(ap); +- return; +- } +- +- alarm_delete(submount); +- st_remove_tasks(submount); +- st_wait_state(submount, ST_READY); +- +- submount->parent->submnt_count--; +- list_del_init(&submount->mounts); +- +- ops->catatonic(submount->logopt, submount->ioctlfd); +- +- mounts_mutex_unlock(ap); +- +- if (submount->thid) { +- pthread_cancel(submount->thid); +- close_mount_fds(submount); +- umount(root); +- destroy_logpri_fifo(submount); +- master_free_mapent_sources(submount->entry, 1); +- master_free_mapent(ap->entry); +- } +- } +- return; +-} +- + static void cleanup_multi_triggers(struct autofs_point *ap, + struct mapent *me, const char *root, int start, + const char *base) +@@ -1166,49 +1082,15 @@ static void cleanup_multi_triggers(struc + return; + } + +-#ifdef ENABLE_MOUNT_MOVE +-static int check_fstype_autofs_option(const char *options) +-{ +- char *tok, *tokbuf; +- int found; +- +- /* +- * Look for fstype= in options and return true if +- * the last occurrence is fstype=autofs. +- */ +- found = 0; +- tokbuf = alloca(strlen(options) + 2); +- strcpy(tokbuf, options); +- tok = strtok_r(tokbuf, ",", &tokbuf); +- if (tok) { +- do { +- if (strstr(tok, "fstype=")) { +- if (strstr(tok, "autofs")) +- found = 1; +- else +- found = 0; +- } +- } while ((tok = strtok_r(NULL, ",", &tokbuf))); +- } +- +- return found; +-} +-#endif +- + static int mount_subtree(struct autofs_point *ap, struct mapent *me, + const char *name, char *loc, char *options, void *ctxt) + { + struct mapent *mm; + struct mapent *ro; + char *mm_root, *mm_base, *mm_key; +- const char *mnt_root, *target; ++ const char *mnt_root; + unsigned int mm_root_len, mnt_root_len; + int start, ret = 0, rv; +- unsigned int move = MOUNT_MOVE_NONE; +-#ifdef ENABLE_MOUNT_MOVE +- char t_dir[] = "/tmp/autoXXXXXX"; +- char *mnt_tmp_root = NULL; +-#endif + + rv = 0; + +@@ -1227,26 +1109,12 @@ static int mount_subtree(struct autofs_p + } + mm_root_len = strlen(mm_root); + +-#ifndef ENABLE_MOUNT_MOVE + mnt_root = mm_root; + mnt_root_len = mm_root_len; +-#else +- if (ap->flags & MOUNT_FLAG_REMOUNT) { +- mnt_root = mm_root; +- mnt_root_len = mm_root_len; +- } else { +- mnt_root = mkdtemp(t_dir); +- if (!mnt_root) +- return 1; +- mnt_root_len = strlen(mnt_root); +- mnt_tmp_root = (char *) mnt_root; +- } +-#endif + + if (me == me->multi) { + /* name = NULL */ + /* destination = mm_root */ +- target = mm_root; + mm_base = "/"; + + /* Mount root offset if it exists */ +@@ -1263,18 +1131,10 @@ static int mount_subtree(struct autofs_p + warn(ap->logopt, + MODPREFIX "failed to parse root offset"); + cache_delete_offset_list(me->mc, name); +- goto error_out; ++ return 1; + } + ro_len = strlen(ro_loc); + +-#ifdef ENABLE_MOUNT_MOVE +- if (!(ap->flags & MOUNT_FLAG_REMOUNT)) { +- move = MOUNT_MOVE_OTHER; +- if (check_fstype_autofs_option(myoptions)) +- move = MOUNT_MOVE_AUTOFS; +- } +-#endif +- + tmp = alloca(mnt_root_len + 1); + strcpy(tmp, mnt_root); + tmp[mnt_root_len] = '/'; +@@ -1293,44 +1153,25 @@ static int mount_subtree(struct autofs_p + error(ap->logopt, MODPREFIX + "failed to mount offset triggers"); + cleanup_multi_triggers(ap, me, mnt_root, start, mm_base); +- cleanup_multi_root(ap, mnt_root, mm_root, move); +- goto error_out; ++ return 1; + } + } else if (rv <= 0) { +-#ifdef ENABLE_MOUNT_MOVE +- move = MOUNT_MOVE_NONE; +-#endif + ret = mount_multi_triggers(ap, me, mm_root, start, mm_base); + if (ret == -1) { + error(ap->logopt, MODPREFIX + "failed to mount offset triggers"); + cleanup_multi_triggers(ap, me, mm_root, start, mm_base); +- goto error_out; ++ return 1; + } + } + } else { + int loclen = strlen(loc); + int namelen = strlen(name); + +-#ifndef ENABLE_MOUNT_MOVE +- /* +- * When using move mount to mount offsets or direct mounts +- * the base of the tree can be the base of the temporary +- * mount point it needs to be the full path when not moving +- * the mount after construction. +- */ + mnt_root = name; +-#else +- if (!(ap->flags & MOUNT_FLAG_REMOUNT)) { +- move = MOUNT_MOVE_OTHER; +- if (check_fstype_autofs_option(options)) +- move = MOUNT_MOVE_AUTOFS; +- } +-#endif + + /* name = mm_root + mm_base */ + /* destination = mm_root + mm_base = name */ +- target = name; + mm_base = &me->key[start]; + + rv = sun_mount(ap, mnt_root, name, namelen, loc, loclen, options, ctxt); +@@ -1340,16 +1181,11 @@ static int mount_subtree(struct autofs_p + error(ap->logopt, MODPREFIX + "failed to mount offset triggers"); + cleanup_multi_triggers(ap, me, mnt_root, start, mm_base); +- cleanup_multi_root(ap, mnt_root, mm_root, move); +- goto error_out; ++ return 1; + } + } else if (rv < 0) { + char *mm_root_base = alloca(strlen(mm_root) + strlen(mm_base) + 1); + +-#ifdef ENABLE_MOUNT_MOVE +- move = MOUNT_MOVE_NONE; +-#endif +- + strcpy(mm_root_base, mm_root); + strcat(mm_root_base, mm_base); + +@@ -1358,22 +1194,11 @@ static int mount_subtree(struct autofs_p + error(ap->logopt, MODPREFIX + "failed to mount offset triggers"); + cleanup_multi_triggers(ap, me, mm_root, start, mm_base); +- goto error_out; ++ return 1; + } + } + } + +-#ifdef ENABLE_MOUNT_MOVE +- if (!move_mount(ap, mnt_root, target, move)) { +- cleanup_multi_triggers(ap, me, mnt_root, start, mm_base); +- cleanup_multi_root(ap, mnt_root, mm_root, move); +- goto error_out; +- } +- +- if (mnt_tmp_root) +- rmdir(mnt_tmp_root); +-#endif +- + /* Mount for base of tree failed */ + if (rv > 0) + return rv; +@@ -1386,14 +1211,6 @@ static int mount_subtree(struct autofs_p + rv = 0; + + return rv; +- +-error_out: +-#ifdef ENABLE_MOUNT_MOVE +- if (mnt_tmp_root) +- rmdir(mnt_tmp_root); +-#endif +- +- return 1; + } + + /* diff --git a/autofs-5.0.6-report-map-not-read-when-debug-logging.patch b/autofs-5.0.6-report-map-not-read-when-debug-logging.patch new file mode 100644 index 0000000..8c14346 --- /dev/null +++ b/autofs-5.0.6-report-map-not-read-when-debug-logging.patch @@ -0,0 +1,99 @@ +autofs-5.0.6 - report map not read when debug logging + +From: Ian Kent + +When a map read is called automount will report that is is reading the +map when debug logging is set. If a map read is not actually needed the +lookup module read map function should also report that it didn't need +to read the map. +--- + + CHANGELOG | 1 + + modules/lookup_hosts.c | 4 +++- + modules/lookup_ldap.c | 4 +++- + modules/lookup_nisplus.c | 4 +++- + modules/lookup_sss.c | 4 +++- + modules/lookup_yp.c | 4 +++- + 6 files changed, 16 insertions(+), 5 deletions(-) + + +--- autofs-5.0.6.orig/CHANGELOG ++++ autofs-5.0.6/CHANGELOG +@@ -42,6 +42,7 @@ + - fix configure string length tests for sss library. + - fix initialization in rpc create_client(). + - fix libtirpc name clash. ++- report map not read when debug logging. + + 28/06/2011 autofs-5.0.6 + ----------------------- +--- autofs-5.0.6.orig/modules/lookup_hosts.c ++++ autofs-5.0.6/modules/lookup_hosts.c +@@ -94,8 +94,10 @@ int lookup_read_map(struct autofs_point + * reading the map. We always need to read the whole map for + * direct mounts in order to mount the triggers. + */ +- if (!(ap->flags & MOUNT_FLAG_GHOST) && ap->type != LKP_DIRECT) ++ if (!(ap->flags & MOUNT_FLAG_GHOST) && ap->type != LKP_DIRECT) { ++ debug(ap->logopt, "map read not needed, so not done"); + return NSS_STATUS_SUCCESS; ++ } + + mc = source->mc; + +--- autofs-5.0.6.orig/modules/lookup_ldap.c ++++ autofs-5.0.6/modules/lookup_ldap.c +@@ -2326,8 +2326,10 @@ static int read_one_map(struct autofs_po + * reading the map. We always need to read the whole map for + * direct mounts in order to mount the triggers. + */ +- if (!(ap->flags & MOUNT_FLAG_GHOST) && ap->type != LKP_DIRECT) ++ if (!(ap->flags & MOUNT_FLAG_GHOST) && ap->type != LKP_DIRECT) { ++ debug(ap->logopt, "map read not needed, so not done"); + return NSS_STATUS_SUCCESS; ++ } + + sp.ap = ap; + sp.age = age; +--- autofs-5.0.6.orig/modules/lookup_nisplus.c ++++ autofs-5.0.6/modules/lookup_nisplus.c +@@ -185,8 +185,10 @@ int lookup_read_map(struct autofs_point + * reading the map. We always need to read the whole map for + * direct mounts in order to mount the triggers. + */ +- if (!(ap->flags & MOUNT_FLAG_GHOST) && ap->type != LKP_DIRECT) ++ if (!(ap->flags & MOUNT_FLAG_GHOST) && ap->type != LKP_DIRECT) { ++ debug(ap->logopt, "map read not needed, so not done"); + return NSS_STATUS_SUCCESS; ++ } + + mc = source->mc; + +--- autofs-5.0.6.orig/modules/lookup_sss.c ++++ autofs-5.0.6/modules/lookup_sss.c +@@ -275,8 +275,10 @@ int lookup_read_map(struct autofs_point + * reading the map. We always need to read the whole map for + * direct mounts in order to mount the triggers. + */ +- if (!(ap->flags & MOUNT_FLAG_GHOST) && ap->type != LKP_DIRECT) ++ if (!(ap->flags & MOUNT_FLAG_GHOST) && ap->type != LKP_DIRECT) { ++ debug(ap->logopt, "map read not needed, so not done"); + return NSS_STATUS_SUCCESS; ++ } + + if (!setautomntent(ap->logopt, ctxt, ctxt->mapname, &sss_ctxt)) + return NSS_STATUS_UNAVAIL; +--- autofs-5.0.6.orig/modules/lookup_yp.c ++++ autofs-5.0.6/modules/lookup_yp.c +@@ -327,8 +327,10 @@ int lookup_read_map(struct autofs_point + * reading the map. We always need to read the whole map for + * direct mounts in order to mount the triggers. + */ +- if (!(ap->flags & MOUNT_FLAG_GHOST) && ap->type != LKP_DIRECT) ++ if (!(ap->flags & MOUNT_FLAG_GHOST) && ap->type != LKP_DIRECT) { ++ debug(ap->logopt, "map read not needed, so not done"); + return NSS_STATUS_SUCCESS; ++ } + + ypcb_data.ap = ap; + ypcb_data.source = source; diff --git a/autofs-5.0.6-update-timeout-function-to-not-return-timeout.patch b/autofs-5.0.6-update-timeout-function-to-not-return-timeout.patch new file mode 100644 index 0000000..d5f8a37 --- /dev/null +++ b/autofs-5.0.6-update-timeout-function-to-not-return-timeout.patch @@ -0,0 +1,171 @@ +autofs-5.0.6 - update ->timeout() function to not return timeout + +From: Ian Kent + +The value returned by the ->timeout() autofs control interface +function is not used so make that usage explict by not using a +pass by address parameter. This saves having to take care to +always use a temporary storage location when using the function. +--- + + CHANGELOG | 1 + + daemon/direct.c | 6 +++--- + daemon/indirect.c | 2 +- + include/dev-ioctl-lib.h | 2 +- + lib/dev-ioctl-lib.c | 15 +++++++-------- + lib/master_parse.y | 3 +-- + lib/mounts.c | 4 ++-- + 7 files changed, 16 insertions(+), 17 deletions(-) + + +--- autofs-5.0.6.orig/CHANGELOG ++++ autofs-5.0.6/CHANGELOG +@@ -44,6 +44,7 @@ + - fix libtirpc name clash. + - report map not read when debug logging. + - duplicate parent options for included maps. ++- update ->timeout() function to not return timeout. + + 28/06/2011 autofs-5.0.6 + ----------------------- +--- autofs-5.0.6.orig/daemon/direct.c ++++ autofs-5.0.6/daemon/direct.c +@@ -302,7 +302,7 @@ static int unlink_active_mounts(struct a + return 0; + } + +- ops->timeout(ap->logopt, ioctlfd, &tout); ++ ops->timeout(ap->logopt, ioctlfd, tout); + + if (save_ioctlfd == -1) + ops->close(ap->logopt, ioctlfd); +@@ -424,7 +424,7 @@ int do_mount_autofs_direct(struct autofs + goto out_umount; + } + +- ops->timeout(ap->logopt, ioctlfd, &timeout); ++ ops->timeout(ap->logopt, ioctlfd, timeout); + notify_mount_result(ap, me->key, str_direct); + cache_set_ino_index(me->mc, me->key, st.st_dev, st.st_ino); + ops->close(ap->logopt, ioctlfd); +@@ -771,7 +771,7 @@ int mount_autofs_offset(struct autofs_po + goto out_umount; + } + +- ops->timeout(ap->logopt, ioctlfd, &timeout); ++ ops->timeout(ap->logopt, ioctlfd, timeout); + cache_set_ino_index(me->mc, me->key, st.st_dev, st.st_ino); + if (ap->logopt & LOGOPT_DEBUG) + notify_mount_result(ap, mountpoint, str_offset); +--- autofs-5.0.6.orig/daemon/indirect.c ++++ autofs-5.0.6/daemon/indirect.c +@@ -172,7 +172,7 @@ static int do_mount_autofs_indirect(stru + ap->dev = st.st_dev; /* Device number for mount point checks */ + ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO; + +- ops->timeout(ap->logopt, ap->ioctlfd, &timeout); ++ ops->timeout(ap->logopt, ap->ioctlfd, timeout); + if (ap->logopt & LOGOPT_DEBUG) + notify_mount_result(ap, root, str_indirect); + else +--- autofs-5.0.6.orig/include/dev-ioctl-lib.h ++++ autofs-5.0.6/include/dev-ioctl-lib.h +@@ -45,7 +45,7 @@ struct ioctl_ops { + int (*send_fail)(unsigned int, int, unsigned int, int); + int (*setpipefd)(unsigned int, int, int); + int (*catatonic)(unsigned int, int); +- int (*timeout)(unsigned int, int, time_t *); ++ int (*timeout)(unsigned int, int, time_t); + int (*requestor)(unsigned int, int, const char *, uid_t *, gid_t *); + int (*expire)(unsigned int, int, const char *, unsigned int); + int (*askumount)(unsigned int, int, unsigned int *); +--- autofs-5.0.6.orig/lib/dev-ioctl-lib.c ++++ autofs-5.0.6/lib/dev-ioctl-lib.c +@@ -55,7 +55,7 @@ static int dev_ioctl_send_ready(unsigned + static int dev_ioctl_send_fail(unsigned int, int, unsigned int, int); + static int dev_ioctl_setpipefd(unsigned int, int, int); + static int dev_ioctl_catatonic(unsigned int, int); +-static int dev_ioctl_timeout(unsigned int, int, time_t *); ++static int dev_ioctl_timeout(unsigned int, int, time_t); + static int dev_ioctl_requestor(unsigned int, int, const char *, uid_t *, gid_t *); + static int dev_ioctl_expire(unsigned int, int, const char *, unsigned int); + static int dev_ioctl_askumount(unsigned int, int, unsigned int *); +@@ -69,7 +69,7 @@ static int ioctl_close(unsigned int, int + static int ioctl_send_ready(unsigned int, int, unsigned int); + static int ioctl_send_fail(unsigned int, int, unsigned int, int); + static int ioctl_catatonic(unsigned int, int); +-static int ioctl_timeout(unsigned int, int, time_t *); ++static int ioctl_timeout(unsigned int, int, time_t); + static int ioctl_expire(unsigned int, int, const char *, unsigned int); + static int ioctl_askumount(unsigned int, int, unsigned int *); + +@@ -577,25 +577,24 @@ static int ioctl_catatonic(unsigned int + } + + /* Set the autofs mount timeout */ +-static int dev_ioctl_timeout(unsigned int logopt, int ioctlfd, time_t *timeout) ++static int dev_ioctl_timeout(unsigned int logopt, int ioctlfd, time_t timeout) + { + struct autofs_dev_ioctl param; + + init_autofs_dev_ioctl(¶m); + param.ioctlfd = ioctlfd; +- param.timeout.timeout = *timeout; ++ param.timeout.timeout = timeout; + + if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_TIMEOUT, ¶m) == -1) + return -1; + +- *timeout = param.timeout.timeout; +- + return 0; + } + +-static int ioctl_timeout(unsigned int logopt, int ioctlfd, time_t *timeout) ++static int ioctl_timeout(unsigned int logopt, int ioctlfd, time_t timeout) + { +- return ioctl(ioctlfd, AUTOFS_IOC_SETTIMEOUT, timeout); ++ time_t tout = timeout; ++ return ioctl(ioctlfd, AUTOFS_IOC_SETTIMEOUT, &tout); + } + + /* +--- autofs-5.0.6.orig/lib/master_parse.y ++++ autofs-5.0.6/lib/master_parse.y +@@ -801,7 +801,6 @@ int master_parse_entry(const char *buffe + } else { + struct ioctl_ops *ops = get_ioctl_ops(); + struct autofs_point *ap = entry->ap; +- time_t tout = timeout; + + /* + * Second and subsequent instances of a mount point +@@ -811,7 +810,7 @@ int master_parse_entry(const char *buffe + ap->exp_timeout = timeout; + ap->exp_runfreq = (ap->exp_timeout + CHECK_RATIO - 1) / CHECK_RATIO; + if (ap->ioctlfd != -1 && ap->type == LKP_INDIRECT) +- ops->timeout(ap->logopt, ap->ioctlfd, &tout); ++ ops->timeout(ap->logopt, ap->ioctlfd, timeout); + } + } + if (random_selection) +--- autofs-5.0.6.orig/lib/mounts.c ++++ autofs-5.0.6/lib/mounts.c +@@ -1404,7 +1404,7 @@ static int remount_active_mount(struct a + + /* Re-reading the map, set timeout and return */ + if (ap->state == ST_READMAP) { +- ops->timeout(ap->logopt, fd, &timeout); ++ ops->timeout(ap->logopt, fd, timeout); + ops->close(ap->logopt, fd); + return REMOUNT_READ_MAP; + } +@@ -1426,7 +1426,7 @@ static int remount_active_mount(struct a + ops->close(ap->logopt, fd); + return REMOUNT_OPEN_FAIL; + } +- ops->timeout(ap->logopt, fd, &timeout); ++ ops->timeout(ap->logopt, fd, timeout); + if (fstat(fd, &st) == -1) { + error(ap->logopt, + "failed to stat %s mount %s", str_type, path);