socklib.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * linux/net/sunrpc/socklib.c
  4. *
  5. * Common socket helper routines for RPC client and server
  6. *
  7. * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
  8. */
  9. #include <linux/compiler.h>
  10. #include <linux/netdevice.h>
  11. #include <linux/gfp.h>
  12. #include <linux/skbuff.h>
  13. #include <linux/types.h>
  14. #include <linux/pagemap.h>
  15. #include <linux/udp.h>
  16. #include <linux/sunrpc/msg_prot.h>
  17. #include <linux/sunrpc/sched.h>
  18. #include <linux/sunrpc/xdr.h>
  19. #include <linux/export.h>
  20. #include "socklib.h"
  21. /*
  22. * Helper structure for copying from an sk_buff.
  23. */
  24. struct xdr_skb_reader {
  25. struct sk_buff *skb;
  26. unsigned int offset;
  27. bool need_checksum;
  28. size_t count;
  29. __wsum csum;
  30. };
  31. /**
  32. * xdr_skb_read_bits - copy some data bits from skb to internal buffer
  33. * @desc: sk_buff copy helper
  34. * @to: copy destination
  35. * @len: number of bytes to copy
  36. *
  37. * Possibly called several times to iterate over an sk_buff and copy data out of
  38. * it.
  39. */
  40. static size_t
  41. xdr_skb_read_bits(struct xdr_skb_reader *desc, void *to, size_t len)
  42. {
  43. len = min(len, desc->count);
  44. if (desc->need_checksum) {
  45. __wsum csum;
  46. csum = skb_copy_and_csum_bits(desc->skb, desc->offset, to, len);
  47. desc->csum = csum_block_add(desc->csum, csum, desc->offset);
  48. } else {
  49. if (unlikely(skb_copy_bits(desc->skb, desc->offset, to, len)))
  50. return 0;
  51. }
  52. desc->count -= len;
  53. desc->offset += len;
  54. return len;
  55. }
  56. static ssize_t
  57. xdr_partial_copy_from_skb(struct xdr_buf *xdr, struct xdr_skb_reader *desc)
  58. {
  59. struct page **ppage = xdr->pages + (xdr->page_base >> PAGE_SHIFT);
  60. unsigned int poff = xdr->page_base & ~PAGE_MASK;
  61. unsigned int pglen = xdr->page_len;
  62. ssize_t copied = 0;
  63. size_t ret;
  64. if (xdr->head[0].iov_len == 0)
  65. return 0;
  66. ret = xdr_skb_read_bits(desc, xdr->head[0].iov_base,
  67. xdr->head[0].iov_len);
  68. if (ret != xdr->head[0].iov_len || !desc->count)
  69. return ret;
  70. copied += ret;
  71. while (pglen) {
  72. unsigned int len = min(PAGE_SIZE - poff, pglen);
  73. char *kaddr;
  74. /* ACL likes to be lazy in allocating pages - ACLs
  75. * are small by default but can get huge. */
  76. if ((xdr->flags & XDRBUF_SPARSE_PAGES) && *ppage == NULL) {
  77. *ppage = alloc_page(GFP_NOWAIT);
  78. if (unlikely(*ppage == NULL)) {
  79. if (copied == 0)
  80. return -ENOMEM;
  81. return copied;
  82. }
  83. }
  84. kaddr = kmap_atomic(*ppage);
  85. ret = xdr_skb_read_bits(desc, kaddr + poff, len);
  86. flush_dcache_page(*ppage);
  87. kunmap_atomic(kaddr);
  88. copied += ret;
  89. if (ret != len || !desc->count)
  90. return copied;
  91. ppage++;
  92. pglen -= len;
  93. poff = 0;
  94. }
  95. if (xdr->tail[0].iov_len) {
  96. copied += xdr_skb_read_bits(desc, xdr->tail[0].iov_base,
  97. xdr->tail[0].iov_len);
  98. }
  99. return copied;
  100. }
  101. /**
  102. * csum_partial_copy_to_xdr - checksum and copy data
  103. * @xdr: target XDR buffer
  104. * @skb: source skb
  105. *
  106. * We have set things up such that we perform the checksum of the UDP
  107. * packet in parallel with the copies into the RPC client iovec. -DaveM
  108. */
  109. int csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb)
  110. {
  111. struct xdr_skb_reader desc = {
  112. .skb = skb,
  113. .count = skb->len - desc.offset,
  114. };
  115. if (skb_csum_unnecessary(skb)) {
  116. if (xdr_partial_copy_from_skb(xdr, &desc) < 0)
  117. return -1;
  118. if (desc.count)
  119. return -1;
  120. return 0;
  121. }
  122. desc.need_checksum = true;
  123. desc.csum = csum_partial(skb->data, desc.offset, skb->csum);
  124. if (xdr_partial_copy_from_skb(xdr, &desc) < 0)
  125. return -1;
  126. if (desc.offset != skb->len) {
  127. __wsum csum2;
  128. csum2 = skb_checksum(skb, desc.offset, skb->len - desc.offset, 0);
  129. desc.csum = csum_block_add(desc.csum, csum2, desc.offset);
  130. }
  131. if (desc.count)
  132. return -1;
  133. if (csum_fold(desc.csum))
  134. return -1;
  135. if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE) &&
  136. !skb->csum_complete_sw)
  137. netdev_rx_csum_fault(skb->dev, skb);
  138. return 0;
  139. }
  140. static inline int xprt_sendmsg(struct socket *sock, struct msghdr *msg,
  141. size_t seek)
  142. {
  143. if (seek)
  144. iov_iter_advance(&msg->msg_iter, seek);
  145. return sock_sendmsg(sock, msg);
  146. }
  147. static int xprt_send_kvec(struct socket *sock, struct msghdr *msg,
  148. struct kvec *vec, size_t seek)
  149. {
  150. iov_iter_kvec(&msg->msg_iter, ITER_SOURCE, vec, 1, vec->iov_len);
  151. return xprt_sendmsg(sock, msg, seek);
  152. }
  153. static int xprt_send_pagedata(struct socket *sock, struct msghdr *msg,
  154. struct xdr_buf *xdr, size_t base)
  155. {
  156. iov_iter_bvec(&msg->msg_iter, ITER_SOURCE, xdr->bvec, xdr_buf_pagecount(xdr),
  157. xdr->page_len + xdr->page_base);
  158. return xprt_sendmsg(sock, msg, base + xdr->page_base);
  159. }
  160. /* Common case:
  161. * - stream transport
  162. * - sending from byte 0 of the message
  163. * - the message is wholly contained in @xdr's head iovec
  164. */
  165. static int xprt_send_rm_and_kvec(struct socket *sock, struct msghdr *msg,
  166. rpc_fraghdr marker, struct kvec *vec,
  167. size_t base)
  168. {
  169. struct kvec iov[2] = {
  170. [0] = {
  171. .iov_base = &marker,
  172. .iov_len = sizeof(marker)
  173. },
  174. [1] = *vec,
  175. };
  176. size_t len = iov[0].iov_len + iov[1].iov_len;
  177. iov_iter_kvec(&msg->msg_iter, ITER_SOURCE, iov, 2, len);
  178. return xprt_sendmsg(sock, msg, base);
  179. }
  180. /**
  181. * xprt_sock_sendmsg - write an xdr_buf directly to a socket
  182. * @sock: open socket to send on
  183. * @msg: socket message metadata
  184. * @xdr: xdr_buf containing this request
  185. * @base: starting position in the buffer
  186. * @marker: stream record marker field
  187. * @sent_p: return the total number of bytes successfully queued for sending
  188. *
  189. * Return values:
  190. * On success, returns zero and fills in @sent_p.
  191. * %-ENOTSOCK if @sock is not a struct socket.
  192. */
  193. int xprt_sock_sendmsg(struct socket *sock, struct msghdr *msg,
  194. struct xdr_buf *xdr, unsigned int base,
  195. rpc_fraghdr marker, unsigned int *sent_p)
  196. {
  197. unsigned int rmsize = marker ? sizeof(marker) : 0;
  198. unsigned int remainder = rmsize + xdr->len - base;
  199. unsigned int want;
  200. int err = 0;
  201. *sent_p = 0;
  202. if (unlikely(!sock))
  203. return -ENOTSOCK;
  204. msg->msg_flags |= MSG_MORE;
  205. want = xdr->head[0].iov_len + rmsize;
  206. if (base < want) {
  207. unsigned int len = want - base;
  208. remainder -= len;
  209. if (remainder == 0)
  210. msg->msg_flags &= ~MSG_MORE;
  211. if (rmsize)
  212. err = xprt_send_rm_and_kvec(sock, msg, marker,
  213. &xdr->head[0], base);
  214. else
  215. err = xprt_send_kvec(sock, msg, &xdr->head[0], base);
  216. if (remainder == 0 || err != len)
  217. goto out;
  218. *sent_p += err;
  219. base = 0;
  220. } else {
  221. base -= want;
  222. }
  223. if (base < xdr->page_len) {
  224. unsigned int len = xdr->page_len - base;
  225. remainder -= len;
  226. if (remainder == 0)
  227. msg->msg_flags &= ~MSG_MORE;
  228. err = xprt_send_pagedata(sock, msg, xdr, base);
  229. if (remainder == 0 || err != len)
  230. goto out;
  231. *sent_p += err;
  232. base = 0;
  233. } else {
  234. base -= xdr->page_len;
  235. }
  236. if (base >= xdr->tail[0].iov_len)
  237. return 0;
  238. msg->msg_flags &= ~MSG_MORE;
  239. err = xprt_send_kvec(sock, msg, &xdr->tail[0], base);
  240. out:
  241. if (err > 0) {
  242. *sent_p += err;
  243. err = 0;
  244. }
  245. return err;
  246. }