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.
239 lines
6.5 KiB
239 lines
6.5 KiB
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); |
|
- |
|
} |
|
} |
|
|
|
|