diff --git a/daemon/lookup.c b/daemon/lookup.c
index 0be10d3..eb72411 100644
--- a/daemon/lookup.c
+++ b/daemon/lookup.c
@@ -298,8 +298,6 @@ static int do_read_map(struct autofs_point *ap, struct map_source *map, time_t a
status = lookup->lookup_read_map(ap, age, lookup->context);
- map->stale = 0;
-
/*
* For maps that don't support enumeration return success
* and do whatever we must to have autofs function with an
@@ -533,6 +531,10 @@ int lookup_nss_read_map(struct autofs_point *ap, struct map_source *source, time
if (result == NSS_STATUS_UNKNOWN)
continue;
+ /* Don't try to update the map cache if it's unavailable */
+ if (result == NSS_STATUS_UNAVAIL)
+ map->stale = 0;
+
if (result == NSS_STATUS_SUCCESS) {
at_least_one = 1;
result = NSS_STATUS_TRYAGAIN;
@@ -553,7 +555,7 @@ int lookup_nss_read_map(struct autofs_point *ap, struct map_source *source, time
}
pthread_cleanup_pop(1);
- if (!result || at_least_one)
+ if (!result || at_least_one)
return 1;
return 0;
diff --git a/daemon/state.c b/daemon/state.c
index cf07aac..5bccfef 100644
--- a/daemon/state.c
+++ b/daemon/state.c
@@ -432,6 +432,7 @@ static void *do_readmap(void *arg)
me = cache_enumerate(mc, me);
}
pthread_cleanup_pop(1);
+ map->stale = 0;
map = map->next;
}
pthread_cleanup_pop(1);
diff --git a/include/automount.h b/include/automount.h
index fa5cd97..133fd32 100644
--- a/include/automount.h
+++ b/include/automount.h
@@ -121,6 +121,7 @@ struct autofs_point;
#define CHE_MISSING 0x0008
#define CHE_COMPLETED 0x0010
#define CHE_DUPLICATE 0x0020
+#define CHE_UNAVAIL 0x0040
#define HASHSIZE 77
#define NEGATIVE_TIMEOUT 10
diff --git a/modules/lookup_file.c b/modules/lookup_file.c
index 550bf5c..a77068a 100644
--- a/modules/lookup_file.c
+++ b/modules/lookup_file.c
@@ -469,11 +469,14 @@ int lookup_read_master(struct master *master, time_t age, void *context)
master->recurse = 1;;
master->depth++;
status = lookup_nss_read_master(master, age);
- if (!status)
+ if (!status) {
warn(logopt,
MODPREFIX
"failed to read included master map %s",
master->name);
+ fclose(f);
+ return NSS_STATUS_UNAVAIL;
+ }
master->depth--;
master->recurse = 0;
@@ -484,6 +487,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
if (!buffer) {
error(logopt,
MODPREFIX "could not malloc parse buffer");
+ fclose(f);
return NSS_STATUS_UNAVAIL;
}
memset(buffer, 0, blen);
@@ -721,9 +725,12 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
/* Gim'ee some o' that 16k stack baby !! */
status = lookup_nss_read_map(ap, inc_source, age);
- if (!status)
+ if (!status) {
warn(ap->logopt,
"failed to read included map %s", key);
+ fclose(f);
+ return NSS_STATUS_UNAVAIL;
+ }
} else {
char *s_key;
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index b8484a2..7effbf1 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -1755,7 +1755,7 @@ static int lookup_one(struct autofs_point *ap,
/* Initialize the LDAP context. */
ldap = do_reconnect(ap->logopt, ctxt);
if (!ldap)
- return CHE_FAIL;
+ return CHE_UNAVAIL;
debug(ap->logopt,
MODPREFIX "searching for \"%s\" under \"%s\"", query, ctxt->qdn);
@@ -1999,6 +1999,21 @@ static int check_map_indirect(struct autofs_point *ap,
if (ret == CHE_FAIL) {
pthread_setcancelstate(cur_state, NULL);
return NSS_STATUS_NOTFOUND;
+ } else if (ret == CHE_UNAVAIL) {
+ /*
+ * If the server is down and the entry exists in the cache
+ * and belongs to this map return success and use the entry.
+ */
+ struct mapent *exists = cache_lookup(mc, key);
+ if (exists && exists->source == source) {
+ pthread_setcancelstate(cur_state, NULL);
+ return NSS_STATUS_SUCCESS;
+ }
+
+ warn(ap->logopt,
+ MODPREFIX "lookup for %s failed: connection failed", key);
+
+ return NSS_STATUS_UNAVAIL;
}
pthread_setcancelstate(cur_state, NULL);
diff --git a/modules/lookup_nisplus.c b/modules/lookup_nisplus.c
index fee8b16..628ffcf 100644
--- a/modules/lookup_nisplus.c
+++ b/modules/lookup_nisplus.c
@@ -385,9 +385,18 @@ static int check_map_indirect(struct autofs_point *ap,
return NSS_STATUS_NOTFOUND;
if (ret < 0) {
+ /*
+ * If the server is down and the entry exists in the cache
+ * and belongs to this map return success and use the entry.
+ */
+ exists = cache_lookup(mc, key);
+ if (exists && exists->source == source)
+ return NSS_STATUS_SUCCESS;
+
warn(ap->logopt,
MODPREFIX "lookup for %s failed: %s",
key, nis_sperrno(-ret));
+
return NSS_STATUS_UNAVAIL;
}
diff --git a/modules/lookup_yp.c b/modules/lookup_yp.c
index 5f4f95f..f5097dc 100644
--- a/modules/lookup_yp.c
+++ b/modules/lookup_yp.c
@@ -239,6 +239,9 @@ int lookup_read_master(struct master *master, time_t age, void *context)
MODPREFIX "read of master map %s failed: %s",
mapname, yperr_string(err));
+ if (err == YPERR_PMAP || err == YPERR_YPSERV)
+ return NSS_STATUS_UNAVAIL;
+
return NSS_STATUS_NOTFOUND;
}
@@ -336,6 +339,9 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
MODPREFIX "read of map %s failed: %s",
ap->path, yperr_string(err));
+ if (err == YPERR_PMAP || err == YPERR_YPSERV)
+ return NSS_STATUS_UNAVAIL;
+
return NSS_STATUS_NOTFOUND;
}
@@ -481,9 +487,18 @@ static int check_map_indirect(struct autofs_point *ap,
return NSS_STATUS_NOTFOUND;
if (ret < 0) {
+ /*
+ * If the server is down and the entry exists in the cache
+ * and belongs to this map return success and use the entry.
+ */
+ exists = cache_lookup(mc, key);
+ if (exists && exists->source == source)
+ return NSS_STATUS_SUCCESS;
+
warn(ap->logopt,
MODPREFIX "lookup for %s failed: %s",
key, yperr_string(-ret));
+
return NSS_STATUS_UNAVAIL;
}