@@ -3526,18 +3526,65 @@ static void bond_fold_stats(struct rtnl_link_stats64 *_res,
35263526 }
35273527}
35283528
3529+ #ifdef CONFIG_LOCKDEP
3530+ static int bond_get_lowest_level_rcu (struct net_device * dev )
3531+ {
3532+ struct net_device * ldev , * next , * now , * dev_stack [MAX_NEST_DEV + 1 ];
3533+ struct list_head * niter , * iter , * iter_stack [MAX_NEST_DEV + 1 ];
3534+ int cur = 0 , max = 0 ;
3535+
3536+ now = dev ;
3537+ iter = & dev -> adj_list .lower ;
3538+
3539+ while (1 ) {
3540+ next = NULL ;
3541+ while (1 ) {
3542+ ldev = netdev_next_lower_dev_rcu (now , & iter );
3543+ if (!ldev )
3544+ break ;
3545+
3546+ next = ldev ;
3547+ niter = & ldev -> adj_list .lower ;
3548+ dev_stack [cur ] = now ;
3549+ iter_stack [cur ++ ] = iter ;
3550+ if (max <= cur )
3551+ max = cur ;
3552+ break ;
3553+ }
3554+
3555+ if (!next ) {
3556+ if (!cur )
3557+ return max ;
3558+ next = dev_stack [-- cur ];
3559+ niter = iter_stack [cur ];
3560+ }
3561+
3562+ now = next ;
3563+ iter = niter ;
3564+ }
3565+
3566+ return max ;
3567+ }
3568+ #endif
3569+
35293570static void bond_get_stats (struct net_device * bond_dev ,
35303571 struct rtnl_link_stats64 * stats )
35313572{
35323573 struct bonding * bond = netdev_priv (bond_dev );
35333574 struct rtnl_link_stats64 temp ;
35343575 struct list_head * iter ;
35353576 struct slave * slave ;
3577+ int nest_level = 0 ;
35363578
3537- spin_lock (& bond -> stats_lock );
3538- memcpy (stats , & bond -> bond_stats , sizeof (* stats ));
35393579
35403580 rcu_read_lock ();
3581+ #ifdef CONFIG_LOCKDEP
3582+ nest_level = bond_get_lowest_level_rcu (bond_dev );
3583+ #endif
3584+
3585+ spin_lock_nested (& bond -> stats_lock , nest_level );
3586+ memcpy (stats , & bond -> bond_stats , sizeof (* stats ));
3587+
35413588 bond_for_each_slave_rcu (bond , slave , iter ) {
35423589 const struct rtnl_link_stats64 * new =
35433590 dev_get_stats (slave -> dev , & temp );
@@ -3547,10 +3594,10 @@ static void bond_get_stats(struct net_device *bond_dev,
35473594 /* save off the slave stats for the next run */
35483595 memcpy (& slave -> slave_stats , new , sizeof (* new ));
35493596 }
3550- rcu_read_unlock ();
35513597
35523598 memcpy (& bond -> bond_stats , stats , sizeof (* stats ));
35533599 spin_unlock (& bond -> stats_lock );
3600+ rcu_read_unlock ();
35543601}
35553602
35563603static int bond_do_ioctl (struct net_device * bond_dev , struct ifreq * ifr , int cmd )
0 commit comments