]> git.pld-linux.org Git - packages/autofs.git/blob - autofs-5.0.4-dont-umount-existing-direct-mount-on-reread.patch
6f760878b56582a78c2b3d8364a571fd8344aa08
[packages/autofs.git] / autofs-5.0.4-dont-umount-existing-direct-mount-on-reread.patch
1 autofs-5.0.4 - dont umount existing direct mount on master re-read
2
3 From: Ian Kent <raven@themaw.net>
4
5 Since direct mounts can have multiple entries in the master map they each
6 have an instance associated with them. If one entry changes, such as the
7 mount options, the instance comparison test fails and a new instance is
8 added. This causes autofs to get confused because there are now two
9 entries that contain the same mount information in different internal
10 caches. There are several consequences of this, most of which are just
11 noise in the log, but it also causes confuion for the expiration of mounts
12 since, for an active mount, the old cache entry can't be pruned until it's
13 umounted. Also, the map caches were not being properly pruned.
14 ---
15
16  CHANGELOG           |    1 
17  daemon/lookup.c     |  160 ++++++++++++++++++++++++++++-----------------------
18  daemon/state.c      |   90 +++++++++++++++++++++--------
19  include/automount.h |    1 
20  4 files changed, 156 insertions(+), 96 deletions(-)
21
22
23 diff --git a/CHANGELOG b/CHANGELOG
24 index 387af5e..7ca45fd 100644
25 --- a/CHANGELOG
26 +++ b/CHANGELOG
27 @@ -43,6 +43,7 @@
28  - use percent hack for master map keys.
29  - use intr option as hosts mount default.
30  - fix kernel includes.
31 +- dont umount existing direct mount on master re-read.
32  
33  4/11/2008 autofs-5.0.4
34  -----------------------
35 diff --git a/daemon/lookup.c b/daemon/lookup.c
36 index fd2ce55..bc94655 100644
37 --- a/daemon/lookup.c
38 +++ b/daemon/lookup.c
39 @@ -1016,96 +1016,114 @@ static char *make_fullpath(const char *root, const char *key)
40         return path;
41  }
42  
43 -int lookup_prune_cache(struct autofs_point *ap, time_t age)
44 +void lookup_prune_one_cache(struct autofs_point *ap, struct mapent_cache *mc, time_t age)
45  {
46 -       struct master_mapent *entry = ap->entry;
47 -       struct map_source *map;
48 -       struct mapent_cache *mc;
49         struct mapent *me, *this;
50         char *path;
51         int status = CHE_FAIL;
52  
53 -       pthread_cleanup_push(master_source_lock_cleanup, entry);
54 -       master_source_readlock(entry);
55 +       me = cache_enumerate(mc, NULL);
56 +       while (me) {
57 +               struct mapent *valid;
58 +               char *key = NULL, *next_key = NULL;
59  
60 -       map = entry->maps;
61 -       while (map) {
62 -               /* Is the map stale */
63 -               if (!map->stale) {
64 -                       map = map->next;
65 +               if (me->age >= age) {
66 +                       me = cache_enumerate(mc, me);
67                         continue;
68                 }
69 -               mc = map->mc;
70 -               pthread_cleanup_push(cache_lock_cleanup, mc);
71 -               cache_readlock(mc);
72 -               me = cache_enumerate(mc, NULL);
73 -               while (me) {
74 -                       char *key = NULL, *next_key = NULL;
75  
76 -                       if (me->age >= age) {
77 -                               me = cache_enumerate(mc, me);
78 -                               continue;
79 -                       }
80 +               key = strdup(me->key);
81 +               me = cache_enumerate(mc, me);
82 +               if (!key || *key == '*') {
83 +                       if (key)
84 +                               free(key);
85 +                       continue;
86 +               }
87  
88 -                       key = strdup(me->key);
89 -                       me = cache_enumerate(mc, me);
90 -                       if (!key || *key == '*') {
91 -                               if (key)
92 -                                       free(key);
93 -                               continue;
94 -                       }
95 +               path = make_fullpath(ap->path, key);
96 +               if (!path) {
97 +                       warn(ap->logopt, "can't malloc storage for path");
98 +                       free(key);
99 +                       continue;
100 +               }
101  
102 -                       path = make_fullpath(ap->path, key);
103 -                       if (!path) {
104 -                               warn(ap->logopt,
105 -                                    "can't malloc storage for path");
106 -                               free(key);
107 -                               continue;
108 -                       }
109 +               /*
110 +                * If this key has another valid entry we want to prune it,
111 +                * even if it's a mount, as the valid entry will take the
112 +                * mount if it is a direct mount or it's just a stale indirect
113 +                * cache entry.
114 +                */
115 +               valid = lookup_source_valid_mapent(ap, key, LKP_DISTINCT);
116 +               if (!valid &&
117 +                   is_mounted(_PATH_MOUNTED, path, MNTS_REAL)) {
118 +                       debug(ap->logopt,
119 +                             "prune check posponed, %s mounted", path);
120 +                       free(key);
121 +                       free(path);
122 +                       continue;
123 +               }
124 +               if (valid)
125 +                       cache_unlock(valid->mc);
126  
127 -                       if (is_mounted(_PATH_MOUNTED, path, MNTS_REAL)) {
128 -                               debug(ap->logopt,
129 -                                     "prune check posponed, %s mounted", path);
130 -                               free(key);
131 -                               free(path);
132 -                               continue;
133 -                       }
134 +               if (me)
135 +                       next_key = strdup(me->key);
136  
137 -                       if (me)
138 -                               next_key = strdup(me->key);
139 +               cache_unlock(mc);
140  
141 +               cache_writelock(mc);
142 +               this = cache_lookup_distinct(mc, key);
143 +               if (!this) {
144                         cache_unlock(mc);
145 +                       goto next;
146 +               }
147  
148 -                       cache_writelock(mc);
149 -                       this = cache_lookup_distinct(mc, key);
150 -                       if (!this) {
151 -                               cache_unlock(mc);
152 -                               goto next;
153 -                       }
154 -
155 -                       if (!is_mounted(_PROC_MOUNTS, path, MNTS_AUTOFS)) {
156 -                               status = CHE_FAIL;
157 -                               if (this->ioctlfd == -1)
158 -                                       status = cache_delete(mc, key);
159 -                               if (status != CHE_FAIL) {
160 -                                       if (ap->type == LKP_INDIRECT) {
161 -                                               if (ap->flags & MOUNT_FLAG_GHOST)
162 -                                                       rmdir_path(ap, path, ap->dev);
163 -                                       } else
164 -                                               rmdir_path(ap, path, this->dev);
165 -                               }
166 +               if (valid)
167 +                       cache_delete(mc, key);
168 +               else if (!is_mounted(_PROC_MOUNTS, path, MNTS_AUTOFS)) {
169 +                       status = CHE_FAIL;
170 +                       if (this->ioctlfd == -1)
171 +                               status = cache_delete(mc, key);
172 +                       if (status != CHE_FAIL) {
173 +                               if (ap->type == LKP_INDIRECT) {
174 +                                       if (ap->flags & MOUNT_FLAG_GHOST)
175 +                                               rmdir_path(ap, path, ap->dev);
176 +                               } else
177 +                                       rmdir_path(ap, path, this->dev);
178                         }
179 -                       cache_unlock(mc);
180 +               }
181 +               cache_unlock(mc);
182  
183  next:
184 -                       cache_readlock(mc);
185 -                       if (next_key) {
186 -                               me = cache_lookup_distinct(mc, next_key);
187 -                               free(next_key);
188 -                       }
189 -                       free(key);
190 -                       free(path);
191 +               cache_readlock(mc);
192 +               if (next_key) {
193 +                       me = cache_lookup_distinct(mc, next_key);
194 +                       free(next_key);
195                 }
196 +               free(key);
197 +               free(path);
198 +       }
199 +
200 +       return;
201 +}
202 +
203 +int lookup_prune_cache(struct autofs_point *ap, time_t age)
204 +{
205 +       struct master_mapent *entry = ap->entry;
206 +       struct map_source *map;
207 +
208 +       pthread_cleanup_push(master_source_lock_cleanup, entry);
209 +       master_source_readlock(entry);
210 +
211 +       map = entry->maps;
212 +       while (map) {
213 +               /* Is the map stale */
214 +               if (!map->stale) {
215 +                       map = map->next;
216 +                       continue;
217 +               }
218 +               pthread_cleanup_push(cache_lock_cleanup, map->mc);
219 +               cache_readlock(map->mc);
220 +               lookup_prune_one_cache(ap, map->mc, age);
221                 pthread_cleanup_pop(1);
222                 map->stale = 0;
223                 map = map->next;
224 @@ -1124,7 +1142,6 @@ struct mapent *lookup_source_valid_mapent(struct autofs_point *ap, const char *k
225         struct mapent_cache *mc;
226         struct mapent *me = NULL;
227  
228 -       master_source_readlock(entry);
229         map = entry->maps;
230         while (map) {
231                 /*
232 @@ -1147,7 +1164,6 @@ struct mapent *lookup_source_valid_mapent(struct autofs_point *ap, const char *k
233                 cache_unlock(mc);
234                 map = map->next;
235         }
236 -       master_source_unlock(entry);
237  
238         return me;
239  }
240 diff --git a/daemon/state.c b/daemon/state.c
241 index 533e241..84ccba3 100644
242 --- a/daemon/state.c
243 +++ b/daemon/state.c
244 @@ -352,6 +352,68 @@ static void tree_mnts_cleanup(void *arg)
245         return;
246  }
247  
248 +static void do_readmap_mount(struct autofs_point *ap, struct mnt_list *mnts,
249 +                            struct map_source *map, struct mapent *me, time_t now)
250 +{
251 +       struct mapent_cache *nc;
252 +       struct mapent *ne, *nested, *valid;
253 +
254 +       nc = ap->entry->master->nc;
255 +
256 +       ne = cache_lookup_distinct(nc, me->key);
257 +       if (!ne) {
258 +               nested = cache_partial_match(nc, me->key);
259 +               if (nested) {
260 +                       error(ap->logopt,
261 +                             "removing invalid nested null entry %s",
262 +                             nested->key);
263 +                       nested = cache_partial_match(nc, me->key);
264 +                       if (nested)
265 +                               cache_delete(nc, nested->key);
266 +               }
267 +       }
268 +
269 +       if (me->age < now || (ne && map->master_line > ne->age)) {
270 +               /*
271 +                * The map instance may have changed, such as the map name or
272 +                * the mount options, but the direct map entry may still exist
273 +                * in one of the other maps. If so then update the new cache
274 +                * entry device and inode so we can find it at lookup. Later,
275 +                * the mount for the new cache entry will just update the
276 +                * timeout.
277 +                *
278 +                * TODO: how do we recognise these orphaned map instances. We
279 +                * can't just delete these instances when the cache becomes
280 +                * empty because that is a valid state for a master map entry.
281 +                * This is becuase of the requirement to continue running with
282 +                * an empty cache awaiting a map re-load.
283 +                */
284 +               valid = lookup_source_valid_mapent(ap, me->key, LKP_DISTINCT);
285 +               if (valid) {
286 +                       struct mapent_cache *vmc = valid->mc;
287 +                       cache_unlock(vmc);
288 +                       debug(ap->logopt,
289 +                            "updating cache entry for valid direct trigger %s",
290 +                            me->key);
291 +                       cache_writelock(vmc);
292 +                       valid = cache_lookup_distinct(vmc, me->key);
293 +                       /* Take over the mount if there is one */
294 +                       valid->ioctlfd = me->ioctlfd;
295 +                       me->ioctlfd = -1;
296 +                       /* Set device and inode number of the new mapent */
297 +                       cache_set_ino_index(vmc, me->key, me->dev, me->ino);
298 +                       cache_unlock(vmc);
299 +               } else if (!tree_is_mounted(mnts, me->key, MNTS_REAL))
300 +                       do_umount_autofs_direct(ap, mnts, me);
301 +               else
302 +                       debug(ap->logopt,
303 +                             "%s is mounted", me->key);
304 +       } else
305 +               do_mount_autofs_direct(ap, mnts, me);
306 +
307 +       return;
308 +}
309 +
310  static void *do_readmap(void *arg)
311  {
312         struct autofs_point *ap;
313 @@ -398,7 +460,8 @@ static void *do_readmap(void *arg)
314                 lookup_prune_cache(ap, now);
315                 status = lookup_ghost(ap, ap->path);
316         } else {
317 -               struct mapent *me, *ne, *nested;
318 +               struct mapent *me;
319 +
320                 mnts = tree_make_mnt_tree(_PROC_MOUNTS, "/");
321                 pthread_cleanup_push(tree_mnts_cleanup, mnts);
322                 pthread_cleanup_push(master_source_lock_cleanup, ap->entry);
323 @@ -418,31 +481,10 @@ static void *do_readmap(void *arg)
324                         cache_readlock(mc);
325                         me = cache_enumerate(mc, NULL);
326                         while (me) {
327 -                               ne = cache_lookup_distinct(nc, me->key);
328 -                               if (!ne) {
329 -                                       nested = cache_partial_match(nc, me->key);
330 -                                       if (nested) {
331 -                                               error(ap->logopt,
332 -                                               "removing invalid nested null entry %s",
333 -                                               nested->key);
334 -                                               nested = cache_partial_match(nc, me->key);
335 -                                               if (nested)
336 -                                                       cache_delete(nc, nested->key);
337 -                                       }
338 -                               }
339 -
340 -                               /* TODO: check return of do_... */
341 -                               if (me->age < now || (ne && map->master_line > ne->age)) {
342 -                                       if (!tree_is_mounted(mnts, me->key, MNTS_REAL))
343 -                                               do_umount_autofs_direct(ap, mnts, me);
344 -                                       else
345 -                                               debug(ap->logopt,
346 -                                                     "%s is mounted", me->key);
347 -                               } else
348 -                                       do_mount_autofs_direct(ap, mnts, me);
349 -
350 +                               do_readmap_mount(ap, mnts, map, me, now);
351                                 me = cache_enumerate(mc, me);
352                         }
353 +                       lookup_prune_one_cache(ap, map->mc, now);
354                         pthread_cleanup_pop(1);
355                         map->stale = 0;
356                         map = map->next;
357 diff --git a/include/automount.h b/include/automount.h
358 index d4675bd..ae517a7 100644
359 --- a/include/automount.h
360 +++ b/include/automount.h
361 @@ -238,6 +238,7 @@ int lookup_enumerate(struct autofs_point *ap,
362  int lookup_ghost(struct autofs_point *ap, const char *root);
363  int lookup_nss_mount(struct autofs_point *ap, struct map_source *source, const char *name, int name_len);
364  void lookup_close_lookup(struct autofs_point *ap);
365 +void lookup_prune_one_cache(struct autofs_point *ap, struct mapent_cache *mc, time_t age);
366  int lookup_prune_cache(struct autofs_point *ap, time_t age);
367  struct mapent *lookup_source_valid_mapent(struct autofs_point *ap, const char *key, unsigned int type);
368  struct mapent *lookup_source_mapent(struct autofs_point *ap, const char *key, unsigned int type);
This page took 0.086079 seconds and 2 git commands to generate.