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.

Merge tag 'io_uring-7.0-20260216' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux

Pull more io_uring updates from Jens Axboe:
"This is a mix of cleanups and fixes. No major fixes in here, just a
bunch of little fixes. Some of them marked for stable as it fixes
behavioral issues

- Fix an issue with SOCKET_URING_OP_SETSOCKOPT for netlink sockets,
due to a too restrictive check on it having an ioctl handler

- Remove a redundant SQPOLL check in ring creation

- Kill dead accounting for zero-copy send, which doesn't use ->buf
or ->len post the initial setup

- Fix missing clamp of the allocation hint, which could cause
allocations to fall outside of the range the application asked
for. Still within the allowed limits.

- Fix for IORING_OP_PIPE's handling of direct descriptors

- Tweak to the API for the newly added BPF filters, making them
more future proof in terms of how applications deal with them

- A few fixes for zcrx, fixing a few error handling conditions

- Fix for zcrx request flag checking

- Add support for querying the zcrx page size

- Improve the NO_SQARRAY static branch inc/dec, avoiding busy
conditions causing too much traffic

- Various little cleanups"

* tag 'io_uring-7.0-20260216' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux:
io_uring/bpf_filter: pass in expected filter payload size
io_uring/bpf_filter: move filter size and populate helper into struct
io_uring/cancel: de-unionize file and user_data in struct io_cancel_data
io_uring/rsrc: improve regbuf iov validation
io_uring: remove unneeded io_send_zc accounting
io_uring/cmd_net: fix too strict requirement on ioctl
io_uring: delay sqarray static branch disablement
io_uring/query: add query.h copyright notice
io_uring/query: return support for custom rx page size
io_uring/zcrx: check unsupported flags on import
io_uring/zcrx: fix post open error handling
io_uring/zcrx: fix sgtable leak on mapping failures
io_uring: use the right type for creds iteration
io_uring/openclose: fix io_pipe_fixed() slot tracking for specific slots
io_uring/filetable: clamp alloc_hint to the configured alloc range
io_uring/rsrc: replace reg buffer bit field with flags
io_uring/zcrx: improve types for size calculation
io_uring/tctx: avoid modifying loop variable in io_ring_add_registered_file
io_uring: simplify IORING_SETUP_DEFER_TASKRUN && !SQPOLL check

+151 -92
+8
include/uapi/linux/io_uring.h
··· 1090 1090 ZCRX_REG_IMPORT = 1, 1091 1091 }; 1092 1092 1093 + enum zcrx_features { 1094 + /* 1095 + * The user can ask for the desired rx page size by passing the 1096 + * value in struct io_uring_zcrx_ifq_reg::rx_buf_len. 1097 + */ 1098 + ZCRX_FEATURE_RX_PAGE_SIZE = 1 << 0, 1099 + }; 1100 + 1093 1101 /* 1094 1102 * Argument for IORING_REGISTER_ZCRX_IFQ 1095 1103 */
+7 -1
include/uapi/linux/io_uring/bpf_filter.h
··· 35 35 * If set, any currently unset opcode will have a deny filter attached 36 36 */ 37 37 IO_URING_BPF_FILTER_DENY_REST = 1, 38 + /* 39 + * If set, if kernel and application don't agree on pdu_size for 40 + * the given opcode, fail the registration of the filter. 41 + */ 42 + IO_URING_BPF_FILTER_SZ_STRICT = 2, 38 43 }; 39 44 40 45 struct io_uring_bpf_filter { 41 46 __u32 opcode; /* io_uring opcode to filter */ 42 47 __u32 flags; 43 48 __u32 filter_len; /* number of BPF instructions */ 44 - __u32 resv; 49 + __u8 pdu_size; /* expected pdu size for opcode */ 50 + __u8 resv[3]; 45 51 __u64 filter_ptr; /* pointer to BPF filter */ 46 52 __u64 resv2[5]; 47 53 };
+5 -1
include/uapi/linux/io_uring/query.h
··· 1 1 /* SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR MIT */ 2 2 /* 3 3 * Header file for the io_uring query interface. 4 + * 5 + * Copyright (C) 2026 Pavel Begunkov <asml.silence@gmail.com> 6 + * Copyright (C) Meta Platforms, Inc. 4 7 */ 5 8 #ifndef LINUX_IO_URING_QUERY_H 6 9 #define LINUX_IO_URING_QUERY_H ··· 53 50 __u64 area_flags; 54 51 /* The number of supported ZCRX_CTRL_* opcodes */ 55 52 __u32 nr_ctrl_opcodes; 56 - __u32 __resv1; 53 + /* Bitmask of ZCRX_FEATURE_* indicating which features are available */ 54 + __u32 features; 57 55 /* The refill ring header size */ 58 56 __u32 rq_hdr_size; 59 57 /* The alignment for the header */
+57 -29
io_uring/bpf_filter.c
··· 26 26 static void io_uring_populate_bpf_ctx(struct io_uring_bpf_ctx *bctx, 27 27 struct io_kiocb *req) 28 28 { 29 + const struct io_issue_def *def = &io_issue_defs[req->opcode]; 30 + 29 31 bctx->opcode = req->opcode; 30 32 bctx->sqe_flags = (__force int) req->flags & SQE_VALID_FLAGS; 31 33 bctx->user_data = req->cqe.user_data; ··· 36 34 sizeof(*bctx) - offsetof(struct io_uring_bpf_ctx, pdu_size)); 37 35 38 36 /* 39 - * Opcodes can provide a handler fo populating more data into bctx, 37 + * Opcodes can provide a handler for populating more data into bctx, 40 38 * for filters to use. 41 39 */ 42 - switch (req->opcode) { 43 - case IORING_OP_SOCKET: 44 - bctx->pdu_size = sizeof(bctx->socket); 45 - io_socket_bpf_populate(bctx, req); 46 - break; 47 - case IORING_OP_OPENAT: 48 - case IORING_OP_OPENAT2: 49 - bctx->pdu_size = sizeof(bctx->open); 50 - io_openat_bpf_populate(bctx, req); 51 - break; 40 + if (def->filter_pdu_size) { 41 + bctx->pdu_size = def->filter_pdu_size; 42 + def->filter_populate(bctx, req); 52 43 } 53 44 } 54 45 ··· 308 313 return ERR_PTR(-EBUSY); 309 314 } 310 315 311 - #define IO_URING_BPF_FILTER_FLAGS IO_URING_BPF_FILTER_DENY_REST 316 + #define IO_URING_BPF_FILTER_FLAGS (IO_URING_BPF_FILTER_DENY_REST | \ 317 + IO_URING_BPF_FILTER_SZ_STRICT) 318 + 319 + static int io_bpf_filter_import(struct io_uring_bpf *reg, 320 + struct io_uring_bpf __user *arg) 321 + { 322 + const struct io_issue_def *def; 323 + int ret; 324 + 325 + if (copy_from_user(reg, arg, sizeof(*reg))) 326 + return -EFAULT; 327 + if (reg->cmd_type != IO_URING_BPF_CMD_FILTER) 328 + return -EINVAL; 329 + if (reg->cmd_flags || reg->resv) 330 + return -EINVAL; 331 + 332 + if (reg->filter.opcode >= IORING_OP_LAST) 333 + return -EINVAL; 334 + if (reg->filter.flags & ~IO_URING_BPF_FILTER_FLAGS) 335 + return -EINVAL; 336 + if (!mem_is_zero(reg->filter.resv, sizeof(reg->filter.resv))) 337 + return -EINVAL; 338 + if (!mem_is_zero(reg->filter.resv2, sizeof(reg->filter.resv2))) 339 + return -EINVAL; 340 + if (!reg->filter.filter_len || reg->filter.filter_len > BPF_MAXINSNS) 341 + return -EINVAL; 342 + 343 + /* Verify filter size */ 344 + def = &io_issue_defs[array_index_nospec(reg->filter.opcode, IORING_OP_LAST)]; 345 + 346 + /* same size, always ok */ 347 + ret = 0; 348 + if (reg->filter.pdu_size == def->filter_pdu_size) 349 + ; 350 + /* size differs, fail in strict mode */ 351 + else if (reg->filter.flags & IO_URING_BPF_FILTER_SZ_STRICT) 352 + ret = -EMSGSIZE; 353 + /* userspace filter is bigger, always disallow */ 354 + else if (reg->filter.pdu_size > def->filter_pdu_size) 355 + ret = -EMSGSIZE; 356 + 357 + /* copy back kernel filter size */ 358 + reg->filter.pdu_size = def->filter_pdu_size; 359 + if (copy_to_user(&arg->filter, &reg->filter, sizeof(reg->filter))) 360 + return -EFAULT; 361 + 362 + return ret; 363 + } 312 364 313 365 int io_register_bpf_filter(struct io_restriction *res, 314 366 struct io_uring_bpf __user *arg) ··· 367 325 struct sock_fprog fprog; 368 326 int ret; 369 327 370 - if (copy_from_user(&reg, arg, sizeof(reg))) 371 - return -EFAULT; 372 - if (reg.cmd_type != IO_URING_BPF_CMD_FILTER) 373 - return -EINVAL; 374 - if (reg.cmd_flags || reg.resv) 375 - return -EINVAL; 376 - 377 - if (reg.filter.opcode >= IORING_OP_LAST) 378 - return -EINVAL; 379 - if (reg.filter.flags & ~IO_URING_BPF_FILTER_FLAGS) 380 - return -EINVAL; 381 - if (reg.filter.resv) 382 - return -EINVAL; 383 - if (!mem_is_zero(reg.filter.resv2, sizeof(reg.filter.resv2))) 384 - return -EINVAL; 385 - if (!reg.filter.filter_len || reg.filter.filter_len > BPF_MAXINSNS) 386 - return -EINVAL; 328 + ret = io_bpf_filter_import(&reg, arg); 329 + if (ret) 330 + return ret; 387 331 388 332 fprog.len = reg.filter.filter_len; 389 333 fprog.filter = u64_to_user_ptr(reg.filter.filter_ptr);
+2 -4
io_uring/cancel.h
··· 6 6 7 7 struct io_cancel_data { 8 8 struct io_ring_ctx *ctx; 9 - union { 10 - u64 data; 11 - struct file *file; 12 - }; 9 + u64 data; 10 + struct file *file; 13 11 u8 opcode; 14 12 u32 flags; 15 13 int seq;
+6 -3
io_uring/cmd_net.c
··· 160 160 struct proto *prot = READ_ONCE(sk->sk_prot); 161 161 int ret, arg = 0; 162 162 163 - if (!prot || !prot->ioctl) 164 - return -EOPNOTSUPP; 165 - 166 163 switch (cmd->cmd_op) { 167 164 case SOCKET_URING_OP_SIOCINQ: 165 + if (!prot || !prot->ioctl) 166 + return -EOPNOTSUPP; 167 + 168 168 ret = prot->ioctl(sk, SIOCINQ, &arg); 169 169 if (ret) 170 170 return ret; 171 171 return arg; 172 172 case SOCKET_URING_OP_SIOCOUTQ: 173 + if (!prot || !prot->ioctl) 174 + return -EOPNOTSUPP; 175 + 173 176 ret = prot->ioctl(sk, SIOCOUTQ, &arg); 174 177 if (ret) 175 178 return ret;
+4
io_uring/filetable.c
··· 22 22 if (!table->bitmap) 23 23 return -ENFILE; 24 24 25 + if (table->alloc_hint < ctx->file_alloc_start || 26 + table->alloc_hint >= ctx->file_alloc_end) 27 + table->alloc_hint = ctx->file_alloc_start; 28 + 25 29 do { 26 30 ret = find_next_zero_bit(table->bitmap, nr, table->alloc_hint); 27 31 if (ret != nr)
+6 -7
io_uring/io_uring.c
··· 119 119 static void io_queue_sqe(struct io_kiocb *req, unsigned int extra_flags); 120 120 static void __io_req_caches_free(struct io_ring_ctx *ctx); 121 121 122 - static __read_mostly DEFINE_STATIC_KEY_FALSE(io_key_has_sqarray); 122 + static __read_mostly DEFINE_STATIC_KEY_DEFERRED_FALSE(io_key_has_sqarray, HZ); 123 123 124 124 struct kmem_cache *req_cachep; 125 125 static struct workqueue_struct *iou_wq __ro_after_init; ··· 1978 1978 unsigned mask = ctx->sq_entries - 1; 1979 1979 unsigned head = ctx->cached_sq_head++ & mask; 1980 1980 1981 - if (static_branch_unlikely(&io_key_has_sqarray) && 1981 + if (static_branch_unlikely(&io_key_has_sqarray.key) && 1982 1982 (!(ctx->flags & IORING_SETUP_NO_SQARRAY))) { 1983 1983 head = READ_ONCE(ctx->sq_array[head]); 1984 1984 if (unlikely(head >= ctx->sq_entries)) { ··· 2173 2173 io_rings_free(ctx); 2174 2174 2175 2175 if (!(ctx->flags & IORING_SETUP_NO_SQARRAY)) 2176 - static_branch_dec(&io_key_has_sqarray); 2176 + static_branch_slow_dec_deferred(&io_key_has_sqarray); 2177 2177 2178 2178 percpu_ref_exit(&ctx->refs); 2179 2179 free_uid(ctx->user); ··· 2398 2398 static __cold void io_ring_ctx_wait_and_kill(struct io_ring_ctx *ctx) 2399 2399 { 2400 2400 unsigned long index; 2401 - struct creds *creds; 2401 + struct cred *creds; 2402 2402 2403 2403 mutex_lock(&ctx->uring_lock); 2404 2404 percpu_ref_kill(&ctx->refs); ··· 2946 2946 ctx->clock_offset = 0; 2947 2947 2948 2948 if (!(ctx->flags & IORING_SETUP_NO_SQARRAY)) 2949 - static_branch_inc(&io_key_has_sqarray); 2949 + static_branch_deferred_inc(&io_key_has_sqarray); 2950 2950 2951 2951 if ((ctx->flags & IORING_SETUP_DEFER_TASKRUN) && 2952 - !(ctx->flags & IORING_SETUP_IOPOLL) && 2953 - !(ctx->flags & IORING_SETUP_SQPOLL)) 2952 + !(ctx->flags & IORING_SETUP_IOPOLL)) 2954 2953 ctx->task_complete = true; 2955 2954 2956 2955 if (ctx->task_complete || (ctx->flags & IORING_SETUP_IOPOLL))
-2
io_uring/net.c
··· 1493 1493 return -EAGAIN; 1494 1494 1495 1495 if (ret > 0 && io_net_retry(sock, kmsg->msg.msg_flags)) { 1496 - zc->len -= ret; 1497 - zc->buf += ret; 1498 1496 zc->done_io += ret; 1499 1497 return -EAGAIN; 1500 1498 }
+6
io_uring/opdef.c
··· 221 221 .issue = io_fallocate, 222 222 }, 223 223 [IORING_OP_OPENAT] = { 224 + .filter_pdu_size = sizeof_field(struct io_uring_bpf_ctx, open), 224 225 .prep = io_openat_prep, 225 226 .issue = io_openat, 227 + .filter_populate = io_openat_bpf_populate, 226 228 }, 227 229 [IORING_OP_CLOSE] = { 228 230 .prep = io_close_prep, ··· 311 309 #endif 312 310 }, 313 311 [IORING_OP_OPENAT2] = { 312 + .filter_pdu_size = sizeof_field(struct io_uring_bpf_ctx, open), 314 313 .prep = io_openat2_prep, 315 314 .issue = io_openat2, 315 + .filter_populate = io_openat_bpf_populate, 316 316 }, 317 317 [IORING_OP_EPOLL_CTL] = { 318 318 .unbound_nonreg_file = 1, ··· 410 406 [IORING_OP_SOCKET] = { 411 407 .audit_skip = 1, 412 408 #if defined(CONFIG_NET) 409 + .filter_pdu_size = sizeof_field(struct io_uring_bpf_ctx, socket), 413 410 .prep = io_socket_prep, 414 411 .issue = io_socket, 412 + .filter_populate = io_socket_bpf_populate, 415 413 #else 416 414 .prep = io_eopnotsupp_prep, 417 415 #endif
+6
io_uring/opdef.h
··· 2 2 #ifndef IOU_OP_DEF_H 3 3 #define IOU_OP_DEF_H 4 4 5 + struct io_uring_bpf_ctx; 6 + 5 7 struct io_issue_def { 6 8 /* needs req->file assigned */ 7 9 unsigned needs_file : 1; ··· 35 33 /* size of async data needed, if any */ 36 34 unsigned short async_size; 37 35 36 + /* bpf filter pdu size, if any */ 37 + unsigned short filter_pdu_size; 38 + 38 39 int (*issue)(struct io_kiocb *, unsigned int); 39 40 int (*prep)(struct io_kiocb *, const struct io_uring_sqe *); 41 + void (*filter_populate)(struct io_uring_bpf_ctx *, struct io_kiocb *); 40 42 }; 41 43 42 44 struct io_cold_def {
+6 -3
io_uring/openclose.c
··· 345 345 { 346 346 struct io_pipe *p = io_kiocb_to_cmd(req, struct io_pipe); 347 347 struct io_ring_ctx *ctx = req->ctx; 348 + bool alloc_slot; 348 349 int ret, fds[2] = { -1, -1 }; 349 350 int slot = p->file_slot; 350 351 351 352 if (p->flags & O_CLOEXEC) 352 353 return -EINVAL; 353 354 355 + alloc_slot = slot == IORING_FILE_INDEX_ALLOC; 356 + 354 357 io_ring_submit_lock(ctx, issue_flags); 355 358 356 359 ret = __io_fixed_fd_install(ctx, files[0], slot); 357 360 if (ret < 0) 358 361 goto err; 359 - fds[0] = ret; 362 + fds[0] = alloc_slot ? ret : slot - 1; 360 363 files[0] = NULL; 361 364 362 365 /* 363 366 * If a specific slot is given, next one will be used for 364 367 * the write side. 365 368 */ 366 - if (slot != IORING_FILE_INDEX_ALLOC) 369 + if (!alloc_slot) 367 370 slot++; 368 371 369 372 ret = __io_fixed_fd_install(ctx, files[1], slot); 370 373 if (ret < 0) 371 374 goto err; 372 - fds[1] = ret; 375 + fds[1] = alloc_slot ? ret : slot - 1; 373 376 files[1] = NULL; 374 377 375 378 io_ring_submit_unlock(ctx, issue_flags);
+1 -1
io_uring/query.c
··· 39 39 e->nr_ctrl_opcodes = __ZCRX_CTRL_LAST; 40 40 e->rq_hdr_size = sizeof(struct io_uring); 41 41 e->rq_hdr_alignment = L1_CACHE_BYTES; 42 - e->__resv1 = 0; 42 + e->features = ZCRX_FEATURE_RX_PAGE_SIZE; 43 43 e->__resv2 = 0; 44 44 return sizeof(*e); 45 45 }
+16 -27
io_uring/rsrc.c
··· 96 96 return 0; 97 97 } 98 98 99 - static int io_buffer_validate(struct iovec *iov) 100 - { 101 - /* 102 - * Don't impose further limits on the size and buffer 103 - * constraints here, we'll -EINVAL later when IO is 104 - * submitted if they are wrong. 105 - */ 106 - if (!iov->iov_base) 107 - return iov->iov_len ? -EFAULT : 0; 108 - 109 - return io_validate_user_buf_range((unsigned long)iov->iov_base, 110 - iov->iov_len); 111 - } 112 - 113 99 static void io_release_ubuf(void *priv) 114 100 { 115 101 struct io_mapped_ubuf *imu = priv; ··· 305 319 err = -EFAULT; 306 320 break; 307 321 } 308 - err = io_buffer_validate(iov); 309 - if (err) 310 - break; 311 322 node = io_sqe_buffer_register(ctx, iov, &last_hpage); 312 323 if (IS_ERR(node)) { 313 324 err = PTR_ERR(node); ··· 773 790 struct io_imu_folio_data data; 774 791 bool coalesced = false; 775 792 776 - if (!iov->iov_base) 793 + if (!iov->iov_base) { 794 + if (iov->iov_len) 795 + return ERR_PTR(-EFAULT); 796 + /* remove the buffer without installing a new one */ 777 797 return NULL; 798 + } 799 + 800 + ret = io_validate_user_buf_range((unsigned long)iov->iov_base, 801 + iov->iov_len); 802 + if (ret) 803 + return ERR_PTR(ret); 778 804 779 805 node = io_rsrc_node_alloc(ctx, IORING_RSRC_BUFFER); 780 806 if (!node) ··· 820 828 imu->folio_shift = PAGE_SHIFT; 821 829 imu->release = io_release_ubuf; 822 830 imu->priv = imu; 823 - imu->is_kbuf = false; 831 + imu->flags = 0; 824 832 imu->dir = IO_IMU_DEST | IO_IMU_SOURCE; 825 833 if (coalesced) 826 834 imu->folio_shift = data.folio_shift; ··· 889 897 ret = PTR_ERR(iov); 890 898 break; 891 899 } 892 - ret = io_buffer_validate(iov); 893 - if (ret) 894 - break; 895 900 if (ctx->compat) 896 901 arg += sizeof(struct compat_iovec); 897 902 else ··· 974 985 refcount_set(&imu->refs, 1); 975 986 imu->release = release; 976 987 imu->priv = rq; 977 - imu->is_kbuf = true; 988 + imu->flags = IO_REGBUF_F_KBUF; 978 989 imu->dir = 1 << rq_data_dir(rq); 979 990 980 991 rq_for_each_bvec(bv, rq, rq_iter) ··· 1009 1020 ret = -EINVAL; 1010 1021 goto unlock; 1011 1022 } 1012 - if (!node->buf->is_kbuf) { 1023 + if (!(node->buf->flags & IO_REGBUF_F_KBUF)) { 1013 1024 ret = -EBUSY; 1014 1025 goto unlock; 1015 1026 } ··· 1065 1076 1066 1077 offset = buf_addr - imu->ubuf; 1067 1078 1068 - if (imu->is_kbuf) 1079 + if (imu->flags & IO_REGBUF_F_KBUF) 1069 1080 return io_import_kbuf(ddir, iter, imu, len, offset); 1070 1081 1071 1082 /* ··· 1485 1496 iovec_off = vec->nr - nr_iovs; 1486 1497 iov = vec->iovec + iovec_off; 1487 1498 1488 - if (imu->is_kbuf) { 1499 + if (imu->flags & IO_REGBUF_F_KBUF) { 1489 1500 int ret = io_kern_bvec_size(iov, nr_iovs, imu, &nr_segs); 1490 1501 1491 1502 if (unlikely(ret)) ··· 1523 1534 req->flags |= REQ_F_NEED_CLEANUP; 1524 1535 } 1525 1536 1526 - if (imu->is_kbuf) 1537 + if (imu->flags & IO_REGBUF_F_KBUF) 1527 1538 return io_vec_fill_kern_bvec(ddir, iter, imu, iov, nr_iovs, vec); 1528 1539 1529 1540 return io_vec_fill_bvec(ddir, iter, imu, iov, nr_iovs, vec);
+5 -1
io_uring/rsrc.h
··· 28 28 IO_IMU_SOURCE = 1 << ITER_SOURCE, 29 29 }; 30 30 31 + enum { 32 + IO_REGBUF_F_KBUF = 1, 33 + }; 34 + 31 35 struct io_mapped_ubuf { 32 36 u64 ubuf; 33 37 unsigned int len; ··· 41 37 unsigned long acct_pages; 42 38 void (*release)(void *); 43 39 void *priv; 44 - bool is_kbuf; 40 + u8 flags; 45 41 u8 dir; 46 42 struct bio_vec bvec[] __counted_by(nr_bvecs); 47 43 };
+2 -1
io_uring/rw.c
··· 702 702 if ((kiocb->ki_flags & IOCB_NOWAIT) && 703 703 !(kiocb->ki_filp->f_flags & O_NONBLOCK)) 704 704 return -EAGAIN; 705 - if ((req->flags & REQ_F_BUF_NODE) && req->buf_node->buf->is_kbuf) 705 + if ((req->flags & REQ_F_BUF_NODE) && 706 + (req->buf_node->buf->flags & IO_REGBUF_F_KBUF)) 706 707 return -EFAULT; 707 708 708 709 ppos = io_kiocb_ppos(kiocb);
+5 -5
io_uring/tctx.c
··· 240 240 int io_ring_add_registered_file(struct io_uring_task *tctx, struct file *file, 241 241 int start, int end) 242 242 { 243 - int offset; 243 + int offset, idx; 244 244 for (offset = start; offset < end; offset++) { 245 - offset = array_index_nospec(offset, IO_RINGFD_REG_MAX); 246 - if (tctx->registered_rings[offset]) 245 + idx = array_index_nospec(offset, IO_RINGFD_REG_MAX); 246 + if (tctx->registered_rings[idx]) 247 247 continue; 248 248 249 - tctx->registered_rings[offset] = file; 250 - return offset; 249 + tctx->registered_rings[idx] = file; 250 + return idx; 251 251 } 252 252 return -EBUSY; 253 253 }
+9 -7
io_uring/zcrx.c
··· 205 205 return PTR_ERR(pages); 206 206 207 207 ret = sg_alloc_table_from_pages(&mem->page_sg_table, pages, nr_pages, 208 - 0, nr_pages << PAGE_SHIFT, 208 + 0, (unsigned long)nr_pages << PAGE_SHIFT, 209 209 GFP_KERNEL_ACCOUNT); 210 210 if (ret) { 211 211 unpin_user_pages(pages, nr_pages); ··· 300 300 } 301 301 302 302 ret = io_populate_area_dma(ifq, area); 303 + if (ret && !area->mem.is_dmabuf) 304 + dma_unmap_sgtable(ifq->dev, &area->mem.page_sg_table, 305 + DMA_FROM_DEVICE, IO_DMA_ATTR); 303 306 if (ret == 0) 304 307 area->is_mapped = true; 305 308 return ret; ··· 541 538 .mp_priv = ifq, 542 539 }; 543 540 544 - if (ifq->if_rxq == -1) 545 - return; 546 - 547 541 scoped_guard(mutex, &ifq->pp_lock) { 548 542 netdev = ifq->netdev; 549 543 netdev_tracker = ifq->netdev_tracker; ··· 548 548 } 549 549 550 550 if (netdev) { 551 - net_mp_close_rxq(netdev, ifq->if_rxq, &p); 551 + if (ifq->if_rxq != -1) 552 + net_mp_close_rxq(netdev, ifq->if_rxq, &p); 552 553 netdev_put(netdev, &netdev_tracker); 553 554 } 554 555 ifq->if_rxq = -1; ··· 702 701 if (!(ctx->flags & (IORING_SETUP_CQE32|IORING_SETUP_CQE_MIXED))) 703 702 return -EINVAL; 704 703 if (reg->if_rxq || reg->rq_entries || reg->area_ptr || reg->region_ptr) 704 + return -EINVAL; 705 + if (reg->flags & ~ZCRX_REG_IMPORT) 705 706 return -EINVAL; 706 707 707 708 fd = reg->if_idx; ··· 861 858 } 862 859 return 0; 863 860 netdev_put_unlock: 864 - netdev_put(ifq->netdev, &ifq->netdev_tracker); 865 861 netdev_unlock(ifq->netdev); 866 862 err: 867 863 scoped_guard(mutex, &ctx->mmap_lock) 868 864 xa_erase(&ctx->zcrx_ctxs, id); 869 865 ifq_free: 870 - io_zcrx_ifq_free(ifq); 866 + zcrx_unregister(ifq); 871 867 return ret; 872 868 } 873 869