/* * Fault injection forcing allocation errors in the xa_store() path * can lead to xa_empty() returning false, even though no actual * node is stored in the xarray. Until that gets sorted out, attempt * an iteration here and warn if any entries are found.
*/
xa_for_each(&tctx->xa, index, node) {
WARN_ON_ONCE(1); break;
}
WARN_ON_ONCE(tctx->io_wq);
WARN_ON_ONCE(tctx->cached_refs);
xa_for_each(&tctx->xa, index, node) {
io_uring_del_tctx_node(index);
cond_resched();
} if (wq) { /* * Must be after io_uring_del_tctx_node() (removes nodes under * uring_lock) to avoid race with io_uring_try_cancel_iowq().
*/
io_wq_put_and_exit(wq);
tctx->io_wq = NULL;
}
}
void io_uring_unreg_ringfd(void)
{ struct io_uring_task *tctx = current->io_uring; int i;
for (i = 0; i < IO_RINGFD_REG_MAX; i++) { if (tctx->registered_rings[i]) {
fput(tctx->registered_rings[i]);
tctx->registered_rings[i] = NULL;
}
}
}
int io_ring_add_registered_file(struct io_uring_task *tctx, struct file *file, int start, int end)
{ int offset; for (offset = start; offset < end; offset++) {
offset = array_index_nospec(offset, IO_RINGFD_REG_MAX); if (tctx->registered_rings[offset]) continue;
/* * Register a ring fd to avoid fdget/fdput for each io_uring_enter() * invocation. User passes in an array of struct io_uring_rsrc_update * with ->data set to the ring_fd, and ->offset given for the desired * index. If no index is desired, application may set ->offset == -1U * and we'll find an available index. Returns number of entries * successfully processed, or < 0 on error if none were processed.
*/ int io_ringfd_register(struct io_ring_ctx *ctx, void __user *__arg, unsigned nr_args)
{ struct io_uring_rsrc_update __user *arg = __arg; struct io_uring_rsrc_update reg; struct io_uring_task *tctx; int ret, i;
if (!nr_args || nr_args > IO_RINGFD_REG_MAX) return -EINVAL;
mutex_unlock(&ctx->uring_lock);
ret = __io_uring_add_tctx_node(ctx);
mutex_lock(&ctx->uring_lock); if (ret) return ret;
tctx = current->io_uring; for (i = 0; i < nr_args; i++) { int start, end;
if (copy_from_user(®, &arg[i], sizeof(reg))) {
ret = -EFAULT; break;
}
if (reg.resv) {
ret = -EINVAL; break;
}
if (reg.offset == -1U) {
start = 0;
end = IO_RINGFD_REG_MAX;
} else { if (reg.offset >= IO_RINGFD_REG_MAX) {
ret = -EINVAL; break;
}
start = reg.offset;
end = start + 1;
}
ret = io_ring_add_registered_fd(tctx, reg.data, start, end); if (ret < 0) break;
reg.offset = ret; if (copy_to_user(&arg[i], ®, sizeof(reg))) {
fput(tctx->registered_rings[reg.offset]);
tctx->registered_rings[reg.offset] = NULL;
ret = -EFAULT; break;
}
}
return i ? i : ret;
}
int io_ringfd_unregister(struct io_ring_ctx *ctx, void __user *__arg, unsigned nr_args)
{ struct io_uring_rsrc_update __user *arg = __arg; struct io_uring_task *tctx = current->io_uring; struct io_uring_rsrc_update reg; int ret = 0, i;
if (!nr_args || nr_args > IO_RINGFD_REG_MAX) return -EINVAL; if (!tctx) return 0;
for (i = 0; i < nr_args; i++) { if (copy_from_user(®, &arg[i], sizeof(reg))) {
ret = -EFAULT; break;
} if (reg.resv || reg.data || reg.offset >= IO_RINGFD_REG_MAX) {
ret = -EINVAL; break;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.