Re: [PATCH] 2.6.10 - direct-io async short read bug

From: Badari Pulavarty
Date: Tue Mar 08 2005 - 14:34:40 EST



> Andrew, please don't apply the original patch. We shouldn't even attempt
> to submit IO beyond the filesize. We should truncate the IO request to
> filesize. I will send a patch today to fix this.
>

Well, spoke too soon. This is an ugly corner case :( But I have
a ugly hack to fix it :)

Let me ask you a basic question: Do we support DIO reads on a file
which is not blocksize multiple in size ? (say 12K - 10 bytes) ?

What about the ones which are not 4K but 512 byte multiple ? (say 7K) ?

I need answer to those, to figure out how hard I should try to fix this.

Anyway, here is ugly version of the patch - which will limit the IO
size to filesize and uses lower blocksizes to read the file (since
the filesize is only 3K, it would go down to 512 byte blocksize).

Thanks,
Badari
--- fs/direct-io.c.org 2005-03-08 09:53:31.823761712 -0800
+++ fs/direct-io.c 2005-03-08 12:09:33.280084600 -0800
@@ -1180,6 +1180,22 @@ __blockdev_direct_IO(int rw, struct kioc
addr = (unsigned long)iov[seg].iov_base;
size = iov[seg].iov_len;
end += size;
+
+ /*
+ * If we are trying to read beyond end of the file
+ * truncate the IO request to filesize.
+ * This is ugly: we change iov_len and nr_segs,
+ * but need to do this here since we may need to
+ * bail out if the filesize is not blocksize multiple
+ * and we may need to do fine-grain blocksizes.
+ */
+ if ((rw == READ) && (end > i_size_read(inode))) {
+ iov[seg].iov_len -= (end - i_size_read(inode));
+ size = iov[seg].iov_len;
+ end = i_size_read(inode);
+ nr_segs = seg + 1; /* Ugly - to break the loop */
+ }
+
if ((addr & blocksize_mask) || (size & blocksize_mask)) {
if (bdev)
blkbits = bdev_blkbits;