drivers: char: ipmi: ipmi_msghandler: Pass lockdep expression to RCU lists
PATCH v3 1/1 drivers: char: ipmi: ipmi_msghandler: Pass lockdep expression to RCU lists
intf->cmd_rcvrs is traversed with list_for_each_entry_rcu outside an RCU read-side critical section but under the protection of intf->cmd_rcvrs_mutex.
ipmi_interfaces is traversed using list_for_each_entry_rcu outside an RCU read-side critical section but under the protection of ipmi_interfaces_mutex.
Hence, add the corresponding lockdep expression to the list traversal primitive to silence false-positive lockdep warnings, and harden RCU lists.
Add macro for the corresponding lockdep expression to make the code clean and concise.
---
v3:
- Remove rcu_read_lock_held() from lockdep expression since it is implicitly checked.
- Remove unintended macro usage.
v2:
- Fix sparse error
CHECK: Alignment should match open parenthesis
drivers/char/ipmi/ipmi_msghandler.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
drivers/char/ipmi/ipmi_msghandler.c +10 -4
@@ -618,6 +618,8 @@ static DEFINE_MUTEX(ipmidriver_mutex);static LIST_HEAD (ipmi_interfaces);static DEFINE_MUTEX (ipmi_interfaces_mutex); +#define ipmi_interfaces_mutex_held () \ + lockdep_is_held(&ipmi_interfaces_mutex)static struct srcu_struct ipmi_interfaces_srcu;/*
@@ -1321,7 +1323,8 @@ static void _ipmi_destroy_user(struct ipmi_user *user)* synchronize_srcu()) then free everything in that list. */ mutex_lock (&intf->cmd_rcvrs_mutex); -list_for_each_entry_rcu (rcvr, &intf->cmd_rcvrs, link) { +list_for_each_entry_rcu (rcvr, &intf->cmd_rcvrs, link, +lockdep_is_held (&intf->cmd_rcvrs_mutex)) {if (rcvr->user == user) {list_del_rcu (&rcvr->link); rcvr->next = rcvrs;
@@ -1599,7 +1602,8 @@ static struct cmd_rcvr *find_cmd_rcvr(struct ipmi_smi *intf, {struct cmd_rcvr *rcvr; -list_for_each_entry_rcu (rcvr, &intf->cmd_rcvrs, link) { +list_for_each_entry_rcu (rcvr, &intf->cmd_rcvrs, link, +lockdep_is_held (&intf->cmd_rcvrs_mutex)) {if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd) && (rcvr->chans & (1 << chan)))return rcvr;
@@ -1614,7 +1618,8 @@ static int is_cmd_rcvr_exclusive(struct ipmi_smi *intf, {struct cmd_rcvr *rcvr; -list_for_each_entry_rcu (rcvr, &intf->cmd_rcvrs, link) { +list_for_each_entry_rcu (rcvr, &intf->cmd_rcvrs, link, +lockdep_is_held (&intf->cmd_rcvrs_mutex)) {if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd) && (rcvr->chans & chans))return 0 ;
@@ -3450,7 +3455,8 @@ int ipmi_add_smi(struct module *owner,/* Look for a hole in the numbers. */ i =0 ; link = &ipmi_interfaces; -list_for_each_entry_rcu (tintf, &ipmi_interfaces, link) { +list_for_each_entry_rcu (tintf, &ipmi_interfaces, link, +ipmi_interfaces_mutex_held ()) {if (tintf->intf_num != i) { link = &tintf->link;break ;
Signature · 1 line
2.24.1
Quoted 8 lines · Amol Grover
intf->cmd_rcvrsis traversed withlist_for_each_entry_rcuoutside an RCU read-side critical section but under the protection ofintf->cmd_rcvrs_mutex.
ipmi_interfacesis traversed usinglist_for_each_entry_rcuoutside an RCU read-side critical section but under the protection ofipmi_interfaces_mutex.
Quoted 8 lines
Hence, add the corresponding lockdep expression to the list traversal primitive to silence false-positive lockdep warnings, and harden RCU lists.
Add macro for the corresponding lockdep expression to make the code clean and concise.
Signed-off-by Amol Grover <[email protected]>
After reading everything, I think this is correct, but I would like Paul's stamp of approval on this.
Thanks,
-corey
Quoted 69 lines
---
v3:
- Removercu_read_lock_held()from lockdep expression since it is implicitly checked.
- Remove unintended macro usage.v2:
- Fix sparse error
CHECK: Alignment should match open parenthesisdrivers/char/ipmi/ipmi_msghandler.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)drivers/char/ipmi/ipmi_msghandler.c +10
-4@@ -618,6 +618,8 @@ static DEFINE_MUTEX(ipmidriver_mutex);static LIST_HEAD (ipmi_interfaces);static DEFINE_MUTEX (ipmi_interfaces_mutex); +#define ipmi_interfaces_mutex_held () \ + lockdep_is_held(&ipmi_interfaces_mutex)static struct srcu_struct ipmi_interfaces_srcu;/* @@ -1321,7 +1323,8 @@ static void _ipmi_destroy_user(struct ipmi_user *user)* synchronize_srcu()) then free everything in that list. */ mutex_lock (&intf->cmd_rcvrs_mutex); -list_for_each_entry_rcu (rcvr, &intf->cmd_rcvrs, link) { +list_for_each_entry_rcu (rcvr, &intf->cmd_rcvrs, link, +lockdep_is_held (&intf->cmd_rcvrs_mutex)) {if (rcvr->user == user) {list_del_rcu (&rcvr->link); rcvr->next = rcvrs;@@ -1599,7 +1602,8 @@ static struct cmd_rcvr *find_cmd_rcvr(struct ipmi_smi *intf, {struct cmd_rcvr *rcvr; -list_for_each_entry_rcu (rcvr, &intf->cmd_rcvrs, link) { +list_for_each_entry_rcu (rcvr, &intf->cmd_rcvrs, link, +lockdep_is_held (&intf->cmd_rcvrs_mutex)) {if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd) && (rcvr->chans & (1 << chan)))return rcvr;@@ -1614,7 +1618,8 @@ static int is_cmd_rcvr_exclusive(struct ipmi_smi *intf, {struct cmd_rcvr *rcvr; -list_for_each_entry_rcu (rcvr, &intf->cmd_rcvrs, link) { +list_for_each_entry_rcu (rcvr, &intf->cmd_rcvrs, link, +lockdep_is_held (&intf->cmd_rcvrs_mutex)) {if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd) && (rcvr->chans & chans))return 0 ;@@ -3450,7 +3455,8 @@ int ipmi_add_smi(struct module *owner,/* Look for a hole in the numbers. */ i =0 ; link = &ipmi_interfaces; -list_for_each_entry_rcu (tintf, &ipmi_interfaces, link) { +list_for_each_entry_rcu (tintf, &ipmi_interfaces, link, +ipmi_interfaces_mutex_held ()) {if (tintf->intf_num != i) { link = &tintf->link;break ;Signature · 1 line
2.24.1
Paul E. McKenney
Acked-byQuoted 13 lines · Corey Minyard
Quoted 12 lines · Amol Grover
intf->cmd_rcvrsis traversed withlist_for_each_entry_rcuoutside an RCU read-side critical section but under the protection ofintf->cmd_rcvrs_mutex.
ipmi_interfacesis traversed usinglist_for_each_entry_rcuoutside an RCU read-side critical section but under the protection ofipmi_interfaces_mutex.Hence, add the corresponding lockdep expression to the list traversal primitive to silence false-positive lockdep warnings, and harden RCU lists.
Quoted 7 lines
Quoted 4 lines
Add macro for the corresponding lockdep expression to make the code clean and concise.
Signed-off-by Amol Grover <[email protected]>After reading everything, I think this is correct, but I would like Paul's stamp of approval on this.
But note that I did not trace the locking in the case of ipmi_add_smi(). I did the others, so lockdep can do the last one. ;-)
Thanx, Paul
Quoted 73 lines
Thanks,
-corey
Quoted 69 lines
---
v3:
- Removercu_read_lock_held()from lockdep expression since it is implicitly checked.
- Remove unintended macro usage.v2:
- Fix sparse error
CHECK: Alignment should match open parenthesisdrivers/char/ipmi/ipmi_msghandler.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)drivers/char/ipmi/ipmi_msghandler.c +10
-4@@ -618,6 +618,8 @@ static DEFINE_MUTEX(ipmidriver_mutex);static LIST_HEAD (ipmi_interfaces);static DEFINE_MUTEX (ipmi_interfaces_mutex); +#define ipmi_interfaces_mutex_held () \ + lockdep_is_held(&ipmi_interfaces_mutex)static struct srcu_struct ipmi_interfaces_srcu;/* @@ -1321,7 +1323,8 @@ static void _ipmi_destroy_user(struct ipmi_user *user)* synchronize_srcu()) then free everything in that list. */ mutex_lock (&intf->cmd_rcvrs_mutex); -list_for_each_entry_rcu (rcvr, &intf->cmd_rcvrs, link) { +list_for_each_entry_rcu (rcvr, &intf->cmd_rcvrs, link, +lockdep_is_held (&intf->cmd_rcvrs_mutex)) {if (rcvr->user == user) {list_del_rcu (&rcvr->link); rcvr->next = rcvrs;@@ -1599,7 +1602,8 @@ static struct cmd_rcvr *find_cmd_rcvr(struct ipmi_smi *intf, {struct cmd_rcvr *rcvr; -list_for_each_entry_rcu (rcvr, &intf->cmd_rcvrs, link) { +list_for_each_entry_rcu (rcvr, &intf->cmd_rcvrs, link, +lockdep_is_held (&intf->cmd_rcvrs_mutex)) {if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd) && (rcvr->chans & (1 << chan)))return rcvr;@@ -1614,7 +1618,8 @@ static int is_cmd_rcvr_exclusive(struct ipmi_smi *intf, {struct cmd_rcvr *rcvr; -list_for_each_entry_rcu (rcvr, &intf->cmd_rcvrs, link) { +list_for_each_entry_rcu (rcvr, &intf->cmd_rcvrs, link, +lockdep_is_held (&intf->cmd_rcvrs_mutex)) {if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd) && (rcvr->chans & chans))return 0 ;@@ -3450,7 +3455,8 @@ int ipmi_add_smi(struct module *owner,/* Look for a hole in the numbers. */ i =0 ; link = &ipmi_interfaces; -list_for_each_entry_rcu (tintf, &ipmi_interfaces, link) { +list_for_each_entry_rcu (tintf, &ipmi_interfaces, link, +ipmi_interfaces_mutex_held ()) {if (tintf->intf_num != i) { link = &tintf->link;break ;Signature · 1 line
2.24.1
Quoted 19 lines · Paul E. McKenney
Quoted 18 lines · Corey Minyard
Quoted 16 lines · Amol Grover
intf->cmd_rcvrsis traversed withlist_for_each_entry_rcuoutside an RCU read-side critical section but under the protection ofintf->cmd_rcvrs_mutex.
ipmi_interfacesis traversed usinglist_for_each_entry_rcuoutside an RCU read-side critical section but under the protection ofipmi_interfaces_mutex.Hence, add the corresponding lockdep expression to the list traversal primitive to silence false-positive lockdep warnings, and harden RCU lists.
Add macro for the corresponding lockdep expression to make the code clean and concise.
Signed-off-by Amol Grover <[email protected]>
Quoted 7 lines
Quoted 2 lines
After reading everything, I think this is correct, but I would like Paul's stamp of approval on this.
Acked-by Paul E. McKenney <[email protected]>But note that I did not trace the locking in the case of
ipmi_add_smi(). I did the others, so lockdep can do the last one. ;-)
Thanks, it's in my queue for 5.7.
-corey
Quoted 76 lines
Thanx, Paul
Quoted 73 lines
Thanks,
-corey
Quoted 69 lines
---
v3:
- Removercu_read_lock_held()from lockdep expression since it is implicitly checked.
- Remove unintended macro usage.v2:
- Fix sparse error
CHECK: Alignment should match open parenthesisdrivers/char/ipmi/ipmi_msghandler.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)drivers/char/ipmi/ipmi_msghandler.c +10
-4@@ -618,6 +618,8 @@ static DEFINE_MUTEX(ipmidriver_mutex);static LIST_HEAD (ipmi_interfaces);static DEFINE_MUTEX (ipmi_interfaces_mutex); +#define ipmi_interfaces_mutex_held () \ + lockdep_is_held(&ipmi_interfaces_mutex)static struct srcu_struct ipmi_interfaces_srcu;/* @@ -1321,7 +1323,8 @@ static void _ipmi_destroy_user(struct ipmi_user *user)* synchronize_srcu()) then free everything in that list. */ mutex_lock (&intf->cmd_rcvrs_mutex); -list_for_each_entry_rcu (rcvr, &intf->cmd_rcvrs, link) { +list_for_each_entry_rcu (rcvr, &intf->cmd_rcvrs, link, +lockdep_is_held (&intf->cmd_rcvrs_mutex)) {if (rcvr->user == user) {list_del_rcu (&rcvr->link); rcvr->next = rcvrs;@@ -1599,7 +1602,8 @@ static struct cmd_rcvr *find_cmd_rcvr(struct ipmi_smi *intf, {struct cmd_rcvr *rcvr; -list_for_each_entry_rcu (rcvr, &intf->cmd_rcvrs, link) { +list_for_each_entry_rcu (rcvr, &intf->cmd_rcvrs, link, +lockdep_is_held (&intf->cmd_rcvrs_mutex)) {if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd) && (rcvr->chans & (1 << chan)))return rcvr;@@ -1614,7 +1618,8 @@ static int is_cmd_rcvr_exclusive(struct ipmi_smi *intf, {struct cmd_rcvr *rcvr; -list_for_each_entry_rcu (rcvr, &intf->cmd_rcvrs, link) { +list_for_each_entry_rcu (rcvr, &intf->cmd_rcvrs, link, +lockdep_is_held (&intf->cmd_rcvrs_mutex)) {if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd) && (rcvr->chans & chans))return 0 ;@@ -3450,7 +3455,8 @@ int ipmi_add_smi(struct module *owner,/* Look for a hole in the numbers. */ i =0 ; link = &ipmi_interfaces; -list_for_each_entry_rcu (tintf, &ipmi_interfaces, link) { +list_for_each_entry_rcu (tintf, &ipmi_interfaces, link, +ipmi_interfaces_mutex_held ()) {if (tintf->intf_num != i) { link = &tintf->link;break ;Signature · 1 line
2.24.1