Skip to contentSkip to conversation

bonding: bond_alb: Replace rcu_dereference() with rcu_access_pointer()

PATCH In review Andreea-Cristina Bernat 2 participants 2 messages Aug 27, 2014

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 bonding: bond_alb: Replace rcu_dereference() with rcu_access_pointer()

The "curr_active_slave" local variable obtained through the rcu_dereference() call it is not dereferenced in the rest of the function. Therefore, it is recommended to use rcu_access_pointer() instead of rcu_dereference().
This patch makes the replacement.

The first step to detect this was made with the following Coccinelle semantic patch:
@@
identifier p;
@@

* p = rcu_dereference(...)
... when any

    when != p

(
* if( (<+...p...+>) ) { ... }
|
* while( (<+...p...+>) ) { ... }
)
... when != p

After the analysis of the output, the change was made manually.

---
 drivers/net/bonding/bond_alb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/bonding/bond_alb.c +1 -1
index 1319c5b..6621ac2 100644
@@ -659,7 +659,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
 
 	_lock_rx_hashtbl(bond);
 
-	curr_active_slave = rcu_dereference(bond->curr_active_slave);
+	curr_active_slave = rcu_access_pointer(bond->curr_active_slave);
 
 	hash_index = _simple_hash((u8 *)&arp->ip_dst, sizeof(arp->ip_dst));
 	client_info = &(bond_info->rx_hashtbl[hash_index]);
Signature · 1 line
1.9.1
#1 lore raw
Quoted 34 lines · Andreea-Cristina Bernat

The "curr_active_slave" local variable obtained through the rcu_dereference() call it is not dereferenced in the rest of the function. Therefore, it is recommended to use rcu_access_pointer() instead of rcu_dereference().
This patch makes the replacement.

The first step to detect this was made with the following Coccinelle semantic patch:
@@
identifier p;
@@

* p = rcu_dereference(...)
... when any

    when != p

(
* if( (<+...p...+>) ) { ... }
|
* while( (<+...p...+>) ) { ... }
)
... when != p

After the analysis of the output, the change was made manually.

---
 drivers/net/bonding/bond_alb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/bonding/bond_alb.c +0 -0
index 1319c5b..6621ac2 100644

drivers/net/bonding/bond_alb.c static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon · line 665

Quoted 8 lines
drivers/net/bonding/bond_alb.c +1 -1
@@ -659,7 +659,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
 
 	_lock_rx_hashtbl(bond);
 
-	curr_active_slave = rcu_dereference(bond->curr_active_slave);
+	curr_active_slave = rcu_access_pointer(bond->curr_active_slave);
 
 	hash_index = _simple_hash((u8 *)&arp->ip_dst, sizeof(arp->ip_dst));
 	client_info = &(bond_info->rx_hashtbl[hash_index]);

This is very error prone, for little immediate gain.

What prevents future changes to deref the pointer without sparse or lockdep support, other than careful code review ?

I would use the __rcu attribute and eventually add _noderef suffix to the variable name.

drivers/net/bonding/bond_alb.c +3 -2
index 73c21e233131..4ddccc72db62 100644
@@ -657,13 +657,14 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
 	struct arp_pkt *arp = arp_pkt(skb);
-	struct slave *assigned_slave, *curr_active_slave;
+	struct slave *assigned_slave;
+	struct slave __rcu *curr_active_slave;
 	struct rlb_client_info *client_info;
 	u32 hash_index = 0;
 
 	_lock_rx_hashtbl(bond);
 
-	curr_active_slave = rcu_dereference(bond->curr_active_slave);
+	curr_active_slave = bond->curr_active_slave;
 
 	hash_index = _simple_hash((u8 *)&arp->ip_dst, sizeof(arp->ip_dst));
 	client_info = &(bond_info->rx_hashtbl[hash_index]);