BUG in the block layer (partial reads not reported)

From: Alan Stern
Date: Thu Oct 20 2005 - 15:40:25 EST


The block layer does not report partial reads correctly back to userspace.

Here's an example which I can replicate at will. This is using the SCSI
cdrom driver and a disc with 326535 hardware sectors, each containing 2048
bytes. The last two sectors are unreadable.

Now consider what should happen when you run

dd if=/dev/scd0 bs=2048 count=1 skip=326532

One would expect to get back the contents of the last readable hardware
sector.

Instead, what happens is this:

1. The block layer issues a read for sectors 326532-3 (i.e., a
page's worth, including the sector we want and the following
unreadable sector).

2. The read partially succeeds, and the driver calls
end_that_request_chunk(req, 1, 2048);
It then requeues the request, more or less by coincidence.

3. This time the request fails since it's trying to read the
second-to-last sector, and the driver calls
end_that_request_chunk(req, 1, 0);
I'm not sure why.

4. Then the driver does what it should have done before, and calls
end_that_request_chunk(req, 0, 2048);
This causes an I/O error message to appear in the system log.

5. The driver calls end_that_request_last(req).

6. Apparently the block layer issues its own retry at this point.
The driver gets another read request for sector 326533.

7. Steps 3 - 5 repeat.

The end result is that dd receives no data, only an error. This is in
spite of the fact that the kernel was able to read successfully all the
data that had been requested!

Now I have only the vaguest notion of how the block layer works, and I
don't know where to begin solving this problem. Any help would be
appreciated.

Alan Stern

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