diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index cd8de8c82d78..74a6089abadf 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -549,10 +549,14 @@ xfs_writeback_submit( } /* - * Send ioends that might require a transaction to the completion wq. + * Send ioends that might require a transaction to the completion wq, + * and disable the block layer task completion for them as there is no + * need to defer twice. */ - if (xfs_ioend_needs_wq_completion(ioend)) + if (xfs_ioend_needs_wq_completion(ioend)) { ioend->io_bio.bi_end_io = xfs_end_bio; + bio_clear_flag(&ioend->io_bio, BIO_COMPLETE_IN_TASK); + } return iomap_ioend_writeback_submit(wpc, error); } @@ -663,7 +667,14 @@ xfs_zoned_writeback_submit( { struct iomap_ioend *ioend = wpc->wb_ctx; + /* + * Defer all completions to our workqueue as all zoned writes require a + * transaction to be persisted. This also means we never need the block + * layer in-task completion for a task context. + */ ioend->io_bio.bi_end_io = xfs_end_bio; + bio_clear_flag(&ioend->io_bio, BIO_COMPLETE_IN_TASK); + if (error) { ioend->io_bio.bi_status = errno_to_blk_status(error); bio_endio(&ioend->io_bio);