From c62b17a58ab5e97534ff6487241addd5fcc606de Mon Sep 17 00:00:00 2001
From: Romit Dasgupta <romit@ti.com>
Date: Thu, 12 Nov 2009 13:08:11 +0100
Subject: 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>
---
 mm/backing-dev.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

(limited to 'mm/backing-dev.c')

diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 11aee09dd2a..67a33a5a1a9 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);
+	}
 }
 
 /*
-- 
cgit v1.2.3-70-g09d2


From bf7ec5bb6114b2f086e536e24486fdacd1c0d339 Mon Sep 17 00:00:00 2001
From: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Date: Thu, 3 Dec 2009 13:49:43 +0100
Subject: flusher: Fix PF_FROZEN race

To touch task->flags directly is racy. thaw_process() still has race
(changing non_current->flags, but this is another issue) though, I think
it's much better off.

So, use thaw_process() instead.

Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
---
 mm/backing-dev.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'mm/backing-dev.c')

diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 67a33a5a1a9..0e8ca034770 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -609,7 +609,7 @@ static void bdi_wb_shutdown(struct backing_dev_info *bdi)
 	 * it would never exet if it is currently stuck in the refrigerator.
 	 */
 	list_for_each_entry(wb, &bdi->wb_list, list) {
-		wb->task->flags &= ~PF_FROZEN;
+		thaw_process(wb->task);
 		kthread_stop(wb->task);
 	}
 }
-- 
cgit v1.2.3-70-g09d2