• Jan Kara's avatar
    ext4: simplify io_end handling for AIO DIO · 109811c2
    Jan Kara authored
    When mapping blocks for direct IO, we allocate io_end structure before
    mapping blocks and store pointer to it in the inode. This creates a
    requirement that any AIO DIO using io_end must be protected by i_mutex.
    This created problems in the past with dioread_nolock mode which was
    corrupting io_end pointers. Also io_end is allocated unnecessarily in
    case where we don't need to convert any extents (which is a common case
    for example when overwriting file).
    
    We fix the problem by allocating io_end only once we return unwritten
    extent from block mapping function for AIO DIO (so we can save some
    pointless io_end allocations) and we pass pointer to it in bh->b_private
    which generic DIO code later passes to our end IO callback. That way we
    remove any need for global pointer to io_end structure and thus fix the
    races.
    
    The downside of this change is that the checking for unwritten IO in
    flight in ext4_extents_can_be_merged() is more racy since we now
    increment i_unwritten / set EXT4_STATE_DIO_UNWRITTEN only after dropping
    i_data_sem. However the check has been racy already before because
    ext4_writepages() already increment i_unwritten after dropping
    i_data_sem and reserved blocks save us from hitting ENOSPC in the worst
    case.
    Signed-off-by: default avatarJan Kara <jack@suse.cz>
    109811c2
extents.c 162 KB