Re: [BUG REPORT] btrfs/io_uring: GPF in tctx_task_work_run after encoded read error completion
From: David Sterba
Date: Tue Jun 30 2026 - 16:22:49 EST
Adding Mark to CC
On Tue, Jun 30, 2026 at 01:00:06PM -0600, Jens Axboe wrote:
> > # Later, the same task waits for io_uring completions and runs task_work.
> > io_uring_enter()
> > io_cqring_wait()
> > io_run_task_work()
> > task_work_run()
> > tctx_task_work()
> > tctx_task_work_run()
> > req = container_of(node, struct io_kiocb, io_task_work.node)
> > ctx = req->ctx
> > mutex_lock(&ctx->uring_lock)
> > # Crash: req->ctx appears poisoned/stale before
> > # btrfs_uring_read_finished() is reached.
>
> If the work is passed to task_work, then btrfs must return -EIOCBQUEUED.
> Looks like a basic bug in btrfs, see below. Caveat - entirely
> untested/compiled/whatever. On vacation, btrfs guys can figure this out.
Thanks for the hint.
> diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
> index 272598f6ae77..51c06618c733 100644
> --- a/fs/btrfs/inode.c
> +++ b/fs/btrfs/inode.c
> @@ -9460,7 +9460,6 @@ int btrfs_encoded_read_regular_fill_pages(struct btrfs_inode *inode,
> ret = blk_status_to_errno(READ_ONCE(priv->status));
> btrfs_uring_read_extent_endio(uring_ctx, ret);
> kfree(priv);
> - return ret;
> }
>
> return -EIOCBQUEUED;
Initial commit 34310c442e175f ("btrfs: add io_uring command for encoded
reads (ENCODED_READ ioctl)").
The ret is initialized from priv->status and is needed for
btrfs_uring_read_extent_endio() but it's apparently not meant as return
due to the task handover. I've checked other locations, this seems
to be the only not following the expected -EIOCBQUEUED.