Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

io_uring: batch io_kiocb allocation

Similarly to how we use the state->ios_left to know how many references
to get to a file, we can use it to allocate the io_kiocb's we need in
bulk.

Reviewed-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

+38 -7
+38 -7
fs/io_uring.c
··· 169 169 struct blk_plug plug; 170 170 171 171 /* 172 + * io_kiocb alloc cache 173 + */ 174 + void *reqs[IO_IOPOLL_BATCH]; 175 + unsigned int free_reqs; 176 + unsigned int cur_req; 177 + 178 + /* 172 179 * File reference cache 173 180 */ 174 181 struct file *file; ··· 312 305 wake_up(&ctx->wait); 313 306 } 314 307 315 - static struct io_kiocb *io_get_req(struct io_ring_ctx *ctx) 308 + static struct io_kiocb *io_get_req(struct io_ring_ctx *ctx, 309 + struct io_submit_state *state) 316 310 { 317 311 struct io_kiocb *req; 318 312 319 313 if (!percpu_ref_tryget(&ctx->refs)) 320 314 return NULL; 321 315 322 - req = kmem_cache_alloc(req_cachep, __GFP_NOWARN); 323 - if (req) { 324 - req->ctx = ctx; 325 - req->flags = 0; 326 - return req; 316 + if (!state) { 317 + req = kmem_cache_alloc(req_cachep, __GFP_NOWARN); 318 + if (unlikely(!req)) 319 + goto out; 320 + } else if (!state->free_reqs) { 321 + size_t sz; 322 + int ret; 323 + 324 + sz = min_t(size_t, state->ios_left, ARRAY_SIZE(state->reqs)); 325 + ret = kmem_cache_alloc_bulk(req_cachep, __GFP_NOWARN, sz, 326 + state->reqs); 327 + if (unlikely(ret <= 0)) 328 + goto out; 329 + state->free_reqs = ret - 1; 330 + state->cur_req = 1; 331 + req = state->reqs[0]; 332 + } else { 333 + req = state->reqs[state->cur_req]; 334 + state->free_reqs--; 335 + state->cur_req++; 327 336 } 328 337 338 + req->ctx = ctx; 339 + req->flags = 0; 340 + return req; 341 + out: 329 342 io_ring_drop_ctx_refs(ctx, 1); 330 343 return NULL; 331 344 } ··· 1034 1007 if (unlikely(s->sqe->flags)) 1035 1008 return -EINVAL; 1036 1009 1037 - req = io_get_req(ctx); 1010 + req = io_get_req(ctx, state); 1038 1011 if (unlikely(!req)) 1039 1012 return -EAGAIN; 1040 1013 ··· 1068 1041 { 1069 1042 blk_finish_plug(&state->plug); 1070 1043 io_file_put(state, NULL); 1044 + if (state->free_reqs) 1045 + kmem_cache_free_bulk(req_cachep, state->free_reqs, 1046 + &state->reqs[state->cur_req]); 1071 1047 } 1072 1048 1073 1049 /* ··· 1080 1050 struct io_ring_ctx *ctx, unsigned max_ios) 1081 1051 { 1082 1052 blk_start_plug(&state->plug); 1053 + state->free_reqs = 0; 1083 1054 state->file = NULL; 1084 1055 state->ios_left = max_ios; 1085 1056 }