162306a36Sopenharmony_ci#include <linux/kernel.h> 262306a36Sopenharmony_ci#include <linux/errno.h> 362306a36Sopenharmony_ci#include <linux/file.h> 462306a36Sopenharmony_ci#include <linux/slab.h> 562306a36Sopenharmony_ci#include <linux/net.h> 662306a36Sopenharmony_ci#include <linux/io_uring.h> 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include "io_uring.h" 962306a36Sopenharmony_ci#include "notif.h" 1062306a36Sopenharmony_ci#include "rsrc.h" 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_cistatic void io_notif_complete_tw_ext(struct io_kiocb *notif, struct io_tw_state *ts) 1362306a36Sopenharmony_ci{ 1462306a36Sopenharmony_ci struct io_notif_data *nd = io_notif_to_data(notif); 1562306a36Sopenharmony_ci struct io_ring_ctx *ctx = notif->ctx; 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci if (nd->zc_report && (nd->zc_copied || !nd->zc_used)) 1862306a36Sopenharmony_ci notif->cqe.res |= IORING_NOTIF_USAGE_ZC_COPIED; 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci if (nd->account_pages && ctx->user) { 2162306a36Sopenharmony_ci __io_unaccount_mem(ctx->user, nd->account_pages); 2262306a36Sopenharmony_ci nd->account_pages = 0; 2362306a36Sopenharmony_ci } 2462306a36Sopenharmony_ci io_req_task_complete(notif, ts); 2562306a36Sopenharmony_ci} 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic void io_tx_ubuf_callback(struct sk_buff *skb, struct ubuf_info *uarg, 2862306a36Sopenharmony_ci bool success) 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci struct io_notif_data *nd = container_of(uarg, struct io_notif_data, uarg); 3162306a36Sopenharmony_ci struct io_kiocb *notif = cmd_to_io_kiocb(nd); 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci if (refcount_dec_and_test(&uarg->refcnt)) 3462306a36Sopenharmony_ci __io_req_task_work_add(notif, IOU_F_TWQ_LAZY_WAKE); 3562306a36Sopenharmony_ci} 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistatic void io_tx_ubuf_callback_ext(struct sk_buff *skb, struct ubuf_info *uarg, 3862306a36Sopenharmony_ci bool success) 3962306a36Sopenharmony_ci{ 4062306a36Sopenharmony_ci struct io_notif_data *nd = container_of(uarg, struct io_notif_data, uarg); 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci if (nd->zc_report) { 4362306a36Sopenharmony_ci if (success && !nd->zc_used && skb) 4462306a36Sopenharmony_ci WRITE_ONCE(nd->zc_used, true); 4562306a36Sopenharmony_ci else if (!success && !nd->zc_copied) 4662306a36Sopenharmony_ci WRITE_ONCE(nd->zc_copied, true); 4762306a36Sopenharmony_ci } 4862306a36Sopenharmony_ci io_tx_ubuf_callback(skb, uarg, success); 4962306a36Sopenharmony_ci} 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_civoid io_notif_set_extended(struct io_kiocb *notif) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci struct io_notif_data *nd = io_notif_to_data(notif); 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci if (nd->uarg.callback != io_tx_ubuf_callback_ext) { 5662306a36Sopenharmony_ci nd->account_pages = 0; 5762306a36Sopenharmony_ci nd->zc_report = false; 5862306a36Sopenharmony_ci nd->zc_used = false; 5962306a36Sopenharmony_ci nd->zc_copied = false; 6062306a36Sopenharmony_ci nd->uarg.callback = io_tx_ubuf_callback_ext; 6162306a36Sopenharmony_ci notif->io_task_work.func = io_notif_complete_tw_ext; 6262306a36Sopenharmony_ci } 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistruct io_kiocb *io_alloc_notif(struct io_ring_ctx *ctx) 6662306a36Sopenharmony_ci __must_hold(&ctx->uring_lock) 6762306a36Sopenharmony_ci{ 6862306a36Sopenharmony_ci struct io_kiocb *notif; 6962306a36Sopenharmony_ci struct io_notif_data *nd; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci if (unlikely(!io_alloc_req(ctx, ¬if))) 7262306a36Sopenharmony_ci return NULL; 7362306a36Sopenharmony_ci notif->opcode = IORING_OP_NOP; 7462306a36Sopenharmony_ci notif->flags = 0; 7562306a36Sopenharmony_ci notif->file = NULL; 7662306a36Sopenharmony_ci notif->task = current; 7762306a36Sopenharmony_ci io_get_task_refs(1); 7862306a36Sopenharmony_ci notif->rsrc_node = NULL; 7962306a36Sopenharmony_ci notif->io_task_work.func = io_req_task_complete; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci nd = io_notif_to_data(notif); 8262306a36Sopenharmony_ci nd->uarg.flags = IO_NOTIF_UBUF_FLAGS; 8362306a36Sopenharmony_ci nd->uarg.callback = io_tx_ubuf_callback; 8462306a36Sopenharmony_ci refcount_set(&nd->uarg.refcnt, 1); 8562306a36Sopenharmony_ci return notif; 8662306a36Sopenharmony_ci} 87