• Jan Kara's avatar
    ext4: fix ext4_writepages() in presence of truncate · 5f1132b2
    Jan Kara authored
    Inode size can arbitrarily change while writeback is in progress. When
    ext4_writepages() has prepared a long extent for mapping and truncate
    then reduces i_size, mpage_map_and_submit_buffers() will always map just
    one buffer in a page instead of all of them due to lblk < blocks check.
    So we end up not using all blocks we've allocated (thus leaking them)
    and also delalloc accounting goes wrong manifesting as a warning like:
    
    ext4_da_release_space:1333: ext4_da_release_space: ino 12, to_free 1
    with only 0 reserved data blocks
    
    Note that the problem can happen only when blocksize < pagesize because
    otherwise we have only a single buffer in the page.
    
    Fix the problem by removing the size check from the mapping loop. We
    have an extent allocated so we have to use it all before checking for
    i_size. We also rename add_page_bufs_to_extent() to
    mpage_process_page_bufs() and make that function submit the page for IO
    if all buffers (upto EOF) in it are mapped.
    Reported-by: default avatarDave Jones <davej@redhat.com>
    Reported-by: default avatarZheng Liu <gnehzuil.liu@gmail.com>
    Signed-off-by: default avatarJan Kara <jack@suse.cz>
    Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
    Cc: stable@vger.kernel.org
    5f1132b2
inode.c 150 KB