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

Configure Feed

Select the types of activity you want to include in your feed.

io_uring/kbuf: refactor __io_remove_buffers

__io_remove_buffers used for two purposes, the first is removing
buffers for non ring based lists, which implies that it can be called
multiple times for the same list. And the second is for destroying
lists, which is not perfectly reentrable for ring based lists.

It's confusing, so just have a helper for the legacy pbuf buffer
removal, make sure it's not called for ring pbuf, and open code all ring
pbuf destruction into io_put_bl().

Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Link: https://lore.kernel.org/r/0ae416b099d311ad23f285cea02f2c94c8ae9a6c.1747150490.git.asml.silence@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Pavel Begunkov and committed by
Jens Axboe
c724e801 52a05d0c

+13 -25
+13 -25
io_uring/kbuf.c
··· 376 376 return ret; 377 377 } 378 378 379 - static int __io_remove_buffers(struct io_ring_ctx *ctx, 380 - struct io_buffer_list *bl, unsigned nbufs) 379 + static int io_remove_buffers_legacy(struct io_ring_ctx *ctx, 380 + struct io_buffer_list *bl, 381 + unsigned long nbufs) 381 382 { 382 - unsigned i = 0; 383 - 384 - /* shouldn't happen */ 385 - if (!nbufs) 386 - return 0; 387 - 388 - if (bl->flags & IOBL_BUF_RING) { 389 - i = bl->buf_ring->tail - bl->head; 390 - io_free_region(ctx, &bl->region); 391 - /* make sure it's seen as empty */ 392 - INIT_LIST_HEAD(&bl->buf_list); 393 - bl->flags &= ~IOBL_BUF_RING; 394 - return i; 395 - } 383 + unsigned long i = 0; 384 + struct io_buffer *nxt; 396 385 397 386 /* protects io_buffers_cache */ 398 387 lockdep_assert_held(&ctx->uring_lock); 388 + WARN_ON_ONCE(bl->flags & IOBL_BUF_RING); 399 389 400 - while (!list_empty(&bl->buf_list)) { 401 - struct io_buffer *nxt; 402 - 390 + for (i = 0; i < nbufs && !list_empty(&bl->buf_list); i++) { 403 391 nxt = list_first_entry(&bl->buf_list, struct io_buffer, list); 404 392 list_del(&nxt->list); 405 393 kfree(nxt); 406 - 407 - if (++i == nbufs) 408 - return i; 409 394 cond_resched(); 410 395 } 411 - 412 396 return i; 413 397 } 414 398 415 399 static void io_put_bl(struct io_ring_ctx *ctx, struct io_buffer_list *bl) 416 400 { 417 - __io_remove_buffers(ctx, bl, -1U); 401 + if (bl->flags & IOBL_BUF_RING) 402 + io_free_region(ctx, &bl->region); 403 + else 404 + io_remove_buffers_legacy(ctx, bl, -1U); 405 + 418 406 kfree(bl); 419 407 } 420 408 ··· 465 477 ret = -EINVAL; 466 478 /* can't use provide/remove buffers command on mapped buffers */ 467 479 if (!(bl->flags & IOBL_BUF_RING)) 468 - ret = __io_remove_buffers(ctx, bl, p->nbufs); 480 + ret = io_remove_buffers_legacy(ctx, bl, p->nbufs); 469 481 } 470 482 io_ring_submit_unlock(ctx, issue_flags); 471 483 if (ret < 0)