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

From: Andrew Morton
Date: Thu Feb 04 2010 - 19:10:21 EST


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?

> /* 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-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/