• E
    ext4: update i_disksize if direct write past ondisk size · 45d8ec4d
    Eryu Guan 提交于
    Currently in ext4 direct write path, we update i_disksize only when
    new eof is greater than i_size, and don't update it even when new
    eof is greater than i_disksize but less than i_size. This doesn't
    work well with delalloc buffer write, which updates i_size and
    i_disksize only when delalloc blocks are resolved (at writeback
    time), the i_disksize from direct write can be lost if a previous
    buffer write succeeded at write time but failed at writeback time,
    then results in corrupted ondisk inode size.
    
    Consider this case, first buffer write 4k data to a new file at
    offset 16k with delayed allocation, then direct write 4k data to the
    same file at offset 4k before delalloc blocks are resolved, which
    doesn't update i_disksize because it writes within i_size(20k), but
    the extent tree metadata has been committed in journal. Then
    writeback of the delalloc blocks fails (due to device error etc.),
    and i_size/i_disksize from buffer write can't be written to disk
    (still zero). A subsequent umount/mount cycle recovers journal and
    writes extent tree metadata from direct write to disk, but with
    i_disksize being zero.
    
    Fix it by updating i_disksize too in direct write path when new eof
    is greater than i_disksize but less than i_size, so i_disksize is
    always consistent with direct write.
    
    This fixes occasional i_size corruption in fstests generic/475.
    Signed-off-by: NEryu Guan <guaneryu@gmail.com>
    Signed-off-by: NTheodore Ts'o <tytso@mit.edu>
    45d8ec4d
inode.c 177.1 KB