notif.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/kernel.h>
  3. #include <linux/errno.h>
  4. #include <linux/file.h>
  5. #include <linux/slab.h>
  6. #include <linux/net.h>
  7. #include <linux/io_uring.h>
  8. #include "io_uring.h"
  9. #include "notif.h"
  10. #include "rsrc.h"
  11. static const struct ubuf_info_ops io_ubuf_ops;
  12. static void io_notif_tw_complete(struct io_tw_req tw_req, io_tw_token_t tw)
  13. {
  14. struct io_kiocb *notif = tw_req.req;
  15. struct io_notif_data *nd = io_notif_to_data(notif);
  16. struct io_ring_ctx *ctx = notif->ctx;
  17. lockdep_assert_held(&ctx->uring_lock);
  18. do {
  19. notif = cmd_to_io_kiocb(nd);
  20. if (WARN_ON_ONCE(ctx != notif->ctx))
  21. return;
  22. lockdep_assert(refcount_read(&nd->uarg.refcnt) == 0);
  23. if (unlikely(nd->zc_report) && (nd->zc_copied || !nd->zc_used))
  24. notif->cqe.res |= IORING_NOTIF_USAGE_ZC_COPIED;
  25. if (nd->account_pages && notif->ctx->user) {
  26. __io_unaccount_mem(notif->ctx->user, nd->account_pages);
  27. nd->account_pages = 0;
  28. }
  29. nd = nd->next;
  30. io_req_task_complete((struct io_tw_req){notif}, tw);
  31. } while (nd);
  32. }
  33. void io_tx_ubuf_complete(struct sk_buff *skb, struct ubuf_info *uarg,
  34. bool success)
  35. {
  36. struct io_notif_data *nd = container_of(uarg, struct io_notif_data, uarg);
  37. struct io_kiocb *notif = cmd_to_io_kiocb(nd);
  38. unsigned tw_flags;
  39. if (nd->zc_report) {
  40. if (success && !nd->zc_used && skb)
  41. WRITE_ONCE(nd->zc_used, true);
  42. else if (!success && !nd->zc_copied)
  43. WRITE_ONCE(nd->zc_copied, true);
  44. }
  45. if (!refcount_dec_and_test(&uarg->refcnt))
  46. return;
  47. if (nd->head != nd) {
  48. io_tx_ubuf_complete(skb, &nd->head->uarg, success);
  49. return;
  50. }
  51. tw_flags = nd->next ? 0 : IOU_F_TWQ_LAZY_WAKE;
  52. notif->io_task_work.func = io_notif_tw_complete;
  53. __io_req_task_work_add(notif, tw_flags);
  54. }
  55. static int io_link_skb(struct sk_buff *skb, struct ubuf_info *uarg)
  56. {
  57. struct io_notif_data *nd, *prev_nd;
  58. struct io_kiocb *prev_notif, *notif;
  59. struct ubuf_info *prev_uarg = skb_zcopy(skb);
  60. nd = container_of(uarg, struct io_notif_data, uarg);
  61. notif = cmd_to_io_kiocb(nd);
  62. if (!prev_uarg) {
  63. net_zcopy_get(&nd->uarg);
  64. skb_zcopy_init(skb, &nd->uarg);
  65. return 0;
  66. }
  67. /* handle it separately as we can't link a notif to itself */
  68. if (unlikely(prev_uarg == &nd->uarg))
  69. return 0;
  70. /* we can't join two links together, just request a fresh skb */
  71. if (unlikely(nd->head != nd || nd->next))
  72. return -EEXIST;
  73. /* don't mix zc providers */
  74. if (unlikely(prev_uarg->ops != &io_ubuf_ops))
  75. return -EEXIST;
  76. prev_nd = container_of(prev_uarg, struct io_notif_data, uarg);
  77. prev_notif = cmd_to_io_kiocb(prev_nd);
  78. /* make sure all notifications can be finished in the same task_work */
  79. if (unlikely(notif->ctx != prev_notif->ctx ||
  80. notif->tctx != prev_notif->tctx))
  81. return -EEXIST;
  82. nd->head = prev_nd->head;
  83. nd->next = prev_nd->next;
  84. prev_nd->next = nd;
  85. net_zcopy_get(&nd->head->uarg);
  86. return 0;
  87. }
  88. static const struct ubuf_info_ops io_ubuf_ops = {
  89. .complete = io_tx_ubuf_complete,
  90. .link_skb = io_link_skb,
  91. };
  92. struct io_kiocb *io_alloc_notif(struct io_ring_ctx *ctx)
  93. __must_hold(&ctx->uring_lock)
  94. {
  95. struct io_kiocb *notif;
  96. struct io_notif_data *nd;
  97. if (unlikely(!io_alloc_req(ctx, &notif)))
  98. return NULL;
  99. notif->ctx = ctx;
  100. notif->opcode = IORING_OP_NOP;
  101. notif->flags = 0;
  102. notif->file = NULL;
  103. notif->tctx = current->io_uring;
  104. io_get_task_refs(1);
  105. notif->file_node = NULL;
  106. notif->buf_node = NULL;
  107. nd = io_notif_to_data(notif);
  108. nd->zc_report = false;
  109. nd->account_pages = 0;
  110. nd->next = NULL;
  111. nd->head = nd;
  112. nd->uarg.flags = IO_NOTIF_UBUF_FLAGS;
  113. nd->uarg.ops = &io_ubuf_ops;
  114. refcount_set(&nd->uarg.refcnt, 1);
  115. return notif;
  116. }