summaryrefslogtreecommitdiffstats
path: root/mm/backing-dev.c
diff options
context:
space:
mode:
authorRomit Dasgupta <romit@ti.com>2009-11-12 13:08:11 +0100
committerJens Axboe <jens.axboe@oracle.com>2009-11-12 13:08:11 +0100
commitc62b17a58ab5e97534ff6487241addd5fcc606de (patch)
tree577c41e145d934d5fc39b6bd0b623ff508a6159d /mm/backing-dev.c
parentaa021baa3295fa6e3f367d80f8955dd5176656eb (diff)
downloadlinux-stable-c62b17a58ab5e97534ff6487241addd5fcc606de.tar.gz
linux-stable-c62b17a58ab5e97534ff6487241addd5fcc606de.tar.bz2
linux-stable-c62b17a58ab5e97534ff6487241addd5fcc606de.zip
Thaw refrigerated bdi flusher threads before invoking kthread_stop on them
Unfreezes the bdi flusher task when the said task needs to exit. Steps to reproduce this. 1) Mount a file system from MMC/SD card. 2) Unmount the file system. This creates a flusher task. 3) Attempt suspend to RAM. System is unresponsive. This is because the bdi flusher thread is already in the refrigerator and will remain so until it is thawed. The MMC driver suspend routine call stack will ultimately issue a 'kthread_stop' on the bdi flusher thread and will block until the flusher thread is exited. Since the bdi flusher thread is in the refrigerator it never cleans up until thawed. Signed-off-by: Romit Dasgupta <romit@ti.com> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'mm/backing-dev.c')
-rw-r--r--mm/backing-dev.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 11aee09dd2a6..67a33a5a1a93 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -604,10 +604,14 @@ static void bdi_wb_shutdown(struct backing_dev_info *bdi)
/*
* Finally, kill the kernel threads. We don't need to be RCU
- * safe anymore, since the bdi is gone from visibility.
+ * safe anymore, since the bdi is gone from visibility. Force
+ * unfreeze of the thread before calling kthread_stop(), otherwise
+ * it would never exet if it is currently stuck in the refrigerator.
*/
- list_for_each_entry(wb, &bdi->wb_list, list)
+ list_for_each_entry(wb, &bdi->wb_list, list) {
+ wb->task->flags &= ~PF_FROZEN;
kthread_stop(wb->task);
+ }
}
/*