On 24/02/2020 19:02, Jens Axboe wrote: >> Usually doesn't work because of such possible "hackier assignments". >> Ok, I have to go and experiment a bit. Anyway, it probably generates a lot of >> useless stuff, e.g. for req->ctx > > Tried this, and it generates the same code... Maybe it wasn't able to optimise in the first place E.g. for the following code any compiler generates 2 reads (thanks godbolt). extern void foo(int); int bar(const int *v) { foo(*v); return *v; } > > diff --git a/fs/io_uring.c b/fs/io_uring.c > index ba8d4e2d9f99..8de5863aa749 100644 > --- a/fs/io_uring.c > +++ b/fs/io_uring.c > @@ -598,7 +598,7 @@ struct io_kiocb { > > struct io_async_ctx *io; > bool needs_fixed_file; > - u8 opcode; > + const u8 opcode; > > struct io_ring_ctx *ctx; > struct list_head list; > @@ -5427,6 +5427,8 @@ static bool io_get_sqring(struct io_ring_ctx *ctx, struct io_kiocb *req, > */ > head = READ_ONCE(sq_array[ctx->cached_sq_head & ctx->sq_mask]); > if (likely(head < ctx->sq_entries)) { > + u8 *op; > + > /* > * All io need record the previous position, if LINK vs DARIN, > * it can be used to mark the position of the first IO in the > @@ -5434,7 +5436,8 @@ static bool io_get_sqring(struct io_ring_ctx *ctx, struct io_kiocb *req, > */ > req->sequence = ctx->cached_sq_head; > *sqe_ptr = &ctx->sq_sqes[head]; > - req->opcode = READ_ONCE((*sqe_ptr)->opcode); > + op = (void *) req + offsetof(struct io_kiocb, opcode); > + *op = READ_ONCE((*sqe_ptr)->opcode); > req->user_data = READ_ONCE((*sqe_ptr)->user_data); > ctx->cached_sq_head++; > return true; > -- Pavel Begunkov