@@ -3436,18 +3436,65 @@ static void bond_fold_stats(struct rtnl_link_stats64 *_res,
3436
3436
}
3437
3437
}
3438
3438
3439
+ #ifdef CONFIG_LOCKDEP
3440
+ static int bond_get_lowest_level_rcu (struct net_device * dev )
3441
+ {
3442
+ struct net_device * ldev , * next , * now , * dev_stack [MAX_NEST_DEV + 1 ];
3443
+ struct list_head * niter , * iter , * iter_stack [MAX_NEST_DEV + 1 ];
3444
+ int cur = 0 , max = 0 ;
3445
+
3446
+ now = dev ;
3447
+ iter = & dev -> adj_list .lower ;
3448
+
3449
+ while (1 ) {
3450
+ next = NULL ;
3451
+ while (1 ) {
3452
+ ldev = netdev_next_lower_dev_rcu (now , & iter );
3453
+ if (!ldev )
3454
+ break ;
3455
+
3456
+ next = ldev ;
3457
+ niter = & ldev -> adj_list .lower ;
3458
+ dev_stack [cur ] = now ;
3459
+ iter_stack [cur ++ ] = iter ;
3460
+ if (max <= cur )
3461
+ max = cur ;
3462
+ break ;
3463
+ }
3464
+
3465
+ if (!next ) {
3466
+ if (!cur )
3467
+ return max ;
3468
+ next = dev_stack [-- cur ];
3469
+ niter = iter_stack [cur ];
3470
+ }
3471
+
3472
+ now = next ;
3473
+ iter = niter ;
3474
+ }
3475
+
3476
+ return max ;
3477
+ }
3478
+ #endif
3479
+
3439
3480
static void bond_get_stats (struct net_device * bond_dev ,
3440
3481
struct rtnl_link_stats64 * stats )
3441
3482
{
3442
3483
struct bonding * bond = netdev_priv (bond_dev );
3443
3484
struct rtnl_link_stats64 temp ;
3444
3485
struct list_head * iter ;
3445
3486
struct slave * slave ;
3487
+ int nest_level = 0 ;
3446
3488
3447
- spin_lock (& bond -> stats_lock );
3448
- memcpy (stats , & bond -> bond_stats , sizeof (* stats ));
3449
3489
3450
3490
rcu_read_lock ();
3491
+ #ifdef CONFIG_LOCKDEP
3492
+ nest_level = bond_get_lowest_level_rcu (bond_dev );
3493
+ #endif
3494
+
3495
+ spin_lock_nested (& bond -> stats_lock , nest_level );
3496
+ memcpy (stats , & bond -> bond_stats , sizeof (* stats ));
3497
+
3451
3498
bond_for_each_slave_rcu (bond , slave , iter ) {
3452
3499
const struct rtnl_link_stats64 * new =
3453
3500
dev_get_stats (slave -> dev , & temp );
@@ -3457,10 +3504,10 @@ static void bond_get_stats(struct net_device *bond_dev,
3457
3504
/* save off the slave stats for the next run */
3458
3505
memcpy (& slave -> slave_stats , new , sizeof (* new ));
3459
3506
}
3460
- rcu_read_unlock ();
3461
3507
3462
3508
memcpy (& bond -> bond_stats , stats , sizeof (* stats ));
3463
3509
spin_unlock (& bond -> stats_lock );
3510
+ rcu_read_unlock ();
3464
3511
}
3465
3512
3466
3513
static int bond_do_ioctl (struct net_device * bond_dev , struct ifreq * ifr , int cmd )
0 commit comments