Re: [PATCH] MMC: fix hang if card was removed during suspend andunsafe resume was enabled

From: Adrian Hunter
Date: Fri Feb 05 2010 - 05:17:46 EST


ext Andrew Morton wrote:
On Fri, 5 Feb 2010 01:18:15 +0200 Maxim Levitsky <maximlevitsky@xxxxxxxxx> wrote:

Currently removal of the card leads to del_disk called indirectly by mmc core.
This function expects userspace to be running, which isn't when .resume is called

Fix that by removing the code that did that in mmc_resume_host. It is possible
because card detection logic will kick it later and remove the card.

I don't really understand. The above implies that to trigger this bug,
one needs to physically remove the card during a resume operation. ie:
a human-vs-computer race. Sounds unlikely?

So... exactly what steps does the user need to take to trigger this
bug?

Also make mtd workqueue freezeable, so it won't attempt to add/remove the card
while userspace is frozen.


diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 30acd52..879d48d 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1257,7 +1257,6 @@ int mmc_suspend_host(struct mmc_host *host, pm_message_t state)
if (host->caps & MMC_CAP_DISABLE)
cancel_delayed_work(&host->disable);
cancel_delayed_work(&host->detect);
- mmc_flush_scheduled_work();
mmc_bus_get(host);
if (host->bus_ops && !host->bus_dead) {
@@ -1300,15 +1299,11 @@ int mmc_resume_host(struct mmc_host *host)
mmc_select_voltage(host, host->ocr);
BUG_ON(!host->bus_ops->resume);
err = host->bus_ops->resume(host);
+
if (err) {
printk(KERN_WARNING "%s: error %d during resume "
"(card was removed?)\n",
mmc_hostname(host), err);
- if (host->bus_ops->remove)
- host->bus_ops->remove(host);
- mmc_claim_host(host);
- mmc_detach_bus(host);
- mmc_release_host(host);

afacit that code's been there since March 2009. I'd have thought that
someone would have noticed "kernel hangs on resume" before now.

Do you think the patch should be backported into 2.6.32.x and eariler?

It looks like the code was introduced in 2.6.32.x by commit

95cdfb72b9bc568803f395c266152c71b034b461

cc'ing the author Nicolas Pitre


/* no need to bother upper layers */
err = 0;
}
@@ -1332,7 +1327,7 @@ static int __init mmc_init(void)
{
int ret;
- workqueue = create_singlethread_workqueue("kmmcd");
+ workqueue = create_freezeable_workqueue("kmmcd");
if (!workqueue)
return -ENOMEM;
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/