@@ -203,6 +203,11 @@ void ipv6_sock_ac_close(struct sock *sk)
203203 rtnl_unlock ();
204204}
205205
206+ static void aca_get (struct ifacaddr6 * aca )
207+ {
208+ atomic_inc (& aca -> aca_refcnt );
209+ }
210+
206211static void aca_put (struct ifacaddr6 * ac )
207212{
208213 if (atomic_dec_and_test (& ac -> aca_refcnt )) {
@@ -212,6 +217,29 @@ static void aca_put(struct ifacaddr6 *ac)
212217 }
213218}
214219
220+ static struct ifacaddr6 * aca_alloc (struct rt6_info * rt ,
221+ const struct in6_addr * addr )
222+ {
223+ struct inet6_dev * idev = rt -> rt6i_idev ;
224+ struct ifacaddr6 * aca ;
225+
226+ aca = kzalloc (sizeof (* aca ), GFP_ATOMIC );
227+ if (aca == NULL )
228+ return NULL ;
229+
230+ aca -> aca_addr = * addr ;
231+ in6_dev_hold (idev );
232+ aca -> aca_idev = idev ;
233+ aca -> aca_rt = rt ;
234+ aca -> aca_users = 1 ;
235+ /* aca_tstamp should be updated upon changes */
236+ aca -> aca_cstamp = aca -> aca_tstamp = jiffies ;
237+ atomic_set (& aca -> aca_refcnt , 1 );
238+ spin_lock_init (& aca -> aca_lock );
239+
240+ return aca ;
241+ }
242+
215243/*
216244 * device anycast group inc (add if not found)
217245 */
@@ -223,7 +251,6 @@ int __ipv6_dev_ac_inc(struct inet6_dev *idev, const struct in6_addr *addr)
223251
224252 ASSERT_RTNL ();
225253
226- in6_dev_hold (idev );
227254 write_lock_bh (& idev -> lock );
228255 if (idev -> dead ) {
229256 err = - ENODEV ;
@@ -238,35 +265,25 @@ int __ipv6_dev_ac_inc(struct inet6_dev *idev, const struct in6_addr *addr)
238265 }
239266 }
240267
241- /*
242- * not found: create a new one.
243- */
244-
245- aca = kzalloc (sizeof (struct ifacaddr6 ), GFP_ATOMIC );
246-
247- if (aca == NULL ) {
248- err = - ENOMEM ;
249- goto out ;
250- }
251-
252268 rt = addrconf_dst_alloc (idev , addr , true);
253269 if (IS_ERR (rt )) {
254- kfree (aca );
255270 err = PTR_ERR (rt );
256271 goto out ;
257272 }
258-
259- aca -> aca_addr = * addr ;
260- aca -> aca_idev = idev ;
261- aca -> aca_rt = rt ;
262- aca -> aca_users = 1 ;
263- /* aca_tstamp should be updated upon changes */
264- aca -> aca_cstamp = aca -> aca_tstamp = jiffies ;
265- atomic_set (& aca -> aca_refcnt , 2 );
266- spin_lock_init (& aca -> aca_lock );
273+ aca = aca_alloc (rt , addr );
274+ if (aca == NULL ) {
275+ ip6_rt_put (rt );
276+ err = - ENOMEM ;
277+ goto out ;
278+ }
267279
268280 aca -> aca_next = idev -> ac_list ;
269281 idev -> ac_list = aca ;
282+
283+ /* Hold this for addrconf_join_solict() below before we unlock,
284+ * it is already exposed via idev->ac_list.
285+ */
286+ aca_get (aca );
270287 write_unlock_bh (& idev -> lock );
271288
272289 ip6_ins_rt (rt );
@@ -277,7 +294,6 @@ int __ipv6_dev_ac_inc(struct inet6_dev *idev, const struct in6_addr *addr)
277294 return 0 ;
278295out :
279296 write_unlock_bh (& idev -> lock );
280- in6_dev_put (idev );
281297 return err ;
282298}
283299
0 commit comments