aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/mroute6.h15
-rw-r--r--net/ipv6/ip6mr.c26
2 files changed, 32 insertions, 9 deletions
diff --git a/include/linux/mroute6.h b/include/linux/mroute6.h
index 2cd9901ee5c7..15d85fe12bbd 100644
--- a/include/linux/mroute6.h
+++ b/include/linux/mroute6.h
@@ -188,6 +188,9 @@ struct mif_device
188struct mfc6_cache 188struct mfc6_cache
189{ 189{
190 struct mfc6_cache *next; /* Next entry on cache line */ 190 struct mfc6_cache *next; /* Next entry on cache line */
191#ifdef CONFIG_NET_NS
192 struct net *mfc6_net;
193#endif
191 struct in6_addr mf6c_mcastgrp; /* Group the entry belongs to */ 194 struct in6_addr mf6c_mcastgrp; /* Group the entry belongs to */
192 struct in6_addr mf6c_origin; /* Source of packet */ 195 struct in6_addr mf6c_origin; /* Source of packet */
193 mifi_t mf6c_parent; /* Source interface */ 196 mifi_t mf6c_parent; /* Source interface */
@@ -210,6 +213,18 @@ struct mfc6_cache
210 } mfc_un; 213 } mfc_un;
211}; 214};
212 215
216static inline
217struct net *mfc6_net(const struct mfc6_cache *mfc)
218{
219 return read_pnet(&mfc->mfc6_net);
220}
221
222static inline
223void mfc6_net_set(struct mfc6_cache *mfc, struct net *net)
224{
225 write_pnet(&mfc->mfc6_net, hold_net(net));
226}
227
213#define MFC_STATIC 1 228#define MFC_STATIC 1
214#define MFC_NOTIFY 2 229#define MFC_NOTIFY 2
215 230
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index bae3ef649664..fab5aba28a20 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -506,6 +506,12 @@ static int mif6_delete(int vifi)
506 return 0; 506 return 0;
507} 507}
508 508
509static inline void ip6mr_cache_free(struct mfc6_cache *c)
510{
511 release_net(mfc6_net(c));
512 kmem_cache_free(mrt_cachep, c);
513}
514
509/* Destroy an unresolved cache entry, killing queued skbs 515/* Destroy an unresolved cache entry, killing queued skbs
510 and reporting error to netlink readers. 516 and reporting error to netlink readers.
511 */ 517 */
@@ -528,7 +534,7 @@ static void ip6mr_destroy_unres(struct mfc6_cache *c)
528 kfree_skb(skb); 534 kfree_skb(skb);
529 } 535 }
530 536
531 kmem_cache_free(mrt_cachep, c); 537 ip6mr_cache_free(c);
532} 538}
533 539
534 540
@@ -685,22 +691,24 @@ static struct mfc6_cache *ip6mr_cache_find(struct in6_addr *origin, struct in6_a
685/* 691/*
686 * Allocate a multicast cache entry 692 * Allocate a multicast cache entry
687 */ 693 */
688static struct mfc6_cache *ip6mr_cache_alloc(void) 694static struct mfc6_cache *ip6mr_cache_alloc(struct net *net)
689{ 695{
690 struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL); 696 struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
691 if (c == NULL) 697 if (c == NULL)
692 return NULL; 698 return NULL;
693 c->mfc_un.res.minvif = MAXMIFS; 699 c->mfc_un.res.minvif = MAXMIFS;
700 mfc6_net_set(c, net);
694 return c; 701 return c;
695} 702}
696 703
697static struct mfc6_cache *ip6mr_cache_alloc_unres(void) 704static struct mfc6_cache *ip6mr_cache_alloc_unres(struct net *net)
698{ 705{
699 struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC); 706 struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC);
700 if (c == NULL) 707 if (c == NULL)
701 return NULL; 708 return NULL;
702 skb_queue_head_init(&c->mfc_un.unres.unresolved); 709 skb_queue_head_init(&c->mfc_un.unres.unresolved);
703 c->mfc_un.unres.expires = jiffies + 10 * HZ; 710 c->mfc_un.unres.expires = jiffies + 10 * HZ;
711 mfc6_net_set(c, net);
704 return c; 712 return c;
705} 713}
706 714
@@ -856,7 +864,7 @@ ip6mr_cache_unresolved(mifi_t mifi, struct sk_buff *skb)
856 */ 864 */
857 865
858 if (atomic_read(&cache_resolve_queue_len) >= 10 || 866 if (atomic_read(&cache_resolve_queue_len) >= 10 ||
859 (c = ip6mr_cache_alloc_unres()) == NULL) { 867 (c = ip6mr_cache_alloc_unres(&init_net)) == NULL) {
860 spin_unlock_bh(&mfc_unres_lock); 868 spin_unlock_bh(&mfc_unres_lock);
861 869
862 kfree_skb(skb); 870 kfree_skb(skb);
@@ -879,7 +887,7 @@ ip6mr_cache_unresolved(mifi_t mifi, struct sk_buff *skb)
879 */ 887 */
880 spin_unlock_bh(&mfc_unres_lock); 888 spin_unlock_bh(&mfc_unres_lock);
881 889
882 kmem_cache_free(mrt_cachep, c); 890 ip6mr_cache_free(c);
883 kfree_skb(skb); 891 kfree_skb(skb);
884 return err; 892 return err;
885 } 893 }
@@ -924,7 +932,7 @@ static int ip6mr_mfc_delete(struct mf6cctl *mfc)
924 *cp = c->next; 932 *cp = c->next;
925 write_unlock_bh(&mrt_lock); 933 write_unlock_bh(&mrt_lock);
926 934
927 kmem_cache_free(mrt_cachep, c); 935 ip6mr_cache_free(c);
928 return 0; 936 return 0;
929 } 937 }
930 } 938 }
@@ -1073,7 +1081,7 @@ static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock)
1073 if (!ipv6_addr_is_multicast(&mfc->mf6cc_mcastgrp.sin6_addr)) 1081 if (!ipv6_addr_is_multicast(&mfc->mf6cc_mcastgrp.sin6_addr))
1074 return -EINVAL; 1082 return -EINVAL;
1075 1083
1076 c = ip6mr_cache_alloc(); 1084 c = ip6mr_cache_alloc(&init_net);
1077 if (c == NULL) 1085 if (c == NULL)
1078 return -ENOMEM; 1086 return -ENOMEM;
1079 1087
@@ -1108,7 +1116,7 @@ static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock)
1108 1116
1109 if (uc) { 1117 if (uc) {
1110 ip6mr_cache_resolve(uc, c); 1118 ip6mr_cache_resolve(uc, c);
1111 kmem_cache_free(mrt_cachep, uc); 1119 ip6mr_cache_free(uc);
1112 } 1120 }
1113 return 0; 1121 return 0;
1114} 1122}
@@ -1145,7 +1153,7 @@ static void mroute_clean_tables(struct sock *sk)
1145 *cp = c->next; 1153 *cp = c->next;
1146 write_unlock_bh(&mrt_lock); 1154 write_unlock_bh(&mrt_lock);
1147 1155
1148 kmem_cache_free(mrt_cachep, c); 1156 ip6mr_cache_free(c);
1149 } 1157 }
1150 } 1158 }
1151 1159