diff options
author | Pavel Begunkov <asml.silence@gmail.com> | 2021-06-17 20:14:02 +0300 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2021-06-18 18:22:02 +0300 |
commit | b8e64b530011162adda0e176150774d22326c50c (patch) | |
tree | 4cc7a9996f02b4d102742b1467e4b278fa5cf881 /fs/io_uring.c | |
parent | c10d1f986b4e2a906862148c77a97f186cc08b9e (diff) | |
download | linux-b8e64b530011162adda0e176150774d22326c50c.tar.xz |
io_uring: track request creds with a flag
Currently, if req->creds is not NULL, then there are creds assigned.
Track the invariant with a new flag in req->flags. No need to clear the
field at init, and also cleanup can be efficiently moved into
io_clean_op().
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Link: https://lore.kernel.org/r/5f8baeb8d3b909487f555542350e2eac97005556.1623949695.git.asml.silence@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'fs/io_uring.c')
-rw-r--r-- | fs/io_uring.c | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/fs/io_uring.c b/fs/io_uring.c index 1b8d0ad9a16d..af93f790a1da 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -718,6 +718,7 @@ enum { REQ_F_COMPLETE_INLINE_BIT, REQ_F_REISSUE_BIT, REQ_F_DONT_REISSUE_BIT, + REQ_F_CREDS_BIT, /* keep async read/write and isreg together and in order */ REQ_F_ASYNC_READ_BIT, REQ_F_ASYNC_WRITE_BIT, @@ -771,6 +772,8 @@ enum { REQ_F_ASYNC_WRITE = BIT(REQ_F_ASYNC_WRITE_BIT), /* regular file */ REQ_F_ISREG = BIT(REQ_F_ISREG_BIT), + /* has creds assigned */ + REQ_F_CREDS = BIT(REQ_F_CREDS_BIT), }; struct async_poll { @@ -1236,8 +1239,10 @@ static void io_prep_async_work(struct io_kiocb *req) const struct io_op_def *def = &io_op_defs[req->opcode]; struct io_ring_ctx *ctx = req->ctx; - if (!req->creds) + if (!(req->flags & REQ_F_CREDS)) { + req->flags |= REQ_F_CREDS; req->creds = get_current_cred(); + } req->work.list.next = NULL; req->work.flags = 0; @@ -1623,7 +1628,7 @@ static void io_req_complete_post(struct io_kiocb *req, long res, static inline bool io_req_needs_clean(struct io_kiocb *req) { return req->flags & (REQ_F_BUFFER_SELECTED | REQ_F_NEED_CLEANUP | - REQ_F_POLLED | REQ_F_INFLIGHT); + REQ_F_POLLED | REQ_F_INFLIGHT | REQ_F_CREDS); } static void io_req_complete_state(struct io_kiocb *req, long res, @@ -1747,10 +1752,6 @@ static void io_dismantle_req(struct io_kiocb *req) percpu_ref_put(req->fixed_rsrc_refs); if (req->async_data) kfree(req->async_data); - if (req->creds) { - put_cred(req->creds); - req->creds = NULL; - } } /* must to be called somewhat shortly after putting a request */ @@ -6133,6 +6134,10 @@ static void io_clean_op(struct io_kiocb *req) atomic_dec(&tctx->inflight_tracked); req->flags &= ~REQ_F_INFLIGHT; } + if (req->flags & REQ_F_CREDS) { + put_cred(req->creds); + req->flags &= ~REQ_F_CREDS; + } } static int io_issue_sqe(struct io_kiocb *req, unsigned int issue_flags) @@ -6141,7 +6146,7 @@ static int io_issue_sqe(struct io_kiocb *req, unsigned int issue_flags) const struct cred *creds = NULL; int ret; - if (req->creds && req->creds != current_cred()) + if ((req->flags & REQ_F_CREDS) && req->creds != current_cred()) creds = override_creds(req->creds); switch (req->opcode) { @@ -6534,7 +6539,6 @@ static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req, atomic_set(&req->refs, 2); req->task = current; req->result = 0; - req->creds = NULL; /* enforce forwards compatibility on users */ if (unlikely(sqe_flags & ~SQE_VALID_FLAGS)) @@ -6556,6 +6560,7 @@ static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req, if (!req->creds) return -EINVAL; get_cred(req->creds); + req->flags |= REQ_F_CREDS; } state = &ctx->submit_state; |