LCOV - code coverage report
Current view: top level - net/sunrpc - socklib.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 71 0.0 %
Date: 2014-04-07 Functions: 0 4 0.0 %
Branches: 0 56 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * linux/net/sunrpc/socklib.c
       3                 :            :  *
       4                 :            :  * Common socket helper routines for RPC client and server
       5                 :            :  *
       6                 :            :  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
       7                 :            :  */
       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/xdr.h>
      17                 :            : #include <linux/export.h>
      18                 :            : 
      19                 :            : 
      20                 :            : /**
      21                 :            :  * xdr_skb_read_bits - copy some data bits from skb to internal buffer
      22                 :            :  * @desc: sk_buff copy helper
      23                 :            :  * @to: copy destination
      24                 :            :  * @len: number of bytes to copy
      25                 :            :  *
      26                 :            :  * Possibly called several times to iterate over an sk_buff and copy
      27                 :            :  * data out of it.
      28                 :            :  */
      29                 :          0 : size_t xdr_skb_read_bits(struct xdr_skb_reader *desc, void *to, size_t len)
      30                 :            : {
      31         [ #  # ]:          0 :         if (len > desc->count)
      32                 :            :                 len = desc->count;
      33         [ #  # ]:          0 :         if (unlikely(skb_copy_bits(desc->skb, desc->offset, to, len)))
      34                 :            :                 return 0;
      35                 :          0 :         desc->count -= len;
      36                 :          0 :         desc->offset += len;
      37                 :          0 :         return len;
      38                 :            : }
      39                 :            : EXPORT_SYMBOL_GPL(xdr_skb_read_bits);
      40                 :            : 
      41                 :            : /**
      42                 :            :  * xdr_skb_read_and_csum_bits - copy and checksum from skb to buffer
      43                 :            :  * @desc: sk_buff copy helper
      44                 :            :  * @to: copy destination
      45                 :            :  * @len: number of bytes to copy
      46                 :            :  *
      47                 :            :  * Same as skb_read_bits, but calculate a checksum at the same time.
      48                 :            :  */
      49                 :          0 : static size_t xdr_skb_read_and_csum_bits(struct xdr_skb_reader *desc, void *to, size_t len)
      50                 :            : {
      51                 :            :         unsigned int pos;
      52                 :            :         __wsum csum2;
      53                 :            : 
      54         [ #  # ]:          0 :         if (len > desc->count)
      55                 :            :                 len = desc->count;
      56                 :          0 :         pos = desc->offset;
      57                 :          0 :         csum2 = skb_copy_and_csum_bits(desc->skb, pos, to, len, 0);
      58                 :          0 :         desc->csum = csum_block_add(desc->csum, csum2, pos);
      59                 :          0 :         desc->count -= len;
      60                 :          0 :         desc->offset += len;
      61                 :          0 :         return len;
      62                 :            : }
      63                 :            : 
      64                 :            : /**
      65                 :            :  * xdr_partial_copy_from_skb - copy data out of an skb
      66                 :            :  * @xdr: target XDR buffer
      67                 :            :  * @base: starting offset
      68                 :            :  * @desc: sk_buff copy helper
      69                 :            :  * @copy_actor: virtual method for copying data
      70                 :            :  *
      71                 :            :  */
      72                 :          0 : 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)
      73                 :            : {
      74                 :          0 :         struct page     **ppage = xdr->pages;
      75                 :          0 :         unsigned int    len, pglen = xdr->page_len;
      76                 :            :         ssize_t         copied = 0;
      77                 :            :         size_t          ret;
      78                 :            : 
      79                 :          0 :         len = xdr->head[0].iov_len;
      80         [ #  # ]:          0 :         if (base < len) {
      81                 :          0 :                 len -= base;
      82                 :          0 :                 ret = copy_actor(desc, (char *)xdr->head[0].iov_base + base, len);
      83                 :          0 :                 copied += ret;
      84 [ #  # ][ #  # ]:          0 :                 if (ret != len || !desc->count)
      85                 :            :                         goto out;
      86                 :            :                 base = 0;
      87                 :            :         } else
      88                 :          0 :                 base -= len;
      89                 :            : 
      90         [ #  # ]:          0 :         if (unlikely(pglen == 0))
      91                 :            :                 goto copy_tail;
      92         [ #  # ]:          0 :         if (unlikely(base >= pglen)) {
      93                 :          0 :                 base -= pglen;
      94                 :          0 :                 goto copy_tail;
      95                 :            :         }
      96 [ #  # ][ #  # ]:          0 :         if (base || xdr->page_base) {
      97                 :          0 :                 pglen -= base;
      98                 :          0 :                 base += xdr->page_base;
      99                 :          0 :                 ppage += base >> PAGE_CACHE_SHIFT;
     100                 :          0 :                 base &= ~PAGE_CACHE_MASK;
     101                 :            :         }
     102                 :            :         do {
     103                 :            :                 char *kaddr;
     104                 :            : 
     105                 :            :                 /* ACL likes to be lazy in allocating pages - ACLs
     106                 :            :                  * are small by default but can get huge. */
     107         [ #  # ]:          0 :                 if (unlikely(*ppage == NULL)) {
     108                 :          0 :                         *ppage = alloc_page(GFP_ATOMIC);
     109         [ #  # ]:          0 :                         if (unlikely(*ppage == NULL)) {
     110         [ #  # ]:          0 :                                 if (copied == 0)
     111                 :            :                                         copied = -ENOMEM;
     112                 :            :                                 goto out;
     113                 :            :                         }
     114                 :            :                 }
     115                 :            : 
     116                 :            :                 len = PAGE_CACHE_SIZE;
     117                 :          0 :                 kaddr = kmap_atomic(*ppage);
     118         [ #  # ]:          0 :                 if (base) {
     119                 :          0 :                         len -= base;
     120         [ #  # ]:          0 :                         if (pglen < len)
     121                 :            :                                 len = pglen;
     122                 :          0 :                         ret = copy_actor(desc, kaddr + base, len);
     123                 :            :                         base = 0;
     124                 :            :                 } else {
     125         [ #  # ]:          0 :                         if (pglen < len)
     126                 :            :                                 len = pglen;
     127                 :          0 :                         ret = copy_actor(desc, kaddr, len);
     128                 :            :                 }
     129                 :          0 :                 flush_dcache_page(*ppage);
     130                 :          0 :                 kunmap_atomic(kaddr);
     131                 :          0 :                 copied += ret;
     132 [ #  # ][ #  # ]:          0 :                 if (ret != len || !desc->count)
     133                 :            :                         goto out;
     134                 :          0 :                 ppage++;
     135         [ #  # ]:          0 :         } while ((pglen -= len) != 0);
     136                 :            : copy_tail:
     137                 :          0 :         len = xdr->tail[0].iov_len;
     138         [ #  # ]:          0 :         if (base < len)
     139                 :          0 :                 copied += copy_actor(desc, (char *)xdr->tail[0].iov_base + base, len - base);
     140                 :            : out:
     141                 :          0 :         return copied;
     142                 :            : }
     143                 :            : EXPORT_SYMBOL_GPL(xdr_partial_copy_from_skb);
     144                 :            : 
     145                 :            : /**
     146                 :            :  * csum_partial_copy_to_xdr - checksum and copy data
     147                 :            :  * @xdr: target XDR buffer
     148                 :            :  * @skb: source skb
     149                 :            :  *
     150                 :            :  * We have set things up such that we perform the checksum of the UDP
     151                 :            :  * packet in parallel with the copies into the RPC client iovec.  -DaveM
     152                 :            :  */
     153                 :          0 : int csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb)
     154                 :            : {
     155                 :            :         struct xdr_skb_reader   desc;
     156                 :            : 
     157                 :          0 :         desc.skb = skb;
     158                 :          0 :         desc.offset = sizeof(struct udphdr);
     159                 :          0 :         desc.count = skb->len - desc.offset;
     160                 :            : 
     161         [ #  # ]:          0 :         if (skb_csum_unnecessary(skb))
     162                 :            :                 goto no_checksum;
     163                 :            : 
     164                 :          0 :         desc.csum = csum_partial(skb->data, desc.offset, skb->csum);
     165         [ #  # ]:          0 :         if (xdr_partial_copy_from_skb(xdr, 0, &desc, xdr_skb_read_and_csum_bits) < 0)
     166                 :            :                 return -1;
     167         [ #  # ]:          0 :         if (desc.offset != skb->len) {
     168                 :            :                 __wsum csum2;
     169                 :          0 :                 csum2 = skb_checksum(skb, desc.offset, skb->len - desc.offset, 0);
     170                 :          0 :                 desc.csum = csum_block_add(desc.csum, csum2, desc.offset);
     171                 :            :         }
     172         [ #  # ]:          0 :         if (desc.count)
     173                 :            :                 return -1;
     174         [ #  # ]:          0 :         if (csum_fold(desc.csum))
     175                 :            :                 return -1;
     176         [ #  # ]:          0 :         if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE))
     177                 :          0 :                 netdev_rx_csum_fault(skb->dev);
     178                 :            :         return 0;
     179                 :            : no_checksum:
     180         [ #  # ]:          0 :         if (xdr_partial_copy_from_skb(xdr, 0, &desc, xdr_skb_read_bits) < 0)
     181                 :            :                 return -1;
     182         [ #  # ]:          0 :         if (desc.count)
     183                 :            :                 return -1;
     184                 :          0 :         return 0;
     185                 :            : }
     186                 :            : EXPORT_SYMBOL_GPL(csum_partial_copy_to_xdr);

Generated by: LCOV version 1.9