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

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