• Qu Wenruo's avatar
    btrfs: qgroup: don't try to wait flushing if we're already holding a transaction · ae5e070e
    Qu Wenruo authored
    There is a chance of racing for qgroup flushing which may lead to
    deadlock:
    
    	Thread A		|	Thread B
       (not holding trans handle)	|  (holding a trans handle)
    --------------------------------+--------------------------------
    __btrfs_qgroup_reserve_meta()   | __btrfs_qgroup_reserve_meta()
    |- try_flush_qgroup()		| |- try_flush_qgroup()
       |- QGROUP_FLUSHING bit set   |    |
       |				|    |- test_and_set_bit()
       |				|    |- wait_event()
       |- btrfs_join_transaction()	|
       |- btrfs_commit_transaction()|
    
    			!!! DEAD LOCK !!!
    
    Since thread A wants to commit transaction, but thread B is holding a
    transaction handle, blocking the commit.
    At the same time, thread B is waiting for thread A to finish its commit.
    
    This is just a hot fix, and would lead to more EDQUOT when we're near
    the qgroup limit.
    
    The proper fix would be to make all metadata/data reservations happen
    without holding a transaction handle.
    
    CC: stable@vger.kernel.org # 5.9+
    Reviewed-by: default avatarFilipe Manana <fdmanana@suse.com>
    Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    ae5e070e
qgroup.c 109 KB