socklib.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  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 <[email protected]>
  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. size_t count;
  28. __wsum csum;
  29. };
  30. typedef size_t (*xdr_skb_read_actor)(struct xdr_skb_reader *desc, void *to,
  31. size_t len);
  32. /**
  33. * xdr_skb_read_bits - copy some data bits from skb to internal buffer
  34. * @desc: sk_buff copy helper
  35. * @to: copy destination
  36. * @len: number of bytes to copy
  37. *
  38. * Possibly called several times to iterate over an sk_buff and copy
  39. * data out of it.
  40. */
  41. static size_t
  42. xdr_skb_read_bits(struct xdr_skb_reader *desc, void *to, size_t len)
  43. {
  44. if (len > desc->count)
  45. len = desc->count;
  46. if (unlikely(skb_copy_bits(desc->skb, desc->offset, to, len)))
  47. return 0;
  48. desc->count -= len;
  49. desc->offset += len;
  50. return len;
  51. }
  52. /**
  53. * xdr_skb_read_and_csum_bits - copy and checksum from skb to buffer
  54. * @desc: sk_buff copy helper
  55. * @to: copy destination
  56. * @len: number of bytes to copy
  57. *
  58. * Same as skb_read_bits, but calculate a checksum at the same time.
  59. */
  60. static size_t xdr_skb_read_and_csum_bits(struct xdr_skb_reader *desc, void *to, size_t len)
  61. {
  62. unsigned int pos;
  63. __wsum csum2;
  64. if (len > desc->count)
  65. len = desc->count;
  66. pos = desc->offset;
  67. csum2 = skb_copy_and_csum_bits(desc->skb, pos, to, len);
  68. desc->csum = csum_block_add(desc->csum, csum2, pos);
  69. desc->count -= len;
  70. desc->offset += len;
  71. return len;
  72. }
  73. /**
  74. * xdr_partial_copy_from_skb - copy data out of an skb
  75. * @xdr: target XDR buffer
  76. * @base: starting offset
  77. * @desc: sk_buff copy helper
  78. * @copy_actor: virtual method for copying data
  79. *
  80. */
  81. static ssize_t
  82. xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base, struct xdr_skb_reader *desc, xdr_skb_read_actor copy_actor)
  83. {
  84. struct page **ppage = xdr->pages;
  85. unsigned int len, pglen = xdr->page_len;
  86. ssize_t copied = 0;
  87. size_t ret;
  88. len = xdr->head[0].iov_len;
  89. if (base < len) {
  90. len -= base;
  91. ret = copy_actor(desc, (char *)xdr->head[0].iov_base + base, len);
  92. copied += ret;
  93. if (ret != len || !desc->count)
  94. goto out;
  95. base = 0;
  96. } else
  97. base -= len;
  98. if (unlikely(pglen == 0))
  99. goto copy_tail;
  100. if (unlikely(base >= pglen)) {
  101. base -= pglen;
  102. goto copy_tail;
  103. }
  104. if (base || xdr->page_base) {
  105. pglen -= base;
  106. base += xdr->page_base;
  107. ppage += base >> PAGE_SHIFT;
  108. base &= ~PAGE_MASK;
  109. }
  110. do {
  111. char *kaddr;
  112. /* ACL likes to be lazy in allocating pages - ACLs
  113. * are small by default but can get huge. */
  114. if ((xdr->flags & XDRBUF_SPARSE_PAGES) && *ppage == NULL) {
  115. *ppage = alloc_page(GFP_NOWAIT | __GFP_NOWARN);
  116. if (unlikely(*ppage == NULL)) {
  117. if (copied == 0)
  118. copied = -ENOMEM;
  119. goto out;
  120. }
  121. }
  122. len = PAGE_SIZE;
  123. kaddr = kmap_atomic(*ppage);
  124. if (base) {
  125. len -= base;
  126. if (pglen < len)
  127. len = pglen;
  128. ret = copy_actor(desc, kaddr + base, len);
  129. base = 0;
  130. } else {
  131. if (pglen < len)
  132. len = pglen;
  133. ret = copy_actor(desc, kaddr, len);
  134. }
  135. flush_dcache_page(*ppage);
  136. kunmap_atomic(kaddr);
  137. copied += ret;
  138. if (ret != len || !desc->count)
  139. goto out;
  140. ppage++;
  141. } while ((pglen -= len) != 0);
  142. copy_tail:
  143. len = xdr->tail[0].iov_len;
  144. if (base < len)
  145. copied += copy_actor(desc, (char *)xdr->tail[0].iov_base + base, len - base);
  146. out:
  147. return copied;
  148. }
  149. /**
  150. * csum_partial_copy_to_xdr - checksum and copy data
  151. * @xdr: target XDR buffer
  152. * @skb: source skb
  153. *
  154. * We have set things up such that we perform the checksum of the UDP
  155. * packet in parallel with the copies into the RPC client iovec. -DaveM
  156. */
  157. int csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb)
  158. {
  159. struct xdr_skb_reader desc;
  160. desc.skb = skb;
  161. desc.offset = 0;
  162. desc.count = skb->len - desc.offset;
  163. if (skb_csum_unnecessary(skb))
  164. goto no_checksum;
  165. desc.csum = csum_partial(skb->data, desc.offset, skb->csum);
  166. if (xdr_partial_copy_from_skb(xdr, 0, &desc, xdr_skb_read_and_csum_bits) < 0)
  167. return -1;
  168. if (desc.offset != skb->len) {
  169. __wsum csum2;
  170. csum2 = skb_checksum(skb, desc.offset, skb->len - desc.offset, 0);
  171. desc.csum = csum_block_add(desc.csum, csum2, desc.offset);
  172. }
  173. if (desc.count)
  174. return -1;
  175. if (csum_fold(desc.csum))
  176. return -1;
  177. if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE) &&
  178. !skb->csum_complete_sw)
  179. netdev_rx_csum_fault(skb->dev, skb);
  180. return 0;
  181. no_checksum:
  182. if (xdr_partial_copy_from_skb(xdr, 0, &desc, xdr_skb_read_bits) < 0)
  183. return -1;
  184. if (desc.count)
  185. return -1;
  186. return 0;
  187. }
  188. EXPORT_SYMBOL_GPL(csum_partial_copy_to_xdr);
  189. static inline int xprt_sendmsg(struct socket *sock, struct msghdr *msg,
  190. size_t seek)
  191. {
  192. if (seek)
  193. iov_iter_advance(&msg->msg_iter, seek);
  194. return sock_sendmsg(sock, msg);
  195. }
  196. static int xprt_send_kvec(struct socket *sock, struct msghdr *msg,
  197. struct kvec *vec, size_t seek)
  198. {
  199. iov_iter_kvec(&msg->msg_iter, ITER_SOURCE, vec, 1, vec->iov_len);
  200. return xprt_sendmsg(sock, msg, seek);
  201. }
  202. static int xprt_send_pagedata(struct socket *sock, struct msghdr *msg,
  203. struct xdr_buf *xdr, size_t base)
  204. {
  205. iov_iter_bvec(&msg->msg_iter, ITER_SOURCE, xdr->bvec, xdr_buf_pagecount(xdr),
  206. xdr->page_len + xdr->page_base);
  207. return xprt_sendmsg(sock, msg, base + xdr->page_base);
  208. }
  209. /* Common case:
  210. * - stream transport
  211. * - sending from byte 0 of the message
  212. * - the message is wholly contained in @xdr's head iovec
  213. */
  214. static int xprt_send_rm_and_kvec(struct socket *sock, struct msghdr *msg,
  215. rpc_fraghdr marker, struct kvec *vec,
  216. size_t base)
  217. {
  218. struct kvec iov[2] = {
  219. [0] = {
  220. .iov_base = &marker,
  221. .iov_len = sizeof(marker)
  222. },
  223. [1] = *vec,
  224. };
  225. size_t len = iov[0].iov_len + iov[1].iov_len;
  226. iov_iter_kvec(&msg->msg_iter, ITER_SOURCE, iov, 2, len);
  227. return xprt_sendmsg(sock, msg, base);
  228. }
  229. /**
  230. * xprt_sock_sendmsg - write an xdr_buf directly to a socket
  231. * @sock: open socket to send on
  232. * @msg: socket message metadata
  233. * @xdr: xdr_buf containing this request
  234. * @base: starting position in the buffer
  235. * @marker: stream record marker field
  236. * @sent_p: return the total number of bytes successfully queued for sending
  237. *
  238. * Return values:
  239. * On success, returns zero and fills in @sent_p.
  240. * %-ENOTSOCK if @sock is not a struct socket.
  241. */
  242. int xprt_sock_sendmsg(struct socket *sock, struct msghdr *msg,
  243. struct xdr_buf *xdr, unsigned int base,
  244. rpc_fraghdr marker, unsigned int *sent_p)
  245. {
  246. unsigned int rmsize = marker ? sizeof(marker) : 0;
  247. unsigned int remainder = rmsize + xdr->len - base;
  248. unsigned int want;
  249. int err = 0;
  250. *sent_p = 0;
  251. if (unlikely(!sock))
  252. return -ENOTSOCK;
  253. msg->msg_flags |= MSG_MORE;
  254. want = xdr->head[0].iov_len + rmsize;
  255. if (base < want) {
  256. unsigned int len = want - base;
  257. remainder -= len;
  258. if (remainder == 0)
  259. msg->msg_flags &= ~MSG_MORE;
  260. if (rmsize)
  261. err = xprt_send_rm_and_kvec(sock, msg, marker,
  262. &xdr->head[0], base);
  263. else
  264. err = xprt_send_kvec(sock, msg, &xdr->head[0], base);
  265. if (remainder == 0 || err != len)
  266. goto out;
  267. *sent_p += err;
  268. base = 0;
  269. } else {
  270. base -= want;
  271. }
  272. if (base < xdr->page_len) {
  273. unsigned int len = xdr->page_len - base;
  274. remainder -= len;
  275. if (remainder == 0)
  276. msg->msg_flags &= ~MSG_MORE;
  277. err = xprt_send_pagedata(sock, msg, xdr, base);
  278. if (remainder == 0 || err != len)
  279. goto out;
  280. *sent_p += err;
  281. base = 0;
  282. } else {
  283. base -= xdr->page_len;
  284. }
  285. if (base >= xdr->tail[0].iov_len)
  286. return 0;
  287. msg->msg_flags &= ~MSG_MORE;
  288. err = xprt_send_kvec(sock, msg, &xdr->tail[0], base);
  289. out:
  290. if (err > 0) {
  291. *sent_p += err;
  292. err = 0;
  293. }
  294. return err;
  295. }