Found the problem:
In page_buf_io.c, on line 710, we have:
rounded_isize = (inode->i_size + rounding - 1) & mask;
However, this overflows for file sizes > 32 bits. Types are:
inode->i_size: loff_t (__kernel_off_t, long long)
rounded_isize: size_t (u int)
rounding: u_int
mask: u_int
This overflow eventually caused the size of the read to be very wrong.
This should fix it (it has been checked in):
================
--- linux/fs/pagebuf/page_buf_io.c.orig Mon Nov 6 11:28:31 2000
+++ linux/fs/pagebuf/page_buf_io.c Mon Nov 6 11:37:59 2000
@@ -692,11 +692,11 @@
int maps_returned, map_entry;
unsigned long chunksize, map_size, size, readahead;
int direct = filp->f_flags & O_DIRECT;
- unsigned int rounding, mask;
- size_t rounded_isize;
-
+ unsigned long rounding;
+ loff_t mask, rounded_isize;
+
rounding = direct ? inode->i_sb->s_blocksize : PAGE_CACHE_SIZE;
- mask = ~(rounding - 1);
+ mask = ~(loff_t)(rounding - 1);
/*
* while we have data to do, get a bunch of mapping for this
================
I also changed "rounding" to unsigned long because it's possibly
assigned from inode->i_sb->s_blocksize, which is an unsigned long.
-Eric
|