• Dave Chinner's avatar
    xfs: DIO write completion size updates race · b9d59846
    Dave Chinner authored
    xfs_end_io_direct_write() can race with other IO completions when
    updating the in-core inode size. The IO completion processing is not
    serialised for direct IO - they are done either under the
    IOLOCK_SHARED for non-AIO DIO, and without any IOLOCK held at all
    during AIO DIO completion. Hence the non-atomic test-and-set update
    of the in-core inode size is racy and can result in the in-core
    inode size going backwards if the race if hit just right.
    
    If the inode size goes backwards, this can trigger the EOF zeroing
    code to run incorrectly on the next IO, which then will zero data
    that has successfully been written to disk by a previous DIO.
    
    To fix this bug, we need to serialise the test/set updates of the
    in-core inode size. This first patch introduces locking around the
    relevant updates and checks in the DIO path. Because we now have an
    ioend in xfs_end_io_direct_write(), we know exactly then we are
    doing an IO that requires an in-core EOF update, and we know that
    they are not running in interrupt context. As such, we do not need to
    use irqsave() spinlock variants to protect against interrupts while
    the lock is held.
    
    Hence we can use an existing spinlock in the inode to do this
    serialisation and so not need to grow the struct xfs_inode just to
    work around this problem.
    
    This patch does not address the test/set EOF update in
    generic_file_write_direct() for various reasons - that will be done
    as a followup with separate explanation.
    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>
    b9d59846
xfs_aops.c 51.9 KB