]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - drivers/net/bonding/bond_main.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[mirror_ubuntu-artful-kernel.git] / drivers / net / bonding / bond_main.c
index b9c2ae62166ddb3e8647a2c756e2ab966d2d8063..4ddcc3e41dabe5059a9981467f2c2bca2d7c5828 100644 (file)
@@ -1445,8 +1445,8 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
        struct sk_buff *skb = *pskb;
        struct slave *slave;
        struct bonding *bond;
-       int (*recv_probe)(struct sk_buff *, struct bonding *,
-                               struct slave *);
+       int (*recv_probe)(const struct sk_buff *, struct bonding *,
+                         struct slave *);
        int ret = RX_HANDLER_ANOTHER;
 
        skb = skb_share_check(skb, GFP_ATOMIC);
@@ -1463,15 +1463,10 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
 
        recv_probe = ACCESS_ONCE(bond->recv_probe);
        if (recv_probe) {
-               struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC);
-
-               if (likely(nskb)) {
-                       ret = recv_probe(nskb, bond, slave);
-                       dev_kfree_skb(nskb);
-                       if (ret == RX_HANDLER_CONSUMED) {
-                               consume_skb(skb);
-                               return ret;
-                       }
+               ret = recv_probe(skb, bond, slave);
+               if (ret == RX_HANDLER_CONSUMED) {
+                       consume_skb(skb);
+                       return ret;
                }
        }
 
@@ -2738,25 +2733,31 @@ static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32
        }
 }
 
-static int bond_arp_rcv(struct sk_buff *skb, struct bonding *bond,
-                        struct slave *slave)
+static int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond,
+                       struct slave *slave)
 {
-       struct arphdr *arp;
+       struct arphdr *arp = (struct arphdr *)skb->data;
        unsigned char *arp_ptr;
        __be32 sip, tip;
+       int alen;
 
        if (skb->protocol != __cpu_to_be16(ETH_P_ARP))
                return RX_HANDLER_ANOTHER;
 
        read_lock(&bond->lock);
+       alen = arp_hdr_len(bond->dev);
 
        pr_debug("bond_arp_rcv: bond %s skb->dev %s\n",
                 bond->dev->name, skb->dev->name);
 
-       if (!pskb_may_pull(skb, arp_hdr_len(bond->dev)))
-               goto out_unlock;
+       if (alen > skb_headlen(skb)) {
+               arp = kmalloc(alen, GFP_ATOMIC);
+               if (!arp)
+                       goto out_unlock;
+               if (skb_copy_bits(skb, 0, arp, alen) < 0)
+                       goto out_unlock;
+       }
 
-       arp = arp_hdr(skb);
        if (arp->ar_hln != bond->dev->addr_len ||
            skb->pkt_type == PACKET_OTHERHOST ||
            skb->pkt_type == PACKET_LOOPBACK ||
@@ -2791,6 +2792,8 @@ static int bond_arp_rcv(struct sk_buff *skb, struct bonding *bond,
 
 out_unlock:
        read_unlock(&bond->lock);
+       if (arp != (struct arphdr *)skb->data)
+               kfree(arp);
        return RX_HANDLER_ANOTHER;
 }
 
@@ -3227,6 +3230,12 @@ static int bond_master_netdev_event(unsigned long event,
        switch (event) {
        case NETDEV_CHANGENAME:
                return bond_event_changename(event_bond);
+       case NETDEV_UNREGISTER:
+               bond_remove_proc_entry(event_bond);
+               break;
+       case NETDEV_REGISTER:
+               bond_create_proc_entry(event_bond);
+               break;
        default:
                break;
        }
@@ -3987,7 +3996,7 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev
 out:
        if (res) {
                /* no suitable interface, frame not sent */
-               dev_kfree_skb(skb);
+               kfree_skb(skb);
        }
 
        return NETDEV_TX_OK;
@@ -4009,11 +4018,11 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d
                res = bond_dev_queue_xmit(bond, skb,
                        bond->curr_active_slave->dev);
 
+       read_unlock(&bond->curr_slave_lock);
+
        if (res)
                /* no suitable interface, frame not sent */
-               dev_kfree_skb(skb);
-
-       read_unlock(&bond->curr_slave_lock);
+               kfree_skb(skb);
 
        return NETDEV_TX_OK;
 }
@@ -4052,7 +4061,7 @@ static int bond_xmit_xor(struct sk_buff *skb, struct net_device *bond_dev)
 
        if (res) {
                /* no suitable interface, frame not sent */
-               dev_kfree_skb(skb);
+               kfree_skb(skb);
        }
 
        return NETDEV_TX_OK;
@@ -4090,7 +4099,7 @@ static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *bond_dev)
 
                                res = bond_dev_queue_xmit(bond, skb2, tx_dev);
                                if (res) {
-                                       dev_kfree_skb(skb2);
+                                       kfree_skb(skb2);
                                        continue;
                                }
                        }
@@ -4104,7 +4113,7 @@ static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *bond_dev)
 out:
        if (res)
                /* no suitable interface, frame not sent */
-               dev_kfree_skb(skb);
+               kfree_skb(skb);
 
        /* frame sent to all suitable interfaces */
        return NETDEV_TX_OK;
@@ -4210,7 +4219,7 @@ static netdev_tx_t __bond_start_xmit(struct sk_buff *skb, struct net_device *dev
                pr_err("%s: Error: Unknown bonding mode %d\n",
                       dev->name, bond->params.mode);
                WARN_ON_ONCE(1);
-               dev_kfree_skb(skb);
+               kfree_skb(skb);
                return NETDEV_TX_OK;
        }
 }
@@ -4232,7 +4241,7 @@ static netdev_tx_t bond_start_xmit(struct sk_buff *skb, struct net_device *dev)
        if (bond->slave_cnt)
                ret = __bond_start_xmit(skb, dev);
        else
-               dev_kfree_skb(skb);
+               kfree_skb(skb);
 
        read_unlock(&bond->lock);
 
@@ -4411,8 +4420,6 @@ static void bond_uninit(struct net_device *bond_dev)
 
        bond_work_cancel_all(bond);
 
-       bond_remove_proc_entry(bond);
-
        bond_debug_unregister(bond);
 
        __hw_addr_flush(&bond->mc_list);
@@ -4814,7 +4821,6 @@ static int bond_init(struct net_device *bond_dev)
 
        bond_set_lockdep_class(bond_dev);
 
-       bond_create_proc_entry(bond);
        list_add_tail(&bond->bond_list, &bn->dev_list);
 
        bond_prepare_sysfs_group(bond);