Blame SOURCES/autofs-5.1.1-fix-handle_mounts-termination-condition-check.patch

306fa1
autofs-5.1.1 - fix handle_mounts() termination condition check
306fa1
306fa1
From: Ian Kent <raven@themaw.net>
306fa1
306fa1
In get_pkt(), if a kernel request is present on the kernel pipe and
306fa1
the autofs mount point state changes to ST_SHUTDOWN after the poll(2)
306fa1
check but before the request has been processed the handle_mounts()
306fa1
thread will exit without shutting down the autofs mount point.
306fa1
306fa1
So change the handle_mounts() exit condition check to take account
306fa1
of this case.
306fa1
306fa1
Signed-off-by: Ian Kent <raven@themaw.net>
306fa1
---
306fa1
 CHANGELOG          |    1 
306fa1
 daemon/automount.c |  191 ++++++++++++++++++++++++++++-------------------------
306fa1
 2 files changed, 105 insertions(+), 87 deletions(-)
306fa1
306fa1
--- autofs-5.0.7.orig/CHANGELOG
306fa1
+++ autofs-5.0.7/CHANGELOG
306fa1
@@ -189,6 +189,7 @@
306fa1
 - always set direct mounts catatonic at exit.
306fa1
 - log pipe read errors.
306fa1
 - fix rwlock unlock crash.
306fa1
+- fix handle_mounts() termination condition check.
306fa1
 
306fa1
 25/07/2012 autofs-5.0.7
306fa1
 =======================
306fa1
--- autofs-5.0.7.orig/daemon/automount.c
306fa1
+++ autofs-5.0.7/daemon/automount.c
306fa1
@@ -1659,6 +1659,99 @@ static void submount_source_unlock_neste
306fa1
 	master_source_unlock(parent->entry);
306fa1
 }
306fa1
 
306fa1
+int handle_mounts_exit(struct autofs_point *ap)
306fa1
+{
306fa1
+	int ret, cur_state;
306fa1
+
306fa1
+	/*
306fa1
+	 * If we're a submount we need to ensure our parent
306fa1
+	 * doesn't try to mount us again until our shutdown
306fa1
+	 * is complete and that any outstanding mounts are
306fa1
+	 * completed before we try to shutdown.
306fa1
+	 */
306fa1
+	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
306fa1
+
306fa1
+	master_mutex_lock();
306fa1
+
306fa1
+	if (!ap->submount)
306fa1
+		master_source_writelock(ap->entry);
306fa1
+	else {
306fa1
+		/*
306fa1
+		 * If a mount request arrives before the locks are
306fa1
+		 * aquired just return to ready state.
306fa1
+		 */
306fa1
+		ret = submount_source_writelock_nested(ap);
306fa1
+		if (ret) {
306fa1
+			warn(ap->logopt,
306fa1
+			     "can't shutdown submount: mount in progress");
306fa1
+			/* Return to ST_READY is done immediately */
306fa1
+			st_add_task(ap, ST_READY);
306fa1
+			master_mutex_unlock();
306fa1
+			pthread_setcancelstate(cur_state, NULL);
306fa1
+			return 0;
306fa1
+		}
306fa1
+	}
306fa1
+
306fa1
+	if (ap->state != ST_SHUTDOWN) {
306fa1
+		if (!ap->submount)
306fa1
+			alarm_add(ap, ap->exp_runfreq);
306fa1
+		/* Return to ST_READY is done immediately */
306fa1
+		st_add_task(ap, ST_READY);
306fa1
+		if (ap->submount)
306fa1
+			submount_source_unlock_nested(ap);
306fa1
+		else
306fa1
+			master_source_unlock(ap->entry);
306fa1
+		master_mutex_unlock();
306fa1
+
306fa1
+		pthread_setcancelstate(cur_state, NULL);
306fa1
+		return 0;
306fa1
+	}
306fa1
+
306fa1
+	alarm_delete(ap);
306fa1
+	st_remove_tasks(ap);
306fa1
+	st_wait_task(ap, ST_ANY, 0);
306fa1
+
306fa1
+	/*
306fa1
+	 * For a direct mount map all mounts have already gone
306fa1
+	 * by the time we get here and since we only ever
306fa1
+	 * umount direct mounts at shutdown there is no need
306fa1
+	 * to check for possible recovery.
306fa1
+	 */
306fa1
+	if (ap->type == LKP_DIRECT) {
306fa1
+		umount_autofs(ap, NULL, 1);
306fa1
+		handle_mounts_cleanup(ap);
306fa1
+		return 1;
306fa1
+	}
306fa1
+
306fa1
+	/*
306fa1
+	 * If umount_autofs returns non-zero it wasn't able
306fa1
+	 * to complete the umount and has left the mount intact
306fa1
+	 * so we can continue. This can happen if a lookup
306fa1
+	 * occurs while we're trying to umount.
306fa1
+	 */
306fa1
+	ret = umount_autofs(ap, NULL, 1);
306fa1
+	if (!ret) {
306fa1
+		handle_mounts_cleanup(ap);
306fa1
+		return 1;
306fa1
+	}
306fa1
+
306fa1
+	/* Failed shutdown returns to ready */
306fa1
+	warn(ap->logopt, "can't shutdown: filesystem %s still busy", ap->path);
306fa1
+	if (!ap->submount)
306fa1
+		alarm_add(ap, ap->exp_runfreq);
306fa1
+	/* Return to ST_READY is done immediately */
306fa1
+	st_add_task(ap, ST_READY);
306fa1
+	if (ap->submount)
306fa1
+		submount_source_unlock_nested(ap);
306fa1
+	else
306fa1
+		master_source_unlock(ap->entry);
306fa1
+	master_mutex_unlock();
306fa1
+
306fa1
+	pthread_setcancelstate(cur_state, NULL);
306fa1
+
306fa1
+	return 0;
306fa1
+}
306fa1
+
306fa1
 void *handle_mounts(void *arg)
306fa1
 {
306fa1
 	struct startup_cond *suc;
306fa1
@@ -1714,97 +1807,21 @@ void *handle_mounts(void *arg)
306fa1
 
306fa1
 	pthread_setcancelstate(cancel_state, NULL);
306fa1
 
306fa1
-	while (ap->state != ST_SHUTDOWN) {
306fa1
+	while (1) {
306fa1
 		if (handle_packet(ap)) {
306fa1
-			int ret, cur_state;
306fa1
-
306fa1
-			/*
306fa1
-			 * If we're a submount we need to ensure our parent
306fa1
-			 * doesn't try to mount us again until our shutdown
306fa1
-			 * is complete and that any outstanding mounts are
306fa1
-			 * completed before we try to shutdown.
306fa1
-			 */
306fa1
-			pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
306fa1
-
306fa1
-			master_mutex_lock();
306fa1
-
306fa1
-			if (ap->submount) {
306fa1
-				/*
306fa1
-				 * If a mount request arrives before the locks are
306fa1
-				 * aquired just return to ready state.
306fa1
-				 */
306fa1
-				ret = submount_source_writelock_nested(ap);
306fa1
-				if (ret) {
306fa1
-					warn(ap->logopt,
306fa1
-					     "can't shutdown submount: mount in progress");
306fa1
-					/* Return to ST_READY is done immediately */
306fa1
-					st_add_task(ap, ST_READY);
306fa1
-					master_mutex_unlock();
306fa1
-					pthread_setcancelstate(cur_state, NULL);
306fa1
-					continue;
306fa1
-				}
306fa1
-			} else
306fa1
-				master_source_writelock(ap->entry);
306fa1
-
306fa1
-			if (ap->state != ST_SHUTDOWN) {
306fa1
-				if (!ap->submount)
306fa1
-					alarm_add(ap, ap->exp_runfreq);
306fa1
-				/* Return to ST_READY is done immediately */
306fa1
-				st_add_task(ap, ST_READY);
306fa1
-				if (ap->submount)
306fa1
-					submount_source_unlock_nested(ap);
306fa1
-				else
306fa1
-					master_source_unlock(ap->entry);
306fa1
-				master_mutex_unlock();
306fa1
-
306fa1
-				pthread_setcancelstate(cur_state, NULL);
306fa1
-				continue;
306fa1
-			}
306fa1
-
306fa1
-			alarm_delete(ap);
306fa1
-			st_remove_tasks(ap);
306fa1
-			st_wait_task(ap, ST_ANY, 0);
306fa1
-
306fa1
-			/*
306fa1
-			 * For a direct mount map all mounts have already gone
306fa1
-			 * by the time we get here and since we only ever
306fa1
-			 * umount direct mounts at shutdown there is no need
306fa1
-			 * to check for possible recovery.
306fa1
-			 */
306fa1
-			if (ap->type == LKP_DIRECT) {
306fa1
-				umount_autofs(ap, NULL, 1);
306fa1
-				handle_mounts_cleanup(ap);
306fa1
+			if (handle_mounts_exit(ap))
306fa1
 				break;
306fa1
-			}
306fa1
+		}
306fa1
 
306fa1
-			/*
306fa1
-			 * If umount_autofs returns non-zero it wasn't able
306fa1
-			 * to complete the umount and has left the mount intact
306fa1
-			 * so we can continue. This can happen if a lookup
306fa1
-			 * occurs while we're trying to umount.
306fa1
-			 */
306fa1
-			ret = umount_autofs(ap, NULL, 1);
306fa1
-			if (!ret) {
306fa1
-				handle_mounts_cleanup(ap);
306fa1
+		/* If we get here a packet has been received and handled
306fa1
+		 * and the autofs mount point has not been shutdown. But
306fa1
+		 * if the autofs mount point has been set to ST_SHUTDOWN
306fa1
+		 * we should attempt to perform the shutdown cleanup and
306fa1
+		 * exit if successful.
306fa1
+		 */
306fa1
+		if (ap->state == ST_SHUTDOWN) {
306fa1
+			if (handle_mounts_exit(ap))
306fa1
 				break;
306fa1
-			}
306fa1
-
306fa1
-			/* Failed shutdown returns to ready */
306fa1
-			warn(ap->logopt,
306fa1
-			     "can't shutdown: filesystem %s still busy",
306fa1
-			     ap->path);
306fa1
-			if (!ap->submount)
306fa1
-				alarm_add(ap, ap->exp_runfreq);
306fa1
-			/* Return to ST_READY is done immediately */
306fa1
-			st_add_task(ap, ST_READY);
306fa1
-			if (ap->submount)
306fa1
-				submount_source_unlock_nested(ap);
306fa1
-			else
306fa1
-				master_source_unlock(ap->entry);
306fa1
-			master_mutex_unlock();
306fa1
-
306fa1
-			pthread_setcancelstate(cur_state, NULL);
306fa1
-
306fa1
 		}
306fa1
 	}
306fa1