autofs-5.1.9 - fix lock ordering deadlock in expire_cleanup()

From: Ian Kent <raven@themaw.net>

Commit 81ac572466e3 ("autofs-5.1.9 - fix submount shutdown race")
introduced a lock ordering deadlock between the state mutex and the
mounts hash list mutex when fixing a submount shutdown race. It's enough
to just move the conditional alarm set function call outside of the
state mutex critical section to fix it.

Fixes: 81ac572466e3 ("autofs-5.1.9 - fix submount shutdown race")
Signed-off-by: Ian Kent <raven@themaw.net>
---
 CHANGELOG      |    1 +
 daemon/state.c |   12 ++++++++----
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index ae8730de3..36751885a 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -31,6 +31,7 @@
 - fix deadlock in master_notify_submount().
 - remove mounts_mutex macros.
 - fix lock not released on error in mnts_add_amdmount().
+- fix lock ordering deadlock in expire_cleanup().
 
 02/11/2023 autofs-5.1.9
 - fix kernel mount status notification.
diff --git a/daemon/state.c b/daemon/state.c
index 4e26bc68f..dbd22be61 100644
--- a/daemon/state.c
+++ b/daemon/state.c
@@ -62,8 +62,9 @@ void expire_cleanup(void *arg)
 	pthread_t thid = pthread_self();
 	struct expire_args *ec;
 	struct autofs_point *ap;
-	int success;
 	enum states next = ST_INVAL;
+	unsigned int need_alarm = 0;
+	int success;
 
 	ec = (struct expire_args *) arg;
 	ap = ec->ap;
@@ -99,7 +100,7 @@ void expire_cleanup(void *arg)
 			}
 
 			if (ap->state == ST_EXPIRE)
-				conditional_alarm_add(ap, ap->exp_runfreq);
+				need_alarm = 1;
 
 			/* FALLTHROUGH */
 
@@ -116,7 +117,7 @@ void expire_cleanup(void *arg)
 			rv = ops->askumount(ap->logopt, ap->ioctlfd, &idle);
 			if (!rv && !idle && !ap->shutdown) {
 				next = ST_READY;
-				conditional_alarm_add(ap, ap->exp_runfreq);
+				need_alarm = 1;
 				break;
 			}
 
@@ -129,7 +130,7 @@ void expire_cleanup(void *arg)
 
 			/* Failed shutdown returns to ready */
 			warn(ap->logopt, "filesystem %s still busy", ap->path);
-			conditional_alarm_add(ap, ap->exp_runfreq);
+			need_alarm = 1;
 			next = ST_READY;
 			break;
 #endif
@@ -156,6 +157,9 @@ void expire_cleanup(void *arg)
 
 	st_mutex_unlock();
 
+	if (need_alarm)
+		conditional_alarm_add(ap, ap->exp_runfreq);
+
 	return;
 }
 
