History

io_uring/zcrx: allow synchronous buffer return

Returning buffers via a ring is performant and convenient, but it becomes a problem when/if the user misconfigured the ring size and it becomes full. Add a synchronous way to return buffers back to the page pool via a new register opcode. It's supposed to be a reliable slow path for refilling.

Pavel Begunkov committed 1 year ago

Commit 705d2ac1 parent 8fd08d84 files · +90 −0Browse files

Unified · Split

4 files
  1. include/uapi/linux/io_uring.h +12 −0
  2. io_uring/register.c +3 −0
  3. io_uring/zcrx.c +68 −0
  4. io_uring/zcrx.h +7 −0
include/uapi/linux/io_uring.h+12−0
@@ -689,6 +689,9 @@ enum io_uring_register_op { · 688 unmodified lines
689689 /* query various aspects of io_uring, see linux/io_uring/query.h */
690690 IORING_REGISTER_QUERY = 35,
691691
692+ /* return zcrx buffers back into circulation */
693+ IORING_REGISTER_ZCRX_REFILL = 36,
694+
692695 /* this goes last */
693696 IORING_REGISTER_LAST,
694697
@@ -1070,6 +1073,15 @@ struct io_uring_zcrx_ifq_reg { · 375 unmodified lines
10701073 __u64 __resv[3];
10711074 };
10721075
1076+struct io_uring_zcrx_sync_refill {
1077+ __u32 zcrx_id;
1078+ /* the number of entries to return */
1079+ __u32 nr_entries;
1080+ /* pointer to an array of struct io_uring_zcrx_rqe */
1081+ __u64 rqes;
1082+ __u64 __resv[2];
1083+};
1084+
10731085 #ifdef __cplusplus
10741086 }
10751087 #endif
io_uring/register.c+3−0
@@ -833,6 +833,9 @@ static int __io_uring_register(struct io_ring_ctx *ctx, unsigned opcode, · 832 unmodified lines
833833 case IORING_REGISTER_QUERY:
834834 ret = io_query(ctx, arg, nr_args);
835835 break;
836+ case IORING_REGISTER_ZCRX_REFILL:
837+ ret = io_zcrx_return_bufs(ctx, arg, nr_args);
838+ break;
836839 default:
837840 ret = -EINVAL;
838841 break;
io_uring/zcrx.c+68−0
@@ -927,6 +927,74 @@ static const struct memory_provider_ops io_uring_pp_zc_ops = { · 926 unmodified lines
927927 .uninstall = io_pp_uninstall,
928928 };
929929
930+#define IO_ZCRX_MAX_SYS_REFILL_BUFS (1 << 16)
931+#define IO_ZCRX_SYS_REFILL_BATCH 32
932+
933+static void io_return_buffers(struct io_zcrx_ifq *ifq,
934+ struct io_uring_zcrx_rqe *rqes, unsigned nr)
935+{
936+ int i;
937+
938+ for (i = 0; i < nr; i++) {
939+ struct net_iov *niov;
940+ netmem_ref netmem;
941+
942+ if (!io_parse_rqe(&rqes[i], ifq, &niov))
943+ continue;
944+
945+ scoped_guard(spinlock_bh, &ifq->rq_lock) {
946+ if (!io_zcrx_put_niov_uref(niov))
947+ continue;
948+ }
949+
950+ netmem = net_iov_to_netmem(niov);
951+ if (!page_pool_unref_and_test(netmem))
952+ continue;
953+ io_zcrx_return_niov(niov);
954+ }
955+}
956+
957+int io_zcrx_return_bufs(struct io_ring_ctx *ctx,
958+ void __user *arg, unsigned nr_arg)
959+{
960+ struct io_uring_zcrx_rqe rqes[IO_ZCRX_SYS_REFILL_BATCH];
961+ struct io_uring_zcrx_rqe __user *user_rqes;
962+ struct io_uring_zcrx_sync_refill zr;
963+ struct io_zcrx_ifq *ifq;
964+ unsigned nr, i;
965+
966+ if (nr_arg)
967+ return -EINVAL;
968+ if (copy_from_user(&zr, arg, sizeof(zr)))
969+ return -EFAULT;
970+ if (!zr.nr_entries || zr.nr_entries > IO_ZCRX_MAX_SYS_REFILL_BUFS)
971+ return -EINVAL;
972+ if (!mem_is_zero(&zr.__resv, sizeof(zr.__resv)))
973+ return -EINVAL;
974+
975+ ifq = xa_load(&ctx->zcrx_ctxs, zr.zcrx_id);
976+ if (!ifq)
977+ return -EINVAL;
978+ nr = zr.nr_entries;
979+ user_rqes = u64_to_user_ptr(zr.rqes);
980+
981+ for (i = 0; i < nr;) {
982+ unsigned batch = min(nr - i, IO_ZCRX_SYS_REFILL_BATCH);
983+ size_t size = batch * sizeof(rqes[0]);
984+
985+ if (copy_from_user(rqes, user_rqes + i, size))
986+ return i ? i : -EFAULT;
987+ io_return_buffers(ifq, rqes, batch);
988+
989+ i += batch;
990+
991+ if (fatal_signal_pending(current))
992+ return i;
993+ cond_resched();
994+ }
995+ return nr;
996+}
997+
930998 static bool io_zcrx_queue_cqe(struct io_kiocb *req, struct net_iov *niov,
931999 struct io_zcrx_ifq *ifq, int off, int len)
9321000 {
io_uring/zcrx.h+7−0
@@ -63,6 +63,8 @@ struct io_zcrx_ifq { · 62 unmodified lines
6363 };
6464
6565 #if defined(CONFIG_IO_URING_ZCRX)
66+int io_zcrx_return_bufs(struct io_ring_ctx *ctx,
67+ void __user *arg, unsigned nr_arg);
6668 int io_register_zcrx_ifq(struct io_ring_ctx *ctx,
6769 struct io_uring_zcrx_ifq_reg __user *arg);
6870 void io_unregister_zcrx_ifqs(struct io_ring_ctx *ctx);
@@ -95,6 +97,11 @@ static inline struct io_mapped_region *io_zcrx_get_region(struct io_ring_ctx *ct · 26 unmodified lines
9597 {
9698 return NULL;
9799 }
100+static inline int io_zcrx_return_bufs(struct io_ring_ctx *ctx,
101+ void __user *arg, unsigned nr_arg)
102+{
103+ return -EOPNOTSUPP;
104+}
98105 #endif
99106
100107 int io_recvzc(struct io_kiocb *req, unsigned int issue_flags);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t