• Lukas Czerner's avatar
    ext4: prevent race while walking extent tree for fiemap · 91dd8c11
    Lukas Czerner authored
    Currently ext4_ext_walk_space() only takes i_data_sem for read when
    searching for the extent at given block with ext4_ext_find_extent().
    Then it drops the lock and the extent tree can be changed at will.
    However later on we're searching for the 'next' extent, but the extent
    tree might already have changed, so the information might not be
    accurate.
    
    In fact we can hit BUG_ON(end <= start) if the extent got inserted into
    the tree after the one we found and before the block we were searching
    for. This has been reproduced by running xfstests 225 in loop on s390x
    architecture, but theoretically we could hit this on any other
    architecture as well, but probably not as often.
    
    Moreover the extent currently in delayed allocation might be allocated
    after we search the extent tree and before we search extent status tree
    delayed buffers resulting in those delayed buffers being completely
    missed, even though completely written and allocated.
    
    We fix all those problems in several steps:
    
     1. remove unnecessary callback indirection
     2. rename functions
            ext4_ext_walk_space -> ext4_fill_fiemap_extents
            ext4_ext_fiemap_cb -> ext4_find_delayed_extent
     3. move fiemap_fill_next_extent() into ext4_fill_fiemap_extents()
     4. hold the i_data_sem for:
            ext4_ext_find_extent()
            ext4_ext_next_allocated_block()
            ext4_find_delayed_extent()
     5. call fiemap_fill_next_extent after releasing the i_data_sem
     6. move path reinitialization into the critical section.
    Signed-off-by: default avatarLukas Czerner <lczerner@redhat.com>
    Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
    91dd8c11
ext4_extents.h 9.66 KB