diff --git a/SOURCES/autofs-5.1.6-add-sss-ECONREFUSED-return-handling.patch b/SOURCES/autofs-5.1.6-add-sss-ECONREFUSED-return-handling.patch new file mode 100644 index 0000000..5430c64 --- /dev/null +++ b/SOURCES/autofs-5.1.6-add-sss-ECONREFUSED-return-handling.patch @@ -0,0 +1,66 @@ +autofs-5.1.6 - add sss ECONREFUSED return handling + +From: Ian Kent + +The sss library has returned ECONNREFUSED for the case of sssd not +running for a long time now but autofs doesn't catch it, fix that. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + modules/lookup_sss.c | 9 +++++++++ + 2 files changed, 10 insertions(+) + +diff --git a/CHANGELOG b/CHANGELOG +index 5a3d785..2a45829 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -94,6 +94,7 @@ xx/xx/2018 autofs-5.1.5 + - fix lookup_nss_read_master() nsswicth check return. + - fix typo in open_sss_lib(). + - fix sss_master_map_wait timing. ++- add sss ECONREFUSED return handling. + + 19/12/2017 autofs-5.1.4 + - fix spec file url. +diff --git a/modules/lookup_sss.c b/modules/lookup_sss.c +index fbb6193..c393296 100644 +--- a/modules/lookup_sss.c ++++ b/modules/lookup_sss.c +@@ -297,6 +297,9 @@ int lookup_read_master(struct master *master, time_t age, void *context) + if (ret) { + unsigned int retries; + ++ if (ret == ECONNREFUSED) ++ return NSS_STATUS_UNKNOWN; ++ + if (ret != ENOENT) + return NSS_STATUS_UNAVAIL; + +@@ -308,6 +311,8 @@ int lookup_read_master(struct master *master, time_t age, void *context) + ctxt, ctxt->mapname, &sss_ctxt, + retries); + if (ret) { ++ if (ret == ECONNREFUSED) ++ return NSS_STATUS_UNKNOWN; + if (ret == ENOENT) + return NSS_STATUS_NOTFOUND; + return NSS_STATUS_UNAVAIL; +@@ -415,6 +420,8 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context) + + ret = setautomntent(ap->logopt, ctxt, ctxt->mapname, &sss_ctxt); + if (ret) { ++ if (ret == ECONNREFUSED) ++ return NSS_STATUS_UNKNOWN; + if (ret == ENOENT) + return NSS_STATUS_NOTFOUND; + return NSS_STATUS_UNAVAIL; +@@ -525,6 +532,8 @@ static int lookup_one(struct autofs_point *ap, + + ret = setautomntent(ap->logopt, ctxt, ctxt->mapname, &sss_ctxt); + if (ret) { ++ if (ret == ECONNREFUSED) ++ return NSS_STATUS_UNKNOWN; + if (ret == ENOENT) + return NSS_STATUS_NOTFOUND; + return NSS_STATUS_UNAVAIL; diff --git a/SOURCES/autofs-5.1.6-add-support-for-new-sss-autofs-proto-version-call.patch b/SOURCES/autofs-5.1.6-add-support-for-new-sss-autofs-proto-version-call.patch new file mode 100644 index 0000000..1cea8cd --- /dev/null +++ b/SOURCES/autofs-5.1.6-add-support-for-new-sss-autofs-proto-version-call.patch @@ -0,0 +1,120 @@ +autofs-5.1.6 - add support for new sss autofs proto version call + +From: Ian Kent + +Add sss protocol feature version function existence check and local get +function. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + modules/lookup_sss.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 45 insertions(+) + +diff --git a/CHANGELOG b/CHANGELOG +index 1830730..7c22aa1 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -96,6 +96,7 @@ xx/xx/2018 autofs-5.1.5 + - fix sss_master_map_wait timing. + - add sss ECONREFUSED return handling. + - use mapname in sss context for setautomntent(). ++- add support for new sss autofs proto version call. + + 19/12/2017 autofs-5.1.4 + - fix spec file url. +diff --git a/modules/lookup_sss.c b/modules/lookup_sss.c +index c44c55d..3819981 100644 +--- a/modules/lookup_sss.c ++++ b/modules/lookup_sss.c +@@ -37,11 +37,29 @@ + + #define SSS_SO_NAME "libsss_autofs" + ++/* If the sss library protocol version is greater than 0 there are ++ * more possibile error returns from the sss autofs library calls. ++ * ++ * If ECONNREFUSED is returned then sssd is not running or not ++ * configured on the system, immediately return an unavailable ++ * status. ++ * ++ * A return of EHOSTDOWN means sss backend server is down so we ++ * should retry. ++ * ++ * With older sss ilibrary we can get a return of ENOENT for the ++ * above cases so also wait in that case since we can't be sure ++ * the map doesn't exist. ++ */ ++#define SSS_PROTO_VERSION 1 ++ ++unsigned int _sss_auto_protocol_version(unsigned int); + int _sss_setautomntent(const char *, void **); + int _sss_getautomntent_r(char **, char **, void *); + int _sss_getautomntbyname_r(char *, char **, void *); + int _sss_endautomntent(void **); + ++typedef unsigned int (*protocol_version_t) (unsigned int); + typedef int (*setautomntent_t) (const char *, void **); + typedef int (*getautomntent_t) (char **, char **, void *); + typedef int (*getautomntbyname_t) (char *, char **, void *); +@@ -50,6 +68,7 @@ typedef int (*endautomntent_t) (void **); + struct lookup_context { + const char *mapname; + void *dlhandle; ++ protocol_version_t protocol_version; + setautomntent_t setautomntent; + getautomntent_t getautomntent_r; + getautomntbyname_t getautomntbyname_r; +@@ -58,6 +77,8 @@ struct lookup_context { + }; + + int lookup_version = AUTOFS_LOOKUP_VERSION; /* Required by protocol */ ++int sss_proto_version = SSS_PROTO_VERSION; /* 0 => initial version, ++ * >= 1 => new error handling. */ + + static int open_sss_lib(struct lookup_context *ctxt) + { +@@ -78,6 +99,11 @@ static int open_sss_lib(struct lookup_context *ctxt) + return 1; + ctxt->dlhandle = dh; + ++ /* Don't fail on NULL, it's simply not present in this version of the ++ * sss autofs library. ++ */ ++ ctxt->protocol_version = (protocol_version_t) dlsym(dh, "_sss_auto_protocol_version"); ++ + ctxt->setautomntent = (setautomntent_t) dlsym(dh, "_sss_setautomntent"); + if (!ctxt->setautomntent) + goto lib_names_fail; +@@ -193,6 +219,7 @@ int lookup_reinit(const char *mapfmt, + } + + new->dlhandle = ctxt->dlhandle; ++ new->protocol_version = ctxt->protocol_version; + new->setautomntent = ctxt->setautomntent; + new->getautomntent_r = ctxt->getautomntent_r; + new->getautomntbyname_r = ctxt->getautomntbyname_r; +@@ -219,6 +246,23 @@ static int setautomntent(unsigned int logopt, + return ret; + } + ++static unsigned int proto_version(struct lookup_context *ctxt) ++{ ++ unsigned int proto_version = 0; ++ ++ if (ctxt->protocol_version) { ++ /* If ctxt->protocol_version() is defined it's assumed ++ * that for sss_proto_version <= sss autofs library ++ * protocol version ctxt->protocol_version() will ++ * return the version requested by autofs to indicate ++ * it userstands what the autofs module is capable of ++ * handling. ++ */ ++ proto_version = ctxt->protocol_version(sss_proto_version); ++ } ++ return proto_version; ++} ++ + static int setautomntent_wait(unsigned int logopt, + struct lookup_context *ctxt, + void **sss_ctxt, unsigned int retries) diff --git a/SOURCES/autofs-5.1.6-dont-prune-offset-map-entries.patch b/SOURCES/autofs-5.1.6-dont-prune-offset-map-entries.patch new file mode 100644 index 0000000..2a4a1c9 --- /dev/null +++ b/SOURCES/autofs-5.1.6-dont-prune-offset-map-entries.patch @@ -0,0 +1,49 @@ +autofs-5.1.6 - dont prune offset map entries + +From: Ian Kent + +Indirect maps create offset map entries for multi-mount map entries on +deamnd and remove them when they expire. + +Since they are created based on an owning map entry they don't correspond +to an actual map entry so they, and their owning map entry, should never +be pruned. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + daemon/lookup.c | 9 +++++++++ + 2 files changed, 10 insertions(+) + +diff --git a/CHANGELOG b/CHANGELOG +index 3608345..34b160e 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -109,6 +109,7 @@ xx/xx/2018 autofs-5.1.5 + - refactor sss getautomntbyname(). + - improve sss getautomntbyname() error handling. + - use a valid timeout in lookup_prune_one_cache(). ++- dont prune offset map entries. + + 19/12/2017 autofs-5.1.4 + - fix spec file url. +diff --git a/daemon/lookup.c b/daemon/lookup.c +index 8bf1335..2de622e 100644 +--- a/daemon/lookup.c ++++ b/daemon/lookup.c +@@ -1355,6 +1355,15 @@ void lookup_prune_one_cache(struct autofs_point *ap, struct mapent_cache *mc, ti + } + + if (ap->type == LKP_INDIRECT) { ++ /* Don't prune offset map entries since they are ++ * created on demand and managed by expire and don't ++ * prune the multi-map owner map entry. ++ */ ++ if (*me->key == '/' || me->multi == me) { ++ me = cache_enumerate(mc, me); ++ continue; ++ } ++ + /* If the map hasn't been read (nobrowse + * indirect mounts) then keep cached entries + * for POSITIVE_TIMEOUT. diff --git a/SOURCES/autofs-5.1.6-fix-lookup_nss_read_master-nsswicth-check-return.patch b/SOURCES/autofs-5.1.6-fix-lookup_nss_read_master-nsswicth-check-return.patch new file mode 100644 index 0000000..15909c5 --- /dev/null +++ b/SOURCES/autofs-5.1.6-fix-lookup_nss_read_master-nsswicth-check-return.patch @@ -0,0 +1,42 @@ +autofs-5.1.6 - fix lookup_nss_read_master() nsswicth check return + +From: Ian Kent + +When reading master map nsswicth sources the result of reading the master +map should be returned rather than the result of the nsswitch check. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + daemon/lookup.c | 6 ++---- + 2 files changed, 3 insertions(+), 4 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 52fc100..3c00184 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -91,6 +91,7 @@ xx/xx/2018 autofs-5.1.5 + - remove command fifo on autofs mount fail. + - add force unlink mounts and exit option. + - cleanup stale logpri fifo pipes on unlink and exit. ++- fix lookup_nss_read_master() nsswicth check return. + + 19/12/2017 autofs-5.1.4 + - fix spec file url. +diff --git a/daemon/lookup.c b/daemon/lookup.c +index d9d3a4e..2b9c7e8 100644 +--- a/daemon/lookup.c ++++ b/daemon/lookup.c +@@ -303,10 +303,8 @@ int lookup_nss_read_master(struct master *master, time_t age) + master->read_fail = 1; + + status = check_nss_result(this, result); +- if (status >= 0) { +- free_sources(&nsslist); +- return status; +- } ++ if (status >= 0) ++ break; + } + + if (!list_empty(&nsslist)) diff --git a/SOURCES/autofs-5.1.6-fix-retries-check-in-setautomntent_wait.patch b/SOURCES/autofs-5.1.6-fix-retries-check-in-setautomntent_wait.patch new file mode 100644 index 0000000..2c3625a --- /dev/null +++ b/SOURCES/autofs-5.1.6-fix-retries-check-in-setautomntent_wait.patch @@ -0,0 +1,38 @@ +autofs-5.1.6 - fix retries check in setautomntent_wait() + +From: Ian Kent + +In setautomntent_wait() on exit from the retry loop retry will always +be greater than retries if the retry limit is reached. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + modules/lookup_sss.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 7c22aa1..b3ffbb6 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -97,6 +97,7 @@ xx/xx/2018 autofs-5.1.5 + - add sss ECONREFUSED return handling. + - use mapname in sss context for setautomntent(). + - add support for new sss autofs proto version call. ++- fix retries check in setautomntent_wait(). + + 19/12/2017 autofs-5.1.4 + - fix spec file url. +diff --git a/modules/lookup_sss.c b/modules/lookup_sss.c +index 3819981..d65e71c 100644 +--- a/modules/lookup_sss.c ++++ b/modules/lookup_sss.c +@@ -299,7 +299,7 @@ static int setautomntent_wait(unsigned int logopt, + *sss_ctxt = NULL; + } + +- if (retry == retries) ++ if (retry > retries) + ret = ETIMEDOUT; + + estr = strerror_r(ret, buf, MAX_ERR_BUF); diff --git a/SOURCES/autofs-5.1.6-fix-sss-master-map-wait-timing.patch b/SOURCES/autofs-5.1.6-fix-sss-master-map-wait-timing.patch new file mode 100644 index 0000000..95d1d09 --- /dev/null +++ b/SOURCES/autofs-5.1.6-fix-sss-master-map-wait-timing.patch @@ -0,0 +1,60 @@ +autofs-5.1.6 - fix sss_master_map_wait timing + +From: Ian Kent + +The sss lookup retry delay is half a second but the sss daemon timeouts +are fairly long so change the retry delay to one second. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + modules/lookup_sss.c | 10 +++++----- + 2 files changed, 6 insertions(+), 5 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 63c6d41..5a3d785 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -93,6 +93,7 @@ xx/xx/2018 autofs-5.1.5 + - cleanup stale logpri fifo pipes on unlink and exit. + - fix lookup_nss_read_master() nsswicth check return. + - fix typo in open_sss_lib(). ++- fix sss_master_map_wait timing. + + 19/12/2017 autofs-5.1.4 + - fix spec file url. +diff --git a/modules/lookup_sss.c b/modules/lookup_sss.c +index cc18e62..fbb6193 100644 +--- a/modules/lookup_sss.c ++++ b/modules/lookup_sss.c +@@ -30,8 +30,8 @@ + + #define MAPFMT_DEFAULT "sun" + +-/* Half a second between retries */ +-#define SETAUTOMOUNTENT_MASTER_INTERVAL 500000000 ++/* One second between retries */ ++#define SSS_WAIT_INTERVAL 1 + + #define MODPREFIX "lookup(sss): " + +@@ -230,8 +230,8 @@ static int setautomntent_wait(unsigned int logopt, + + *sss_ctxt = NULL; + +- while (++retry < retries) { +- struct timespec t = { 0, SETAUTOMOUNTENT_MASTER_INTERVAL }; ++ while (++retry <= retries) { ++ struct timespec t = { SSS_WAIT_INTERVAL, 0 }; + struct timespec r; + + ret = ctxt->setautomntent(mapname, sss_ctxt); +@@ -300,7 +300,7 @@ int lookup_read_master(struct master *master, time_t age, void *context) + if (ret != ENOENT) + return NSS_STATUS_UNAVAIL; + +- retries = defaults_get_sss_master_map_wait() * 2; ++ retries = defaults_get_sss_master_map_wait(); + if (retries <= 0) + return NSS_STATUS_NOTFOUND; + diff --git a/SOURCES/autofs-5.1.6-fix-typo-in-open_sss_lib.patch b/SOURCES/autofs-5.1.6-fix-typo-in-open_sss_lib.patch new file mode 100644 index 0000000..13f568d --- /dev/null +++ b/SOURCES/autofs-5.1.6-fix-typo-in-open_sss_lib.patch @@ -0,0 +1,37 @@ +autofs-5.1.6 - fix typo in open_sss_lib() + +From: Ian Kent + +Fix obvious typo in modules/lookup_sss.c:open_sss_lib(). + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + modules/lookup_sss.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 3c00184..63c6d41 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -92,6 +92,7 @@ xx/xx/2018 autofs-5.1.5 + - add force unlink mounts and exit option. + - cleanup stale logpri fifo pipes on unlink and exit. + - fix lookup_nss_read_master() nsswicth check return. ++- fix typo in open_sss_lib(). + + 19/12/2017 autofs-5.1.4 + - fix spec file url. +diff --git a/modules/lookup_sss.c b/modules/lookup_sss.c +index 7859830..cc18e62 100644 +--- a/modules/lookup_sss.c ++++ b/modules/lookup_sss.c +@@ -91,7 +91,7 @@ static int open_sss_lib(struct lookup_context *ctxt) + goto lib_names_fail; + + ctxt->endautomntent = (endautomntent_t) dlsym(dh, "_sss_endautomntent"); +- if (!ctxt->setautomntent) ++ if (!ctxt->endautomntent) + goto lib_names_fail; + + return 0; diff --git a/SOURCES/autofs-5.1.6-improve-sss-getautomntbyname-error-handling.patch b/SOURCES/autofs-5.1.6-improve-sss-getautomntbyname-error-handling.patch new file mode 100644 index 0000000..43d81e0 --- /dev/null +++ b/SOURCES/autofs-5.1.6-improve-sss-getautomntbyname-error-handling.patch @@ -0,0 +1,189 @@ +autofs-5.1.6 - improve sss getautomntbyname() error handling + +From: Ian Kent + +Recent versions of the sss autofs access library will return EHOSTDOWN +if the backend server is down. + +The presence of this improvement in error handling is determined by an +added function to get the sss autofs protocol version. + +Update the getautomntbyname() function to use this. + +Also introduce a wait function so we can wait (for a while) for the host +to come back up. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + modules/lookup_sss.c | 106 ++++++++++++++++++++++++++++++++++++++++++++------ + 2 files changed, 95 insertions(+), 12 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 8b662d7..309def2 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -107,6 +107,7 @@ xx/xx/2018 autofs-5.1.5 + - sss introduce a flag to indicate map being read. + - update sss timeout documentation. + - refactor sss getautomntbyname(). ++- improve sss getautomntbyname() error handling. + + 19/12/2017 autofs-5.1.4 + - fix spec file url. +diff --git a/modules/lookup_sss.c b/modules/lookup_sss.c +index 1a56ea1..70efc11 100644 +--- a/modules/lookup_sss.c ++++ b/modules/lookup_sss.c +@@ -566,27 +566,106 @@ free: + return err; + } + ++static int getautomntbyname_wait(unsigned int logopt, ++ struct lookup_context *ctxt, ++ char *key, char **value, void *sss_ctxt, ++ unsigned int flags) ++{ ++ unsigned int retries; ++ unsigned int retry = 0; ++ int ret = 0; ++ ++ retries = calculate_retry_count(ctxt, flags); ++ if (retries == 0) { ++ if (proto_version(ctxt) == 0) ++ return EINVAL; ++ return ENOENT; ++ } ++ ++ warn(logopt, ++ "can't contact sssd to to lookup key value, retry for %d seconds", ++ retries); ++ ++ while (++retry <= retries) { ++ struct timespec t = { SSS_WAIT_INTERVAL, 0 }; ++ struct timespec r; ++ ++ ret = ctxt->getautomntbyname_r(key, value, sss_ctxt); ++ if (proto_version(ctxt) == 0) { ++ if (ret != ENOENT) ++ break; ++ } else { ++ if (ret != EHOSTDOWN) ++ break; ++ } ++ ++ while (nanosleep(&t, &r) == -1 && errno == EINTR) ++ memcpy(&t, &r, sizeof(struct timespec)); ++ } ++ ++ if (!ret) ++ info(logopt, ++ "successfully contacted sssd to lookup key value"); ++ else { ++ if (proto_version(ctxt) == 0 && retry > retries) ++ ret = ETIMEDOUT; ++ } ++ return ret; ++} ++ + static int getautomntbyname(unsigned int logopt, + struct lookup_context *ctxt, +- char *key, char **value, void *sss_ctxt) ++ char *key, char **value, void *sss_ctxt, ++ unsigned int flags) + { + char buf[MAX_ERR_BUF]; + char *estr; +- int ret = NSS_STATUS_UNAVAIL; ++ int err = NSS_STATUS_UNAVAIL; ++ int ret; + + ret = ctxt->getautomntbyname_r(key, value, sss_ctxt); + if (ret) { + /* Host has gone down */ + if (ret == ECONNREFUSED) +- return NSS_STATUS_UNKNOWN; +- +- if (ret != ENOENT) + goto error; + +- ret = NSS_STATUS_NOTFOUND; +- goto free; ++ if (proto_version(ctxt) == 0) { ++ if (ret != ENOENT) ++ goto error; ++ /* For prorocol version 0 ENOENT can only be ++ * used to indicate no entry was found. So it ++ * can't be used to determine if we need to wait ++ * on sss. ++ */ ++ err = NSS_STATUS_NOTFOUND; ++ goto free; ++ } else { ++ if (ret == ENOENT) { ++ err = NSS_STATUS_NOTFOUND; ++ goto free; ++ } ++ if (ret != EHOSTDOWN) ++ goto error; ++ } ++ ++ ret = getautomntbyname_wait(logopt, ctxt, ++ key, value, sss_ctxt, flags); ++ if (ret) { ++ if (ret == ECONNREFUSED) ++ goto free; ++ if (ret == ETIMEDOUT) ++ goto error; ++ /* sss proto version 0 and sss timeout not set */ ++ if (ret == EINVAL) ++ goto free; ++ if (ret == ENOENT) { ++ err = NSS_STATUS_NOTFOUND; ++ goto free; ++ } ++ goto error; ++ } + } +- return ret; ++ return NSS_STATUS_SUCCESS; + + error: + estr = strerror_r(ret, buf, MAX_ERR_BUF); +@@ -596,7 +675,7 @@ free: + free(*value); + *value = NULL; + } +- return ret; ++ return err; + } + + int lookup_read_master(struct master *master, time_t age, void *context) +@@ -802,7 +881,8 @@ static int lookup_one(struct autofs_point *ap, + if (ret) + return ret; + +- ret = getautomntbyname(ap->logopt, ctxt, qKey, &value, sss_ctxt); ++ ret = getautomntbyname(ap->logopt, ctxt, ++ qKey, &value, sss_ctxt, SSS_LOOKUP_KEY); + if (ret == NSS_STATUS_NOTFOUND) + goto wild; + if (ret) { +@@ -829,13 +909,15 @@ static int lookup_one(struct autofs_point *ap, + return NSS_STATUS_SUCCESS; + + wild: +- ret = getautomntbyname(ap->logopt, ctxt, "/", &value, sss_ctxt); ++ ret = getautomntbyname(ap->logopt, ctxt, ++ "/", &value, sss_ctxt, SSS_LOOKUP_KEY); + if (ret) { + if (ret != NSS_STATUS_NOTFOUND) { + endautomntent(ap->logopt, ctxt, &sss_ctxt); + return ret; + } +- ret = getautomntbyname(ap->logopt, ctxt, "*", &value, sss_ctxt); ++ ret = getautomntbyname(ap->logopt, ctxt, ++ "*", &value, sss_ctxt, SSS_LOOKUP_KEY); + if (ret && ret != NSS_STATUS_NOTFOUND) { + endautomntent(ap->logopt, ctxt, &sss_ctxt); + return ret; diff --git a/SOURCES/autofs-5.1.6-improve-sss-getautomntent-error-handling.patch b/SOURCES/autofs-5.1.6-improve-sss-getautomntent-error-handling.patch new file mode 100644 index 0000000..b548efd --- /dev/null +++ b/SOURCES/autofs-5.1.6-improve-sss-getautomntent-error-handling.patch @@ -0,0 +1,205 @@ +autofs-5.1.6 - improve sss getautomntent() error handling + +From: Ian Kent + +Recent versions of the sss autofs access library will return EHOSTDOWN +if the backend server is down. + +The presence of this improvement in error handling is determined by an +added function to get the sss autofs protocol version. + +Update the getautomntent() function to use this. + +Also introduce a wait function so we can wait (for a while) for the host +to come back up. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + modules/lookup_sss.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++---- + 2 files changed, 116 insertions(+), 11 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index ecd54e9..434e23d 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -101,6 +101,7 @@ xx/xx/2018 autofs-5.1.5 + - refactor sss setautomntent(). + - improve sss setautomntent() error handling. + - refactor sss getautomntent(). ++- improve sss getautomntent() error handling. + + 19/12/2017 autofs-5.1.4 + - fix spec file url. +diff --git a/modules/lookup_sss.c b/modules/lookup_sss.c +index 5addd87..f366b48 100644 +--- a/modules/lookup_sss.c ++++ b/modules/lookup_sss.c +@@ -377,38 +377,136 @@ static int endautomntent(unsigned int logopt, + return ret; + } + ++static int getautomntent_wait(unsigned int logopt, ++ struct lookup_context *ctxt, ++ char **key, char **value, void *sss_ctxt) ++{ ++ unsigned int retries; ++ unsigned int retry = 0; ++ int ret = 0; ++ ++ retries = defaults_get_sss_master_map_wait(); ++ ++ /* Use the sss_master_map_wait configuration option ++ * for the time to wait when reading a map too. If ++ * it isn't set in the antofs configuration give it ++ * a sensible value since we want to wait for a host ++ * that's down in case it comes back up. ++ */ ++ if (retries <= 0) { ++ /* Protocol version 0 cant't tell us about ++ * a host being down, return not found. ++ */ ++ if (proto_version(ctxt) == 0) ++ return ENOENT; ++ retries = 10; ++ } ++ ++ warn(logopt, ++ "can't contact sssd to to get map entry, retry for %d seconds", ++ retries); ++ ++ while (++retry <= retries) { ++ struct timespec t = { SSS_WAIT_INTERVAL, 0 }; ++ struct timespec r; ++ ++ ret = ctxt->getautomntent_r(key, value, sss_ctxt); ++ if (proto_version(ctxt) == 0) { ++ if (ret != ENOENT) ++ break; ++ } else { ++ if (ret != EHOSTDOWN) ++ break; ++ } ++ ++ while (nanosleep(&t, &r) == -1 && errno == EINTR) ++ memcpy(&t, &r, sizeof(struct timespec)); ++ } ++ ++ if (!ret) ++ info(logopt, ++ "successfully contacted sssd to get map entry"); ++ else { ++ if (retry == retries) ++ ret = ETIMEDOUT; ++ } ++ return ret; ++} ++ + static int getautomntent(unsigned int logopt, + struct lookup_context *ctxt, + char **key, char **value, int count, void *sss_ctxt) + { + char buf[MAX_ERR_BUF]; + char *estr; +- int ret = NSS_STATUS_UNAVAIL; ++ int err = NSS_STATUS_UNAVAIL; ++ int ret; + + ret = ctxt->getautomntent_r(key, value, sss_ctxt); + if (ret) { + /* Host has gone down */ +- if (ret == ECONNREFUSED) +- return NSS_STATUS_UNKNOWN; +- if (ret != ENOENT) ++ if (ret == ECONNREFUSED) { ++ err = NSS_STATUS_UNKNOWN; + goto error; +- if (!count) { +- ret = NSS_STATUS_NOTFOUND; ++ } ++ ++ if (proto_version(ctxt) == 0) { ++ if (ret != ENOENT) ++ goto error; ++ /* For prorocol version 0 ENOENT can only be ++ * used to indicate we've read all entries. ++ * So even if we haven't got any values yet we ++ * can't use it to determine if we need to wait ++ * on sss. ++ */ ++ err = NSS_STATUS_NOTFOUND; ++ if (count) ++ err = NSS_STATUS_SUCCESS; + goto free; ++ } else { ++ if (ret == ENOENT) { ++ err = NSS_STATUS_NOTFOUND; ++ if (count) ++ err = NSS_STATUS_SUCCESS; ++ goto free; ++ } ++ if (ret != EHOSTDOWN) ++ goto error; ++ } ++ ++ ret = getautomntent_wait(logopt, ctxt, ++ key, value, sss_ctxt); ++ if (ret) { ++ if (ret == ECONNREFUSED) { ++ err = NSS_STATUS_UNKNOWN; ++ goto free; ++ } ++ if (ret == ETIMEDOUT) ++ goto error; ++ if (ret == ENOENT) { ++ err = NSS_STATUS_NOTFOUND; ++ if (count) ++ err = NSS_STATUS_SUCCESS; ++ goto free; ++ } ++ goto error; + } +- goto error; + } +- return ret; ++ return NSS_STATUS_SUCCESS; + + error: + estr = strerror_r(ret, buf, MAX_ERR_BUF); + error(logopt, MODPREFIX "getautomntent: %s", estr); + free: +- if (*key) ++ if (*key) { + free(*key); +- if (*value) ++ *key = NULL; ++ } ++ if (*value) { + free(*value); +- return ret; ++ *value = NULL; ++ } ++ return err; + } + + int lookup_read_master(struct master *master, time_t age, void *context) +@@ -439,6 +537,9 @@ int lookup_read_master(struct master *master, time_t age, void *context) + return ret; + } + ++ if (!key || !value) ++ break; ++ + count++; + + buffer_len = strlen(key) + 1 + strlen(value) + 2; +@@ -523,6 +624,9 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context) + return ret; + } + ++ if (!key || !value) ++ break; ++ + /* + * Ignore keys beginning with '+' as plus map + * inclusion is only valid in file maps. diff --git a/SOURCES/autofs-5.1.6-improve-sss-setautomntent-error-handling.patch b/SOURCES/autofs-5.1.6-improve-sss-setautomntent-error-handling.patch new file mode 100644 index 0000000..f3eda36 --- /dev/null +++ b/SOURCES/autofs-5.1.6-improve-sss-setautomntent-error-handling.patch @@ -0,0 +1,159 @@ +autofs-5.1.6 - improve sss setautomntent() error handling + +From: Ian Kent + +Recent versions of the sss autofs access library will return EHOSTDOWN +if the backend server is down. + +The presence of this improvement in error handling is determined by an +added function to get the sss autofs protocol version. + +Update the setautomntent() function to use this. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + modules/lookup_sss.c | 72 ++++++++++++++++++++++++++++++++++++++------------ + 2 files changed, 55 insertions(+), 18 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 141658d..5ccd787 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -99,6 +99,7 @@ xx/xx/2018 autofs-5.1.5 + - add support for new sss autofs proto version call. + - fix retries check in setautomntent_wait(). + - refactor sss setautomntent(). ++- improve sss setautomntent() error handling. + + 19/12/2017 autofs-5.1.4 + - fix spec file url. +diff --git a/modules/lookup_sss.c b/modules/lookup_sss.c +index 011b232..e1ed83c 100644 +--- a/modules/lookup_sss.c ++++ b/modules/lookup_sss.c +@@ -259,16 +259,37 @@ static int setautomntent_wait(unsigned int logopt, + *sss_ctxt = NULL; + + retries = defaults_get_sss_master_map_wait(); +- if (retries <= 0) +- return ENOENT; ++ ++ /* If sss_master_map_wait is not set in the autofs ++ * configuration give it a sensible value since we ++ * want to wait for a host that's down in case it ++ * comes back up. ++ */ ++ if (retries <= 0) { ++ /* Protocol version 0 cant't tell us about ++ * a host being down, return not found. ++ */ ++ if (proto_version(ctxt) == 0) ++ return ENOENT; ++ retries = 10; ++ } ++ ++ warn(logopt, ++ "can't connect to sssd, retry for %d seconds", ++ retries); + + while (++retry <= retries) { + struct timespec t = { SSS_WAIT_INTERVAL, 0 }; + struct timespec r; + + ret = ctxt->setautomntent(ctxt->mapname, sss_ctxt); +- if (ret != ENOENT) +- break; ++ if (proto_version(ctxt) == 0) { ++ if (ret != ENOENT) ++ break; ++ } else { ++ if (ret != EHOSTDOWN) ++ break; ++ } + + if (*sss_ctxt) { + free(*sss_ctxt); +@@ -279,17 +300,17 @@ static int setautomntent_wait(unsigned int logopt, + memcpy(&t, &r, sizeof(struct timespec)); + } + +- +- if (ret) { ++ if (!ret) ++ info(logopt, "successfully connected to sssd"); ++ else { + if (*sss_ctxt) { + free(*sss_ctxt); + *sss_ctxt = NULL; + } + +- if (retry > retries) ++ if (proto_version(ctxt) == 0 && retry > retries) + ret = ETIMEDOUT; + } +- + return ret; + } + +@@ -298,35 +319,50 @@ static int setautomntent(unsigned int logopt, + { + char buf[MAX_ERR_BUF]; + char *estr; ++ int err = NSS_STATUS_UNAVAIL; + int ret; + + ret = ctxt->setautomntent(ctxt->mapname, sss_ctxt); + if (ret) { +- if (ret == ECONNREFUSED) +- return NSS_STATUS_UNKNOWN; +- +- if (ret != ENOENT) ++ if (ret == ECONNREFUSED) { ++ err = NSS_STATUS_UNKNOWN; + goto error; ++ } ++ ++ if (proto_version(ctxt) == 0) { ++ if (ret != ENOENT) ++ goto error; ++ } else { ++ if (ret != ENOENT && ret != EHOSTDOWN) ++ goto error; ++ } + + ret = setautomntent_wait(logopt, ctxt, sss_ctxt); + if (ret) { +- if (ret == ECONNREFUSED) +- return NSS_STATUS_UNKNOWN; +- if (ret == ENOENT) +- return NSS_STATUS_NOTFOUND; ++ if (ret == ECONNREFUSED) { ++ err = NSS_STATUS_UNKNOWN; ++ goto error; ++ } ++ if (ret == ETIMEDOUT) ++ goto error; ++ if (ret == ENOENT) { ++ err = NSS_STATUS_NOTFOUND; ++ goto free; ++ } + goto error; + } + } +- return ret; ++ return NSS_STATUS_SUCCESS; + + error: + estr = strerror_r(ret, buf, MAX_ERR_BUF); + error(logopt, MODPREFIX "setautomntent: %s", estr); ++free: + if (*sss_ctxt) { + free(*sss_ctxt); + *sss_ctxt = NULL; + } +- return NSS_STATUS_UNAVAIL; ++ return err; + } + + static int endautomntent(unsigned int logopt, diff --git a/SOURCES/autofs-5.1.6-move-readall-into-struct-master.patch b/SOURCES/autofs-5.1.6-move-readall-into-struct-master.patch new file mode 100644 index 0000000..9555edd --- /dev/null +++ b/SOURCES/autofs-5.1.6-move-readall-into-struct-master.patch @@ -0,0 +1,203 @@ +autofs-5.1.6 - move readall into struct master + +From: Ian Kent + +The lookup modules may need to know if the master map is being re-read +vis a HUP signal or is being read for the first time. + +This is indicated by the readall variable so move it into the master +map structure so it's accessable to lookup modules. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + daemon/automount.c | 28 +++++++++++++++++----------- + include/master.h | 5 +++-- + lib/master.c | 15 ++++++++------- + 4 files changed, 29 insertions(+), 20 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 4d83df2..4a6c042 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -103,6 +103,7 @@ xx/xx/2018 autofs-5.1.5 + - refactor sss getautomntent(). + - improve sss getautomntent() error handling. + - sss introduce calculate_retry_count() function. ++- move readall into struct master. + + 19/12/2017 autofs-5.1.4 + - fix spec file url. +diff --git a/daemon/automount.c b/daemon/automount.c +index 019bd81..9660f3f 100644 +--- a/daemon/automount.c ++++ b/daemon/automount.c +@@ -1465,7 +1465,6 @@ static void *do_read_master(void *arg) + struct master *master; + unsigned int logopt; + time_t age; +- int readall = 1; + int status; + + status = pthread_mutex_lock(&mrc.mutex); +@@ -1496,8 +1495,11 @@ static void *do_read_master(void *arg) + + info(logopt, "re-reading master map %s", master->name); + +- status = master_read_master(master, age, readall); ++ master->readall = 1; + ++ status = master_read_master(master, age); ++ ++ master->readall = 0; + master->reading = 0; + + return NULL; +@@ -2196,7 +2198,7 @@ static void do_master_list_reset(struct master *master) + master_mutex_unlock(); + } + +-static int do_master_read_master(struct master *master, int wait) ++static int do_master_read_master(struct master *master, time_t *age, int wait) + { + sigset_t signalset; + /* Wait must be at least 1 second */ +@@ -2204,7 +2206,6 @@ static int do_master_read_master(struct master *master, int wait) + unsigned int elapsed = 0; + int max_wait = wait; + int ret = 0; +- time_t age; + + sigemptyset(&signalset); + sigaddset(&signalset, SIGTERM); +@@ -2217,8 +2218,8 @@ static int do_master_read_master(struct master *master, int wait) + + do_master_list_reset(master); + +- age = monotonic_time(NULL); +- if (master_read_master(master, age, 0)) { ++ *age = monotonic_time(NULL); ++ if (master_read_master(master, *age)) { + ret = 1; + break; + } +@@ -2692,14 +2693,14 @@ int main(int argc, char *argv[]) + dh_tirpc = dlopen("libtirpc.so.3", RTLD_NOW); + #endif + +- master_read = master_read_master(master_list, age, 0); ++ master_read = master_read_master(master_list, age); + if (!master_read) { + /* + * Read master map, waiting until it is available, unless + * a signal is received, in which case exit returning an + * error. + */ +- if (!do_master_read_master(master_list, master_wait)) { ++ if (!do_master_read_master(master_list, &age, master_wait)) { + logmsg("%s: warning: could not read at least one " + "map source after waiting, continuing ...", + program); +@@ -2707,9 +2708,14 @@ int main(int argc, char *argv[]) + * Failed to read master map, continue with what + * we have anyway. + */ +- do_master_list_reset(master_list); +- age = monotonic_time(NULL); +- master_read_master(master_list, age, 1); ++ master_mutex_lock(); ++ master_list->readall = 1; ++ master_mount_mounts(master_list, age); ++ master_list->readall = 0; ++ ++ if (list_empty(&master_list->mounts)) ++ warn(master_list->logopt, "no mounts in table"); ++ master_mutex_unlock(); + } + } + +diff --git a/include/master.h b/include/master.h +index e1d272f..f689297 100644 +--- a/include/master.h ++++ b/include/master.h +@@ -63,6 +63,7 @@ struct master { + unsigned int depth; + unsigned int reading; + unsigned int read_fail; ++ unsigned int readall; + unsigned int default_ghost; + unsigned int default_logging; + unsigned int default_timeout; +@@ -118,11 +119,11 @@ void master_remove_mapent(struct master_mapent *); + void master_free_mapent_sources(struct master_mapent *, unsigned int); + void master_free_mapent(struct master_mapent *); + struct master *master_new(const char *, unsigned int, unsigned int); +-int master_read_master(struct master *, time_t, int); ++int master_read_master(struct master *, time_t); + int master_submount_list_empty(struct autofs_point *ap); + int master_notify_submount(struct autofs_point *, const char *path, enum states); + void master_notify_state_change(struct master *, int); +-int master_mount_mounts(struct master *, time_t, int); ++int master_mount_mounts(struct master *, time_t); + int dump_map(struct master *, const char *, const char *); + int master_show_mounts(struct master *); + unsigned int master_get_logopt(void); +diff --git a/lib/master.c b/lib/master.c +index fedf807..d87d7e2 100644 +--- a/lib/master.c ++++ b/lib/master.c +@@ -951,6 +951,7 @@ struct master *master_new(const char *name, unsigned int timeout, unsigned int f + master->depth = 0; + master->reading = 0; + master->read_fail = 0; ++ master->readall = 0; + master->default_ghost = flags & DAEMON_FLAGS_GHOST; + master->default_timeout = timeout; + master->default_logging = defaults_get_logging(); +@@ -1126,7 +1127,7 @@ again: + } + } + +-int master_read_master(struct master *master, time_t age, int readall) ++int master_read_master(struct master *master, time_t age) + { + unsigned int logopt = master->logopt; + struct mapent_cache *nc; +@@ -1157,15 +1158,15 @@ int master_read_master(struct master *master, time_t age, int readall) + master_add_amd_mount_section_mounts(master, age); + + if (!master->read_fail) +- master_mount_mounts(master, age, readall); ++ master_mount_mounts(master, age); + else { + master->read_fail = 0; +- /* HUP signal sets readall == 1 only */ +- if (!readall) { ++ /* HUP signal sets master->readall == 1 only */ ++ if (!master->readall) { + master_mutex_unlock(); + return 0; + } else +- master_mount_mounts(master, age, readall); ++ master_mount_mounts(master, age); + } + + if (list_empty(&master->mounts)) +@@ -1452,7 +1453,7 @@ static void check_update_map_sources(struct master_mapent *entry, int readall) + return; + } + +-int master_mount_mounts(struct master *master, time_t age, int readall) ++int master_mount_mounts(struct master *master, time_t age) + { + struct mapent_cache *nc = master->nc; + struct list_head *p, *head; +@@ -1536,7 +1537,7 @@ cont: + st_mutex_unlock(); + + if (!ret) +- check_update_map_sources(this, readall); ++ check_update_map_sources(this, master->readall); + else if (ret == -1 && save_errno == EBADF) { + if (!master_do_mount(this)) { + list_del_init(&this->list); diff --git a/SOURCES/autofs-5.1.6-refactor-sss-getautomntbyname.patch b/SOURCES/autofs-5.1.6-refactor-sss-getautomntbyname.patch new file mode 100644 index 0000000..c02228d --- /dev/null +++ b/SOURCES/autofs-5.1.6-refactor-sss-getautomntbyname.patch @@ -0,0 +1,172 @@ +autofs-5.1.6 - refactor sss getautomntbyname() + +From: Ian Kent + +Refactor the sss getautomntbyname_r() to consolidate the error handling +in one location. + +Also add the missing ECONREFUSED handling while we are at it. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + modules/lookup_sss.c | 110 +++++++++++++++++++++++++++++--------------------- + 2 files changed, 65 insertions(+), 46 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index e48e2c0..8b662d7 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -106,6 +106,7 @@ xx/xx/2018 autofs-5.1.5 + - move readall into struct master. + - sss introduce a flag to indicate map being read. + - update sss timeout documentation. ++- refactor sss getautomntbyname(). + + 19/12/2017 autofs-5.1.4 + - fix spec file url. +diff --git a/modules/lookup_sss.c b/modules/lookup_sss.c +index 3c0ffde..1a56ea1 100644 +--- a/modules/lookup_sss.c ++++ b/modules/lookup_sss.c +@@ -566,6 +566,39 @@ free: + return err; + } + ++static int getautomntbyname(unsigned int logopt, ++ struct lookup_context *ctxt, ++ char *key, char **value, void *sss_ctxt) ++{ ++ char buf[MAX_ERR_BUF]; ++ char *estr; ++ int ret = NSS_STATUS_UNAVAIL; ++ ++ ret = ctxt->getautomntbyname_r(key, value, sss_ctxt); ++ if (ret) { ++ /* Host has gone down */ ++ if (ret == ECONNREFUSED) ++ return NSS_STATUS_UNKNOWN; ++ ++ if (ret != ENOENT) ++ goto error; ++ ++ ret = NSS_STATUS_NOTFOUND; ++ goto free; ++ } ++ return ret; ++ ++error: ++ estr = strerror_r(ret, buf, MAX_ERR_BUF); ++ error(logopt, MODPREFIX "getautomntbyname: %s", estr); ++free: ++ if (*value) { ++ free(*value); ++ *value = NULL; ++ } ++ return ret; ++} ++ + int lookup_read_master(struct master *master, time_t age, void *context) + { + struct lookup_context *ctxt = (struct lookup_context *) context; +@@ -755,7 +788,6 @@ static int lookup_one(struct autofs_point *ap, + struct mapent *we; + void *sss_ctxt = NULL; + time_t age = monotonic_time(NULL); +- char buf[MAX_ERR_BUF]; + char *value = NULL; + char *s_key; + int ret; +@@ -770,61 +802,47 @@ static int lookup_one(struct autofs_point *ap, + if (ret) + return ret; + +- ret = ctxt->getautomntbyname_r(qKey, &value, sss_ctxt); +- if (ret && ret != ENOENT) { +- char *estr = strerror_r(ret, buf, MAX_ERR_BUF); +- error(ap->logopt, +- MODPREFIX "getautomntbyname_r: %s", estr); ++ ret = getautomntbyname(ap->logopt, ctxt, qKey, &value, sss_ctxt); ++ if (ret == NSS_STATUS_NOTFOUND) ++ goto wild; ++ if (ret) { + endautomntent(ap->logopt, ctxt, &sss_ctxt); +- if (value) +- free(value); +- return NSS_STATUS_UNAVAIL; ++ return ret; + } +- if (ret != ENOENT) { +- /* +- * TODO: implement sun % hack for key translation for +- * mixed case keys in schema that are single case only. +- */ +- s_key = sanitize_path(qKey, qKey_len, ap->type, ap->logopt); +- if (!s_key) { +- free(value); +- value = NULL; +- goto wild; +- } +- cache_writelock(mc); +- ret = cache_update(mc, source, s_key, value, age); +- cache_unlock(mc); +- endautomntent(ap->logopt, ctxt, &sss_ctxt); +- free(s_key); ++ ++ /* ++ * TODO: implement sun % hack for key translation for ++ * mixed case keys in schema that are single case only. ++ */ ++ s_key = sanitize_path(qKey, qKey_len, ap->type, ap->logopt); ++ if (!s_key) { + free(value); +- return NSS_STATUS_SUCCESS; ++ value = NULL; ++ goto wild; + } ++ cache_writelock(mc); ++ ret = cache_update(mc, source, s_key, value, age); ++ cache_unlock(mc); ++ endautomntent(ap->logopt, ctxt, &sss_ctxt); ++ free(s_key); ++ free(value); ++ return NSS_STATUS_SUCCESS; + + wild: +- ret = ctxt->getautomntbyname_r("/", &value, sss_ctxt); +- if (ret && ret != ENOENT) { +- char *estr = strerror_r(ret, buf, MAX_ERR_BUF); +- error(ap->logopt, +- MODPREFIX "getautomntbyname_r: %s", estr); +- endautomntent(ap->logopt, ctxt, &sss_ctxt); +- if (value) +- free(value); +- return NSS_STATUS_UNAVAIL; +- } +- if (ret == ENOENT) { +- ret = ctxt->getautomntbyname_r("*", &value, sss_ctxt); +- if (ret && ret != ENOENT) { +- char *estr = strerror_r(ret, buf, MAX_ERR_BUF); +- error(ap->logopt, +- MODPREFIX "getautomntbyname_r: %s", estr); ++ ret = getautomntbyname(ap->logopt, ctxt, "/", &value, sss_ctxt); ++ if (ret) { ++ if (ret != NSS_STATUS_NOTFOUND) { + endautomntent(ap->logopt, ctxt, &sss_ctxt); +- if (value) +- free(value); +- return NSS_STATUS_UNAVAIL; ++ return ret; ++ } ++ ret = getautomntbyname(ap->logopt, ctxt, "*", &value, sss_ctxt); ++ if (ret && ret != NSS_STATUS_NOTFOUND) { ++ endautomntent(ap->logopt, ctxt, &sss_ctxt); ++ return ret; + } + } + +- if (ret == ENOENT) { ++ if (ret == NSS_STATUS_NOTFOUND) { + /* Failed to find wild entry, update cache if needed */ + cache_writelock(mc); + we = cache_lookup_distinct(mc, "*"); diff --git a/SOURCES/autofs-5.1.6-refactor-sss-getautomntent.patch b/SOURCES/autofs-5.1.6-refactor-sss-getautomntent.patch new file mode 100644 index 0000000..3e83679 --- /dev/null +++ b/SOURCES/autofs-5.1.6-refactor-sss-getautomntent.patch @@ -0,0 +1,150 @@ +autofs-5.1.6 - refactor sss getautomntent() + +From: Ian Kent + +Refactor the sss getautomntent_r() to consolidate the error handling in +one location. + +Also add the missing ECONREFUSED handling while we are at it. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + modules/lookup_sss.c | 88 +++++++++++++++++++++++--------------------------- + 2 files changed, 42 insertions(+), 47 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 5ccd787..ecd54e9 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -100,6 +100,7 @@ xx/xx/2018 autofs-5.1.5 + - fix retries check in setautomntent_wait(). + - refactor sss setautomntent(). + - improve sss setautomntent() error handling. ++- refactor sss getautomntent(). + + 19/12/2017 autofs-5.1.4 + - fix spec file url. +diff --git a/modules/lookup_sss.c b/modules/lookup_sss.c +index e1ed83c..5addd87 100644 +--- a/modules/lookup_sss.c ++++ b/modules/lookup_sss.c +@@ -377,6 +377,40 @@ static int endautomntent(unsigned int logopt, + return ret; + } + ++static int getautomntent(unsigned int logopt, ++ struct lookup_context *ctxt, ++ char **key, char **value, int count, void *sss_ctxt) ++{ ++ char buf[MAX_ERR_BUF]; ++ char *estr; ++ int ret = NSS_STATUS_UNAVAIL; ++ ++ ret = ctxt->getautomntent_r(key, value, sss_ctxt); ++ if (ret) { ++ /* Host has gone down */ ++ if (ret == ECONNREFUSED) ++ return NSS_STATUS_UNKNOWN; ++ if (ret != ENOENT) ++ goto error; ++ if (!count) { ++ ret = NSS_STATUS_NOTFOUND; ++ goto free; ++ } ++ goto error; ++ } ++ return ret; ++ ++error: ++ estr = strerror_r(ret, buf, MAX_ERR_BUF); ++ error(logopt, MODPREFIX "getautomntent: %s", estr); ++free: ++ if (*key) ++ free(*key); ++ if (*value) ++ free(*value); ++ return ret; ++} ++ + int lookup_read_master(struct master *master, time_t age, void *context) + { + struct lookup_context *ctxt = (struct lookup_context *) context; +@@ -399,30 +433,12 @@ int lookup_read_master(struct master *master, time_t age, void *context) + while (1) { + key = NULL; + value = NULL; +- ret = ctxt->getautomntent_r(&key, &value, sss_ctxt); +- if (ret && ret != ENOENT) { +- char *estr = strerror_r(ret, buf, MAX_ERR_BUF); +- error(logopt, MODPREFIX "getautomntent_r: %s", estr); ++ ret = getautomntent(logopt, ctxt, &key, &value, count, sss_ctxt); ++ if (ret) { + endautomntent(logopt, ctxt, &sss_ctxt); +- if (key) +- free(key); +- if (value) +- free(value); +- return NSS_STATUS_UNAVAIL; +- } +- if (ret == ENOENT) { +- if (!count) { +- char *estr = strerror_r(ret, buf, MAX_ERR_BUF); +- error(logopt, MODPREFIX "getautomntent_r: %s", estr); +- endautomntent(logopt, ctxt, &sss_ctxt); +- if (key) +- free(key); +- if (value) +- free(value); +- return NSS_STATUS_NOTFOUND; +- } +- break; ++ return ret; + } ++ + count++; + + buffer_len = strlen(key) + 1 + strlen(value) + 2; +@@ -470,7 +486,6 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context) + struct map_source *source; + struct mapent_cache *mc; + void *sss_ctxt = NULL; +- char buf[MAX_ERR_BUF]; + char *key; + char *value = NULL; + char *s_key; +@@ -502,31 +517,10 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context) + while (1) { + key = NULL; + value = NULL; +- ret = ctxt->getautomntent_r(&key, &value, sss_ctxt); +- if (ret && ret != ENOENT) { +- char *estr = strerror_r(ret, buf, MAX_ERR_BUF); +- error(ap->logopt, +- MODPREFIX "getautomntent_r: %s", estr); ++ ret = getautomntent(ap->logopt, ctxt, &key, &value, count, sss_ctxt); ++ if (ret) { + endautomntent(ap->logopt, ctxt, &sss_ctxt); +- if (key) +- free(key); +- if (value) +- free(value); +- return NSS_STATUS_UNAVAIL; +- } +- if (ret == ENOENT) { +- if (!count) { +- char *estr = strerror_r(ret, buf, MAX_ERR_BUF); +- error(ap->logopt, +- MODPREFIX "getautomntent_r: %s", estr); +- endautomntent(ap->logopt, ctxt, &sss_ctxt); +- if (key) +- free(key); +- if (value) +- free(value); +- return NSS_STATUS_NOTFOUND; +- } +- break; ++ return ret; + } + + /* diff --git a/SOURCES/autofs-5.1.6-refactor-sss-setautomntent.patch b/SOURCES/autofs-5.1.6-refactor-sss-setautomntent.patch new file mode 100644 index 0000000..38f7357 --- /dev/null +++ b/SOURCES/autofs-5.1.6-refactor-sss-setautomntent.patch @@ -0,0 +1,198 @@ +autofs-5.1.6 - refactor sss setautomntent() + +From: Ian Kent + +Refactor the sss setautomntent() to consolidate the error handling in +one location. + +Also move the number of retries calculation into the wait function +as it's a much more sensible place for it. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + modules/lookup_sss.c | 106 +++++++++++++++++++++++--------------------------- + 2 files changed, 49 insertions(+), 58 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index b3ffbb6..141658d 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -98,6 +98,7 @@ xx/xx/2018 autofs-5.1.5 + - use mapname in sss context for setautomntent(). + - add support for new sss autofs proto version call. + - fix retries check in setautomntent_wait(). ++- refactor sss setautomntent(). + + 19/12/2017 autofs-5.1.4 + - fix spec file url. +diff --git a/modules/lookup_sss.c b/modules/lookup_sss.c +index d65e71c..011b232 100644 +--- a/modules/lookup_sss.c ++++ b/modules/lookup_sss.c +@@ -232,20 +232,6 @@ int lookup_reinit(const char *mapfmt, + return 0; + } + +-static int setautomntent(unsigned int logopt, +- struct lookup_context *ctxt, void **sss_ctxt) +-{ +- int ret = ctxt->setautomntent(ctxt->mapname, sss_ctxt); +- if (ret) { +- char buf[MAX_ERR_BUF]; +- char *estr = strerror_r(ret, buf, MAX_ERR_BUF); +- error(logopt, MODPREFIX "setautomntent: %s", estr); +- if (*sss_ctxt) +- free(*sss_ctxt); +- } +- return ret; +-} +- + static unsigned int proto_version(struct lookup_context *ctxt) + { + unsigned int proto_version = 0; +@@ -264,14 +250,18 @@ static unsigned int proto_version(struct lookup_context *ctxt) + } + + static int setautomntent_wait(unsigned int logopt, +- struct lookup_context *ctxt, +- void **sss_ctxt, unsigned int retries) ++ struct lookup_context *ctxt, void **sss_ctxt) + { ++ unsigned int retries; + unsigned int retry = 0; + int ret = 0; + + *sss_ctxt = NULL; + ++ retries = defaults_get_sss_master_map_wait(); ++ if (retries <= 0) ++ return ENOENT; ++ + while (++retry <= retries) { + struct timespec t = { SSS_WAIT_INTERVAL, 0 }; + struct timespec r; +@@ -291,9 +281,6 @@ static int setautomntent_wait(unsigned int logopt, + + + if (ret) { +- char buf[MAX_ERR_BUF]; +- char *estr; +- + if (*sss_ctxt) { + free(*sss_ctxt); + *sss_ctxt = NULL; +@@ -301,14 +288,47 @@ static int setautomntent_wait(unsigned int logopt, + + if (retry > retries) + ret = ETIMEDOUT; +- +- estr = strerror_r(ret, buf, MAX_ERR_BUF); +- error(logopt, MODPREFIX "setautomntent: %s", estr); + } + + return ret; + } + ++static int setautomntent(unsigned int logopt, ++ struct lookup_context *ctxt, void **sss_ctxt) ++{ ++ char buf[MAX_ERR_BUF]; ++ char *estr; ++ int ret; ++ ++ ret = ctxt->setautomntent(ctxt->mapname, sss_ctxt); ++ if (ret) { ++ if (ret == ECONNREFUSED) ++ return NSS_STATUS_UNKNOWN; ++ ++ if (ret != ENOENT) ++ goto error; ++ ++ ret = setautomntent_wait(logopt, ctxt, sss_ctxt); ++ if (ret) { ++ if (ret == ECONNREFUSED) ++ return NSS_STATUS_UNKNOWN; ++ if (ret == ENOENT) ++ return NSS_STATUS_NOTFOUND; ++ goto error; ++ } ++ } ++ return ret; ++ ++error: ++ estr = strerror_r(ret, buf, MAX_ERR_BUF); ++ error(logopt, MODPREFIX "setautomntent: %s", estr); ++ if (*sss_ctxt) { ++ free(*sss_ctxt); ++ *sss_ctxt = NULL; ++ } ++ return NSS_STATUS_UNAVAIL; ++} ++ + static int endautomntent(unsigned int logopt, + struct lookup_context *ctxt, void **sss_ctxt) + { +@@ -336,28 +356,8 @@ int lookup_read_master(struct master *master, time_t age, void *context) + int count, ret; + + ret = setautomntent(logopt, ctxt, &sss_ctxt); +- if (ret) { +- unsigned int retries; +- +- if (ret == ECONNREFUSED) +- return NSS_STATUS_UNKNOWN; +- +- if (ret != ENOENT) +- return NSS_STATUS_UNAVAIL; +- +- retries = defaults_get_sss_master_map_wait(); +- if (retries <= 0) +- return NSS_STATUS_NOTFOUND; +- +- ret = setautomntent_wait(logopt, ctxt, &sss_ctxt, retries); +- if (ret) { +- if (ret == ECONNREFUSED) +- return NSS_STATUS_UNKNOWN; +- if (ret == ENOENT) +- return NSS_STATUS_NOTFOUND; +- return NSS_STATUS_UNAVAIL; +- } +- } ++ if (ret) ++ return ret; + + count = 0; + while (1) { +@@ -459,13 +459,8 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context) + } + + ret = setautomntent(ap->logopt, ctxt, &sss_ctxt); +- if (ret) { +- if (ret == ECONNREFUSED) +- return NSS_STATUS_UNKNOWN; +- if (ret == ENOENT) +- return NSS_STATUS_NOTFOUND; +- return NSS_STATUS_UNAVAIL; +- } ++ if (ret) ++ return ret; + + count = 0; + while (1) { +@@ -571,13 +566,8 @@ static int lookup_one(struct autofs_point *ap, + mc = source->mc; + + ret = setautomntent(ap->logopt, ctxt, &sss_ctxt); +- if (ret) { +- if (ret == ECONNREFUSED) +- return NSS_STATUS_UNKNOWN; +- if (ret == ENOENT) +- return NSS_STATUS_NOTFOUND; +- return NSS_STATUS_UNAVAIL; +- } ++ if (ret) ++ return ret; + + ret = ctxt->getautomntbyname_r(qKey, &value, sss_ctxt); + if (ret && ret != ENOENT) { diff --git a/SOURCES/autofs-5.1.6-simplify-sss-source-stale-check.patch b/SOURCES/autofs-5.1.6-simplify-sss-source-stale-check.patch new file mode 100644 index 0000000..16adf90 --- /dev/null +++ b/SOURCES/autofs-5.1.6-simplify-sss-source-stale-check.patch @@ -0,0 +1,120 @@ +autofs-5.1.6 - simplify sss source stale check + +From: Ian Kent + +Now that there's a positive timeout on valid map cache entries +simplifying the map stale checks should be able to be done, and +eventually this will be much simpler in a lot of places. + +Start with the key lookup in the sss lookup module since that's +needed to prevent recently retrieved map keys from being pruned +immediately after being used since the existing check wasn't +working and was questionable anyway (and likely hadn't for worked +some time). + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + modules/lookup_sss.c | 47 ++++++++++------------------------------------- + 2 files changed, 11 insertions(+), 37 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 34b160e..e9c7a59 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -110,6 +110,7 @@ xx/xx/2018 autofs-5.1.5 + - improve sss getautomntbyname() error handling. + - use a valid timeout in lookup_prune_one_cache(). + - dont prune offset map entries. ++- simplify sss source stale check. + + 19/12/2017 autofs-5.1.4 + - fix spec file url. +diff --git a/modules/lookup_sss.c b/modules/lookup_sss.c +index 70efc11..69be765 100644 +--- a/modules/lookup_sss.c ++++ b/modules/lookup_sss.c +@@ -869,7 +869,7 @@ static int lookup_one(struct autofs_point *ap, + time_t age = monotonic_time(NULL); + char *value = NULL; + char *s_key; +- int ret; ++ int err, ret; + + source = ap->entry->current; + ap->entry->current = NULL; +@@ -901,8 +901,11 @@ static int lookup_one(struct autofs_point *ap, + goto wild; + } + cache_writelock(mc); +- ret = cache_update(mc, source, s_key, value, age); ++ err = cache_update(mc, source, s_key, value, age); + cache_unlock(mc); ++ /* Entry in map but not in cache, map is stale */ ++ if (err & CHE_UPDATED) ++ source->stale = 1; + endautomntent(ap->logopt, ctxt, &sss_ctxt); + free(s_key); + free(value); +@@ -952,12 +955,12 @@ wild: + } + + cache_writelock(mc); +- /* Wildcard not in map but now is */ +- we = cache_lookup_distinct(mc, "*"); +- if (!we) +- source->stale = 1; +- ret = cache_update(mc, source, "*", value, age); ++ /* Wildcard in map but not in cache, update it */ ++ err = cache_update(mc, source, "*", value, age); + cache_unlock(mc); ++ /* Wildcard in map but not in cache, map is stale */ ++ if (err & CHE_UPDATED) ++ source->stale = 1; + + endautomntent(ap->logopt, ctxt, &sss_ctxt); + free(value); +@@ -971,9 +974,6 @@ static int check_map_indirect(struct autofs_point *ap, + { + struct map_source *source; + struct mapent_cache *mc; +- struct mapent *me; +- time_t now = monotonic_time(NULL); +- time_t t_last_read; + int ret, cur_state; + + source = ap->entry->current; +@@ -1009,33 +1009,6 @@ static int check_map_indirect(struct autofs_point *ap, + } + pthread_setcancelstate(cur_state, NULL); + +- /* +- * Check for map change and update as needed for +- * following cache lookup. +- */ +- cache_readlock(mc); +- t_last_read = ap->exp_runfreq + 1; +- me = cache_lookup_first(mc); +- while (me) { +- if (me->source == source) { +- t_last_read = now - me->age; +- break; +- } +- me = cache_lookup_next(mc, me); +- } +- cache_unlock(mc); +- +- if (t_last_read > ap->exp_runfreq && ret & CHE_UPDATED) +- source->stale = 1; +- +- cache_readlock(mc); +- me = cache_lookup_distinct(mc, "*"); +- if (ret == CHE_MISSING && (!me || me->source != source)) { +- cache_unlock(mc); +- return NSS_STATUS_NOTFOUND; +- } +- cache_unlock(mc); +- + return NSS_STATUS_SUCCESS; + } + diff --git a/SOURCES/autofs-5.1.6-sss-introduce-a-flag-to-indicate-map-being-read.patch b/SOURCES/autofs-5.1.6-sss-introduce-a-flag-to-indicate-map-being-read.patch new file mode 100644 index 0000000..18c420b --- /dev/null +++ b/SOURCES/autofs-5.1.6-sss-introduce-a-flag-to-indicate-map-being-read.patch @@ -0,0 +1,235 @@ +autofs-5.1.6 - sss introduce a flag to indicate map being read + +From: Ian Kent + +When the master map is being read for the first time a retry loop is +used by the caller to try harder to read the master map because it +is required for autofs to start up. + +But when re-reading the master map, reading dependent maps, or doing +key lookups that loop isn't used so a longer retry is needed for those +cases. + +Introduce a flag to indicate which map is being read, or if the master +map is being re-read, or if a key lookup is being done so the number +of retries can be adjusted accordingly. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + modules/lookup_sss.c | 87 +++++++++++++++++++++++++++++++++++++++++--------- + 2 files changed, 72 insertions(+), 16 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 4a6c042..2d98a3a 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -104,6 +104,7 @@ xx/xx/2018 autofs-5.1.5 + - improve sss getautomntent() error handling. + - sss introduce calculate_retry_count() function. + - move readall into struct master. ++- sss introduce a flag to indicate map being read. + + 19/12/2017 autofs-5.1.4 + - fix spec file url. +diff --git a/modules/lookup_sss.c b/modules/lookup_sss.c +index 29666a3..3c0ffde 100644 +--- a/modules/lookup_sss.c ++++ b/modules/lookup_sss.c +@@ -53,6 +53,24 @@ + */ + #define SSS_PROTO_VERSION 1 + ++#define SSS_DEFAULT_WAIT 10 ++ ++/* When the master map is being read a retry loop is used by the ++ * caller to try harder to read the master map because it is required ++ * for autofs to start up. ++ * ++ * But when reading dependent maps or looking up a key that loop isn't ++ * used so a longer retry is needed for those cases. ++ * ++ * Introduce a flag to indicate which map is being read or if a lookup ++ * is being done so the number of retries can be adjusted accordingly. ++ */ ++#define SSS_READ_NONE 0x00 ++#define SSS_READ_MASTER_MAP 0x01 ++#define SSS_REREAD_MASTER_MAP 0x02 ++#define SSS_READ_DEPENDENT_MAP 0x04 ++#define SSS_LOOKUP_KEY 0x08 ++ + unsigned int _sss_auto_protocol_version(unsigned int); + int _sss_setautomntent(const char *, void **); + int _sss_getautomntent_r(char **, char **, void *); +@@ -249,7 +267,7 @@ static unsigned int proto_version(struct lookup_context *ctxt) + return proto_version; + } + +-static unsigned int calculate_retry_count(struct lookup_context *ctxt) ++static unsigned int calculate_retry_count(struct lookup_context *ctxt, unsigned int flags) + { + int retries; + +@@ -269,15 +287,39 @@ static unsigned int calculate_retry_count(struct lookup_context *ctxt) + * a host being down, return 0 for retries. + */ + if (proto_version(ctxt) == 0) +- retries = 0; ++ return 0; + else +- retries = 10; ++ retries = SSS_DEFAULT_WAIT; + } ++ ++ if (proto_version(ctxt) == 0) ++ return retries; ++ ++ /* When the master map is being read there's an additional ++ * outer wait loop. ++ * ++ * If master map wait is set in the configuration there ++ * will be an outer loop interating master_map_wait / 2 ++ * times so adjust the number of retries here to account ++ * for this for the cases where the master map isn't being ++ * read. ++ */ ++ ++ if (!(flags & SSS_READ_MASTER_MAP) || ++ (flags & SSS_REREAD_MASTER_MAP)) { ++ unsigned int master_map_wait = defaults_get_master_wait(); ++ unsigned int m_wait; ++ ++ m_wait = master_map_wait ? master_map_wait : SSS_DEFAULT_WAIT; ++ retries *= (m_wait / 2); ++ } ++ + return retries; + } + + static int setautomntent_wait(unsigned int logopt, +- struct lookup_context *ctxt, void **sss_ctxt) ++ struct lookup_context *ctxt, void **sss_ctxt, ++ unsigned int flags) + { + unsigned int retries; + unsigned int retry = 0; +@@ -285,7 +327,7 @@ static int setautomntent_wait(unsigned int logopt, + + *sss_ctxt = NULL; + +- retries = calculate_retry_count(ctxt); ++ retries = calculate_retry_count(ctxt, flags); + if (retries == 0) { + if (proto_version(ctxt) == 0) + return EINVAL; +@@ -333,7 +375,8 @@ static int setautomntent_wait(unsigned int logopt, + } + + static int setautomntent(unsigned int logopt, +- struct lookup_context *ctxt, void **sss_ctxt) ++ struct lookup_context *ctxt, void **sss_ctxt, ++ unsigned int flags) + { + char buf[MAX_ERR_BUF]; + char *estr; +@@ -355,7 +398,7 @@ static int setautomntent(unsigned int logopt, + goto error; + } + +- ret = setautomntent_wait(logopt, ctxt, sss_ctxt); ++ ret = setautomntent_wait(logopt, ctxt, sss_ctxt, flags); + if (ret) { + if (ret == ECONNREFUSED) { + err = NSS_STATUS_UNKNOWN; +@@ -400,13 +443,14 @@ static int endautomntent(unsigned int logopt, + + static int getautomntent_wait(unsigned int logopt, + struct lookup_context *ctxt, +- char **key, char **value, void *sss_ctxt) ++ char **key, char **value, void *sss_ctxt, ++ unsigned int flags) + { + unsigned int retries; + unsigned int retry = 0; + int ret = 0; + +- retries = calculate_retry_count(ctxt); ++ retries = calculate_retry_count(ctxt, flags); + if (retries == 0) { + if (proto_version(ctxt) == 0) + return EINVAL; +@@ -446,7 +490,8 @@ static int getautomntent_wait(unsigned int logopt, + + static int getautomntent(unsigned int logopt, + struct lookup_context *ctxt, +- char **key, char **value, int count, void *sss_ctxt) ++ char **key, char **value, int count, ++ void *sss_ctxt, unsigned int flags) + { + char buf[MAX_ERR_BUF]; + char *estr; +@@ -486,7 +531,7 @@ static int getautomntent(unsigned int logopt, + } + + ret = getautomntent_wait(logopt, ctxt, +- key, value, sss_ctxt); ++ key, value, sss_ctxt, flags); + if (ret) { + if (ret == ECONNREFUSED) { + err = NSS_STATUS_UNKNOWN; +@@ -534,8 +579,13 @@ int lookup_read_master(struct master *master, time_t age, void *context) + char *key; + char *value = NULL; + int count, ret; ++ unsigned int flags; ++ ++ flags = SSS_READ_MASTER_MAP; ++ if (master->readall) ++ flags |= SSS_REREAD_MASTER_MAP; + +- ret = setautomntent(logopt, ctxt, &sss_ctxt); ++ ret = setautomntent(logopt, ctxt, &sss_ctxt, flags); + if (ret) + return ret; + +@@ -543,7 +593,9 @@ int lookup_read_master(struct master *master, time_t age, void *context) + while (1) { + key = NULL; + value = NULL; +- ret = getautomntent(logopt, ctxt, &key, &value, count, sss_ctxt); ++ ret = getautomntent(logopt, ctxt, ++ &key, &value, count, ++ sss_ctxt, SSS_READ_MASTER_MAP); + if (ret) { + endautomntent(logopt, ctxt, &sss_ctxt); + return ret; +@@ -622,7 +674,8 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context) + return NSS_STATUS_SUCCESS; + } + +- ret = setautomntent(ap->logopt, ctxt, &sss_ctxt); ++ ret = setautomntent(ap->logopt, ctxt, ++ &sss_ctxt, SSS_READ_DEPENDENT_MAP); + if (ret) + return ret; + +@@ -630,7 +683,9 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context) + while (1) { + key = NULL; + value = NULL; +- ret = getautomntent(ap->logopt, ctxt, &key, &value, count, sss_ctxt); ++ ret = getautomntent(ap->logopt, ctxt, ++ &key, &value, count, ++ sss_ctxt, SSS_READ_DEPENDENT_MAP); + if (ret) { + endautomntent(ap->logopt, ctxt, &sss_ctxt); + return ret; +@@ -711,7 +766,7 @@ static int lookup_one(struct autofs_point *ap, + + mc = source->mc; + +- ret = setautomntent(ap->logopt, ctxt, &sss_ctxt); ++ ret = setautomntent(ap->logopt, ctxt, &sss_ctxt, SSS_LOOKUP_KEY); + if (ret) + return ret; + diff --git a/SOURCES/autofs-5.1.6-sss-introduce-retries-calcuation-function.patch b/SOURCES/autofs-5.1.6-sss-introduce-retries-calcuation-function.patch new file mode 100644 index 0000000..0661da6 --- /dev/null +++ b/SOURCES/autofs-5.1.6-sss-introduce-retries-calcuation-function.patch @@ -0,0 +1,133 @@ +autofs-5.1.6 - sss introduce calculate_retry_count() function + +From: Ian Kent + +Add a function calculate_retry_count() to consolidate the calculation +of the retry count into a single location. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + modules/lookup_sss.c | 62 ++++++++++++++++++++++++++++++-------------------- + 2 files changed, 38 insertions(+), 25 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 434e23d..4d83df2 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -102,6 +102,7 @@ xx/xx/2018 autofs-5.1.5 + - improve sss setautomntent() error handling. + - refactor sss getautomntent(). + - improve sss getautomntent() error handling. ++- sss introduce calculate_retry_count() function. + + 19/12/2017 autofs-5.1.4 + - fix spec file url. +diff --git a/modules/lookup_sss.c b/modules/lookup_sss.c +index f366b48..29666a3 100644 +--- a/modules/lookup_sss.c ++++ b/modules/lookup_sss.c +@@ -249,14 +249,9 @@ static unsigned int proto_version(struct lookup_context *ctxt) + return proto_version; + } + +-static int setautomntent_wait(unsigned int logopt, +- struct lookup_context *ctxt, void **sss_ctxt) ++static unsigned int calculate_retry_count(struct lookup_context *ctxt) + { +- unsigned int retries; +- unsigned int retry = 0; +- int ret = 0; +- +- *sss_ctxt = NULL; ++ int retries; + + retries = defaults_get_sss_master_map_wait(); + +@@ -264,14 +259,37 @@ static int setautomntent_wait(unsigned int logopt, + * configuration give it a sensible value since we + * want to wait for a host that's down in case it + * comes back up. ++ * ++ * Use the sss_master_map_wait configuration option ++ * for the time to wait when reading a dependednt map ++ * or performing a key lookup too. + */ + if (retries <= 0) { + /* Protocol version 0 cant't tell us about +- * a host being down, return not found. ++ * a host being down, return 0 for retries. + */ + if (proto_version(ctxt) == 0) +- return ENOENT; +- retries = 10; ++ retries = 0; ++ else ++ retries = 10; ++ } ++ return retries; ++} ++ ++static int setautomntent_wait(unsigned int logopt, ++ struct lookup_context *ctxt, void **sss_ctxt) ++{ ++ unsigned int retries; ++ unsigned int retry = 0; ++ int ret = 0; ++ ++ *sss_ctxt = NULL; ++ ++ retries = calculate_retry_count(ctxt); ++ if (retries == 0) { ++ if (proto_version(ctxt) == 0) ++ return EINVAL; ++ return ENOENT; + } + + warn(logopt, +@@ -345,6 +363,9 @@ static int setautomntent(unsigned int logopt, + } + if (ret == ETIMEDOUT) + goto error; ++ /* sss proto version 0 and sss timeout not set */ ++ if (ret == EINVAL) ++ goto free; + if (ret == ENOENT) { + err = NSS_STATUS_NOTFOUND; + goto free; +@@ -385,21 +406,11 @@ static int getautomntent_wait(unsigned int logopt, + unsigned int retry = 0; + int ret = 0; + +- retries = defaults_get_sss_master_map_wait(); +- +- /* Use the sss_master_map_wait configuration option +- * for the time to wait when reading a map too. If +- * it isn't set in the antofs configuration give it +- * a sensible value since we want to wait for a host +- * that's down in case it comes back up. +- */ +- if (retries <= 0) { +- /* Protocol version 0 cant't tell us about +- * a host being down, return not found. +- */ ++ retries = calculate_retry_count(ctxt); ++ if (retries == 0) { + if (proto_version(ctxt) == 0) +- return ENOENT; +- retries = 10; ++ return EINVAL; ++ return ENOENT; + } + + warn(logopt, +@@ -483,7 +494,8 @@ static int getautomntent(unsigned int logopt, + } + if (ret == ETIMEDOUT) + goto error; +- if (ret == ENOENT) { ++ /* sss proto version 0 and sss timeout not set => EINVAL */ ++ if (ret == ENOENT || ret == EINVAL) { + err = NSS_STATUS_NOTFOUND; + if (count) + err = NSS_STATUS_SUCCESS; diff --git a/SOURCES/autofs-5.1.6-update-sss-timeout-documentation.patch b/SOURCES/autofs-5.1.6-update-sss-timeout-documentation.patch new file mode 100644 index 0000000..0954604 --- /dev/null +++ b/SOURCES/autofs-5.1.6-update-sss-timeout-documentation.patch @@ -0,0 +1,155 @@ +autofs-5.1.6 - update sss timeout documentation + +From: Ian Kent + +Update then man page documentation and the configuration file +comments to reflect the changes to map reading and key lookups +with the sss lookup module. +--- + CHANGELOG | 1 + + man/autofs.conf.5.in | 20 +++++++++++++------- + redhat/autofs.conf.default.in | 28 +++++++++++++++++++--------- + samples/autofs.conf.default.in | 26 ++++++++++++++++++-------- + 4 files changed, 51 insertions(+), 24 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 2d98a3a..e48e2c0 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -105,6 +105,7 @@ xx/xx/2018 autofs-5.1.5 + - sss introduce calculate_retry_count() function. + - move readall into struct master. + - sss introduce a flag to indicate map being read. ++- update sss timeout documentation. + + 19/12/2017 autofs-5.1.4 + - fix spec file url. +diff --git a/man/autofs.conf.5.in b/man/autofs.conf.5.in +index 8dbc313..57dd421 100644 +--- a/man/autofs.conf.5.in ++++ b/man/autofs.conf.5.in +@@ -31,9 +31,11 @@ overrides this and sets the timeout to 5 minutes to be consistent + with earlier autofs releases. + .TP + .B master_wait +-sets the default maximum time to wait for the master map to become +-available if it cannot be read at program start (program default 10, +-wait for 10 seconds then continue). ++Sets the default maximum number of retries (actaul iterations is half ++this, each is delayed by 2 seconds before retrying) waiting for the ++master map to become available if it cannot be read at program start ++(program default 10, then continue). This can be longer if the map ++source itself waits for availability (such as sss). + .TP + .B negative_timeout + .br +@@ -160,10 +162,14 @@ behaviour and so is an opt-in setting. + .TP + .B sss_master_map_wait + .br +-Set the time to wait and retry if sssd returns "no such entry" when starting +-up. When sssd is starting up it can sometimes return "no such entry" for a +-short time until it has read in the LDAP map information. Default is 0 seconds, +-don't wait. ++Set the time to wait and retry if sssd is unable to read the master map ++at program start. Program default is 0 (don't wait) or 10 if sss supports ++returning EHSTDOWN when the provider isn't available. ++ ++If the sss library supports returning EHOSTDOWN when the provider is down ++then this value is how long to wait between retries reading the master map. ++When reading dependent maps or looking up a map key this value is multiplied ++by the number of retries that would be used when reading the master map. + .TP + .B use_mount_request_log_id + .br +diff --git a/redhat/autofs.conf.default.in b/redhat/autofs.conf.default.in +index bd52730..2a5a1c2 100644 +--- a/redhat/autofs.conf.default.in ++++ b/redhat/autofs.conf.default.in +@@ -14,10 +14,13 @@ + # + timeout = 300 + # +-# master_wait - set the default maximum time to wait for the +-# master map to become available if it cannot +-# be read at program start (default 10, wait +-# for 10 seconds then continue). ++# master_wait - set the default maximum number of retries (actual ++# iterations is half this, each is delayed by 2 seconds ++# before retrying) waiting for the master map to become ++# available if it cannot be read at program start ++# (default 10, then continue). This can be longer ++# if the map source itself waits for availability ++# (such as sss). + # + #master_wait = 10 + # +@@ -193,12 +196,19 @@ mount_nfs_default_protocol = 4 + #use_ignore_mount_option = no + # + # sss_master_map_wait - When sssd is starting up it can sometimes return +-# "no such entry" for a short time until it has read ++# "no such entry" for a short time until it has read + # in the LDAP map information. Internal default is 0 +-# seconds, don't wait but if there is a problem with +-# autofs not finding the master map at startup (when +-# it should) then try setting this to 10 to work +-# around it. ++# (don't wait) or 10 if sss supports returning EHSTDOWN. ++# If there is a problem with autofs not finding the ++# master map at startup (when it should) then try setting ++# this to 10 or more. If the sss library supports returning ++# EHOSTDOWN when the provider is down then this value ++# is how long to wait between retries reading the ++# master map. When reading dependent maps or looking ++# up a map key this value is multiplied by the number ++# of retries that would be used when reading the master ++# map. (Default, 0 or 10 if sss suppprts returning ++# EHOSTDOWN). + # + #sss_master_map_wait = 0 + # +diff --git a/samples/autofs.conf.default.in b/samples/autofs.conf.default.in +index 1f55709..dd716c6 100644 +--- a/samples/autofs.conf.default.in ++++ b/samples/autofs.conf.default.in +@@ -14,10 +14,13 @@ + # + timeout = 300 + # +-# master_wait - set the default maximum time to wait for the +-# master map to become available if it cannot +-# be read at program start (default 10, wait +-# for 10 seconds then continue). ++# master_wait - set the default maximum number of retries (actual ++# iterations is half this, each is delayed by 2 seconds ++# before retrying) waiting for the master map to become ++# available if it cannot be read at program start ++# (default 10, then continue). This can be longer ++# if the map source itself waits for availability ++# (such as sss). + # + # master_wait = 10 + # +@@ -194,10 +197,17 @@ browse_mode = no + # sss_master_map_wait - When sssd is starting up it can sometimes return + # "no such entry" for a short time until it has read + # in the LDAP map information. Internal default is 0 +-# seconds, don't wait but if there is a problem with +-# autofs not finding the master map at startup (when +-# it should) then try setting this to 10 to work +-# around it. ++# (don't wait) or 10 if sss supports returning EHSTDOWN. ++# If there is a problem with autofs not finding the ++# master map at startup (when it should) then try setting ++# this to 10 or more. If the sss library supports returning ++# EHOSTDOWN when the provider is down then this value ++# is how long to wait between retries reading the ++# master map. When reading dependent maps or looking ++# up a map key this value is multiplied by the number ++# of retries that would be used when reading the master ++# map. (Default, 0 or 10 if sss suppprts returning ++# EHOSTDOWN). + # + #sss_master_map_wait = 0 + # diff --git a/SOURCES/autofs-5.1.6-use-a-valid-timeout-in-lookup_prune_one_cache.patch b/SOURCES/autofs-5.1.6-use-a-valid-timeout-in-lookup_prune_one_cache.patch new file mode 100644 index 0000000..561f35d --- /dev/null +++ b/SOURCES/autofs-5.1.6-use-a-valid-timeout-in-lookup_prune_one_cache.patch @@ -0,0 +1,78 @@ +autofs-5.1.6 - use a valid timeout in lookup_prune_one_cache() + +From: Ian Kent + +For a very long time the map entry cache has been allowed to grow +without pruning old entries until a map read is needed and there's +been a constant struggle to set the map stale only when really needed +so that in use entries aren't pruned. + +But somewhere along the line that's become broken and the sss error +handling updates don't work properly because of this (or rather don't +work well). + +Add a positive map entry cache timeout so that recently seen map +entries don't get removed in the map read following the lookup that +added them when the map isn't actually read such as with nobrowse +indirect mounts. + +The valid timeout probably should become configurable at some point +too. + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + daemon/lookup.c | 15 +++++++++++++++ + include/automount.h | 1 + + 3 files changed, 17 insertions(+) + +diff --git a/CHANGELOG b/CHANGELOG +index 309def2..3608345 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -108,6 +108,7 @@ xx/xx/2018 autofs-5.1.5 + - update sss timeout documentation. + - refactor sss getautomntbyname(). + - improve sss getautomntbyname() error handling. ++- use a valid timeout in lookup_prune_one_cache(). + + 19/12/2017 autofs-5.1.4 + - fix spec file url. +diff --git a/daemon/lookup.c b/daemon/lookup.c +index 2b9c7e8..8bf1335 100644 +--- a/daemon/lookup.c ++++ b/daemon/lookup.c +@@ -1354,6 +1354,21 @@ void lookup_prune_one_cache(struct autofs_point *ap, struct mapent_cache *mc, ti + continue; + } + ++ if (ap->type == LKP_INDIRECT) { ++ /* If the map hasn't been read (nobrowse ++ * indirect mounts) then keep cached entries ++ * for POSITIVE_TIMEOUT. ++ */ ++ if (!(ap->flags & (MOUNT_FLAG_GHOST | ++ MOUNT_FLAG_AMD_CACHE_ALL))) { ++ time_t until = me->age + POSITIVE_TIMEOUT; ++ if ((long) age - (long) until < 0) { ++ me = cache_enumerate(mc, me); ++ continue; ++ } ++ } ++ } ++ + key = strdup(me->key); + me = cache_enumerate(mc, me); + /* Don't consider any entries with a wildcard */ +diff --git a/include/automount.h b/include/automount.h +index 49c9ff9..bb264a1 100644 +--- a/include/automount.h ++++ b/include/automount.h +@@ -139,6 +139,7 @@ struct autofs_point; + + #define NULL_MAP_HASHSIZE 64 + #define NEGATIVE_TIMEOUT 10 ++#define POSITIVE_TIMEOUT 120 + #define UMOUNT_RETRIES 8 + #define EXPIRE_RETRIES 3 + diff --git a/SOURCES/autofs-5.1.6-use-mapname-in-sss-context-for-setautomntent.patch b/SOURCES/autofs-5.1.6-use-mapname-in-sss-context-for-setautomntent.patch new file mode 100644 index 0000000..5eb8e18 --- /dev/null +++ b/SOURCES/autofs-5.1.6-use-mapname-in-sss-context-for-setautomntent.patch @@ -0,0 +1,96 @@ +autofs-5.1.6 - use mapname in sss context for setautomntent() + +From: Ian Kent + +There's no need to pass mapname seperately when calling setautomntent(). + +Signed-off-by: Ian Kent +--- + CHANGELOG | 1 + + modules/lookup_sss.c | 18 +++++++----------- + 2 files changed, 8 insertions(+), 11 deletions(-) + +diff --git a/CHANGELOG b/CHANGELOG +index 2a45829..1830730 100644 +--- a/CHANGELOG ++++ b/CHANGELOG +@@ -95,6 +95,7 @@ xx/xx/2018 autofs-5.1.5 + - fix typo in open_sss_lib(). + - fix sss_master_map_wait timing. + - add sss ECONREFUSED return handling. ++- use mapname in sss context for setautomntent(). + + 19/12/2017 autofs-5.1.4 + - fix spec file url. +diff --git a/modules/lookup_sss.c b/modules/lookup_sss.c +index c393296..c44c55d 100644 +--- a/modules/lookup_sss.c ++++ b/modules/lookup_sss.c +@@ -206,10 +206,9 @@ int lookup_reinit(const char *mapfmt, + } + + static int setautomntent(unsigned int logopt, +- struct lookup_context *ctxt, const char *mapname, +- void **sss_ctxt) ++ struct lookup_context *ctxt, void **sss_ctxt) + { +- int ret = ctxt->setautomntent(mapname, sss_ctxt); ++ int ret = ctxt->setautomntent(ctxt->mapname, sss_ctxt); + if (ret) { + char buf[MAX_ERR_BUF]; + char *estr = strerror_r(ret, buf, MAX_ERR_BUF); +@@ -222,7 +221,6 @@ static int setautomntent(unsigned int logopt, + + static int setautomntent_wait(unsigned int logopt, + struct lookup_context *ctxt, +- const char *mapname, + void **sss_ctxt, unsigned int retries) + { + unsigned int retry = 0; +@@ -234,7 +232,7 @@ static int setautomntent_wait(unsigned int logopt, + struct timespec t = { SSS_WAIT_INTERVAL, 0 }; + struct timespec r; + +- ret = ctxt->setautomntent(mapname, sss_ctxt); ++ ret = ctxt->setautomntent(ctxt->mapname, sss_ctxt); + if (ret != ENOENT) + break; + +@@ -293,7 +291,7 @@ int lookup_read_master(struct master *master, time_t age, void *context) + char *value = NULL; + int count, ret; + +- ret = setautomntent(logopt, ctxt, ctxt->mapname, &sss_ctxt); ++ ret = setautomntent(logopt, ctxt, &sss_ctxt); + if (ret) { + unsigned int retries; + +@@ -307,9 +305,7 @@ int lookup_read_master(struct master *master, time_t age, void *context) + if (retries <= 0) + return NSS_STATUS_NOTFOUND; + +- ret = setautomntent_wait(logopt, +- ctxt, ctxt->mapname, &sss_ctxt, +- retries); ++ ret = setautomntent_wait(logopt, ctxt, &sss_ctxt, retries); + if (ret) { + if (ret == ECONNREFUSED) + return NSS_STATUS_UNKNOWN; +@@ -418,7 +414,7 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context) + return NSS_STATUS_SUCCESS; + } + +- ret = setautomntent(ap->logopt, ctxt, ctxt->mapname, &sss_ctxt); ++ ret = setautomntent(ap->logopt, ctxt, &sss_ctxt); + if (ret) { + if (ret == ECONNREFUSED) + return NSS_STATUS_UNKNOWN; +@@ -530,7 +526,7 @@ static int lookup_one(struct autofs_point *ap, + + mc = source->mc; + +- ret = setautomntent(ap->logopt, ctxt, ctxt->mapname, &sss_ctxt); ++ ret = setautomntent(ap->logopt, ctxt, &sss_ctxt); + if (ret) { + if (ret == ECONNREFUSED) + return NSS_STATUS_UNKNOWN; diff --git a/SPECS/autofs.spec b/SPECS/autofs.spec index 5a55891..79146dd 100644 --- a/SPECS/autofs.spec +++ b/SPECS/autofs.spec @@ -8,7 +8,7 @@ Summary: A tool for automatically mounting and unmounting filesystems Name: autofs Version: 5.1.4 -Release: 47%{?dist} +Release: 48%{?dist} Epoch: 1 License: GPLv2+ Group: System Environment/Daemons @@ -113,6 +113,27 @@ Patch96: autofs-5.1.6-remove-logpri-fifo-on-autofs-mount-fail.patch Patch97: autofs-5.1.6-add-force-unlink-mounts-and-exit-option.patch Patch98: autofs-5.1.6-cleanup-stale-logpri-fifo-pipes-on-unlink-and-exit.patch +Patch100: autofs-5.1.6-fix-lookup_nss_read_master-nsswicth-check-return.patch +Patch101: autofs-5.1.6-fix-typo-in-open_sss_lib.patch +Patch102: autofs-5.1.6-fix-sss-master-map-wait-timing.patch +Patch103: autofs-5.1.6-add-sss-ECONREFUSED-return-handling.patch +Patch104: autofs-5.1.6-use-mapname-in-sss-context-for-setautomntent.patch +Patch105: autofs-5.1.6-add-support-for-new-sss-autofs-proto-version-call.patch +Patch106: autofs-5.1.6-fix-retries-check-in-setautomntent_wait.patch +Patch107: autofs-5.1.6-refactor-sss-setautomntent.patch +Patch108: autofs-5.1.6-improve-sss-setautomntent-error-handling.patch +Patch109: autofs-5.1.6-refactor-sss-getautomntent.patch +Patch110: autofs-5.1.6-improve-sss-getautomntent-error-handling.patch +Patch111: autofs-5.1.6-sss-introduce-retries-calcuation-function.patch +Patch112: autofs-5.1.6-move-readall-into-struct-master.patch +Patch113: autofs-5.1.6-sss-introduce-a-flag-to-indicate-map-being-read.patch +Patch114: autofs-5.1.6-update-sss-timeout-documentation.patch +Patch115: autofs-5.1.6-refactor-sss-getautomntbyname.patch +Patch116: autofs-5.1.6-improve-sss-getautomntbyname-error-handling.patch +Patch117: autofs-5.1.6-use-a-valid-timeout-in-lookup_prune_one_cache.patch +Patch118: autofs-5.1.6-dont-prune-offset-map-entries.patch +Patch119: autofs-5.1.6-simplify-sss-source-stale-check.patch + %if %{with_systemd} BuildRequires: systemd-units BuildRequires: systemd-devel @@ -272,6 +293,27 @@ echo %{version}-%{release} > .version %patch97 -p1 %patch98 -p1 +%patch100 -p1 +%patch101 -p1 +%patch102 -p1 +%patch103 -p1 +%patch104 -p1 +%patch105 -p1 +%patch106 -p1 +%patch107 -p1 +%patch108 -p1 +%patch109 -p1 +%patch110 -p1 +%patch111 -p1 +%patch112 -p1 +%patch113 -p1 +%patch114 -p1 +%patch115 -p1 +%patch116 -p1 +%patch117 -p1 +%patch118 -p1 +%patch119 -p1 + %build LDFLAGS=-Wl,-z,now %configure --disable-mount-locking --enable-ignore-busy --with-libtirpc --without-hesiod %{?systemd_configure_arg:} @@ -366,6 +408,30 @@ fi %dir /etc/auto.master.d %changelog +* Fri Nov 27 2020 Ian Kent - 5.1.4-48 +- bz1892184 - autofs: return a connection failure until maps have been fetched + - fix lookup_nss_read_master() nsswicth check return. + - fix typo in open_sss_lib(). + - fix sss_master_map_wait timing. + - add sss ECONREFUSED return handling. + - use mapname in sss context for setautomntent(). + - add support for new sss autofs proto version call. + - fix retries check in setautomntent_wait(). + - refactor sss setautomntent(). + - improve sss setautomntent() error handling. + - refactor sss getautomntent(). + - improve sss getautomntent() error handling. + - sss introduce calculate_retry_count() function. + - move readall into struct master. + - sss introduce a flag to indicate map being read. + - update sss timeout documentation. + - refactor sss getautomntbyname(). + - improve sss getautomntbyname() error handling. + - use a valid timeout in lookup_prune_one_cache(). + - dont prune offset map entries. + - simplify sss source stale check. +- Resolves: rhbz#1892184 + * Wed Nov 04 2020 Ian Kent - 5.1.4-47 - bz1887681 - automount force unlink option (-F) does not work as expected on autofs-5.0.7-109.el7