rpms/autofs/devel autofs-5.0.1-rc2-fix-null-map-semantics.patch, NONE, 1.1 autofs.spec, 1.163, 1.164

fedora-cvs-commits at redhat.com fedora-cvs-commits at redhat.com
Wed Dec 6 05:31:47 UTC 2006


Author: ikent

Update of /cvs/dist/rpms/autofs/devel
In directory cvs.devel.redhat.com:/tmp/cvs-serv18146

Modified Files:
	autofs.spec 
Added Files:
	autofs-5.0.1-rc2-fix-null-map-semantics.patch 
Log Message:
* Wed Dec 6 2006 Ian Kent <ikent at redhat.com> - 5.0.1-0.rc2.29
- correct semantics of "-null" map handling (bzs 214800, 208091).


autofs-5.0.1-rc2-fix-null-map-semantics.patch:
 CHANGELOG              |    1 
 daemon/automount.c     |   25 ++++++++---
 daemon/direct.c        |   74 +++++++++++++++++++++++++--------
 daemon/lookup.c        |   16 +++----
 daemon/spawn.c         |    1 
 daemon/state.c         |   48 +++++++++++++++++++--
 include/automount.h    |    3 +
 include/master.h       |    6 +-
 lib/cache.c            |  107 +++++++++++++++++++++++++++++++++++++++++++++++++
 lib/master.c           |   67 ++++++++++++++++++++++--------
 lib/master_parse.y     |   25 ++++++++++-
 modules/lookup_file.c  |    6 +-
 modules/mount_autofs.c |    5 +-
 13 files changed, 320 insertions(+), 64 deletions(-)

--- NEW FILE autofs-5.0.1-rc2-fix-null-map-semantics.patch ---
diff --git a/CHANGELOG b/CHANGELOG
index 2ffef53..f5f9efb 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -43,6 +43,7 @@
 - eliminate use of pthread_kill to detect task completion.
 - alter nfs4 host probing to not use portmap lookup and add options
   check for "port=" parameter.
+- correct semantics of "-null" map handling.
 
 1/9/2006 autofs-5.0.1 rc2
 -------------------------
diff --git a/daemon/automount.c b/daemon/automount.c
index ae87556..5628425 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -379,7 +379,7 @@ static void update_map_cache(struct auto
 
 	pthread_cleanup_push(master_source_lock_cleanup, ap->entry);
 	master_source_readlock(ap->entry);
-	map = ap->entry->first;
+	map = ap->entry->maps;
 	while (map) {
 		struct mapent *me = NULL;
 
@@ -390,11 +390,13 @@ static void update_map_cache(struct auto
 		}
 
 		mc = map->mc;
-		cache_writelock(mc);
-		me = cache_lookup_distinct(mc, key);
-		if (me && me->ioctlfd == -1)
-			cache_delete(mc, key);
-		cache_unlock(mc);
+		/* If the lock is busy try later */
+		if (cache_try_writelock(mc)) {
+			me = cache_lookup_distinct(mc, key);
+			if (me && me->ioctlfd == -1)
+				cache_delete(mc, key);
+			cache_unlock(mc);
+		}
 
 		map = map->next;
 	}
@@ -487,12 +489,21 @@ static int umount_subtree_mounts(struct 
    it also tries to umount path itself */
 int umount_multi(struct autofs_point *ap, const char *path, int incl)
 {
+	struct mapent_cache *nc;
 	struct statfs fs;
 	int is_autofs_fs;
 	int ret, left;
 
 	debug(ap->logopt, "path %s incl %d", path, incl);
 
+	nc = ap->entry->master->nc;
+	cache_readlock(nc);
+	if (cache_lookup_distinct(nc, path)) {
+		cache_unlock(nc);
+		return 0;
+	}
+	cache_unlock(nc);
+
 	ret = statfs(path, &fs);
 	if (ret == -1) {
 		error(ap->logopt, "could not stat fs of %s", path);
@@ -513,7 +524,7 @@ int umount_multi(struct autofs_point *ap
 	left += umount_subtree_mounts(ap, path, is_autofs_fs);
 
 	/* Delete detritus like unwanted mountpoints and symlinks */
-	if (left == 0) {
+	if (left == 0 && ap->state != ST_READMAP) {
 		update_map_cache(ap, path);
 		check_rm_dirs(ap, path, incl);
 	}
diff --git a/daemon/direct.c b/daemon/direct.c
index b8dbbc0..8971d99 100644
--- a/daemon/direct.c
+++ b/daemon/direct.c
@@ -79,6 +79,13 @@ static void key_mnt_params_init(void)
 	return;
 }
 
+static void mnts_cleanup(void *arg)
+{
+	struct mnt_list *mnts = (struct mnt_list *) arg;
+	tree_free_mnt_tree(mnts);
+	return;
+}
+
 static int autofs_init_direct(struct autofs_point *ap)
 {
 	int pipefd[2], cl_flags;
@@ -194,7 +201,7 @@ int do_umount_autofs_direct(struct autof
 	} else {
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
 		error(ap->logopt,
-		      "couldn't get ioctl fd for offset %s", me->key);
+		      "couldn't get ioctl fd for direct mount %s", me->key);
 		debug(ap->logopt, "open: %s", estr);
 		return 1;
 	}
@@ -252,9 +259,9 @@ force_umount:
 int umount_autofs_direct(struct autofs_point *ap)
 {
 	struct map_source *map;
-	struct mapent_cache *mc;
+	struct mapent_cache *nc, *mc;
 	struct mnt_list *mnts;
-	struct mapent *me;
+	struct mapent *me, *ne;
 
 	close(ap->state_pipe[0]);
 	close(ap->state_pipe[1]);
@@ -266,24 +273,36 @@ int umount_autofs_direct(struct autofs_p
 	}
 
 	mnts = tree_make_mnt_tree(_PROC_MOUNTS, "/");
+	pthread_cleanup_push(mnts_cleanup, mnts);
 	pthread_cleanup_push(master_source_lock_cleanup, ap->entry);
 	master_source_readlock(ap->entry);
-	map = ap->entry->first;
+	nc = ap->entry->master->nc;
+	cache_readlock(nc);
+	pthread_cleanup_push(cache_lock_cleanup, nc);
+	map = ap->entry->maps;
 	while (map) {
 		mc = map->mc;
 		pthread_cleanup_push(cache_lock_cleanup, mc);
 		cache_readlock(mc);
 		me = cache_enumerate(mc, NULL);
 		while (me) {
+			ne = cache_lookup_distinct(nc, me->key);
+			if (ne && map->master_line > ne->age) {
+				me = cache_enumerate(mc, me);
+				continue;
+			}
+
 			/* TODO: check return, locking me */
 			do_umount_autofs_direct(ap, mnts, me);
+
 			me = cache_enumerate(mc, me);
 		}
 		pthread_cleanup_pop(1);
 		map = map->next;
 	}
 	pthread_cleanup_pop(1);
-	tree_free_mnt_tree(mnts);
+	pthread_cleanup_pop(1);
+	pthread_cleanup_pop(1);
 
 	return 0;
 }
@@ -490,8 +509,8 @@ out_err:
 int mount_autofs_direct(struct autofs_point *ap)
 {
 	struct map_source *map;
-	struct mapent_cache *mc;
-	struct mapent *me;
+	struct mapent_cache *nc, *mc;
+	struct mapent *me, *ne, *nested;
 	struct mnt_list *mnts;
 	time_t now = time(NULL);
 
@@ -512,9 +531,13 @@ int mount_autofs_direct(struct autofs_po
 	}
 
 	mnts = tree_make_mnt_tree(_PROC_MOUNTS, "/");
+	pthread_cleanup_push(mnts_cleanup, mnts);
 	pthread_cleanup_push(master_source_lock_cleanup, ap->entry);
 	master_source_readlock(ap->entry);
-	map = ap->entry->first;
+	nc = ap->entry->master->nc;
+	cache_readlock(nc);
+	pthread_cleanup_push(cache_lock_cleanup, nc);
+	map = ap->entry->maps;
 	while (map) {
 		/*
 		 * Only consider map sources that have been read since
@@ -530,15 +553,37 @@ int mount_autofs_direct(struct autofs_po
 		cache_readlock(mc);
 		me = cache_enumerate(mc, NULL);
 		while (me) {
+			ne = cache_lookup_distinct(nc, me->key);
+			if (ne) {
+				if (map->master_line < ne->age) {
+					/* TODO: check return, locking me */
+					do_mount_autofs_direct(ap, mnts, me);
+				}
+				me = cache_enumerate(mc, me);
+				continue;
+			}
+
+			nested = cache_partial_match(nc, me->key);
+			if (nested) {
+				error(ap->logopt,
+				   "removing invalid nested null entry %s",
+				   nested->key);
+				nested = cache_partial_match(nc, me->key);
+				if (nested)
+					cache_delete(nc, nested->key);
+			}
+
 			/* TODO: check return, locking me */
 			do_mount_autofs_direct(ap, mnts, me);
+
 			me = cache_enumerate(mc, me);
 		}
 		pthread_cleanup_pop(1);
 		map = map->next;
 	}
 	pthread_cleanup_pop(1);
-	tree_free_mnt_tree(mnts);
+	pthread_cleanup_pop(1);
+	pthread_cleanup_pop(1);
 
 	return 0;
 }
@@ -821,13 +866,6 @@ static int expire_direct(int ioctlfd, co
 	return 1;
 }
 
-static void mnts_cleanup(void *arg)
-{
-	struct mnt_list *mnts = (struct mnt_list *) arg;
-	tree_free_mnt_tree(mnts);
-	return;
-}
-
 void *expire_proc_direct(void *arg)
 {
 	struct mnt_list *mnts = NULL, *next;
@@ -1090,7 +1128,7 @@ int handle_packet_expire_direct(struct a
 	 * there is an entry in the cache.
 	 */
 	master_source_readlock(ap->entry);
-	map = ap->entry->first;
+	map = ap->entry->maps;
 	while (map) {
 		mc = map->mc;
 		cache_readlock(mc);
@@ -1395,7 +1433,7 @@ int handle_packet_missing_direct(struct 
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state);
 
 	master_source_readlock(ap->entry);
-	map = ap->entry->first;
+	map = ap->entry->maps;
 	while (map) {
 		/*
 		 * Only consider map sources that have been read since
diff --git a/daemon/lookup.c b/daemon/lookup.c
index d13886b..db3dac0 100644
--- a/daemon/lookup.c
+++ b/daemon/lookup.c
@@ -432,7 +432,7 @@ int lookup_nss_read_map(struct autofs_po
 	 */
 	pthread_cleanup_push(master_source_lock_cleanup, entry);
 	master_source_readlock(entry);
-	map = entry->first;
+	map = entry->maps;
 	while (map) {
 		/* Is map source up to date or no longer valid */
 		if (!map->stale || entry->age > map->age) {
@@ -531,7 +531,7 @@ int lookup_ghost(struct autofs_point *ap
 
 	pthread_cleanup_push(master_source_lock_cleanup, entry);
 	master_source_readlock(entry);
-	map = entry->first;
+	map = entry->maps;
 	while (map) {
 		/*
 		 * Only consider map sources that have been read since 
@@ -769,7 +769,7 @@ int lookup_nss_mount(struct autofs_point
 	 */
 	pthread_cleanup_push(master_source_lock_cleanup, entry);
 	master_source_readlock(entry);
-	map = entry->first;
+	map = entry->maps;
 	while (map) {
 		/*
 		 * Only consider map sources that have been read since 
@@ -859,7 +859,7 @@ void lookup_close_lookup(struct autofs_p
 {
 	struct map_source *map;
 
-	map = ap->entry->first;
+	map = ap->entry->maps;
 	if (!map)
 		return;
 
@@ -917,7 +917,7 @@ int lookup_prune_cache(struct autofs_poi
 	pthread_cleanup_push(master_source_lock_cleanup, entry);
 	master_source_readlock(entry);
 
-	map = entry->first;
+	map = entry->maps;
 	while (map) {
 		if (!map->stale) {
 			map = map->next;
@@ -1017,7 +1017,7 @@ struct mapent *lookup_source_valid_mapen
 	struct mapent *me = NULL;
 
 	master_source_readlock(entry);
-	map = entry->first;
+	map = entry->maps;
 	while (map) {
 		/*
 		 * Only consider map sources that have been read since
@@ -1053,7 +1053,7 @@ struct mapent *lookup_source_mapent(stru
 	struct mapent *me = NULL;
 
 	master_source_readlock(entry);
-	map = entry->first;
+	map = entry->maps;
 	while (map) {
 		mc = map->mc;
 		cache_readlock(mc);
@@ -1081,7 +1081,7 @@ int lookup_source_close_ioctlfd(struct a
 
 	pthread_cleanup_push(master_source_lock_cleanup, entry);
 	master_source_readlock(entry);
-	map = entry->first;
+	map = entry->maps;
 	while (map) {
 		mc = map->mc;
 		cache_readlock(mc);
diff --git a/daemon/spawn.c b/daemon/spawn.c
index 2ede231..7f0a6e0 100644
--- a/daemon/spawn.c
+++ b/daemon/spawn.c
@@ -133,7 +133,6 @@ static int do_spawn(logger *log, unsigne
 			char **pargv = (char **) argv;
 			int argc = 0;
 			pid_t pgrp = getpgrp();
-			DIR *dfd;
 
 			/* what to mount must always be second last */
 			while (*pargv++)
diff --git a/daemon/state.c b/daemon/state.c
index 948ba88..d5eca8b 100644
--- a/daemon/state.c
+++ b/daemon/state.c
@@ -331,6 +331,9 @@ static void do_readmap_cleanup(void *arg
 
 	st_set_done(ap);
 
+	if (!ap->submount)
+		alarm_add(ap, ap->exp_runfreq);
+
 	free(ra);
 
 	return;
@@ -347,7 +350,7 @@ static void *do_readmap(void *arg)
 {
 	struct autofs_point *ap;
 	struct map_source *map;
-	struct mapent_cache *mc;
+	struct mapent_cache *nc, *mc;
 	struct readmap_args *ra;
 	struct mnt_list *mnts;
 	int status;
@@ -384,15 +387,18 @@ static void *do_readmap(void *arg)
 		lookup_prune_cache(ap, now);
 		status = lookup_ghost(ap);
 	} else {
-		struct mapent *me;
+		struct mapent *me, *ne, *nested;
 		mnts = tree_make_mnt_tree(_PROC_MOUNTS, "/");
 		pthread_cleanup_push(tree_mnts_cleanup, mnts);
 		pthread_cleanup_push(master_source_lock_cleanup, ap->entry);
 		master_source_readlock(ap->entry);
-		map = ap->entry->first;
+		nc = ap->entry->master->nc;
+		cache_readlock(nc);
+		pthread_cleanup_push(cache_lock_cleanup, nc);
+		map = ap->entry->maps;
 		while (map) {
 			/* Is map source up to date or no longer valid */
-			if (!map->stale || ap->entry->age > map->age) {
+			if (!map->stale) {
 				map = map->next;
 				continue;
 			}
@@ -401,15 +407,29 @@ static void *do_readmap(void *arg)
 			cache_readlock(mc);
 			me = cache_enumerate(mc, NULL);
 			while (me) {
+				ne = cache_lookup_distinct(nc, me->key);
+				if (!ne) {
+					nested = cache_partial_match(nc, me->key);
+					if (nested) {
+						error(ap->logopt,
+						"removing invalid nested null entry %s",
+						nested->key);
+						nested = cache_partial_match(nc, me->key);
+						if (nested)
+							cache_delete(nc, nested->key);
+					}
+				}
+
 				/* TODO: check return of do_... */
-				if (me->age < now) {
+				if (me->age < now || (ne && map->master_line > ne->age)) {
 					if (!tree_is_mounted(mnts, me->key, MNTS_REAL))
 						do_umount_autofs_direct(ap, mnts, me);
 					else
                                 		debug(ap->logopt,
-						      "%s id mounted", me->key);
+						      "%s is mounted", me->key);
 				} else
 					do_mount_autofs_direct(ap, mnts, me);
+
 				me = cache_enumerate(mc, me);
 			}
 			pthread_cleanup_pop(1);
@@ -417,6 +437,7 @@ static void *do_readmap(void *arg)
 		}
 		pthread_cleanup_pop(1);
 		pthread_cleanup_pop(1);
+		pthread_cleanup_pop(1);
 		lookup_prune_cache(ap, now);
 	}
 
@@ -459,12 +480,21 @@ static unsigned int st_readmap(struct au
 	assert(ap->state == ST_READY);
 	assert(ap->readmap_thread == 0);
 
+	/* Turn off timeouts for this mountpoint */
+	if (!ap->submount)
+		alarm_delete(ap);
+
 	ap->state = ST_READMAP;
 
 	ra = malloc(sizeof(struct readmap_args));
 	if (!ra) {
 		error(ap->logopt, "failed to malloc reamap cond struct");
+		state_mutex_lock(ap);
 		nextstate(ap->state_pipe[1], ST_READY);
+		state_mutex_unlock(ap);
+		/* It didn't work: return to ready */
+		if (!ap->submount)
+			alarm_add(ap, ap->exp_runfreq);
 		return 0;
 	}
 
@@ -488,6 +518,12 @@ static unsigned int st_readmap(struct au
 		error(ap->logopt, "read map thread create failed");
 		st_readmap_cleanup(ra);
 		free(ra);
+		state_mutex_lock(ap);
+		nextstate(ap->state_pipe[1], ST_READY);
+		state_mutex_unlock(ap);
+		/* It didn't work: return to ready */
+		if (!ap->submount)
+			alarm_add(ap, ap->exp_runfreq);
 		return 0;
 	}
 	ap->readmap_thread = thid;
diff --git a/include/automount.h b/include/automount.h
index 92da8f9..6c866dc 100644
--- a/include/automount.h
+++ b/include/automount.h
@@ -160,8 +160,10 @@ struct mapent {
 void cache_lock_cleanup(void *arg);
 void cache_readlock(struct mapent_cache *mc);
 void cache_writelock(struct mapent_cache *mc);
+int cache_try_writelock(struct mapent_cache *mc);
 void cache_unlock(struct mapent_cache *mc);
 struct mapent_cache *cache_init(struct map_source *map);
+struct mapent_cache *cache_init_null_cache(struct master *master);
 int cache_set_ino_index(struct mapent_cache *mc, const char *key, dev_t dev, ino_t ino);
 /* void cache_set_ino(struct mapent *me, dev_t dev, ino_t ino); */
 struct mapent *cache_lookup_ino(struct mapent_cache *mc, dev_t dev, ino_t ino);
@@ -181,6 +183,7 @@ void cache_multi_lock(struct mapent *me)
 void cache_multi_unlock(struct mapent *me);
 int cache_delete_offset_list(struct mapent_cache *mc, const char *key);
 void cache_release(struct map_source *map);
+void cache_release_null_cache(struct master *master);
 struct mapent *cache_enumerate(struct mapent_cache *mc, struct mapent *me);
 char *cache_get_offset(const char *prefix, char *offset, int start, struct list_head *head, struct list_head **pos);
 
diff --git a/include/master.h b/include/master.h
index f1f675c..96dfbd2 100644
--- a/include/master.h
+++ b/include/master.h
@@ -28,6 +28,7 @@ struct map_source {
 	char *type;
 	char *format;
 	time_t age;
+	unsigned int master_line;
 	struct mapent_cache *mc;
 	unsigned int stale;
 	unsigned int recurse;
@@ -43,10 +44,10 @@ struct master_mapent {
 	char *path;
 	pthread_t thid;
 	time_t age;
+	struct master *master;
 	pthread_rwlock_t source_lock;
 	pthread_mutex_t current_mutex;
 	pthread_cond_t current_cond;
-	struct map_source *first;
 	struct map_source *current;
 	struct map_source *maps;
 	struct autofs_point *ap;
@@ -61,6 +62,7 @@ struct master {
 	unsigned int default_ghost;
 	unsigned int default_logging;
 	unsigned int default_timeout;
+	struct mapent_cache *nc;
 	struct list_head mounts;
 };
 
@@ -91,7 +93,7 @@ void master_source_lock_cleanup(void *);
 void master_source_current_wait(struct master_mapent *);
 void master_source_current_signal(struct master_mapent *);
 struct master_mapent *master_find_mapent(struct master *, const char *);
-struct master_mapent *master_new_mapent(const char *, time_t);
+struct master_mapent *master_new_mapent(struct master *, const char *, time_t);
 void master_add_mapent(struct master *, struct master_mapent *);
 void master_remove_mapent(struct master_mapent *);
 void master_free_mapent_sources(struct master_mapent *, unsigned int);
diff --git a/lib/cache.c b/lib/cache.c
index fde050d..9bb692e 100644
--- a/lib/cache.c
+++ b/lib/cache.c
@@ -79,6 +79,18 @@ void cache_writelock(struct mapent_cache
 	return;
 }
 
+int cache_try_writelock(struct mapent_cache *mc)
+{
+	int status;
+
+	status = pthread_rwlock_trywrlock(&mc->rwlock);
+	if (status) {
+		debug(LOGOPT_ANY, "mapent cache rwlock busy");
+		return 0;
+	}
+	return 1;
+}
+
 void cache_unlock(struct mapent_cache *mc)
 {
 	int status;
@@ -200,6 +212,54 @@ struct mapent_cache *cache_init(struct m
 	return mc;
 }
 
+struct mapent_cache *cache_init_null_cache(struct master *master)
+{
+	struct mapent_cache *mc;
+	unsigned int i;
+	int status;
+
+	if (master->nc)
+		cache_release_null_cache(master);
+
+	mc = malloc(sizeof(struct mapent_cache));
+	if (!mc)
+		return NULL;
+
+	mc->size = HASHSIZE;
+
+	mc->hash = malloc(mc->size * sizeof(struct entry *));
+	if (!mc->hash) {
+		free(mc);
+		return NULL;
+	}
+
+	mc->ino_index = malloc(mc->size * sizeof(struct list_head));
+	if (!mc->ino_index) {
+		free(mc->hash);
+		free(mc);
+		return NULL;
+	}
+
+	status = pthread_mutex_init(&mc->ino_index_mutex, NULL);
+	if (status)
+		fatal(status);
+
+	status = pthread_rwlock_init(&mc->rwlock, NULL);
+	if (status)
+		fatal(status);
+
+	cache_writelock(mc);
+
+	for (i = 0; i < mc->size; i++) {
+		mc->hash[i] = NULL;
+		INIT_LIST_HEAD(&mc->ino_index[i]);
+	}
+
+	cache_unlock(mc);
+
+	return mc;
+}
+
 static unsigned int hash(const char *key)
 {
 	unsigned long hashval;
@@ -834,6 +894,53 @@ void cache_release(struct map_source *ma
 	free(mc);
 }
 
+void cache_release_null_cache(struct master *master)
+{
+	struct mapent_cache *mc;
+	struct mapent *me, *next;
+	int status;
+	unsigned int i;
+
+	mc = master->nc;
+
+	cache_writelock(mc);
+
+	for (i = 0; i < mc->size; i++) {
+		me = mc->hash[i];
+		if (me == NULL)
+			continue;
+		next = me->next;
+		free(me->key);
+		if (me->mapent)
+			free(me->mapent);
+		free(me);
+
+		while (next != NULL) {
+			me = next;
+			next = me->next;
+			free(me->key);
+			free(me);
+		}
+	}
+
+	master->nc = NULL;
+
+	cache_unlock(mc);
+
+	status = pthread_mutex_destroy(&mc->ino_index_mutex);
+	if (status)
+		fatal(status);
+
+	status = pthread_rwlock_destroy(&mc->rwlock);
+	if (status)
+		fatal(status);
+
+	free(mc->hash);
+	free(mc->ino_index);
+	free(mc);
+}
+
+
 
 /* cache must be read locked by caller */
 struct mapent *cache_enumerate(struct mapent_cache *mc, struct mapent *me)
diff --git a/lib/master.c b/lib/master.c
index 1c499d6..0066f8b 100644
--- a/lib/master.c
+++ b/lib/master.c
@@ -190,10 +190,9 @@ master_add_map_source(struct master_mape
 
 	master_source_writelock(entry);
 
-	if (!entry->maps) {
+	if (!entry->maps)
 		entry->maps = source;
-		entry->first = source;
-	} else {
+	else {
 		struct map_source *this, *last, *next;
 
 		/* Typically there only a few map sources */
@@ -259,7 +258,7 @@ __master_find_map_source(struct master_m
 	struct map_source *source = NULL;
 	int res;
 
-	map = entry->first;
+	map = entry->maps;
 	while (map) {
 		res = compare_source_type_and_format(map, type, format);
 		if (!res)
@@ -417,6 +416,7 @@ master_add_source_instance(struct map_so
 	}
 
 	new->age = age;
+	new->master_line = 0;
 	new->mc = source->mc;
 
 	tmpargv = copy_argv(source->argc, source->argv);
@@ -565,7 +565,7 @@ struct master_mapent *master_find_mapent
 	return NULL;
 }
 
-struct master_mapent *master_new_mapent(const char *path, time_t age)
+struct master_mapent *master_new_mapent(struct master *master, const char *path, time_t age)
 {
 	struct master_mapent *entry;
 	int status;
@@ -586,7 +586,7 @@ struct master_mapent *master_new_mapent(
 
 	entry->thid = 0;
 	entry->age = age;
-	entry->first = NULL;
+	entry->master = master;
 	entry->current = NULL;
 	entry->maps = NULL;
 	entry->ap = NULL;
@@ -642,7 +642,6 @@ void master_free_mapent_sources(struct m
 			m = n;
 		}
 		entry->maps = NULL;
-		entry->first = NULL;
 	}
 
 	master_source_unlock(entry);
@@ -690,10 +689,13 @@ struct master *master_new(const char *na
 	else
 		tmp = strdup(name);
 
-	if (!tmp)
+	if (!tmp) {
+		free(master);
 		return NULL;
+	}
 
 	master->name = tmp;
+	master->nc = NULL;
 
 	master->recurse = 0;
 	master->depth = 0;
@@ -709,6 +711,18 @@ struct master *master_new(const char *na
 
 int master_read_master(struct master *master, time_t age, int readall)
 {
+	struct mapent_cache *nc;
+
+	nc = cache_init_null_cache(master);
+	if (!nc) {
+		error(LOGOPT_ANY,
+		      "failed to init null map cache for %s", master->name);
+		return 0;
+	}
+	master->nc = nc;
+
+	master_init_scan();
+
 	if (!lookup_nss_read_master(master, age)) {
 		error(LOGOPT_ANY,
 		      "can't read master map %s", master->name);
@@ -1013,30 +1027,28 @@ static void check_update_map_sources(str
 			struct mapent *me;
 			cache_readlock(source->mc);
 			me = cache_lookup_first(source->mc);
-			cache_unlock(source->mc);
 			if (!me) {
 				struct map_source *next = source->next;
 
+				cache_unlock(source->mc);
+
 				if (!last)
 					entry->maps = next;
 				else
 					last->next = next;
 
-				if (entry->first == source)
-					entry->first = next;
+				if (entry->maps == source)
+					entry->maps = next;
 
 				master_free_map_source(source, 1);
 
 				source = next;
 				continue;
-			}
-		} else if (source->type) {
-			if (!strcmp(source->type, "null")) {
-/*				entry->ap->mc = cache_init(entry->ap); */
-				entry->first = source->next;
-				readall = 1;
+			} else {
+				source->stale = 1;
 				map_stale = 1;
 			}
+			cache_unlock(source->mc);
 		}
 		last = source;
 		source = source->next;
@@ -1062,6 +1074,7 @@ static void check_update_map_sources(str
 
 int master_mount_mounts(struct master *master, time_t age, int readall)
 {
+	struct mapent_cache *nc = master->nc;
 	struct list_head *p, *head;
 	int cur_state;
 
@@ -1073,6 +1086,7 @@ int master_mount_mounts(struct master *m
 	while (p != head) {
 		struct master_mapent *this;
 		struct autofs_point *ap;
+		struct mapent *ne, *nested;
 		struct stat st;
 		int state_pipe, save_errno;
 		int ret;
@@ -1088,6 +1102,24 @@ int master_mount_mounts(struct master *m
 			continue;
 		}
 
+		cache_readlock(nc);
+		ne = cache_lookup_distinct(nc, this->path);
+		if (ne && this->age > ne->age) {
+			cache_unlock(nc);
+			shutdown_entry(this);
+			continue;
+		}
+		nested = cache_partial_match(nc, this->path);
+		if (nested) {
+			error(ap->logopt,
+			     "removing invalid nested null entry %s",
+			     nested->key);
+			nested = cache_partial_match(nc, this->path);
+			if (nested)
+				cache_delete(nc, nested->key);
+		}
+		cache_unlock(nc);
+
 		check_update_map_sources(this, readall);
 
 		state_mutex_lock(ap);
@@ -1134,6 +1166,7 @@ int master_kill(struct master *master)
 	if (master->name)
 		free(master->name);
 
+	cache_release_null_cache(master);
 	free(master);
 
 	return 1;
diff --git a/lib/master_parse.y b/lib/master_parse.y
index 3250d39..e0af295 100644
--- a/lib/master_parse.y
+++ b/lib/master_parse.y
@@ -510,6 +510,7 @@ void master_init_scan(void)
 int master_parse_entry(const char *buffer, unsigned int default_timeout, unsigned int logging, time_t age)
 {
 	struct master *master = master_list;
+	struct mapent_cache *nc;
 	struct master_mapent *entry, *new;
 	struct map_source *source;
 	unsigned int logopt = logging;
@@ -527,6 +528,26 @@ int master_parse_entry(const char *buffe
 		return 0;
 	}
 
+	nc = master->nc;
+
+	/* Add null map entries to the null map cache */
+	if (type && !strcmp(type, "null")) {
+		cache_writelock(nc);
+		cache_update(nc, path, NULL, lineno);
+		cache_unlock(nc);
+		local_free_vars();
+		return 1;
+	}
+
+	/* Ignore all subsequent matching nulled entries */
+	cache_readlock(nc);
+	if (cache_lookup_distinct(nc, path)) {
+		cache_unlock(nc);
+		local_free_vars();
+		return 1;
+	}
+	cache_unlock(nc);
+
 	if (debug || verbose) {
 		logopt = (debug ? LOGOPT_DEBUG : 0);
 		logopt |= (verbose ? LOGOPT_VERBOSE : 0);
@@ -538,7 +559,7 @@ int master_parse_entry(const char *buffe
 	new = NULL;
 	entry = master_find_mapent(master, path);
 	if (!entry) {
-		new = master_new_mapent(path, age);
+		new = master_new_mapent(master, path, age);
 		if (!new) {
 			local_free_vars();
 			return 0;
@@ -604,9 +625,9 @@ int master_parse_entry(const char *buffe
 			return 0;
 		}
 	}
+	source->master_line = lineno;
 
 	entry->age = age;
-	entry->first = entry->maps;
 	entry->current = NULL;
 
 	if (new)
diff --git a/modules/lookup_file.c b/modules/lookup_file.c
index a0e22d2..051e5b5 100644
--- a/modules/lookup_file.c
+++ b/modules/lookup_file.c
@@ -402,7 +402,6 @@ int lookup_read_master(struct master *ma
 		fcntl(fd, F_SETFD, cl_flags);
 	}
 
-	master_init_scan();
 	while(1) {
 		entry = read_one(f, path, &path_len, ent, &ent_len);
 		if (!entry) {
@@ -516,6 +515,7 @@ static int check_self_include(const char
 static struct autofs_point *
 prepare_plus_include(struct autofs_point *ap, time_t age, char *key, unsigned int inc)
 {
+	struct master *master;
 	struct master_mapent *entry;
 	struct map_source *current;
 	struct map_source *source;
@@ -532,7 +532,9 @@ prepare_plus_include(struct autofs_point
 	ap->entry->current = NULL;
 	master_source_current_signal(ap->entry);
 
-	entry = master_new_mapent(ap->path, ap->entry->age);
+	master = ap->entry->master;
+
+	entry = master_new_mapent(master, ap->path, ap->entry->age);
 	if (!entry) {
 		error(ap->logopt, MODPREFIX "malloc failed for entry");
 		return NULL;
diff --git a/modules/mount_autofs.c b/modules/mount_autofs.c
index e901f20..f8d8ed2 100644
--- a/modules/mount_autofs.c
+++ b/modules/mount_autofs.c
@@ -53,6 +53,7 @@ int mount_mount(struct autofs_point *ap,
 	time_t timeout = ap->exp_timeout;
 	unsigned logopt = ap->logopt;
 	char *type, *format, *tmp, *tmp2;
+	struct master *master;
 	struct master_mapent *entry;
 	struct map_source *source;
 	struct autofs_point *nap;
@@ -137,7 +138,9 @@ int mount_mount(struct autofs_point *ap,
 	      MODPREFIX "fullpath=%s what=%s options=%s",
 	      fullpath, what, options);
 
-	entry = master_new_mapent(fullpath, ap->entry->age);
+	master = ap->entry->master;
+
+	entry = master_new_mapent(master, fullpath, ap->entry->age);
 	if (!entry) {
 		error(ap->logopt,
 		      MODPREFIX "failed to malloc master_mapent struct");


Index: autofs.spec
===================================================================
RCS file: /cvs/dist/rpms/autofs/devel/autofs.spec,v
retrieving revision 1.163
retrieving revision 1.164
diff -u -r1.163 -r1.164
--- autofs.spec	25 Nov 2006 03:14:32 -0000	1.163
+++ autofs.spec	6 Dec 2006 05:31:45 -0000	1.164
@@ -4,7 +4,7 @@
 Summary: A tool for automatically mounting and unmounting filesystems.
 Name: autofs
 %define version 5.0.1
-%define release 0.rc2.26
+%define release 0.rc2.29
 Version: %{version}
 Release: %{release}
 Epoch: 1
@@ -50,6 +50,7 @@
 Patch36: autofs-5.0.1-rc2-parse-bad-master-map-mountpoint.patch
 Patch37: autofs-5.0.1-rc2-fix-use-after-free.patch
 Patch38: autofs-5.0.1-rc2-use-task-done.patch
+Patch39: autofs-5.0.1-rc2-fix-null-map-semantics.patch
 Buildroot: /var/tmp/autofs-tmp
 BuildRequires: autoconf, hesiod-devel, openldap-devel, bison, flex, libxml2-devel, cyrus-sasl-devel, openssl-devel
 Prereq: chkconfig
@@ -128,6 +129,7 @@
 %patch36 -p1
 %patch37 -p1
 %patch38 -p1
+%patch39 -p1
 
 %build
 #CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=/usr --libdir=%{_libdir}
@@ -184,6 +186,9 @@
 %{_libdir}/autofs/*
 
 %changelog
+* Wed Dec 6 2006 Ian Kent <ikent at redhat.com> - 5.0.1-0.rc2.29
+- correct semantics of "-null" map handling (bzs 214800, 208091).
+
 * Sat Nov 25 2006 Ian Kent <ikent at redhat.com> - 5.0.1-0.rc2.26
 - fix parsing of bad mount mount point in master map (bz 215620).
 - fix use after free memory access in cache.c and lookup_yp.c (bz 208091).




More information about the fedora-cvs-commits mailing list