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