• Omar Sandoval's avatar
    ext4: fix indirect punch hole corruption · 6f30b7e3
    Omar Sandoval authored
    Commit 4f579ae7 (ext4: fix punch hole on files with indirect
    mapping) rewrote FALLOC_FL_PUNCH_HOLE for ext4 files with indirect
    mapping. However, there are bugs in several corner cases. This fixes 5
    distinct bugs:
    
    1. When there is at least one entire level of indirection between the
    start and end of the punch range and the end of the punch range is the
    first block of its level, we can't return early; we have to free the
    intervening levels.
    
    2. When the end is at a higher level of indirection than the start and
    ext4_find_shared returns a top branch for the end, we still need to free
    the rest of the shared branch it returns; we can't decrement partial2.
    
    3. When a punch happens within one level of indirection, we need to
    converge on an indirect block that contains the start and end. However,
    because the branches returned from ext4_find_shared do not necessarily
    start at the same level (e.g., the partial2 chain will be shallower if
    the last block occurs at the beginning of an indirect group), the walk
    of the two chains can end up "missing" each other and freeing a bunch of
    extra blocks in the process. This mismatch can be handled by first
    making sure that the chains are at the same level, then walking them
    together until they converge.
    
    4. When the punch happens within one level of indirection and
    ext4_find_shared returns a top branch for the start, we must free it,
    but only if the end does not occur within that branch.
    
    5. When the punch happens within one level of indirection and
    ext4_find_shared returns a top branch for the end, then we shouldn't
    free the block referenced by the end of the returned chain (this mirrors
    the different levels case).
    Signed-off-by: default avatarOmar Sandoval <osandov@osandov.com>
    6f30b7e3
indirect.c 45.3 KB