]> git.pld-linux.org Git - packages/autofs.git/blame - autofs-5.0.4-dont-umount-existing-direct-mount-on-reread.patch
- import latest patchset.
[packages/autofs.git] / autofs-5.0.4-dont-umount-existing-direct-mount-on-reread.patch
CommitLineData
e5fd101c
PS
1autofs-5.0.4 - dont umount existing direct mount on master re-read
2
3From: Ian Kent <raven@themaw.net>
4
5Since direct mounts can have multiple entries in the master map they each
6have an instance associated with them. If one entry changes, such as the
7mount options, the instance comparison test fails and a new instance is
8added. This causes autofs to get confused because there are now two
9entries that contain the same mount information in different internal
10caches. There are several consequences of this, most of which are just
11noise in the log, but it also causes confuion for the expiration of mounts
12since, for an active mount, the old cache entry can't be pruned until it's
13umounted. 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
23diff --git a/CHANGELOG b/CHANGELOG
24index 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 -----------------------
35diff --git a/daemon/lookup.c b/daemon/lookup.c
36index 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 }
240diff --git a/daemon/state.c b/daemon/state.c
241index 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;
357diff --git a/include/automount.h b/include/automount.h
358index 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.067222 seconds and 4 git commands to generate.