• D
    xfs: fix transaction leak in xfs_reflink_allocate_cow() · df307077
    Dave Chinner 提交于
    When xfs_reflink_allocate_cow() allocates a transaction, it drops
    the ILOCK to perform the operation. This Introduces a race condition
    where another thread modifying the file can perform the COW
    allocation operation underneath us. This result in the retry loop
    finding an allocated block and jumping straight to the conversion
    code. It does not, however, cancel the transaction it holds and so
    this gets leaked. This results in a lockdep warning:
    
    ================================================
    WARNING: lock held when returning to user space!
    4.18.5 #1 Not tainted
    ------------------------------------------------
    worker/6123 is leaving the kernel with locks still held!
    1 lock held by worker/6123:
     #0: 000000009eab4f1b (sb_internal#2){.+.+}, at: xfs_trans_alloc+0x17c/0x220
    
    And eventually the filesystem deadlocks because it runs out of log
    space that is reserved by the leaked transaction and never gets
    released.
    
    The logic flow in xfs_reflink_allocate_cow() is a convoluted mess of
    gotos - it's no surprise that it has bug where the flow through
    several goto jumps then fails to clean up context from a non-obvious
    logic path. CLean up the logic flow and make sure every path does
    the right thing.
    Reported-by: NAlexander Y. Fomichev <git.user@gmail.com>
    Tested-by: NAlexander Y. Fomichev <git.user@gmail.com>
    Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=200981Signed-off-by: NDave Chinner <dchinner@redhat.com>
    [hch: slight refactor]
    Signed-off-by: NChristoph Hellwig <hch@lst.de>
    Reviewed-by: NDarrick J. Wong <darrick.wong@oracle.com>
    Signed-off-by: NDave Chinner <david@fromorbit.com>
    df307077
xfs_reflink.c 42.7 KB