net: fix bogus cast in skb_pagelen() and use unsigned variables
authorAlexey Dobriyan <adobriyan@gmail.com>
Sat, 19 Nov 2016 01:08:08 +0000 (04:08 +0300)
committerDavid S. Miller <davem@davemloft.net>
Sun, 20 Nov 2016 03:11:25 +0000 (22:11 -0500)
1) cast to "int" is unnecessary:
   u8 will be promoted to int before decrementing,
   small positive numbers fit into "int", so their values won't be changed
   during promotion.

   Once everything is int including loop counters, signedness doesn't
   matter: 32-bit operations will stay 32-bit operations.

   But! Someone tried to make this loop smart by making everything of
   the same type apparently in an attempt to optimise it.
   Do the optimization, just differently.
   Do the cast where it matters. :^)

2) frag size is unsigned entity and sum of fragments sizes is also
   unsigned.

Make everything unsigned, leave no MOVSX instruction behind.

add/remove: 0/0 grow/shrink: 0/3 up/down: 0/-4 (-4)
function                                     old     new   delta
skb_cow_data                                 835     834      -1
ip_do_fragment                              2549    2548      -1
ip6_fragment                                3130    3128      -2
Total: Before=154865032, After=154865028, chg -0.00%

Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/skbuff.h
net/ipv4/ip_output.c
net/ipv6/ip6_output.c

index a4aeeca7e805d8eca763fcb5a31741961c0c4ec8..9c535fbccf2c7dbfae04cee393460e86d588c26b 100644 (file)
@@ -1799,11 +1799,11 @@ static inline unsigned int skb_headlen(const struct sk_buff *skb)
        return skb->len - skb->data_len;
 }
 
-static inline int skb_pagelen(const struct sk_buff *skb)
+static inline unsigned int skb_pagelen(const struct sk_buff *skb)
 {
-       int i, len = 0;
+       unsigned int i, len = 0;
 
-       for (i = (int)skb_shinfo(skb)->nr_frags - 1; i >= 0; i--)
+       for (i = skb_shinfo(skb)->nr_frags - 1; (int)i >= 0; i--)
                len += skb_frag_size(&skb_shinfo(skb)->frags[i]);
        return len + skb_headlen(skb);
 }
index eaf720b65d7ede3707d802777e76b66608124716..358f2c82b03067955064e69fe19b921d9d643c39 100644 (file)
@@ -581,7 +581,7 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
         */
        if (skb_has_frag_list(skb)) {
                struct sk_buff *frag, *frag2;
-               int first_len = skb_pagelen(skb);
+               unsigned int first_len = skb_pagelen(skb);
 
                if (first_len - hlen > mtu ||
                    ((first_len - hlen) & 7) ||
index b37054b1873d4951b5c9e33c4cea775cf2af187a..312cbd0e5038de3031c87d600d13006472b2432d 100644 (file)
@@ -625,7 +625,7 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
 
        hroom = LL_RESERVED_SPACE(rt->dst.dev);
        if (skb_has_frag_list(skb)) {
-               int first_len = skb_pagelen(skb);
+               unsigned int first_len = skb_pagelen(skb);
                struct sk_buff *frag2;
 
                if (first_len - hlen > mtu ||