summaryrefslogtreecommitdiff
path: root/net/sunrpc/svcsock.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc/svcsock.c')
-rw-r--r--net/sunrpc/svcsock.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index bd85f3516a70..39b2989c6331 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -381,10 +381,17 @@ svc_udp_recvfrom(struct svc_rqst *rqstp)
dprintk("svc: recvfrom returned error %d\n", -err);
}
+ /* Sorry. */
+ if (skb_is_nonlinear(skb)) {
+ if (skb_linearize(skb, GFP_ATOMIC) != 0) {
+ kfree_skb(skb);
+ svc_sock_received(svsk, 0);
+ return 0;
+ }
+ }
+
if (skb->ip_summed != CHECKSUM_UNNECESSARY) {
- unsigned int csum = skb->csum;
- csum = csum_partial(skb->h.raw, skb->len, csum);
- if ((unsigned short)csum_fold(csum)) {
+ if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) {
skb_free_datagram(svsk->sk_sk, skb);
svc_sock_received(svsk, 0);
return 0;
@@ -395,7 +402,7 @@ svc_udp_recvfrom(struct svc_rqst *rqstp)
svsk->sk_data = 1;
len = skb->len - sizeof(struct udphdr);
- data = (u32 *) (skb->h.raw + sizeof(struct udphdr));
+ data = (u32 *) (skb->data + sizeof(struct udphdr));
rqstp->rq_skbuff = skb;
rqstp->rq_argbuf.base = data;