]> www.infradead.org Git - users/jedix/linux-maple.git/commit
ext4: don't read blocks from disk after extents being swapped
authorEryu Guan <guaneryu@gmail.com>
Fri, 12 Feb 2016 06:20:43 +0000 (01:20 -0500)
committerChuck Anderson <chuck.anderson@oracle.com>
Thu, 26 May 2016 22:45:03 +0000 (15:45 -0700)
commit3a3126715efc5c59b6038fe503490c9d1d166ecf
tree8d1ef8285b266dfc4a9a81e964d5d53420ff57ba
parentdacbc6874d349a6a49fb651c69e49ae8129ab105
ext4: don't read blocks from disk after extents being swapped

Orabug: 23330859

[ Upstream commit bcff24887d00bce102e0857d7b0a8c44a40f53d1 ]

I notice ext4/307 fails occasionally on ppc64 host, reporting md5
checksum mismatch after moving data from original file to donor file.

The reason is that move_extent_per_page() calls __block_write_begin()
and block_commit_write() to write saved data from original inode blocks
to donor inode blocks, but __block_write_begin() not only maps buffer
heads but also reads block content from disk if the size is not block
size aligned.  At this time the physical block number in mapped buffer
head is pointing to the donor file not the original file, and that
results in reading wrong data to page, which get written to disk in
following block_commit_write call.

This also can be reproduced by the following script on 1k block size ext4
on x86_64 host:

    mnt=/mnt/ext4
    donorfile=$mnt/donor
    testfile=$mnt/testfile
    e4compact=~/xfstests/src/e4compact

    rm -f $donorfile $testfile

    # reserve space for donor file, written by 0xaa and sync to disk to
    # avoid EBUSY on EXT4_IOC_MOVE_EXT
    xfs_io -fc "pwrite -S 0xaa 0 1m" -c "fsync" $donorfile

    # create test file written by 0xbb
    xfs_io -fc "pwrite -S 0xbb 0 1023" -c "fsync" $testfile

    # compute initial md5sum
    md5sum $testfile | tee md5sum.txt
    # drop cache, force e4compact to read data from disk
    echo 3 > /proc/sys/vm/drop_caches

    # test defrag
    echo "$testfile" | $e4compact -i -v -f $donorfile
    # check md5sum
    md5sum -c md5sum.txt

Fix it by creating & mapping buffer heads only but not reading blocks
from disk, because all the data in page is guaranteed to be up-to-date
in mext_page_mkuptodate().

Cc: stable@vger.kernel.org
Signed-off-by: Eryu Guan <guaneryu@gmail.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
(cherry picked from commit a285eee1ce6b0efc4bcc2599cd3fd96dd6103e6d)

Signed-off-by: Dan Duval <dan.duval@oracle.com>
fs/ext4/move_extent.c