net: rename sysfs symlinks on device name change
[firefly-linux-kernel-4.4.55.git] / net / core / dev.c
index ce01847793c0a0fd7b73cf02cf9cf21bbc96bf5c..99575573399701b5736adc31b6e77ac9cbabea75 100644 (file)
@@ -147,6 +147,8 @@ struct list_head ptype_base[PTYPE_HASH_SIZE] __read_mostly;
 struct list_head ptype_all __read_mostly;      /* Taps */
 static struct list_head offload_base __read_mostly;
 
+static int netif_rx_internal(struct sk_buff *skb);
+
 /*
  * The @dev_base_head list is protected by @dev_base_lock and the rtnl
  * semaphore.
@@ -1117,6 +1119,8 @@ rollback:
 
        write_seqcount_end(&devnet_rename_seq);
 
+       netdev_adjacent_rename_links(dev, oldname);
+
        write_lock_bh(&dev_base_lock);
        hlist_del_rcu(&dev->name_hlist);
        write_unlock_bh(&dev_base_lock);
@@ -1136,6 +1140,7 @@ rollback:
                        err = ret;
                        write_seqcount_begin(&devnet_rename_seq);
                        memcpy(dev->name, oldname, IFNAMSIZ);
+                       memcpy(oldname, newname, IFNAMSIZ);
                        goto rollback;
                } else {
                        pr_err("%s: name change rollback failed: %d\n",
@@ -1698,7 +1703,7 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
        skb_scrub_packet(skb, true);
        skb->protocol = eth_type_trans(skb, dev);
 
-       return netif_rx(skb);
+       return netif_rx_internal(skb);
 }
 EXPORT_SYMBOL_GPL(dev_forward_skb);
 
@@ -2530,7 +2535,7 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)
 EXPORT_SYMBOL(netif_skb_features);
 
 int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
-                       struct netdev_queue *txq, void *accel_priv)
+                       struct netdev_queue *txq)
 {
        const struct net_device_ops *ops = dev->netdev_ops;
        int rc = NETDEV_TX_OK;
@@ -2596,13 +2601,10 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
                        dev_queue_xmit_nit(skb, dev);
 
                skb_len = skb->len;
-               if (accel_priv)
-                       rc = ops->ndo_dfwd_start_xmit(skb, dev, accel_priv);
-               else
-                       rc = ops->ndo_start_xmit(skb, dev);
-
+               trace_net_dev_start_xmit(skb, dev);
+               rc = ops->ndo_start_xmit(skb, dev);
                trace_net_dev_xmit(skb, rc, dev, skb_len);
-               if (rc == NETDEV_TX_OK && txq)
+               if (rc == NETDEV_TX_OK)
                        txq_trans_update(txq);
                return rc;
        }
@@ -2618,10 +2620,8 @@ gso:
                        dev_queue_xmit_nit(nskb, dev);
 
                skb_len = nskb->len;
-               if (accel_priv)
-                       rc = ops->ndo_dfwd_start_xmit(nskb, dev, accel_priv);
-               else
-                       rc = ops->ndo_start_xmit(nskb, dev);
+               trace_net_dev_start_xmit(nskb, dev);
+               rc = ops->ndo_start_xmit(nskb, dev);
                trace_net_dev_xmit(nskb, rc, dev, skb_len);
                if (unlikely(rc != NETDEV_TX_OK)) {
                        if (rc & ~NETDEV_TX_MASK)
@@ -2802,7 +2802,7 @@ EXPORT_SYMBOL(dev_loopback_xmit);
  *      the BH enable code must have IRQs enabled so that it will not deadlock.
  *          --BLG
  */
-int dev_queue_xmit(struct sk_buff *skb)
+int __dev_queue_xmit(struct sk_buff *skb, void *accel_priv)
 {
        struct net_device *dev = skb->dev;
        struct netdev_queue *txq;
@@ -2818,7 +2818,7 @@ int dev_queue_xmit(struct sk_buff *skb)
 
        skb_update_prio(skb);
 
-       txq = netdev_pick_tx(dev, skb);
+       txq = netdev_pick_tx(dev, skb, accel_priv);
        q = rcu_dereference_bh(txq->qdisc);
 
 #ifdef CONFIG_NET_CLS_ACT
@@ -2854,7 +2854,7 @@ int dev_queue_xmit(struct sk_buff *skb)
 
                        if (!netif_xmit_stopped(txq)) {
                                __this_cpu_inc(xmit_recursion);
-                               rc = dev_hard_start_xmit(skb, dev, txq, NULL);
+                               rc = dev_hard_start_xmit(skb, dev, txq);
                                __this_cpu_dec(xmit_recursion);
                                if (dev_xmit_complete(rc)) {
                                        HARD_TX_UNLOCK(dev, txq);
@@ -2883,8 +2883,19 @@ out:
        rcu_read_unlock_bh();
        return rc;
 }
+
+int dev_queue_xmit(struct sk_buff *skb)
+{
+       return __dev_queue_xmit(skb, NULL);
+}
 EXPORT_SYMBOL(dev_queue_xmit);
 
+int dev_queue_xmit_accel(struct sk_buff *skb, void *accel_priv)
+{
+       return __dev_queue_xmit(skb, accel_priv);
+}
+EXPORT_SYMBOL(dev_queue_xmit_accel);
+
 
 /*=======================================================================
                        Receiver routines
@@ -3213,22 +3224,7 @@ enqueue:
        return NET_RX_DROP;
 }
 
-/**
- *     netif_rx        -       post buffer to the network code
- *     @skb: buffer to post
- *
- *     This function receives a packet from a device driver and queues it for
- *     the upper (protocol) levels to process.  It always succeeds. The buffer
- *     may be dropped during processing for congestion control or by the
- *     protocol layers.
- *
- *     return values:
- *     NET_RX_SUCCESS  (no congestion)
- *     NET_RX_DROP     (packet was dropped)
- *
- */
-
-int netif_rx(struct sk_buff *skb)
+static int netif_rx_internal(struct sk_buff *skb)
 {
        int ret;
 
@@ -3264,14 +3260,38 @@ int netif_rx(struct sk_buff *skb)
        }
        return ret;
 }
+
+/**
+ *     netif_rx        -       post buffer to the network code
+ *     @skb: buffer to post
+ *
+ *     This function receives a packet from a device driver and queues it for
+ *     the upper (protocol) levels to process.  It always succeeds. The buffer
+ *     may be dropped during processing for congestion control or by the
+ *     protocol layers.
+ *
+ *     return values:
+ *     NET_RX_SUCCESS  (no congestion)
+ *     NET_RX_DROP     (packet was dropped)
+ *
+ */
+
+int netif_rx(struct sk_buff *skb)
+{
+       trace_netif_rx_entry(skb);
+
+       return netif_rx_internal(skb);
+}
 EXPORT_SYMBOL(netif_rx);
 
 int netif_rx_ni(struct sk_buff *skb)
 {
        int err;
 
+       trace_netif_rx_ni_entry(skb);
+
        preempt_disable();
-       err = netif_rx(skb);
+       err = netif_rx_internal(skb);
        if (local_softirq_pending())
                do_softirq();
        preempt_enable();
@@ -3656,22 +3676,7 @@ static int __netif_receive_skb(struct sk_buff *skb)
        return ret;
 }
 
-/**
- *     netif_receive_skb - process receive buffer from network
- *     @skb: buffer to process
- *
- *     netif_receive_skb() is the main receive data processing function.
- *     It always succeeds. The buffer may be dropped during processing
- *     for congestion control or by the protocol layers.
- *
- *     This function may only be called from softirq context and interrupts
- *     should be enabled.
- *
- *     Return values (usually ignored):
- *     NET_RX_SUCCESS: no congestion
- *     NET_RX_DROP: packet was dropped
- */
-int netif_receive_skb(struct sk_buff *skb)
+static int netif_receive_skb_internal(struct sk_buff *skb)
 {
        net_timestamp_check(netdev_tstamp_prequeue, skb);
 
@@ -3697,6 +3702,28 @@ int netif_receive_skb(struct sk_buff *skb)
 #endif
        return __netif_receive_skb(skb);
 }
+
+/**
+ *     netif_receive_skb - process receive buffer from network
+ *     @skb: buffer to process
+ *
+ *     netif_receive_skb() is the main receive data processing function.
+ *     It always succeeds. The buffer may be dropped during processing
+ *     for congestion control or by the protocol layers.
+ *
+ *     This function may only be called from softirq context and interrupts
+ *     should be enabled.
+ *
+ *     Return values (usually ignored):
+ *     NET_RX_SUCCESS: no congestion
+ *     NET_RX_DROP: packet was dropped
+ */
+int netif_receive_skb(struct sk_buff *skb)
+{
+       trace_netif_receive_skb_entry(skb);
+
+       return netif_receive_skb_internal(skb);
+}
 EXPORT_SYMBOL(netif_receive_skb);
 
 /* Network device is going away, flush any packets still pending
@@ -3758,7 +3785,7 @@ static int napi_gro_complete(struct sk_buff *skb)
        }
 
 out:
-       return netif_receive_skb(skb);
+       return netif_receive_skb_internal(skb);
 }
 
 /* napi->gro_list contains packets ordered by age.
@@ -3882,10 +3909,23 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
        if (same_flow)
                goto ok;
 
-       if (NAPI_GRO_CB(skb)->flush || napi->gro_count >= MAX_GRO_SKBS)
+       if (NAPI_GRO_CB(skb)->flush)
                goto normal;
 
-       napi->gro_count++;
+       if (unlikely(napi->gro_count >= MAX_GRO_SKBS)) {
+               struct sk_buff *nskb = napi->gro_list;
+
+               /* locate the end of the list to select the 'oldest' flow */
+               while (nskb->next) {
+                       pp = &nskb->next;
+                       nskb = *pp;
+               }
+               *pp = NULL;
+               nskb->next = NULL;
+               napi_gro_complete(nskb);
+       } else {
+               napi->gro_count++;
+       }
        NAPI_GRO_CB(skb)->count = 1;
        NAPI_GRO_CB(skb)->age = jiffies;
        skb_shinfo(skb)->gso_size = skb_gro_len(skb);
@@ -3953,7 +3993,7 @@ static gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb)
 {
        switch (ret) {
        case GRO_NORMAL:
-               if (netif_receive_skb(skb))
+               if (netif_receive_skb_internal(skb))
                        ret = GRO_DROP;
                break;
 
@@ -3978,6 +4018,8 @@ static gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb)
 
 gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
 {
+       trace_napi_gro_receive_entry(skb);
+
        return napi_skb_finish(dev_gro_receive(napi, skb), skb);
 }
 EXPORT_SYMBOL(napi_gro_receive);
@@ -4011,7 +4053,7 @@ static gro_result_t napi_frags_finish(struct napi_struct *napi, struct sk_buff *
 {
        switch (ret) {
        case GRO_NORMAL:
-               if (netif_receive_skb(skb))
+               if (netif_receive_skb_internal(skb))
                        ret = GRO_DROP;
                break;
 
@@ -4050,6 +4092,8 @@ gro_result_t napi_gro_frags(struct napi_struct *napi)
        if (!skb)
                return GRO_DROP;
 
+       trace_napi_gro_frags_entry(skb);
+
        return napi_frags_finish(napi, skb, dev_gro_receive(napi, skb));
 }
 EXPORT_SYMBOL(napi_gro_frags);
@@ -4582,13 +4626,36 @@ struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev)
 }
 EXPORT_SYMBOL(netdev_master_upper_dev_get_rcu);
 
+int netdev_adjacent_sysfs_add(struct net_device *dev,
+                             struct net_device *adj_dev,
+                             struct list_head *dev_list)
+{
+       char linkname[IFNAMSIZ+7];
+       sprintf(linkname, dev_list == &dev->adj_list.upper ?
+               "upper_%s" : "lower_%s", adj_dev->name);
+       return sysfs_create_link(&(dev->dev.kobj), &(adj_dev->dev.kobj),
+                                linkname);
+}
+void netdev_adjacent_sysfs_del(struct net_device *dev,
+                              char *name,
+                              struct list_head *dev_list)
+{
+       char linkname[IFNAMSIZ+7];
+       sprintf(linkname, dev_list == &dev->adj_list.upper ?
+               "upper_%s" : "lower_%s", name);
+       sysfs_remove_link(&(dev->dev.kobj), linkname);
+}
+
+#define netdev_adjacent_is_neigh_list(dev, dev_list) \
+               (dev_list == &dev->adj_list.upper || \
+                dev_list == &dev->adj_list.lower)
+
 static int __netdev_adjacent_dev_insert(struct net_device *dev,
                                        struct net_device *adj_dev,
                                        struct list_head *dev_list,
                                        void *private, bool master)
 {
        struct netdev_adjacent *adj;
-       char linkname[IFNAMSIZ+7];
        int ret;
 
        adj = __netdev_find_adj(dev, adj_dev, dev_list);
@@ -4611,16 +4678,8 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
        pr_debug("dev_hold for %s, because of link added from %s to %s\n",
                 adj_dev->name, dev->name, adj_dev->name);
 
-       if (dev_list == &dev->adj_list.lower) {
-               sprintf(linkname, "lower_%s", adj_dev->name);
-               ret = sysfs_create_link(&(dev->dev.kobj),
-                                       &(adj_dev->dev.kobj), linkname);
-               if (ret)
-                       goto free_adj;
-       } else if (dev_list == &dev->adj_list.upper) {
-               sprintf(linkname, "upper_%s", adj_dev->name);
-               ret = sysfs_create_link(&(dev->dev.kobj),
-                                       &(adj_dev->dev.kobj), linkname);
+       if (netdev_adjacent_is_neigh_list(dev, dev_list)) {
+               ret = netdev_adjacent_sysfs_add(dev, adj_dev, dev_list);
                if (ret)
                        goto free_adj;
        }
@@ -4640,14 +4699,8 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev,
        return 0;
 
 remove_symlinks:
-       if (dev_list == &dev->adj_list.lower) {
-               sprintf(linkname, "lower_%s", adj_dev->name);
-               sysfs_remove_link(&(dev->dev.kobj), linkname);
-       } else if (dev_list == &dev->adj_list.upper) {
-               sprintf(linkname, "upper_%s", adj_dev->name);
-               sysfs_remove_link(&(dev->dev.kobj), linkname);
-       }
-
+       if (netdev_adjacent_is_neigh_list(dev, dev_list))
+               netdev_adjacent_sysfs_del(dev, adj_dev->name, dev_list);
 free_adj:
        kfree(adj);
        dev_put(adj_dev);
@@ -4660,7 +4713,6 @@ static void __netdev_adjacent_dev_remove(struct net_device *dev,
                                         struct list_head *dev_list)
 {
        struct netdev_adjacent *adj;
-       char linkname[IFNAMSIZ+7];
 
        adj = __netdev_find_adj(dev, adj_dev, dev_list);
 
@@ -4680,13 +4732,8 @@ static void __netdev_adjacent_dev_remove(struct net_device *dev,
        if (adj->master)
                sysfs_remove_link(&(dev->dev.kobj), "master");
 
-       if (dev_list == &dev->adj_list.lower) {
-               sprintf(linkname, "lower_%s", adj_dev->name);
-               sysfs_remove_link(&(dev->dev.kobj), linkname);
-       } else if (dev_list == &dev->adj_list.upper) {
-               sprintf(linkname, "upper_%s", adj_dev->name);
-               sysfs_remove_link(&(dev->dev.kobj), linkname);
-       }
+       if (netdev_adjacent_is_neigh_list(dev, dev_list))
+               netdev_adjacent_sysfs_del(dev, adj_dev->name, dev_list);
 
        list_del_rcu(&adj->list);
        pr_debug("dev_put for %s, because link removed from %s to %s\n",
@@ -4955,6 +5002,25 @@ void netdev_upper_dev_unlink(struct net_device *dev,
 }
 EXPORT_SYMBOL(netdev_upper_dev_unlink);
 
+void netdev_adjacent_rename_links(struct net_device *dev, char *oldname)
+{
+       struct netdev_adjacent *iter;
+
+       list_for_each_entry(iter, &dev->adj_list.upper, list) {
+               netdev_adjacent_sysfs_del(iter->dev, oldname,
+                                         &iter->dev->adj_list.lower);
+               netdev_adjacent_sysfs_add(iter->dev, dev,
+                                         &iter->dev->adj_list.lower);
+       }
+
+       list_for_each_entry(iter, &dev->adj_list.lower, list) {
+               netdev_adjacent_sysfs_del(iter->dev, oldname,
+                                         &iter->dev->adj_list.upper);
+               netdev_adjacent_sysfs_add(iter->dev, dev,
+                                         &iter->dev->adj_list.upper);
+       }
+}
+
 void *netdev_lower_dev_get_private(struct net_device *dev,
                                   struct net_device *lower_dev)
 {
@@ -5287,6 +5353,17 @@ int dev_change_flags(struct net_device *dev, unsigned int flags)
 }
 EXPORT_SYMBOL(dev_change_flags);
 
+static int __dev_set_mtu(struct net_device *dev, int new_mtu)
+{
+       const struct net_device_ops *ops = dev->netdev_ops;
+
+       if (ops->ndo_change_mtu)
+               return ops->ndo_change_mtu(dev, new_mtu);
+
+       dev->mtu = new_mtu;
+       return 0;
+}
+
 /**
  *     dev_set_mtu - Change maximum transfer unit
  *     @dev: device
@@ -5296,8 +5373,7 @@ EXPORT_SYMBOL(dev_change_flags);
  */
 int dev_set_mtu(struct net_device *dev, int new_mtu)
 {
-       const struct net_device_ops *ops = dev->netdev_ops;
-       int err;
+       int err, orig_mtu;
 
        if (new_mtu == dev->mtu)
                return 0;
@@ -5309,14 +5385,20 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
        if (!netif_device_present(dev))
                return -ENODEV;
 
-       err = 0;
-       if (ops->ndo_change_mtu)
-               err = ops->ndo_change_mtu(dev, new_mtu);
-       else
-               dev->mtu = new_mtu;
+       orig_mtu = dev->mtu;
+       err = __dev_set_mtu(dev, new_mtu);
 
-       if (!err)
-               call_netdevice_notifiers(NETDEV_CHANGEMTU, dev);
+       if (!err) {
+               err = call_netdevice_notifiers(NETDEV_CHANGEMTU, dev);
+               err = notifier_to_errno(err);
+               if (err) {
+                       /* setting mtu back and notifying everyone again,
+                        * so that they have a chance to revert changes.
+                        */
+                       __dev_set_mtu(dev, orig_mtu);
+                       call_netdevice_notifiers(NETDEV_CHANGEMTU, dev);
+               }
+       }
        return err;
 }
 EXPORT_SYMBOL(dev_set_mtu);
@@ -6586,11 +6668,11 @@ static int dev_cpu_callback(struct notifier_block *nfb,
 
        /* Process offline CPU's input_pkt_queue */
        while ((skb = __skb_dequeue(&oldsd->process_queue))) {
-               netif_rx(skb);
+               netif_rx_internal(skb);
                input_queue_head_incr(oldsd);
        }
        while ((skb = __skb_dequeue(&oldsd->input_pkt_queue))) {
-               netif_rx(skb);
+               netif_rx_internal(skb);
                input_queue_head_incr(oldsd);
        }