• D
    ext4: ext4_split_extent should take care of extent zeroout · 357b66fd
    Dmitry Monakhov 提交于
    When ext4_split_extent_at() ends up doing zeroout & conversion to
    initialized instead of split & conversion, ext4_split_extent() gets
    confused and can wrongly mark the extent back as uninitialized
    resulting in end IO code getting confused from large unwritten extents
    and may result in data loss.
    
    The example of problematic behavior is:
    			    lblk len              lblk len
      ext4_split_extent() (ex=[1000,30,uninit], map=[1010,10])
        ext4_split_extent_at() (split [1000,30,uninit] at 1020)
          ext4_ext_insert_extent() -> ENOSPC
          ext4_ext_zeroout()
    	 -> extent [1000,30] is now initialized
        ext4_split_extent_at() (split [1000,30,init] at 1010,
    			     MARK_UNINIT1 | MARK_UNINIT2)
          -> extent is split and parts marked as uninitialized
    
    Fix the problem by rechecking extent type after the first
    ext4_split_extent_at() returns. None of split_flags can not be applied
    to initialized extent so this patch also add BUG_ON to prevent similar
    issues in future.
    
    TESTCASE: https://github.com/dmonakhov/xfstests/commit/b8a55eb5ce28c6ff29e620ab090902fcd5833597Signed-off-by: NDmitry Monakhov <dmonakhov@openvz.org>
    Signed-off-by: N"Theodore Ts'o" <tytso@mit.edu>
    Reviewed-by: NJan Kara <jack@suse.cz>
    357b66fd
extents.c 130.1 KB