Created attachment 166156 [details]
fix handling files with sparse blocks before extent's index, and implement runb in mmap
It turns out that the ei_blk on the first struct ext4_extent_index in an EXT4 file's root extent isn't 0 if the file starts with sparse blocks. This will cause ext4_ext_binsearch_index() to keep passing the "if (lbn < m->ei_blk)" test, moving r to the left, until r < l, then set "path->ep_index = l - 1;" resulting in garbage data being read from wrong disk blocks since path->ep_index is pointing to before the first element of the array.
I've attached a patch that keeps track of the first and last block in each extent as it descends down the extent tree, thus being able to work out that some blocks are sparse earlier, preventing the previous out of range problem. Tracking the first and last block in each extent also lets us calculate where sparse extents end better, passing larger values to read ahead in mmap.
In ext4_bmapext() I've also started supporting the runb parameter (which is apparently the number of adjacent blocks prior to the block being converted in the same way that runp is the number of blocks after), which has sped up random access to mmaped files.
Created attachment 166850 [details]
Some style(9) cleanups:
When returning a value enclose it in parenthesis.
Lines too long.
A commit references this bug:
Date: Thu Feb 11 00:34:12 UTC 2016
New revision: 295494
Ext4: fix handling of files with sparse blocks before extent's index.
This is ongoing work from Damjan Jovanovic to improve ext4 read support
with sparse files:
Keep track of the first and last block in each extent as it descends down
the extent tree, thus being able to work out that some blocks are sparse
earlier. This solves an issue on r293680.
In ext4_bmapext() start supporting the runb parameter, which appears to be
the number of adjacent blocks prior to the block being converted in the
same way that runp is the number of blocks after, speding up random access
to mmaped files.
I think, ep_is_sparse should be a boolean, but it is better to change that in a subsequent commit.
Note that I won't be merging this code to the stable branches.