Patchwork [PATCHv2,net-next,01/15] net: add skb_dst_set_unref

login
register
mail settings
Submitter Julian Anastasov
Date March 9, 2013, 9:16 p.m.
Message ID <1362863815-5898-2-git-send-email-ja@ssi.bg>
Download mbox | patch
Permalink /patch/226388/
State Changes Requested
Delegated to: David Miller
Headers show

Comments

Julian Anastasov - March 9, 2013, 9:16 p.m.
skb_dst_set_unref will use noref version even for
DST_NOCACHE entries because DST_NOCACHE means dst is not
cached in routing structures, still dst could be cached
by routing users and used to produce noref instances.

Signed-off-by: Julian Anastasov <ja@ssi.bg>
---
 include/linux/skbuff.h |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)
David Miller - March 10, 2013, 9:17 a.m.
From: Julian Anastasov <ja@ssi.bg>
Date: Sat,  9 Mar 2013 23:16:41 +0200

> 	skb_dst_set_unref will use noref version even for
> DST_NOCACHE entries because DST_NOCACHE means dst is not
> cached in routing structures, still dst could be cached
> by routing users and used to produce noref instances.
> 
> Signed-off-by: Julian Anastasov <ja@ssi.bg>

I'm fine with this approach, but I think the name of this
interface could be better.

In fact you could do something like:

1) Rename skb_dst_set_noref() to __skb_dst_set_noref() and add
   a new "bool force" parameter.  DST_NOCACHE check is overriden
   when 'force' is true.

2) skb_dst_set_noref() is an inline that passes 'force' as false.

3) New interface skb_dst_set_noref_force() passes 'force' as true
   and will be used by your IPVS changes.

Then all of the RCU checks etc. happen in one shared function.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 821c7f4..4d422af 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -573,6 +573,20 @@  static inline void skb_dst_set(struct sk_buff *skb, struct dst_entry *dst)
 extern void skb_dst_set_noref(struct sk_buff *skb, struct dst_entry *dst);
 
 /**
+ * skb_dst_set_unref - sets skb dst, without a reference
+ * @skb: buffer
+ * @dst: dst entry
+ *
+ * Sets skb dst, assuming a reference was not taken on dst
+ * skb_dst_drop() should not dst_release() this dst
+ */
+static inline void skb_dst_set_unref(struct sk_buff *skb, struct dst_entry *dst)
+{
+	WARN_ON(!rcu_read_lock_held() && !rcu_read_lock_bh_held());
+	skb->_skb_refdst = (unsigned long)dst | SKB_DST_NOREF;
+}
+
+/**
  * skb_dst_is_noref - Test if skb dst isn't refcounted
  * @skb: buffer
  */