txbuf.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /* RxRPC Tx data buffering.
  3. *
  4. * Copyright (C) 2022 Red Hat, Inc. All Rights Reserved.
  5. * Written by David Howells (dhowells@redhat.com)
  6. */
  7. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  8. #include <linux/slab.h>
  9. #include "ar-internal.h"
  10. static atomic_t rxrpc_txbuf_debug_ids;
  11. atomic_t rxrpc_nr_txbuf;
  12. /*
  13. * Allocate and partially initialise a data transmission buffer.
  14. */
  15. struct rxrpc_txbuf *rxrpc_alloc_data_txbuf(struct rxrpc_call *call, size_t data_size,
  16. size_t data_align, gfp_t gfp)
  17. {
  18. struct rxrpc_txbuf *txb;
  19. size_t total, doff, jsize = sizeof(struct rxrpc_jumbo_header);
  20. void *buf;
  21. txb = kzalloc_obj(*txb, gfp);
  22. if (!txb)
  23. return NULL;
  24. /* We put a jumbo header in the buffer, but not a full wire header to
  25. * avoid delayed-corruption problems with zerocopy.
  26. */
  27. doff = round_up(jsize, data_align);
  28. total = doff + data_size;
  29. data_align = umax(data_align, L1_CACHE_BYTES);
  30. mutex_lock(&call->conn->tx_data_alloc_lock);
  31. buf = page_frag_alloc_align(&call->conn->tx_data_alloc, total, gfp,
  32. data_align);
  33. mutex_unlock(&call->conn->tx_data_alloc_lock);
  34. if (!buf) {
  35. kfree(txb);
  36. return NULL;
  37. }
  38. refcount_set(&txb->ref, 1);
  39. txb->call_debug_id = call->debug_id;
  40. txb->debug_id = atomic_inc_return(&rxrpc_txbuf_debug_ids);
  41. txb->alloc_size = data_size;
  42. txb->space = data_size;
  43. txb->offset = 0;
  44. txb->flags = call->conn->out_clientflag;
  45. txb->seq = call->send_top + 1;
  46. txb->data = buf + doff;
  47. trace_rxrpc_txbuf(txb->debug_id, txb->call_debug_id, txb->seq, 1,
  48. rxrpc_txbuf_alloc_data);
  49. atomic_inc(&rxrpc_nr_txbuf);
  50. return txb;
  51. }
  52. void rxrpc_see_txbuf(struct rxrpc_txbuf *txb, enum rxrpc_txbuf_trace what)
  53. {
  54. int r = refcount_read(&txb->ref);
  55. trace_rxrpc_txbuf(txb->debug_id, txb->call_debug_id, txb->seq, r, what);
  56. }
  57. static void rxrpc_free_txbuf(struct rxrpc_txbuf *txb)
  58. {
  59. trace_rxrpc_txbuf(txb->debug_id, txb->call_debug_id, txb->seq, 0,
  60. rxrpc_txbuf_free);
  61. if (txb->data)
  62. page_frag_free(txb->data);
  63. kfree(txb);
  64. atomic_dec(&rxrpc_nr_txbuf);
  65. }
  66. void rxrpc_put_txbuf(struct rxrpc_txbuf *txb, enum rxrpc_txbuf_trace what)
  67. {
  68. unsigned int debug_id, call_debug_id;
  69. rxrpc_seq_t seq;
  70. bool dead;
  71. int r;
  72. if (txb) {
  73. debug_id = txb->debug_id;
  74. call_debug_id = txb->call_debug_id;
  75. seq = txb->seq;
  76. dead = __refcount_dec_and_test(&txb->ref, &r);
  77. trace_rxrpc_txbuf(debug_id, call_debug_id, seq, r - 1, what);
  78. if (dead)
  79. rxrpc_free_txbuf(txb);
  80. }
  81. }