aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv6/addrconf_core.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c
index d873ceea86e6..ca09bf49ac68 100644
--- a/net/ipv6/addrconf_core.c
+++ b/net/ipv6/addrconf_core.c
@@ -133,6 +133,14 @@ static void snmp6_free_dev(struct inet6_dev *idev)
133 free_percpu(idev->stats.ipv6); 133 free_percpu(idev->stats.ipv6);
134} 134}
135 135
136static void in6_dev_finish_destroy_rcu(struct rcu_head *head)
137{
138 struct inet6_dev *idev = container_of(head, struct inet6_dev, rcu);
139
140 snmp6_free_dev(idev);
141 kfree(idev);
142}
143
136/* Nobody refers to this device, we may destroy it. */ 144/* Nobody refers to this device, we may destroy it. */
137 145
138void in6_dev_finish_destroy(struct inet6_dev *idev) 146void in6_dev_finish_destroy(struct inet6_dev *idev)
@@ -151,7 +159,6 @@ void in6_dev_finish_destroy(struct inet6_dev *idev)
151 pr_warn("Freeing alive inet6 device %p\n", idev); 159 pr_warn("Freeing alive inet6 device %p\n", idev);
152 return; 160 return;
153 } 161 }
154 snmp6_free_dev(idev); 162 call_rcu(&idev->rcu, in6_dev_finish_destroy_rcu);
155 kfree_rcu(idev, rcu);
156} 163}
157EXPORT_SYMBOL(in6_dev_finish_destroy); 164EXPORT_SYMBOL(in6_dev_finish_destroy);