Re: mcdx -- do_request(): non-read command to cd!!

Pekka Enberg
2007-04-01T10:07:03Z

[-- Attachment #1: Type: text/plain, Size: 729 bytes --]

On 3/31/07, Rene Herman <rene.herman@gmail.com> wrote:
> There's quite a bit of noise in dmesg though. Repeated 5 times:
>
> ===BUG: scheduling while atomic: mount/0x00000001/1166
> [<c1170bff>] __sched_text_start+0x57/0x574
> [<c1171964>] schedule_timeout+0x70/0x8f
> [<c10199b2>] process_timeout+0x0/0x5
> [<c11716a2>] interruptible_sleep_on_timeout+0x5d/0xa5
> [<c100e695>] default_wake_function+0x0/0xc
> [<c482b8fb>] mcdx_xfer+0xae/0x2a5 [mcdx]

[snip]

> [<c482b473>] do_mcdx_request+0x9b/0xd2 [mcdx]
> [<c1096d06>] __generic_unplug_device+0x1d/0x1f
> [<c1096d19>] generic_unplug_device+0x11/0x29

Looks like mcdx_xfer is sleeping while holding q->queue_lock. The
attached (untested) patch should fix it.

[-- Attachment #2: mcdx-drop-queue_lock-before-sleeping --]
[-- Type: application/octet-stream, Size: 1588 bytes --]

diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c
index f574962..e14dc03 100644
--- a/drivers/cdrom/mcdx.c
+++ b/drivers/cdrom/mcdx.c
@@ -577,11 +577,14 @@ static void do_mcdx_request(request_queue_t * q)
if (!req)
return;

+ spin_unlock_irq(q->queue_lock);
+
stuffp = req->rq_disk->private_data;

if (!stuffp->present) {
xwarn("do_request(): bad device: %s\n",req->rq_disk->disk_name);
xtrace(REQUEST, "end_request(0): bad device\n");
+ spin_lock_irq(q->queue_lock);
end_request(req, 0);
return;
}
@@ -589,6 +592,7 @@ static void do_mcdx_request(request_queue_t * q)
if (stuffp->audio) {
xwarn("do_request() attempt to read from audio cd\n");
xtrace(REQUEST, "end_request(0): read from audio\n");
+ spin_lock_irq(q->queue_lock);
end_request(req, 0);
return;
}
@@ -599,6 +603,7 @@ static void do_mcdx_request(request_queue_t * q)
if (req->cmd != READ) {
xwarn("do_request(): non-read command to cd!!\n");
xtrace(REQUEST, "end_request(0): write\n");
+ spin_lock_irq(q->queue_lock);
end_request(req, 0);
return;
}
@@ -613,6 +618,7 @@ static void do_mcdx_request(request_queue_t * q)
req->nr_sectors);

if (i == -1) {
+ spin_lock_irq(q->queue_lock);
end_request(req, 0);
goto again;
}
@@ -620,10 +626,12 @@ static void do_mcdx_request(request_queue_t * q)
req->nr_sectors -= i;
req->buffer += (i * 512);
}
+ spin_lock_irq(q->queue_lock);
end_request(req, 1);
goto again;

xtrace(REQUEST, "end_request(1)\n");
+ spin_lock_irq(q->queue_lock);
end_request(req, 1);
}