• Jan Kara's avatar
    ext4: fix SEEK_HOLE · 07e47097
    Jan Kara authored
    commit 7d95eddf upstream.
    
    Currently, SEEK_HOLE implementation in ext4 may both return that there's
    a hole at some offset although that offset already has data and skip
    some holes during a search for the next hole. The first problem is
    demostrated by:
    
    xfs_io -c "falloc 0 256k" -c "pwrite 0 56k" -c "seek -h 0" file
    wrote 57344/57344 bytes at offset 0
    56 KiB, 14 ops; 0.0000 sec (2.054 GiB/sec and 538461.5385 ops/sec)
    Whence	Result
    HOLE	0
    
    Where we can see that SEEK_HOLE wrongly returned offset 0 as containing
    a hole although we have written data there. The second problem can be
    demonstrated by:
    
    xfs_io -c "falloc 0 256k" -c "pwrite 0 56k" -c "pwrite 128k 8k"
           -c "seek -h 0" file
    
    wrote 57344/57344 bytes at offset 0
    56 KiB, 14 ops; 0.0000 sec (1.978 GiB/sec and 518518.5185 ops/sec)
    wrote 8192/8192 bytes at offset 131072
    8 KiB, 2 ops; 0.0000 sec (2 GiB/sec and 500000.0000 ops/sec)
    Whence	Result
    HOLE	139264
    
    Where we can see that hole at offsets 56k..128k has been ignored by the
    SEEK_HOLE call.
    
    The underlying problem is in the ext4_find_unwritten_pgoff() which is
    just buggy. In some cases it fails to update returned offset when it
    finds a hole (when no pages are found or when the first found page has
    higher index than expected), in some cases conditions for detecting hole
    are just missing (we fail to detect a situation where indices of
    returned pages are not contiguous).
    
    Fix ext4_find_unwritten_pgoff() to properly detect non-contiguous page
    indices and also handle all cases where we got less pages then expected
    in one place and handle it properly there.
    
    Fixes: c8c0df24
    CC: Zheng Liu <wenqing.lz@taobao.com>
    Signed-off-by: default avatarJan Kara <jack@suse.cz>
    Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    07e47097
file.c 14.8 KB