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-6.19-20260102' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux

Pull io_uring fixes from Jens Axboe:

- Removed dead argument length for io_uring_validate_mmap_request()

- Use GFP_NOWAIT for overflow CQEs on legacy ring setups rather than
GFP_ATOMIC, which makes it play nicer with memcg limits

- Fix a potential circular locking issue with tctx node removal and
exec based cancelations

* tag 'io_uring-6.19-20260102' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux:
io_uring/memmap: drop unused sz param in io_uring_validate_mmap_request()
io_uring/tctx: add separate lock for list of tctx's in ctx
io_uring: use GFP_NOWAIT for overflow CQEs on legacy rings

+28 -11
+7 -1
include/linux/io_uring_types.h
··· 424 424 struct user_struct *user; 425 425 struct mm_struct *mm_account; 426 426 427 + /* 428 + * List of tctx nodes for this ctx, protected by tctx_lock. For 429 + * cancelation purposes, nests under uring_lock. 430 + */ 431 + struct list_head tctx_list; 432 + struct mutex tctx_lock; 433 + 427 434 /* ctx exit and cancelation */ 428 435 struct llist_head fallback_llist; 429 436 struct delayed_work fallback_work; 430 437 struct work_struct exit_work; 431 - struct list_head tctx_list; 432 438 struct completion ref_comp; 433 439 434 440 /* io-wq management, e.g. thread count */
+5
io_uring/cancel.c
··· 184 184 } while (1); 185 185 186 186 /* slow path, try all io-wq's */ 187 + __set_current_state(TASK_RUNNING); 187 188 io_ring_submit_lock(ctx, issue_flags); 189 + mutex_lock(&ctx->tctx_lock); 188 190 ret = -ENOENT; 189 191 list_for_each_entry(node, &ctx->tctx_list, ctx_node) { 190 192 ret = io_async_cancel_one(node->task->io_uring, cd); ··· 196 194 nr++; 197 195 } 198 196 } 197 + mutex_unlock(&ctx->tctx_lock); 199 198 io_ring_submit_unlock(ctx, issue_flags); 200 199 return all ? nr : ret; 201 200 } ··· 487 484 bool ret = false; 488 485 489 486 mutex_lock(&ctx->uring_lock); 487 + mutex_lock(&ctx->tctx_lock); 490 488 list_for_each_entry(node, &ctx->tctx_list, ctx_node) { 491 489 struct io_uring_task *tctx = node->task->io_uring; 492 490 ··· 500 496 cret = io_wq_cancel_cb(tctx->io_wq, io_cancel_ctx_cb, ctx, true); 501 497 ret |= (cret != IO_WQ_CANCEL_NOTFOUND); 502 498 } 499 + mutex_unlock(&ctx->tctx_lock); 503 500 mutex_unlock(&ctx->uring_lock); 504 501 505 502 return ret;
+6 -1
io_uring/io_uring.c
··· 340 340 INIT_LIST_HEAD(&ctx->ltimeout_list); 341 341 init_llist_head(&ctx->work_llist); 342 342 INIT_LIST_HEAD(&ctx->tctx_list); 343 + mutex_init(&ctx->tctx_lock); 343 344 ctx->submit_state.free_list.next = NULL; 344 345 INIT_HLIST_HEAD(&ctx->waitid_list); 345 346 xa_init_flags(&ctx->zcrx_ctxs, XA_FLAGS_ALLOC); ··· 865 864 { 866 865 struct io_overflow_cqe *ocqe; 867 866 868 - ocqe = io_alloc_ocqe(ctx, cqe, big_cqe, GFP_ATOMIC); 867 + ocqe = io_alloc_ocqe(ctx, cqe, big_cqe, GFP_NOWAIT); 869 868 return io_cqring_add_overflow(ctx, ocqe); 870 869 } 871 870 ··· 3046 3045 exit.ctx = ctx; 3047 3046 3048 3047 mutex_lock(&ctx->uring_lock); 3048 + mutex_lock(&ctx->tctx_lock); 3049 3049 while (!list_empty(&ctx->tctx_list)) { 3050 3050 WARN_ON_ONCE(time_after(jiffies, timeout)); 3051 3051 ··· 3058 3056 if (WARN_ON_ONCE(ret)) 3059 3057 continue; 3060 3058 3059 + mutex_unlock(&ctx->tctx_lock); 3061 3060 mutex_unlock(&ctx->uring_lock); 3062 3061 /* 3063 3062 * See comment above for ··· 3067 3064 */ 3068 3065 wait_for_completion_interruptible(&exit.completion); 3069 3066 mutex_lock(&ctx->uring_lock); 3067 + mutex_lock(&ctx->tctx_lock); 3070 3068 } 3069 + mutex_unlock(&ctx->tctx_lock); 3071 3070 mutex_unlock(&ctx->uring_lock); 3072 3071 spin_lock(&ctx->completion_lock); 3073 3072 spin_unlock(&ctx->completion_lock);
+4 -5
io_uring/memmap.c
··· 268 268 return io_region_get_ptr(mr); 269 269 } 270 270 271 - static void *io_uring_validate_mmap_request(struct file *file, loff_t pgoff, 272 - size_t sz) 271 + static void *io_uring_validate_mmap_request(struct file *file, loff_t pgoff) 273 272 { 274 273 struct io_ring_ctx *ctx = file->private_data; 275 274 struct io_mapped_region *region; ··· 303 304 304 305 guard(mutex)(&ctx->mmap_lock); 305 306 306 - ptr = io_uring_validate_mmap_request(file, vma->vm_pgoff, sz); 307 + ptr = io_uring_validate_mmap_request(file, vma->vm_pgoff); 307 308 if (IS_ERR(ptr)) 308 309 return PTR_ERR(ptr); 309 310 ··· 335 336 336 337 guard(mutex)(&ctx->mmap_lock); 337 338 338 - ptr = io_uring_validate_mmap_request(filp, pgoff, len); 339 + ptr = io_uring_validate_mmap_request(filp, pgoff); 339 340 if (IS_ERR(ptr)) 340 341 return -ENOMEM; 341 342 ··· 385 386 386 387 guard(mutex)(&ctx->mmap_lock); 387 388 388 - ptr = io_uring_validate_mmap_request(file, pgoff, len); 389 + ptr = io_uring_validate_mmap_request(file, pgoff); 389 390 if (IS_ERR(ptr)) 390 391 return PTR_ERR(ptr); 391 392
+2
io_uring/register.c
··· 320 320 return 0; 321 321 322 322 /* now propagate the restriction to all registered users */ 323 + mutex_lock(&ctx->tctx_lock); 323 324 list_for_each_entry(node, &ctx->tctx_list, ctx_node) { 324 325 tctx = node->task->io_uring; 325 326 if (WARN_ON_ONCE(!tctx->io_wq)) ··· 331 330 /* ignore errors, it always returns zero anyway */ 332 331 (void)io_wq_max_workers(tctx->io_wq, new_count); 333 332 } 333 + mutex_unlock(&ctx->tctx_lock); 334 334 return 0; 335 335 err: 336 336 if (sqd) {
+4 -4
io_uring/tctx.c
··· 136 136 return ret; 137 137 } 138 138 139 - mutex_lock(&ctx->uring_lock); 139 + mutex_lock(&ctx->tctx_lock); 140 140 list_add(&node->ctx_node, &ctx->tctx_list); 141 - mutex_unlock(&ctx->uring_lock); 141 + mutex_unlock(&ctx->tctx_lock); 142 142 } 143 143 return 0; 144 144 } ··· 176 176 WARN_ON_ONCE(current != node->task); 177 177 WARN_ON_ONCE(list_empty(&node->ctx_node)); 178 178 179 - mutex_lock(&node->ctx->uring_lock); 179 + mutex_lock(&node->ctx->tctx_lock); 180 180 list_del(&node->ctx_node); 181 - mutex_unlock(&node->ctx->uring_lock); 181 + mutex_unlock(&node->ctx->tctx_lock); 182 182 183 183 if (tctx->last == node->ctx) 184 184 tctx->last = NULL;