• Josef Bacik's avatar
    btrfs: dio iomap DSYNC workaround · 0eb79294
    Josef Bacik authored
    iomap dio will run generic_write_sync() for us if the iocb is DSYNC.
    This is problematic for us because of 2 reasons:
    
    1. we hold the inode_lock() during this operation, and we take it in
       generic_write_sync()
    2. we hold a read lock on the dio_sem but take the write lock in fsync
    
    Since we don't want to rip out this code right now, but reworking the
    locking is a bit much to do at this point, work around this problem with
    this masterpiece of a patch.
    
    First, we clear DSYNC on the iocb so that the iomap stuff doesn't know
    that it needs to handle the sync.  We save this fact in
    current->journal_info, because we need to see do special things once
    we're in iomap_begin, and we have no way to pass private information
    into iomap_dio_rw().
    
    Next we specify a separate iomap_dio_ops for sync, which implements an
    ->end_io() callback that gets called when the dio completes.  This is
    important for AIO, because we really do need to run generic_write_sync()
    if we complete asynchronously.  However if we're still in the submitting
    context when we enter ->end_io() we clear the flag so that the submitter
    knows they're the ones that needs to run generic_write_sync().
    
    This is meant to be temporary.  We need to work out how to eliminate the
    inode_lock() and the dio_sem in our fsync and use another mechanism to
    protect these operations.
    Tested-by: default avatarJohannes Thumshirn <johannes.thumshirn@wdc.com>
    Signed-off-by: default avatarJosef Bacik <josef@toxicpanda.com>
    Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    0eb79294
file.c 97.7 KB