Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 130701790bf2d95e902edf16031ff596 > files > 136

autofs-5.0.1-0.rc2.164.el5_8.src.rpm

diff --git a/CHANGELOG b/CHANGELOG
index bcd6e5c..88b6a47 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -31,6 +31,7 @@
 - fix nsswitch parser locking.
 - allow only one master map read task at a time.
 - fix misc memory leaks.
+- mitigate manual umount of automounts where possible.
 
 1/9/2006 autofs-5.0.1 rc2
 -------------------------
diff --git a/daemon/direct.c b/daemon/direct.c
index c92a745..ef96cc4 100644
--- a/daemon/direct.c
+++ b/daemon/direct.c
@@ -848,13 +848,14 @@ static int expire_direct(int ioctlfd, co
 static void mnts_cleanup(void *arg)
 {
 	struct mnt_list *mnts = (struct mnt_list *) arg;
-	free_mnt_list(mnts);
+	tree_free_mnt_tree(mnts);
 	return;
 }
 
 void *expire_proc_direct(void *arg)
 {
 	struct mnt_list *mnts = NULL, *next;
+	struct list_head list, *p;
 	struct expire_args *ea;
 	struct expire_args ec;
 	struct autofs_point *ap;
@@ -886,10 +887,27 @@ void *expire_proc_direct(void *arg)
 
 	left = 0;
 
-	/* Get a list of real mounts and expire them if possible */
-	mnts = get_mnt_list(_PROC_MOUNTS, "/", 0);
+	mnts = tree_make_mnt_tree(_PROC_MOUNTS, "/");
+
+	/* Get a list of mounts select real ones and expire them if possible */
+	INIT_LIST_HEAD(&list);
+	if (!tree_get_mnt_list(mnts, &list, "/", 0)) {
+		ec.status = 0;
+		return NULL;
+	}
 	pthread_cleanup_push(mnts_cleanup, mnts);
-	for (next = mnts; next; next = next->next) {
+
+	list_for_each(p, &list) {
+		next = list_entry(p, struct mnt_list, list);
+
+		/*
+		 * All direct mounts must be present in the map
+		 * entry cache.
+		 */
+		me = lookup_source_mapent(ap, next->path, LKP_DISTINCT);
+		if (!me)
+			continue;
+
 		if (!strcmp(next->fs_type, "autofs")) {
 			/*
 			 * If we have submounts check if this path lives below
@@ -897,27 +915,32 @@ void *expire_proc_direct(void *arg)
 			 */
 			pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
 			if (strstr(next->opts, "indirect")) {
+				cache_unlock(me->mc);
 				master_notify_submount(ap, next->path, ap->state);
 				pthread_setcancelstate(cur_state, NULL);
 				continue;
 			}
-			pthread_setcancelstate(cur_state, NULL);
-
-			/* Skip offsets */
-			if (strstr(next->opts, "offset"))
-				continue;
-		}
-
-		if (ap->state == ST_EXPIRE || ap->state == ST_PRUNE)
-			pthread_testcancel();
 
-		/*
-		 * All direct mounts must be present in the map
-		 * entry cache.
-		 */
-		me = lookup_source_mapent(ap, next->path, LKP_DISTINCT);
-		if (!me)
+			if (!tree_is_mounted(mnts, next->path, MNTS_REAL)) {
+				/*
+				 * Maybe a manual umount, repair.
+				 * It will take ap->exp_timeout/4 for us to relaize
+				 * this so user must still use USR1 signal to close
+				 * the open file handle for mounts atop multi-mount
+				 * triggers. There is no way that I'm aware of to
+				 * to avoid maintaining a file handle for control
+				 * functions as once it's mounted all opens are
+				 * directed to the mount not the trigger.
+				 */
+				if (me->ioctlfd != -1) {
+					close(me->ioctlfd);
+					me->ioctlfd = -1;
+				}
+			}
+			cache_unlock(me->mc);
+			pthread_setcancelstate(cur_state, NULL);
 			continue;
+		}
 
 		if (me->ioctlfd >= 0) {
 			/* Real mounts have an open ioctl fd */
@@ -928,6 +951,9 @@ void *expire_proc_direct(void *arg)
 			continue;
 		}
 
+		if (ap->state == ST_EXPIRE || ap->state == ST_PRUNE)
+			pthread_testcancel();
+
 		debug(ap->logopt, "send expire to trigger %s", next->path);
 
 		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
@@ -1392,8 +1418,14 @@ int handle_packet_missing_direct(struct 
 		return 1;
 	}
 
-	ioctlfd = open(me->key, O_RDONLY);
-	if (ioctlfd < 0) {
+	if (me->ioctlfd != -1) {
+		/* Maybe someone did a manual umount, clean up ! */
+		ioctlfd = me->ioctlfd;
+		me->ioctlfd = -1;
+	} else
+		ioctlfd = open(me->key, O_RDONLY);
+
+	if (ioctlfd == -1) {
 		cache_unlock(mc);
 		pthread_setcancelstate(state, NULL);
 		crit(ap->logopt, "failed to create ioctl fd for %s", me->key);
diff --git a/include/automount.h b/include/automount.h
index 798cc50..89610ee 100644
--- a/include/automount.h
+++ b/include/automount.h
@@ -338,6 +338,7 @@ struct mnt_list {
 	struct mnt_list *right;
 	struct list_head self;
 	struct list_head list;
+	struct list_head entries;
 	struct list_head sublist;
 	/*
 	 * Offset mount handling ie. add_ordered_list
diff --git a/lib/mounts.c b/lib/mounts.c
index 1e92ca5..a4f68c5 100644
--- a/lib/mounts.c
+++ b/lib/mounts.c
@@ -606,6 +606,7 @@ struct mnt_list *tree_make_mnt_tree(cons
 
 		INIT_LIST_HEAD(&ent->self);
 		INIT_LIST_HEAD(&ent->list);
+		INIT_LIST_HEAD(&ent->entries);
 		INIT_LIST_HEAD(&ent->sublist);
 		INIT_LIST_HEAD(&ent->ordered);
 
@@ -824,8 +825,8 @@ int tree_find_mnt_ents(struct mnt_list *
 		tree_find_mnt_ents(mnts->left, list, path);
 
 		if (!strcmp(mnts->path, path)) {
-			INIT_LIST_HEAD(&mnts->list);
-			list_add(&mnts->list, list);
+			INIT_LIST_HEAD(&mnts->entries);
+			list_add(&mnts->entries, list);
 		}
 
 		self = &mnts->self;
@@ -835,8 +836,8 @@ int tree_find_mnt_ents(struct mnt_list *
 			this = list_entry(p, struct mnt_list, self);
 
 			if (!strcmp(this->path, path)) {
-				INIT_LIST_HEAD(&this->list);
-				list_add(&this->list, list);
+				INIT_LIST_HEAD(&this->entries);
+				list_add(&this->entries, list);
 			}
 		}
 
@@ -863,7 +864,7 @@ int tree_is_mounted(struct mnt_list *mnt
 	list_for_each(p, &list) {
 		struct mnt_list *mptr;
 
-		mptr = list_entry(p, struct mnt_list, list);
+		mptr = list_entry(p, struct mnt_list, entries);
 
 		if (type) {
 			unsigned int autofs_fs;