As I mentioned in the bug-report, when the file size is not n * BUFFERSIZE, this file cannot be read correctly and the system will crash or hang up.
After investigation, I fount that data_len should be checked before lock_extent, in order to prevent the situation that when it comes to the file end, diocb->lockstart changes to lockend+1, then lock_extent will cause system's crash or hang. So move the data_len's check ahead. Signed-off-by: Liu Bo <[email protected]> Signed-off-by: Miao Xie <[email protected]> --- fs/btrfs/dio.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/btrfs/dio.c b/fs/btrfs/dio.c index c930ff5..7178a25 100644 --- a/fs/btrfs/dio.c +++ b/fs/btrfs/dio.c @@ -517,11 +517,6 @@ static void btrfs_dio_read(struct btrfs_diocb *diocb) lockend = ALIGN(end, blocksize) - 1; getlock: - /* writeout everything we read for checksum or compressed extents */ - filemap_write_and_wait_range(diocb->inode->i_mapping, - diocb->lockstart, lockend); - lock_extent(io_tree, diocb->lockstart, lockend, GFP_NOFS); - data_len = min_t(u64, end, i_size_read(diocb->inode)); if (data_len <= diocb->start) { /* whatever we finished (or 0) is returned past EOF */ @@ -529,6 +524,11 @@ getlock: } data_len -= diocb->start; + /* writeout everything we read for checksum or compressed extents */ + filemap_write_and_wait_range(diocb->inode->i_mapping, + diocb->lockstart, lockend); + lock_extent(io_tree, diocb->lockstart, lockend, GFP_NOFS); + safe_to_read = 0; while (data_len && !diocb->error) { /* error in reaper stops submit */ struct extent_map *em; -- 1.6.2.5 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
