]> git.pld-linux.org Git - packages/autofs.git/blob - autofs-5.0.4-fix-negative-cache-non-existent-key.patch
- updated to 5.0.5, nfy.
[packages/autofs.git] / autofs-5.0.4-fix-negative-cache-non-existent-key.patch
1 autofs-5.0.4 - fix negative cache non-existent key
2
3 From: Ian Kent <raven@themaw.net>
4
5 autofs was not recording map entries that don't exist for negative
6 caching. This was causing unwanted network map lookups.
7 ---
8
9  CHANGELOG                |    1 +
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(-)
18
19
20 diff --git a/CHANGELOG b/CHANGELOG
21 index 88ca579..bd35b00 100644
22 --- a/CHANGELOG
23 +++ b/CHANGELOG
24 @@ -2,6 +2,7 @@
25  -----------------------
26  - fix dumb libxml2 check
27  - fix nested submount expire deadlock.
28 +- fix negative caching for non-existent map keys.
29  
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
34 --- a/daemon/lookup.c
35 +++ b/daemon/lookup.c
36 @@ -804,6 +804,45 @@ static enum nsswitch_status lookup_map_name(struct nss_source *this,
37         return result;
38  }
39  
40 +static void update_negative_cache(struct autofs_point *ap, struct map_source *source, const char *name)
41 +{
42 +       struct master_mapent *entry = ap->entry;
43 +       struct map_source *map;
44 +       struct mapent *me;
45 +
46 +       /* Have we recorded the lookup fail for negative caching? */
47 +       me = lookup_source_mapent(ap, name, LKP_DISTINCT);
48 +       if (me)
49 +               /*
50 +                *  Already exists in the cache, the mount fail updates
51 +                *  will update negative timeout status.
52 +                */
53 +               cache_unlock(me->mc);
54 +       else {
55 +               /* Notify only once after fail */
56 +               error(ap->logopt, "key \"%s\" not found in map.", name);
57 +
58 +               /* Doesn't exist in any source, just add it somewhere */
59 +               if (source)
60 +                       map = source;
61 +               else
62 +                       map = entry->maps;
63 +               if (map) {
64 +                       time_t now = time(NULL);
65 +                       int rv = CHE_FAIL;
66 +
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;
72 +                       }
73 +                       cache_unlock(map->mc);
74 +               }
75 +       }
76 +       return;
77 +}
78 +
79  int lookup_nss_mount(struct autofs_point *ap, struct map_source *source, const char *name, int name_len)
80  {
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);
85  
86 -       if (result == NSS_STATUS_NOTFOUND)
87 -               error(ap->logopt, "key \"%s\" not found in map.", name);
88 +       /*
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.
92 +        */
93 +       if (result == NSS_STATUS_NOTFOUND || result == NSS_STATUS_UNAVAIL)
94 +               update_negative_cache(ap, source, name);
95  
96         return !result;
97  }
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;
105  
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)) {
110 -               cache_unlock(mc);
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);
114 +       if (me) {
115 +               if (me->status >= time(NULL)) {
116 +                       cache_unlock(me->mc);
117 +                       return NSS_STATUS_NOTFOUND;
118 +               }
119 +
120 +               /* Negative timeout expired for non-existent entry. */
121 +               if (!me->mapent)
122 +                       cache_delete(me->mc, key);
123 +
124 +               cache_unlock(me->mc);
125         }
126 -       cache_unlock(mc);
127  
128         /*
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 *
135  
136         mc = source->mc;
137  
138 +       /* Check if we recorded a mount fail for this key anywhere */
139 +       me = lookup_source_mapent(ap, name, LKP_DISTINCT);
140 +       if (me) {
141 +               if (me->status >= time(NULL)) {
142 +                       cache_unlock(me->mc);
143 +                       return NSS_STATUS_NOTFOUND;
144 +               }
145 +
146 +               if (!me->mapent) {
147 +                       cache_delete(me->mc, name);
148 +                       me = NULL;
149 +               }
150 +
151 +               cache_unlock(me->mc);
152 +       }
153 +
154         cache_readlock(mc);
155         me = cache_lookup_distinct(mc, name);
156 -       if (me && me->status >= time(NULL)) {
157 -               cache_unlock(mc);
158 -               return NSS_STATUS_NOTFOUND;
159 -       } else if (!me) {
160 +       if (!me) {
161                 cache_unlock(mc);
162                 /*
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;
171  
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)) {
176 -               cache_unlock(mc);
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);
180 +       if (me) {
181 +               if (me->status >= time(NULL)) {
182 +                       cache_unlock(me->mc);
183 +                       return NSS_STATUS_NOTFOUND;
184 +               }
185 +
186 +               /* Negative timeout expired for non-existent entry. */
187 +               if (!me->mapent)
188 +                       cache_delete(me->mc, key);
189 +
190 +               cache_unlock(me->mc);
191         }
192 -       cache_unlock(mc);
193  
194          /*
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;
203  
204 -       cache_readlock(mc);
205 -       me = cache_lookup_distinct(mc, key);
206 -       if (me && me->status >= time(NULL)) {
207 -               cache_unlock(mc);
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);
211 +       if (me) {
212 +               if (me->status >= time(NULL)) {
213 +                       cache_unlock(me->mc);
214 +                       return NSS_STATUS_NOTFOUND;
215 +               }
216 +
217 +               /* Negative timeout expired for non-existent entry. */
218 +               if (!me->mapent)
219 +                       cache_delete(me->mc, key);
220 +
221 +               cache_unlock(me->mc);
222         }
223 -       cache_unlock(mc);
224  
225         /*
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 *
232  
233         mc = source->mc;
234  
235 +       /* Check if we recorded a mount fail for this key anywhere */
236 +       me = lookup_source_mapent(ap, name, LKP_DISTINCT);
237 +       if (me) {
238 +               if (me->status >= time(NULL)) {
239 +                       cache_unlock(me->mc);
240 +                       return NSS_STATUS_NOTFOUND;
241 +               }
242 +
243 +               /* Negative timeout expired for non-existent entry. */
244 +               if (!me->mapent)
245 +                       cache_delete(me->mc, name);
246 +
247 +               cache_unlock(me->mc);
248 +       }
249 +
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)) {
255 -               cache_unlock(mc);
256 -               return NSS_STATUS_NOTFOUND;
257 -       } else if (!me) {
258 +       if (!me) {
259                 cache_unlock(mc);
260                 /*
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;
264                 }
265         } else {
266 -               cache_unlock(mc);
267 -
268                 /* Otherwise we found a valid offset so try mount it */
269                 debug(ap->logopt, MODPREFIX "%s -> %s", name, me->mapent);
270  
271 @@ -163,19 +173,28 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
272                  */
273                 if (strchr(name, '/') ||
274                     me->age + ap->negative_timeout > time(NULL)) {
275 +                       char *ent = NULL;
276 +
277 +                       if (me->mapent) {
278 +                               ent = alloca(strlen(me->mapent) + 1);
279 +                               strcpy(ent, me->mapent);
280 +                       }
281 +                       cache_unlock(mc);
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);
287                         goto out_free;
288                 } else {
289                         if (me->multi) {
290 +                               cache_unlock(mc);
291                                 warn(ap->logopt, MODPREFIX
292                                      "unexpected lookup for active multi-mount"
293                                      " key %s, returning fail", name);
294                                 return NSS_STATUS_UNAVAIL;
295                         }
296                         cache_delete(mc, name);
297 +                       cache_unlock(mc);
298                 }
299         }
300  
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;
308  
309 -       cache_readlock(mc);
310 -       me = cache_lookup_distinct(mc, key);
311 -       if (me && me->status >= time(NULL)) {
312 -               cache_unlock(mc);
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);
316 +       if (me) {
317 +               if (me->status >= time(NULL)) {
318 +                       cache_unlock(me->mc);
319 +                       return NSS_STATUS_NOTFOUND;
320 +               }
321 +
322 +               /* Negative timeout expired for non-existent entry. */
323 +               if (!me->mapent)
324 +                       cache_delete(me->mc, key);
325 +
326 +               cache_unlock(me->mc);
327         }
328 -       cache_unlock(mc);
329  
330          /*
331           * We can't check the direct mount map as if it's not in
This page took 0.071104 seconds and 3 git commands to generate.