Modified patch originates from Andy Green http://www.mail-archive.com/openmoko-kernel@lists.openmoko.org/msg05708.html --- fs/ext2/ext2fs.c 2008-12-17 23:21:29.000000000 +0100 +++ fs/ext2/ext2fs.c.new 2008-12-17 23:27:47.000000000 +0100 @@ -390,6 +390,13 @@ int log2blocksize = LOG2_EXT2_BLOCK_SIZE (node->data); int blocksize = 1 << (log2blocksize + DISK_SECTOR_BITS); unsigned int filesize = __le32_to_cpu(node->inode.size); + int previous_block_number = -1; + int delayed_start = 0; + int delayed_extent = 0; + int delayed_skipfirst = 0; + int delayed_next = 0; + char * delayed_buf = NULL; + int status; /* Adjust len so it we can't read past the end of the file. */ if (len > filesize) { @@ -431,15 +438,56 @@ if (blknr) { int status; - status = ext2fs_devread (blknr, skipfirst, blockend, buf); - if (status == 0) { - return (-1); + if (previous_block_number != -1) { + if (delayed_next == blknr) { + delayed_extent += blockend; + delayed_next += blockend >> SECTOR_BITS; + } else { /* spill */ + status = ext2fs_devread(delayed_start, + delayed_skipfirst, + delayed_extent, delayed_buf); + if (status == 0) + return -1; + previous_block_number = blknr; + delayed_start = blknr; + delayed_extent = blockend; + delayed_skipfirst = skipfirst; + delayed_buf = buf; + delayed_next = blknr + (blockend >> SECTOR_BITS); + } + } else { + previous_block_number = blknr; + delayed_start = blknr; + delayed_extent = blockend; + delayed_skipfirst = skipfirst; + delayed_buf = buf; + delayed_next = blknr + (blockend >> SECTOR_BITS); } } else { - memset (buf, 0, blocksize - skipfirst); + if (previous_block_number != -1) { + /* spill */ + status = ext2fs_devread(delayed_start, + delayed_skipfirst, + delayed_extent, delayed_buf); + if (status == 0) + return -1; + previous_block_number = -1; + } + memset(buf, 0, blocksize - skipfirst); } buf += blocksize - skipfirst; } + + if (previous_block_number != -1) { + /* spill */ + status = ext2fs_devread(delayed_start, + delayed_skipfirst, + delayed_extent, delayed_buf); + if (status == 0) + return -1; + previous_block_number = -1; + } + return (len); }