@@ -3448,18 +3448,65 @@ static int bond_get_nest_level(struct net_device *bond_dev)
34483448 return bond -> nest_level ;
34493449}
34503450
3451+ #ifdef CONFIG_LOCKDEP
3452+ static int bond_get_lowest_level_rcu (struct net_device * dev )
3453+ {
3454+ struct net_device * ldev , * next , * now , * dev_stack [MAX_NEST_DEV + 1 ];
3455+ struct list_head * niter , * iter , * iter_stack [MAX_NEST_DEV + 1 ];
3456+ int cur = 0 , max = 0 ;
3457+
3458+ now = dev ;
3459+ iter = & dev -> adj_list .lower ;
3460+
3461+ while (1 ) {
3462+ next = NULL ;
3463+ while (1 ) {
3464+ ldev = netdev_next_lower_dev_rcu (now , & iter );
3465+ if (!ldev )
3466+ break ;
3467+
3468+ next = ldev ;
3469+ niter = & ldev -> adj_list .lower ;
3470+ dev_stack [cur ] = now ;
3471+ iter_stack [cur ++ ] = iter ;
3472+ if (max <= cur )
3473+ max = cur ;
3474+ break ;
3475+ }
3476+
3477+ if (!next ) {
3478+ if (!cur )
3479+ return max ;
3480+ next = dev_stack [-- cur ];
3481+ niter = iter_stack [cur ];
3482+ }
3483+
3484+ now = next ;
3485+ iter = niter ;
3486+ }
3487+
3488+ return max ;
3489+ }
3490+ #endif
3491+
34513492static void bond_get_stats (struct net_device * bond_dev ,
34523493 struct rtnl_link_stats64 * stats )
34533494{
34543495 struct bonding * bond = netdev_priv (bond_dev );
34553496 struct rtnl_link_stats64 temp ;
34563497 struct list_head * iter ;
34573498 struct slave * slave ;
3499+ int nest_level = 0 ;
34583500
3459- spin_lock (& bond -> stats_lock );
3460- memcpy (stats , & bond -> bond_stats , sizeof (* stats ));
34613501
34623502 rcu_read_lock ();
3503+ #ifdef CONFIG_LOCKDEP
3504+ nest_level = bond_get_lowest_level_rcu (bond_dev );
3505+ #endif
3506+
3507+ spin_lock_nested (& bond -> stats_lock , nest_level );
3508+ memcpy (stats , & bond -> bond_stats , sizeof (* stats ));
3509+
34633510 bond_for_each_slave_rcu (bond , slave , iter ) {
34643511 const struct rtnl_link_stats64 * new =
34653512 dev_get_stats (slave -> dev , & temp );
@@ -3469,10 +3516,10 @@ static void bond_get_stats(struct net_device *bond_dev,
34693516 /* save off the slave stats for the next run */
34703517 memcpy (& slave -> slave_stats , new , sizeof (* new ));
34713518 }
3472- rcu_read_unlock ();
34733519
34743520 memcpy (& bond -> bond_stats , stats , sizeof (* stats ));
34753521 spin_unlock (& bond -> stats_lock );
3522+ rcu_read_unlock ();
34763523}
34773524
34783525static int bond_do_ioctl (struct net_device * bond_dev , struct ifreq * ifr , int cmd )
0 commit comments