• Filipe Manana's avatar
    Btrfs: fix race between fsync and lockless direct IO writes · de0ee0ed
    Filipe Manana authored
    An fsync, using the fast path, can race with a concurrent lockless direct
    IO write and end up logging a file extent item that points to an extent
    that wasn't written to yet. This is because the fast fsync path collects
    ordered extents into a local list and then collects all the new extent
    maps to log file extent items based on them, while the direct IO write
    path creates the new extent map before it creates the corresponding
    ordered extent (and submitting the respective bio(s)).
    
    So fix this by making the direct IO write path create ordered extents
    before the extent maps and make the fast fsync path collect any new
    ordered extents after it collects the extent maps.
    Note that making the fsync handler call inode_dio_wait() (after acquiring
    the inode's i_mutex) would not work and lead to a deadlock when doing
    AIO, as through AIO we end up in a path where the fsync handler is called
    (through dio_aio_complete_work() -> dio_complete() -> vfs_fsync_range())
    before the inode's dio counter is decremented (inode_dio_wait() waits
    for this counter to have a value of zero).
    Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
    Signed-off-by: default avatarChris Mason <clm@fb.com>
    de0ee0ed
inode.c 268 KB