Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[firefly-linux-kernel-4.4.55.git] / net / core / dst.c
index 35fd12f1a69c38ad899a12392fcdfc768081bdb9..df9cc810ec8e3a78bbdb3b4480deeb8fd35df721 100644 (file)
@@ -320,27 +320,28 @@ void __dst_destroy_metrics_generic(struct dst_entry *dst, unsigned long old)
 EXPORT_SYMBOL(__dst_destroy_metrics_generic);
 
 /**
- * skb_dst_set_noref - sets skb dst, without a reference
+ * __skb_dst_set_noref - sets skb dst, without a reference
  * @skb: buffer
  * @dst: dst entry
+ * @force: if force is set, use noref version even for DST_NOCACHE entries
  *
  * Sets skb dst, assuming a reference was not taken on dst
  * skb_dst_drop() should not dst_release() this dst
  */
-void skb_dst_set_noref(struct sk_buff *skb, struct dst_entry *dst)
+void __skb_dst_set_noref(struct sk_buff *skb, struct dst_entry *dst, bool force)
 {
        WARN_ON(!rcu_read_lock_held() && !rcu_read_lock_bh_held());
        /* If dst not in cache, we must take a reference, because
         * dst_release() will destroy dst as soon as its refcount becomes zero
         */
-       if (unlikely(dst->flags & DST_NOCACHE)) {
+       if (unlikely((dst->flags & DST_NOCACHE) && !force)) {
                dst_hold(dst);
                skb_dst_set(skb, dst);
        } else {
                skb->_skb_refdst = (unsigned long)dst | SKB_DST_NOREF;
        }
 }
-EXPORT_SYMBOL(skb_dst_set_noref);
+EXPORT_SYMBOL(__skb_dst_set_noref);
 
 /* Dirty hack. We did it in 2.2 (in __dst_free),
  * we have _very_ good reasons not to repeat