]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - include/net/dst.h
net: dst: Force 4-byte alignment of dst_metrics
[mirror_ubuntu-bionic-kernel.git] / include / net / dst.h
index 694c2e6ae618df5347e8e54d8741e9985925236d..f95335e3790ffa8706e114d0b7475f6a84b5c550 100644 (file)
@@ -102,7 +102,7 @@ struct dst_entry {
        union {
                struct dst_entry        *next;
                struct rtable __rcu     *rt_next;
-               struct rt6_info         *rt6_next;
+               struct rt6_info __rcu   *rt6_next;
                struct dn_route __rcu   *dn_next;
        };
 };
@@ -110,7 +110,7 @@ struct dst_entry {
 struct dst_metrics {
        u32             metrics[RTAX_MAX];
        refcount_t      refcnt;
-};
+} __aligned(4);                /* Low pointer bits contain DST_METRICS_FLAGS */
 extern const struct dst_metrics dst_default_metrics;
 
 u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old);
@@ -256,17 +256,18 @@ static inline void dst_hold(struct dst_entry *dst)
        WARN_ON(atomic_inc_not_zero(&dst->__refcnt) == 0);
 }
 
-static inline void dst_use(struct dst_entry *dst, unsigned long time)
+static inline void dst_use_noref(struct dst_entry *dst, unsigned long time)
 {
-       dst_hold(dst);
-       dst->__use++;
-       dst->lastuse = time;
+       if (unlikely(time != dst->lastuse)) {
+               dst->__use++;
+               dst->lastuse = time;
+       }
 }
 
-static inline void dst_use_noref(struct dst_entry *dst, unsigned long time)
+static inline void dst_hold_and_use(struct dst_entry *dst, unsigned long time)
 {
-       dst->__use++;
-       dst->lastuse = time;
+       dst_hold(dst);
+       dst_use_noref(dst, time);
 }
 
 static inline struct dst_entry *dst_clone(struct dst_entry *dst)
@@ -329,8 +330,9 @@ static inline bool dst_hold_safe(struct dst_entry *dst)
  * @skb: buffer
  *
  * If dst is not yet refcounted and not destroyed, grab a ref on it.
+ * Returns true if dst is refcounted.
  */
-static inline void skb_dst_force(struct sk_buff *skb)
+static inline bool skb_dst_force(struct sk_buff *skb)
 {
        if (skb_dst_is_noref(skb)) {
                struct dst_entry *dst = skb_dst(skb);
@@ -341,6 +343,8 @@ static inline void skb_dst_force(struct sk_buff *skb)
 
                skb->_skb_refdst = (unsigned long)dst;
        }
+
+       return skb->_skb_refdst != 0UL;
 }
 
 
@@ -520,4 +524,12 @@ static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst)
 }
 #endif
 
+static inline void skb_dst_update_pmtu(struct sk_buff *skb, u32 mtu)
+{
+       struct dst_entry *dst = skb_dst(skb);
+
+       if (dst && dst->ops->update_pmtu)
+               dst->ops->update_pmtu(dst, NULL, skb, mtu);
+}
+
 #endif /* _NET_DST_H */