• Dave Chinner's avatar
    xfs: flush entire last page of old EOF on truncate up · 2ebff7bb
    Dave Chinner authored
    On a sub-page sized filesystem, truncating a mapped region down
    leaves us in a world of hurt. We truncate the pagecache, zeroing the
    newly unused tail, then punch blocks out from under the page. If we
    then truncate the file back up immediately, we expose that unmapped
    hole to a dirty page mapped into the user application, and that's
    where it all goes wrong.
    
    In truncating the page cache, we avoid unmapping the tail page of
    the cache because it still contains valid data. The problem is that
    it also contains a hole after the truncate, but nobody told the mm
    subsystem that. Therefore, if the page is dirty before the truncate,
    we'll never get a .page_mkwrite callout after we extend the file and
    the application writes data into the hole on the page.  Hence when
    we come to writing that region of the page, it has no blocks and no
    delayed allocation reservation and hence we toss the data away.
    
    This patch adds code to the truncate up case to solve it, by
    ensuring the partial page at the old EOF is always cleaned after we
    do any zeroing and move the EOF upwards. We can't actually serialise
    the page writeback and truncate against page faults (yes, that
    problem AGAIN) so this is really just a best effort and assumes it
    is extremely unlikely that someone is concurrently writing to the
    page at the EOF while extending the file.
    Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
    Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
    Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
    2ebff7bb
xfs_iops.c 34.1 KB