diff options
-rw-r--r-- | include/linux/mroute6.h | 15 | ||||
-rw-r--r-- | net/ipv6/ip6mr.c | 26 |
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 | |||
188 | struct mfc6_cache | 188 | struct 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 | ||
216 | static inline | ||
217 | struct net *mfc6_net(const struct mfc6_cache *mfc) | ||
218 | { | ||
219 | return read_pnet(&mfc->mfc6_net); | ||
220 | } | ||
221 | |||
222 | static inline | ||
223 | void 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 | ||
509 | static 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 | */ |
688 | static struct mfc6_cache *ip6mr_cache_alloc(void) | 694 | static 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 | ||
697 | static struct mfc6_cache *ip6mr_cache_alloc_unres(void) | 704 | static 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 | ||