forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-08 01573e231f18eb2d99162747186f59511f56b64d
kernel/net/sunrpc/socklib.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * linux/net/sunrpc/socklib.c
34 *
....@@ -13,9 +14,24 @@
1314 #include <linux/types.h>
1415 #include <linux/pagemap.h>
1516 #include <linux/udp.h>
17
+#include <linux/sunrpc/msg_prot.h>
1618 #include <linux/sunrpc/xdr.h>
1719 #include <linux/export.h>
1820
21
+#include "socklib.h"
22
+
23
+/*
24
+ * Helper structure for copying from an sk_buff.
25
+ */
26
+struct xdr_skb_reader {
27
+ struct sk_buff *skb;
28
+ unsigned int offset;
29
+ size_t count;
30
+ __wsum csum;
31
+};
32
+
33
+typedef size_t (*xdr_skb_read_actor)(struct xdr_skb_reader *desc, void *to,
34
+ size_t len);
1935
2036 /**
2137 * xdr_skb_read_bits - copy some data bits from skb to internal buffer
....@@ -26,7 +42,8 @@
2642 * Possibly called several times to iterate over an sk_buff and copy
2743 * data out of it.
2844 */
29
-size_t xdr_skb_read_bits(struct xdr_skb_reader *desc, void *to, size_t len)
45
+static size_t
46
+xdr_skb_read_bits(struct xdr_skb_reader *desc, void *to, size_t len)
3047 {
3148 if (len > desc->count)
3249 len = desc->count;
....@@ -36,7 +53,6 @@
3653 desc->offset += len;
3754 return len;
3855 }
39
-EXPORT_SYMBOL_GPL(xdr_skb_read_bits);
4056
4157 /**
4258 * xdr_skb_read_and_csum_bits - copy and checksum from skb to buffer
....@@ -54,7 +70,7 @@
5470 if (len > desc->count)
5571 len = desc->count;
5672 pos = desc->offset;
57
- csum2 = skb_copy_and_csum_bits(desc->skb, pos, to, len, 0);
73
+ csum2 = skb_copy_and_csum_bits(desc->skb, pos, to, len);
5874 desc->csum = csum_block_add(desc->csum, csum2, pos);
5975 desc->count -= len;
6076 desc->offset += len;
....@@ -69,7 +85,8 @@
6985 * @copy_actor: virtual method for copying data
7086 *
7187 */
72
-ssize_t xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base, struct xdr_skb_reader *desc, xdr_skb_read_actor copy_actor)
88
+static ssize_t
89
+xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base, struct xdr_skb_reader *desc, xdr_skb_read_actor copy_actor)
7390 {
7491 struct page **ppage = xdr->pages;
7592 unsigned int len, pglen = xdr->page_len;
....@@ -104,8 +121,8 @@
104121
105122 /* ACL likes to be lazy in allocating pages - ACLs
106123 * are small by default but can get huge. */
107
- if (unlikely(*ppage == NULL)) {
108
- *ppage = alloc_page(GFP_ATOMIC);
124
+ if ((xdr->flags & XDRBUF_SPARSE_PAGES) && *ppage == NULL) {
125
+ *ppage = alloc_page(GFP_NOWAIT | __GFP_NOWARN);
109126 if (unlikely(*ppage == NULL)) {
110127 if (copied == 0)
111128 copied = -ENOMEM;
....@@ -140,7 +157,6 @@
140157 out:
141158 return copied;
142159 }
143
-EXPORT_SYMBOL_GPL(xdr_partial_copy_from_skb);
144160
145161 /**
146162 * csum_partial_copy_to_xdr - checksum and copy data
....@@ -175,7 +191,7 @@
175191 return -1;
176192 if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE) &&
177193 !skb->csum_complete_sw)
178
- netdev_rx_csum_fault(skb->dev);
194
+ netdev_rx_csum_fault(skb->dev, skb);
179195 return 0;
180196 no_checksum:
181197 if (xdr_partial_copy_from_skb(xdr, 0, &desc, xdr_skb_read_bits) < 0)
....@@ -185,3 +201,129 @@
185201 return 0;
186202 }
187203 EXPORT_SYMBOL_GPL(csum_partial_copy_to_xdr);
204
+
205
+static inline int xprt_sendmsg(struct socket *sock, struct msghdr *msg,
206
+ size_t seek)
207
+{
208
+ if (seek)
209
+ iov_iter_advance(&msg->msg_iter, seek);
210
+ return sock_sendmsg(sock, msg);
211
+}
212
+
213
+static int xprt_send_kvec(struct socket *sock, struct msghdr *msg,
214
+ struct kvec *vec, size_t seek)
215
+{
216
+ iov_iter_kvec(&msg->msg_iter, WRITE, vec, 1, vec->iov_len);
217
+ return xprt_sendmsg(sock, msg, seek);
218
+}
219
+
220
+static int xprt_send_pagedata(struct socket *sock, struct msghdr *msg,
221
+ struct xdr_buf *xdr, size_t base)
222
+{
223
+ int err;
224
+
225
+ err = xdr_alloc_bvec(xdr, GFP_KERNEL);
226
+ if (err < 0)
227
+ return err;
228
+
229
+ iov_iter_bvec(&msg->msg_iter, WRITE, xdr->bvec, xdr_buf_pagecount(xdr),
230
+ xdr->page_len + xdr->page_base);
231
+ return xprt_sendmsg(sock, msg, base + xdr->page_base);
232
+}
233
+
234
+/* Common case:
235
+ * - stream transport
236
+ * - sending from byte 0 of the message
237
+ * - the message is wholly contained in @xdr's head iovec
238
+ */
239
+static int xprt_send_rm_and_kvec(struct socket *sock, struct msghdr *msg,
240
+ rpc_fraghdr marker, struct kvec *vec,
241
+ size_t base)
242
+{
243
+ struct kvec iov[2] = {
244
+ [0] = {
245
+ .iov_base = &marker,
246
+ .iov_len = sizeof(marker)
247
+ },
248
+ [1] = *vec,
249
+ };
250
+ size_t len = iov[0].iov_len + iov[1].iov_len;
251
+
252
+ iov_iter_kvec(&msg->msg_iter, WRITE, iov, 2, len);
253
+ return xprt_sendmsg(sock, msg, base);
254
+}
255
+
256
+/**
257
+ * xprt_sock_sendmsg - write an xdr_buf directly to a socket
258
+ * @sock: open socket to send on
259
+ * @msg: socket message metadata
260
+ * @xdr: xdr_buf containing this request
261
+ * @base: starting position in the buffer
262
+ * @marker: stream record marker field
263
+ * @sent_p: return the total number of bytes successfully queued for sending
264
+ *
265
+ * Return values:
266
+ * On success, returns zero and fills in @sent_p.
267
+ * %-ENOTSOCK if @sock is not a struct socket.
268
+ */
269
+int xprt_sock_sendmsg(struct socket *sock, struct msghdr *msg,
270
+ struct xdr_buf *xdr, unsigned int base,
271
+ rpc_fraghdr marker, unsigned int *sent_p)
272
+{
273
+ unsigned int rmsize = marker ? sizeof(marker) : 0;
274
+ unsigned int remainder = rmsize + xdr->len - base;
275
+ unsigned int want;
276
+ int err = 0;
277
+
278
+ *sent_p = 0;
279
+
280
+ if (unlikely(!sock))
281
+ return -ENOTSOCK;
282
+
283
+ msg->msg_flags |= MSG_MORE;
284
+ want = xdr->head[0].iov_len + rmsize;
285
+ if (base < want) {
286
+ unsigned int len = want - base;
287
+
288
+ remainder -= len;
289
+ if (remainder == 0)
290
+ msg->msg_flags &= ~MSG_MORE;
291
+ if (rmsize)
292
+ err = xprt_send_rm_and_kvec(sock, msg, marker,
293
+ &xdr->head[0], base);
294
+ else
295
+ err = xprt_send_kvec(sock, msg, &xdr->head[0], base);
296
+ if (remainder == 0 || err != len)
297
+ goto out;
298
+ *sent_p += err;
299
+ base = 0;
300
+ } else {
301
+ base -= want;
302
+ }
303
+
304
+ if (base < xdr->page_len) {
305
+ unsigned int len = xdr->page_len - base;
306
+
307
+ remainder -= len;
308
+ if (remainder == 0)
309
+ msg->msg_flags &= ~MSG_MORE;
310
+ err = xprt_send_pagedata(sock, msg, xdr, base);
311
+ if (remainder == 0 || err != len)
312
+ goto out;
313
+ *sent_p += err;
314
+ base = 0;
315
+ } else {
316
+ base -= xdr->page_len;
317
+ }
318
+
319
+ if (base >= xdr->tail[0].iov_len)
320
+ return 0;
321
+ msg->msg_flags &= ~MSG_MORE;
322
+ err = xprt_send_kvec(sock, msg, &xdr->tail[0], base);
323
+out:
324
+ if (err > 0) {
325
+ *sent_p += err;
326
+ err = 0;
327
+ }
328
+ return err;
329
+}