diff options
| -rw-r--r-- | net/ipv6/addrlabel.c | 14 |
1 files changed, 6 insertions, 8 deletions
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c index 38674121ae5f..a3c5a72218fd 100644 --- a/net/ipv6/addrlabel.c +++ b/net/ipv6/addrlabel.c | |||
| @@ -106,6 +106,11 @@ static inline void ip6addrlbl_free(struct ip6addrlbl_entry *p) | |||
| 106 | kfree(p); | 106 | kfree(p); |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | static void ip6addrlbl_free_rcu(struct rcu_head *h) | ||
| 110 | { | ||
| 111 | ip6addrlbl_free(container_of(h, struct ip6addrlbl_entry, rcu)); | ||
| 112 | } | ||
| 113 | |||
| 109 | static inline int ip6addrlbl_hold(struct ip6addrlbl_entry *p) | 114 | static inline int ip6addrlbl_hold(struct ip6addrlbl_entry *p) |
| 110 | { | 115 | { |
| 111 | return atomic_inc_not_zero(&p->refcnt); | 116 | return atomic_inc_not_zero(&p->refcnt); |
| @@ -114,12 +119,7 @@ static inline int ip6addrlbl_hold(struct ip6addrlbl_entry *p) | |||
| 114 | static inline void ip6addrlbl_put(struct ip6addrlbl_entry *p) | 119 | static inline void ip6addrlbl_put(struct ip6addrlbl_entry *p) |
| 115 | { | 120 | { |
| 116 | if (atomic_dec_and_test(&p->refcnt)) | 121 | if (atomic_dec_and_test(&p->refcnt)) |
| 117 | ip6addrlbl_free(p); | 122 | call_rcu(&p->rcu, ip6addrlbl_free_rcu); |
| 118 | } | ||
| 119 | |||
| 120 | static void ip6addrlbl_free_rcu(struct rcu_head *h) | ||
| 121 | { | ||
| 122 | ip6addrlbl_free(container_of(h, struct ip6addrlbl_entry, rcu)); | ||
| 123 | } | 123 | } |
| 124 | 124 | ||
| 125 | /* Find label */ | 125 | /* Find label */ |
| @@ -240,7 +240,6 @@ static int __ip6addrlbl_add(struct ip6addrlbl_entry *newp, int replace) | |||
| 240 | } | 240 | } |
| 241 | hlist_replace_rcu(&p->list, &newp->list); | 241 | hlist_replace_rcu(&p->list, &newp->list); |
| 242 | ip6addrlbl_put(p); | 242 | ip6addrlbl_put(p); |
| 243 | call_rcu(&p->rcu, ip6addrlbl_free_rcu); | ||
| 244 | goto out; | 243 | goto out; |
| 245 | } else if ((p->prefixlen == newp->prefixlen && !p->ifindex) || | 244 | } else if ((p->prefixlen == newp->prefixlen && !p->ifindex) || |
| 246 | (p->prefixlen < newp->prefixlen)) { | 245 | (p->prefixlen < newp->prefixlen)) { |
| @@ -300,7 +299,6 @@ static int __ip6addrlbl_del(const struct in6_addr *prefix, int prefixlen, | |||
| 300 | ipv6_addr_equal(&p->prefix, prefix)) { | 299 | ipv6_addr_equal(&p->prefix, prefix)) { |
| 301 | hlist_del_rcu(&p->list); | 300 | hlist_del_rcu(&p->list); |
| 302 | ip6addrlbl_put(p); | 301 | ip6addrlbl_put(p); |
| 303 | call_rcu(&p->rcu, ip6addrlbl_free_rcu); | ||
| 304 | ret = 0; | 302 | ret = 0; |
| 305 | break; | 303 | break; |
| 306 | } | 304 | } |
