1 autofs-5.0.4 - fix negative cache non-existent key
3 From: Ian Kent <raven@themaw.net>
5 autofs was not recording map entries that don't exist for negative
6 caching. This was causing unwanted network map lookups.
10 daemon/lookup.c | 48 ++++++++++++++++++++++++++++++++++++++++++++--
11 modules/lookup_file.c | 20 ++++++++++++-------
12 modules/lookup_hosts.c | 21 ++++++++++++++++----
13 modules/lookup_ldap.c | 20 ++++++++++++-------
14 modules/lookup_nisplus.c | 19 ++++++++++++------
15 modules/lookup_program.c | 35 ++++++++++++++++++++++++++--------
16 modules/lookup_yp.c | 19 ++++++++++++------
17 8 files changed, 143 insertions(+), 40 deletions(-)
20 diff --git a/CHANGELOG b/CHANGELOG
21 index 88ca579..bd35b00 100644
25 -----------------------
26 - fix dumb libxml2 check
27 - fix nested submount expire deadlock.
28 +- fix negative caching for non-existent map keys.
30 4/11/2008 autofs-5.0.4
31 -----------------------
32 diff --git a/daemon/lookup.c b/daemon/lookup.c
33 index 803df4f..0cf6e3f 100644
36 @@ -804,6 +804,45 @@ static enum nsswitch_status lookup_map_name(struct nss_source *this,
40 +static void update_negative_cache(struct autofs_point *ap, struct map_source *source, const char *name)
42 + struct master_mapent *entry = ap->entry;
43 + struct map_source *map;
46 + /* Have we recorded the lookup fail for negative caching? */
47 + me = lookup_source_mapent(ap, name, LKP_DISTINCT);
50 + * Already exists in the cache, the mount fail updates
51 + * will update negative timeout status.
53 + cache_unlock(me->mc);
55 + /* Notify only once after fail */
56 + error(ap->logopt, "key \"%s\" not found in map.", name);
58 + /* Doesn't exist in any source, just add it somewhere */
64 + time_t now = time(NULL);
67 + cache_writelock(map->mc);
68 + rv = cache_update(map->mc, map, name, NULL, now);
69 + if (rv != CHE_FAIL) {
70 + me = cache_lookup_distinct(map->mc, name);
71 + me->status = now + ap->negative_timeout;
73 + cache_unlock(map->mc);
79 int lookup_nss_mount(struct autofs_point *ap, struct map_source *source, const char *name, int name_len)
81 struct master_mapent *entry = ap->entry;
82 @@ -907,8 +946,13 @@ int lookup_nss_mount(struct autofs_point *ap, struct map_source *source, const c
83 send_map_update_request(ap);
84 pthread_cleanup_pop(1);
86 - if (result == NSS_STATUS_NOTFOUND)
87 - error(ap->logopt, "key \"%s\" not found in map.", name);
89 + * The last source lookup will return NSS_STATUS_NOTFOUND if the
90 + * map exits and the key has not been found but the map may also
91 + * not exist in which case the key is also not found.
93 + if (result == NSS_STATUS_NOTFOUND || result == NSS_STATUS_UNAVAIL)
94 + update_negative_cache(ap, source, name);
98 diff --git a/modules/lookup_file.c b/modules/lookup_file.c
99 index 807ceab..9e34b72 100644
100 --- a/modules/lookup_file.c
101 +++ b/modules/lookup_file.c
102 @@ -1069,14 +1069,20 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
103 if (key_len > KEY_MAX_LEN)
104 return NSS_STATUS_NOTFOUND;
106 - /* Check if we recorded a mount fail for this key */
107 - cache_readlock(mc);
108 - me = cache_lookup_distinct(mc, key);
109 - if (me && me->status >= time(NULL)) {
111 - return NSS_STATUS_UNAVAIL;
112 + /* Check if we recorded a mount fail for this key anywhere */
113 + me = lookup_source_mapent(ap, key, LKP_DISTINCT);
115 + if (me->status >= time(NULL)) {
116 + cache_unlock(me->mc);
117 + return NSS_STATUS_NOTFOUND;
120 + /* Negative timeout expired for non-existent entry. */
122 + cache_delete(me->mc, key);
124 + cache_unlock(me->mc);
129 * We can't check the direct mount map as if it's not in
130 diff --git a/modules/lookup_hosts.c b/modules/lookup_hosts.c
131 index bf24d7f..f8d4269 100644
132 --- a/modules/lookup_hosts.c
133 +++ b/modules/lookup_hosts.c
134 @@ -136,12 +136,25 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
138 + /* Check if we recorded a mount fail for this key anywhere */
139 + me = lookup_source_mapent(ap, name, LKP_DISTINCT);
141 + if (me->status >= time(NULL)) {
142 + cache_unlock(me->mc);
143 + return NSS_STATUS_NOTFOUND;
147 + cache_delete(me->mc, name);
151 + cache_unlock(me->mc);
155 me = cache_lookup_distinct(mc, name);
156 - if (me && me->status >= time(NULL)) {
158 - return NSS_STATUS_NOTFOUND;
163 * We haven't read the list of hosts into the
164 diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
165 index 31c2c13..42c3235 100644
166 --- a/modules/lookup_ldap.c
167 +++ b/modules/lookup_ldap.c
168 @@ -2709,14 +2709,20 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
169 if (key_len > KEY_MAX_LEN)
170 return NSS_STATUS_NOTFOUND;
172 - /* Check if we recorded a mount fail for this key */
173 - cache_readlock(mc);
174 - me = cache_lookup_distinct(mc, key);
175 - if (me && me->status >= time(NULL)) {
177 - return NSS_STATUS_NOTFOUND;
178 + /* Check if we recorded a mount fail for this key anywhere */
179 + me = lookup_source_mapent(ap, key, LKP_DISTINCT);
181 + if (me->status >= time(NULL)) {
182 + cache_unlock(me->mc);
183 + return NSS_STATUS_NOTFOUND;
186 + /* Negative timeout expired for non-existent entry. */
188 + cache_delete(me->mc, key);
190 + cache_unlock(me->mc);
195 * We can't check the direct mount map as if it's not in
196 diff --git a/modules/lookup_nisplus.c b/modules/lookup_nisplus.c
197 index 755556d..f15465f 100644
198 --- a/modules/lookup_nisplus.c
199 +++ b/modules/lookup_nisplus.c
200 @@ -493,13 +493,20 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
201 if (key_len > KEY_MAX_LEN)
202 return NSS_STATUS_NOTFOUND;
204 - cache_readlock(mc);
205 - me = cache_lookup_distinct(mc, key);
206 - if (me && me->status >= time(NULL)) {
208 - return NSS_STATUS_NOTFOUND;
209 + /* Check if we recorded a mount fail for this key anywhere */
210 + me = lookup_source_mapent(ap, key, LKP_DISTINCT);
212 + if (me->status >= time(NULL)) {
213 + cache_unlock(me->mc);
214 + return NSS_STATUS_NOTFOUND;
217 + /* Negative timeout expired for non-existent entry. */
219 + cache_delete(me->mc, key);
221 + cache_unlock(me->mc);
226 * We can't check the direct mount map as if it's not in
227 diff --git a/modules/lookup_program.c b/modules/lookup_program.c
228 index daf874d..bf32d3b 100644
229 --- a/modules/lookup_program.c
230 +++ b/modules/lookup_program.c
231 @@ -131,13 +131,25 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
235 + /* Check if we recorded a mount fail for this key anywhere */
236 + me = lookup_source_mapent(ap, name, LKP_DISTINCT);
238 + if (me->status >= time(NULL)) {
239 + cache_unlock(me->mc);
240 + return NSS_STATUS_NOTFOUND;
243 + /* Negative timeout expired for non-existent entry. */
245 + cache_delete(me->mc, name);
247 + cache_unlock(me->mc);
250 /* Catch installed direct offset triggers */
251 - cache_readlock(mc);
252 + cache_writelock(mc);
253 me = cache_lookup_distinct(mc, name);
254 - if (me && me->status >= time(NULL)) {
256 - return NSS_STATUS_NOTFOUND;
261 * If there's a '/' in the name and the offset is not in
262 @@ -149,8 +161,6 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
263 return NSS_STATUS_NOTFOUND;
268 /* Otherwise we found a valid offset so try mount it */
269 debug(ap->logopt, MODPREFIX "%s -> %s", name, me->mapent);
271 @@ -163,19 +173,28 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
273 if (strchr(name, '/') ||
274 me->age + ap->negative_timeout > time(NULL)) {
278 + ent = alloca(strlen(me->mapent) + 1);
279 + strcpy(ent, me->mapent);
282 master_source_current_wait(ap->entry);
283 ap->entry->current = source;
284 ret = ctxt->parse->parse_mount(ap, name,
285 - name_len, me->mapent, ctxt->parse->context);
286 + name_len, ent, ctxt->parse->context);
291 warn(ap->logopt, MODPREFIX
292 "unexpected lookup for active multi-mount"
293 " key %s, returning fail", name);
294 return NSS_STATUS_UNAVAIL;
296 cache_delete(mc, name);
301 diff --git a/modules/lookup_yp.c b/modules/lookup_yp.c
302 index 8b6408b..1b62f57 100644
303 --- a/modules/lookup_yp.c
304 +++ b/modules/lookup_yp.c
305 @@ -603,13 +603,20 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
306 if (key_len > KEY_MAX_LEN)
307 return NSS_STATUS_NOTFOUND;
309 - cache_readlock(mc);
310 - me = cache_lookup_distinct(mc, key);
311 - if (me && me->status >= time(NULL)) {
313 - return NSS_STATUS_NOTFOUND;
314 + /* Check if we recorded a mount fail for this key anywhere */
315 + me = lookup_source_mapent(ap, key, LKP_DISTINCT);
317 + if (me->status >= time(NULL)) {
318 + cache_unlock(me->mc);
319 + return NSS_STATUS_NOTFOUND;
322 + /* Negative timeout expired for non-existent entry. */
324 + cache_delete(me->mc, key);
326 + cache_unlock(me->mc);
331 * We can't check the direct mount map as if it's not in