ipmi: Fix RCU list lockdep debugging warnings
PATCH 1/1 ipmi: Fix RCU list lockdep debugging warnings
It is completely safe to traverse ipmi_interfaces and intf->users under SRCU read lock using list_for_each_entry_rcu(). Tell lockdep about it as well else it will show false-positive warnings as the one below.
Fixes the following false-positive warning and others that may follow.
[ 29.772408] ============================= [ 29.776863] WARNING: suspicious RCU usage [ 29.780915] 5.6.0-rc3-00001-g907305ae6618-dirty #1755 Not tainted [ 29.787046] ----------------------------- [ 29.791100] drivers/char/ipmi/ipmi_msghandler.c:744 RCU-list traversed in
non-reader section!!
--- drivers/char/ipmi/ipmi_msghandler.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
drivers/char/ipmi/ipmi_msghandler.c +12 -6
@@ -741,7 +741,8 @@ int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher)list_add (&watcher->link, &smi_watchers); index =srcu_read_lock (&ipmi_interfaces_srcu); -list_for_each_entry_rcu (intf, &ipmi_interfaces, link) { +list_for_each_entry_rcu (intf, &ipmi_interfaces, link, +srcu_read_lock_held (&ipmi_interfaces_srcu)) {int intf_num =READ_ONCE (intf->intf_num);if (intf_num ==-1 )
@@ -1188,7 +1189,8 @@ int ipmi_create_user(unsigned int if_num,return -ENOMEM ; index =srcu_read_lock (&ipmi_interfaces_srcu); -list_for_each_entry_rcu (intf, &ipmi_interfaces, link) { +list_for_each_entry_rcu (intf, &ipmi_interfaces, link, +srcu_read_lock_held (&ipmi_interfaces_srcu)) {if (intf->intf_num == if_num) goto found; }
@@ -1241,7 +1243,8 @@ int ipmi_get_smi_info(int if_num, struct ipmi_smi_info *data)struct ipmi_smi *intf; index =srcu_read_lock (&ipmi_interfaces_srcu); -list_for_each_entry_rcu (intf, &ipmi_interfaces, link) { +list_for_each_entry_rcu (intf, &ipmi_interfaces, link, +srcu_read_lock_held (&ipmi_interfaces_srcu)) {if (intf->intf_num == if_num) goto found; }
@@ -4098,7 +4101,8 @@ static int handle_read_event_rsp(struct ipmi_smi *intf,* getting events. */ index =srcu_read_lock (&intf->users_srcu); -list_for_each_entry_rcu (user, &intf->users, link) { +list_for_each_entry_rcu (user, &intf->users, link, +srcu_read_lock_held (&intf->users_srcu)) {if (!user->gets_events)continue ;
@@ -4453,7 +4457,8 @@ static void handle_new_recv_msgs(struct ipmi_smi *intf)int index; index =srcu_read_lock (&intf->users_srcu); -list_for_each_entry_rcu (user, &intf->users, link) { +list_for_each_entry_rcu (user, &intf->users, link, +srcu_read_lock_held (&intf->users_srcu)) {if (user->handler->ipmi_watchdog_pretimeout) user->handler->ipmi_watchdog_pretimeout ( user->handler_data);
@@ -4746,7 +4751,8 @@ static void ipmi_timeout(struct timer_list *unused)return ; index =srcu_read_lock (&ipmi_interfaces_srcu); -list_for_each_entry_rcu (intf, &ipmi_interfaces, link) { +list_for_each_entry_rcu (intf, &ipmi_interfaces, link, +srcu_read_lock_held (&ipmi_interfaces_srcu)) {if (atomic_read (&intf->event_waiters)) { intf->ticks_to_req_ev--;if (intf->ticks_to_req_ev ==0 ) {
Signature · 1 line
2.25.0
Quoted 12 lines · Amol Grover
It is completely safe to traverse
ipmi_interfacesandintf->usersunder SRCU read lock usinglist_for_each_entry_rcu(). Tell lockdep about it as well else it will show false-positive warnings as the one below.Fixes the following false-positive warning and others that may follow.
[ 29.772408] ============================= [ 29.776863] WARNING: suspicious RCU usage [ 29.780915] 5.6.0-rc3-00001-g907305ae6618-dirty #1755 Not tainted [ 29.787046] ----------------------------- [ 29.791100] drivers/char/ipmi/ipmi_msghandler.c:744 RCU-list traversed in
Quoted 5 lines
non-reader section!!
Reported-by John Garry <[email protected]>Suggested-by Paul E. McKenney <[email protected]>Signed-off-by Amol Grover <[email protected]>
Thanks, the warnings have gone away with this
Quoted 69 lines
--- drivers/char/ipmi/ipmi_msghandler.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)drivers/char/ipmi/ipmi_msghandler.c +12
-6@@ -741,7 +741,8 @@ int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher)list_add (&watcher->link, &smi_watchers); index =srcu_read_lock (&ipmi_interfaces_srcu); -list_for_each_entry_rcu (intf, &ipmi_interfaces, link) { +list_for_each_entry_rcu (intf, &ipmi_interfaces, link, +srcu_read_lock_held (&ipmi_interfaces_srcu)) {int intf_num =READ_ONCE (intf->intf_num);if (intf_num ==-1 )@@ -1188,7 +1189,8 @@ int ipmi_create_user(unsigned int if_num,return -ENOMEM ; index =srcu_read_lock (&ipmi_interfaces_srcu); -list_for_each_entry_rcu (intf, &ipmi_interfaces, link) { +list_for_each_entry_rcu (intf, &ipmi_interfaces, link, +srcu_read_lock_held (&ipmi_interfaces_srcu)) {if (intf->intf_num == if_num) goto found; }@@ -1241,7 +1243,8 @@ int ipmi_get_smi_info(int if_num, struct ipmi_smi_info *data)struct ipmi_smi *intf; index =srcu_read_lock (&ipmi_interfaces_srcu); -list_for_each_entry_rcu (intf, &ipmi_interfaces, link) { +list_for_each_entry_rcu (intf, &ipmi_interfaces, link, +srcu_read_lock_held (&ipmi_interfaces_srcu)) {if (intf->intf_num == if_num) goto found; }@@ -4098,7 +4101,8 @@ static int handle_read_event_rsp(struct ipmi_smi *intf,* getting events. */ index =srcu_read_lock (&intf->users_srcu); -list_for_each_entry_rcu (user, &intf->users, link) { +list_for_each_entry_rcu (user, &intf->users, link, +srcu_read_lock_held (&intf->users_srcu)) {if (!user->gets_events)continue ;@@ -4453,7 +4457,8 @@ static void handle_new_recv_msgs(struct ipmi_smi *intf)int index; index =srcu_read_lock (&intf->users_srcu); -list_for_each_entry_rcu (user, &intf->users, link) { +list_for_each_entry_rcu (user, &intf->users, link, +srcu_read_lock_held (&intf->users_srcu)) {if (user->handler->ipmi_watchdog_pretimeout) user->handler->ipmi_watchdog_pretimeout ( user->handler_data);@@ -4746,7 +4751,8 @@ static void ipmi_timeout(struct timer_list *unused)return ; index =srcu_read_lock (&ipmi_interfaces_srcu); -list_for_each_entry_rcu (intf, &ipmi_interfaces, link) { +list_for_each_entry_rcu (intf, &ipmi_interfaces, link, +srcu_read_lock_held (&ipmi_interfaces_srcu)) {if (atomic_read (&intf->event_waiters)) { intf->ticks_to_req_ev--;if (intf->ticks_to_req_ev ==0 ) {
Quoted 4 lines · Amol Grover
It is completely safe to traverse
ipmi_interfacesandintf->usersunder SRCU read lock usinglist_for_each_entry_rcu(). Tell lockdep about it as well else it will show false-positive warnings as the one below.
Thanks, this is queued for 5.7, and I hadded John Garry's test by.
-corey
Quoted 84 lines
Fixes the following false-positive warning and others that may follow.
[ 29.772408] ============================= [ 29.776863] WARNING: suspicious RCU usage [ 29.780915] 5.6.0-rc3-00001-g907305ae6618-dirty #1755 Not tainted [ 29.787046] ----------------------------- [ 29.791100] drivers/char/ipmi/ipmi_msghandler.c:744 RCU-list traversed innon-reader section!!
Reported-by John Garry <[email protected]>Suggested-by Paul E. McKenney <[email protected]>Signed-off-by Amol Grover <[email protected]>--- drivers/char/ipmi/ipmi_msghandler.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)drivers/char/ipmi/ipmi_msghandler.c +12
-6@@ -741,7 +741,8 @@ int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher)list_add (&watcher->link, &smi_watchers); index =srcu_read_lock (&ipmi_interfaces_srcu); -list_for_each_entry_rcu (intf, &ipmi_interfaces, link) { +list_for_each_entry_rcu (intf, &ipmi_interfaces, link, +srcu_read_lock_held (&ipmi_interfaces_srcu)) {int intf_num =READ_ONCE (intf->intf_num);if (intf_num ==-1 )@@ -1188,7 +1189,8 @@ int ipmi_create_user(unsigned int if_num,return -ENOMEM ; index =srcu_read_lock (&ipmi_interfaces_srcu); -list_for_each_entry_rcu (intf, &ipmi_interfaces, link) { +list_for_each_entry_rcu (intf, &ipmi_interfaces, link, +srcu_read_lock_held (&ipmi_interfaces_srcu)) {if (intf->intf_num == if_num) goto found; }@@ -1241,7 +1243,8 @@ int ipmi_get_smi_info(int if_num, struct ipmi_smi_info *data)struct ipmi_smi *intf; index =srcu_read_lock (&ipmi_interfaces_srcu); -list_for_each_entry_rcu (intf, &ipmi_interfaces, link) { +list_for_each_entry_rcu (intf, &ipmi_interfaces, link, +srcu_read_lock_held (&ipmi_interfaces_srcu)) {if (intf->intf_num == if_num) goto found; }@@ -4098,7 +4101,8 @@ static int handle_read_event_rsp(struct ipmi_smi *intf,* getting events. */ index =srcu_read_lock (&intf->users_srcu); -list_for_each_entry_rcu (user, &intf->users, link) { +list_for_each_entry_rcu (user, &intf->users, link, +srcu_read_lock_held (&intf->users_srcu)) {if (!user->gets_events)continue ;@@ -4453,7 +4457,8 @@ static void handle_new_recv_msgs(struct ipmi_smi *intf)int index; index =srcu_read_lock (&intf->users_srcu); -list_for_each_entry_rcu (user, &intf->users, link) { +list_for_each_entry_rcu (user, &intf->users, link, +srcu_read_lock_held (&intf->users_srcu)) {if (user->handler->ipmi_watchdog_pretimeout) user->handler->ipmi_watchdog_pretimeout ( user->handler_data);@@ -4746,7 +4751,8 @@ static void ipmi_timeout(struct timer_list *unused)return ; index =srcu_read_lock (&ipmi_interfaces_srcu); -list_for_each_entry_rcu (intf, &ipmi_interfaces, link) { +list_for_each_entry_rcu (intf, &ipmi_interfaces, link, +srcu_read_lock_held (&ipmi_interfaces_srcu)) {if (atomic_read (&intf->event_waiters)) { intf->ticks_to_req_ev--;if (intf->ticks_to_req_ev ==0 ) {Signature · 1 line
2.25.0