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