Add lockdep_assert_not_held()
v3 cover Add lockdep_assert_not_held()
Some kernel functions must not be called holding a specific lock. Doing so could lead to locking problems. Currently these routines call lock_is_held() to check for lock hold followed by WARN_ON.
Adding a common lockdep interface will help reduce the duplication of this logic in the rest of the kernel.
Add lockdep_assert_not_held() to be used in these functions to detect incorrect calls while holding a lock.
lockdep_assert_not_held() provides the opposite functionality of lockdep_assert_held() which is used to assert calls that require holding a specific lock.
The need for lockdep_assert_not_held() came up in a discussion on ath10k patch. ath10k_drain_tx() and i915_vma_pin_ww() are examples of functions that can use lockdep_assert_not_held().
This patch series adds lockdep_assert_not_held() and uses it in the second patch in ath10k_drain_tx() function.
Changes since v2:
-- Fixed coding style issues
-- Patch 2 uses new lock states in __lock_is_held() and
lock_is_held_type
Patch 1 incorporates suggestions from Peter Zijlstra on v1 series to avoid misfires when lockdep_off() is employed.
Patch 2 Johannes Berg's suggestions as it make it easier to read and maintain the lock states. These are defines and a enum to avoid changes to lock_is_held_type() and lockdep_is_held() return types.
Patch 2 is a separate patch because it adds defines to lockdep.h and kernel/locking/lockdep.c now includes lockdep.h - decided make this a separate patch just in case issues related to header dependencies pop up. I can combine Patches 1&2 if that is preferred.
Patch 3 uses the new interface in ath10k_drain_tx() function. Added Kalle Valo's Ack from v1 for this change.
Tested on the mainline from yesterday.
Shuah Khan (3):
lockdep: add lockdep_assert_not_held()
lockdep: add lockdep lock state defines
ath10k: detect conf_mutex held ath10k_drain_tx() calls
drivers/net/wireless/ath/ath10k/mac.c | 2 ++ include/linux/lockdep.h | 18 +++++++++++++++--- kernel/locking/lockdep.c | 15 ++++++++++----- 3 files changed, 27 insertions(+), 8 deletions(-)
Signature · 7 lines
2.27.0 _______________________________________________ ath10k mailing list [email protected] http://lists.infradead.org/mailman/listinfo/ath10k
PATCH v3 1/3 lockdep: add lockdep_assert_not_held()
Some kernel functions must be called without holding a specific lock. Add lockdep_assert_not_held() to be used in these functions to detect incorrect calls while holding a lock.
lockdep_assert_not_held() provides the opposite functionality of lockdep_assert_held() which is used to assert calls that require holding a specific lock.
Incorporates suggestions from Peter Zijlstra to avoid misfires when lockdep_off() is employed.
The need for lockdep_assert_not_held() came up in a discussion on ath10k patch. ath10k_drain_tx() and i915_vma_pin_ww() are examples of functions that can use lockdep_assert_not_held().
--- include/linux/lockdep.h | 11 ++++++++--- kernel/locking/lockdep.c | 6 +++++- 2 files changed, 13 insertions(+), 4 deletions(-)
include/linux/lockdep.h +8 -3
@@ -301,8 +301,12 @@ extern void lock_unpin_lock(struct lockdep_map *lock, struct pin_cookie);#define lockdep_depth (tsk) (debug_locks ? (tsk)->lockdep_depth : 0) -#define lockdep_assert_held (l) do { \ - WARN_ON(debug_locks && !lockdep_is_held(l)); \ +#define lockdep_assert_held (l) do { \ + WARN_ON(debug_locks && lockdep_is_held(l) == 0); \ + } while (0) + +#define lockdep_assert_not_held (l) do { \ + WARN_ON(debug_locks && lockdep_is_held(l) == 1); \ } while (0)#define lockdep_assert_held_write (l) do { \
@@ -393,7 +397,8 @@ extern int lockdep_is_held(const void *);#define lockdep_is_held_type (l, r) (1)#define lockdep_assert_held (l) do { (void)(l); } while (0) -#define lockdep_assert_held_write (l) do { (void)(l); } while (0) +#define lockdep_assert_not_held (l) do { (void)(l); } while (0) +#define lockdep_assert_held_write (l) do { (void)(l); } while (0)#define lockdep_assert_held_read (l) do { (void)(l); } while (0)#define lockdep_assert_held_once (l) do { (void)(l); } while (0)
kernel/locking/lockdep.c +5 -1
@@ -5539,8 +5539,12 @@ noinstr int lock_is_held_type(const struct lockdep_map *lock, int read)unsigned long flags;int ret =0 ; +/* +* avoid false negative lockdep_assert_held() and +* lockdep_assert_not_held() +*/ if (unlikely (!lockdep_enabled ())) -return 1 ;/* avoid false negative lockdep_assert_held() */ +return -1 ;raw_local_irq_save (flags);check_flags (flags);
Signature · 7 lines
2.27.0 _______________________________________________ ath10k mailing list [email protected] http://lists.infradead.org/mailman/listinfo/ath10k
PATCH v3 2/3 lockdep: add lockdep lock state defines
In reply to Shuah KhanAdds defines for lock state returns from lock_is_held_type() based on Johannes Berg's suggestions as it make it easier to read and maintain the lock states. These are defines and a enum to avoid changes to lock_is_held_type() and lockdep_is_held() return types.
Updates to lock_is_held_type() and __lock_is_held() to use the new defines.
--- include/linux/lockdep.h | 11 +++++++++-- kernel/locking/lockdep.c | 11 ++++++----- 2 files changed, 15 insertions(+), 7 deletions(-)
include/linux/lockdep.h +9 -2
@@ -268,6 +268,11 @@ extern void lock_acquire(struct lockdep_map *lock, unsigned int subclass,extern void lock_release (struct lockdep_map *lock,unsigned long ip); +/* lock_is_held_type() returns */ +#define LOCK_STATE_UNKNOWN -1 +#define LOCK_STATE_NOT_HELD 0 +#define LOCK_STATE_HELD 1 +/* * Same "read" as for lock_acquire(), except -1 means any. */
@@ -302,11 +307,13 @@ extern void lock_unpin_lock(struct lockdep_map *lock, struct pin_cookie);#define lockdep_depth (tsk) (debug_locks ? (tsk)->lockdep_depth : 0)#define lockdep_assert_held (l) do { \ - WARN_ON(debug_locks && lockdep_is_held(l) == 0); \ + WARN_ON(debug_locks && \ + lockdep_is_held(l) == LOCK_STATE_NOT_HELD); \ } while (0)#define lockdep_assert_not_held (l) do { \ - WARN_ON(debug_locks && lockdep_is_held(l) == 1); \ + WARN_ON(debug_locks && \ + lockdep_is_held(l) == LOCK_STATE_HELD); \ } while (0)#define lockdep_assert_held_write (l) do { \
kernel/locking/lockdep.c +6 -5
@@ -54,6 +54,7 @@#include <linux/nmi.h> #include <linux/rcupdate.h> #include <linux/kprobes.h> +#include <linux/lockdep.h> #include <asm/sections.h>
@@ -5252,13 +5253,13 @@ int __lock_is_held(const struct lockdep_map *lock, int read)if (match_held_lock (hlock, lock)) {if (read ==-1 || hlock->read == read) -return 1 ; +return LOCK_STATE_HELD ; -return 0 ; +return LOCK_STATE_NOT_HELD ; } } -return 0 ; +return LOCK_STATE_NOT_HELD ; }static struct pin_cookie __lock_pin_lock (struct lockdep_map *lock)
@@ -5537,14 +5538,14 @@ EXPORT_SYMBOL_GPL(lock_release); noinstr int lock_is_held_type(const struct lockdep_map *lock, int read) {unsigned long flags; -int ret =0 ; +int ret =LOCK_STATE_NOT_HELD ;/* * avoid false negative lockdep_assert_held() and * lockdep_assert_not_held() */ if (unlikely (!lockdep_enabled ())) -return -1 ; +return LOCK_STATE_UNKNOWN ;raw_local_irq_save (flags);check_flags (flags);
Signature · 7 lines
2.27.0 _______________________________________________ ath10k mailing list [email protected] http://lists.infradead.org/mailman/listinfo/ath10k
PATCH v3 3/3 ath10k: detect conf_mutex held ath10k_drain_tx() calls
In reply to Shuah Khanath10k_drain_tx() must not be called with conf_mutex held as workers can use that also. Add call to lockdep_assert_not_held() on conf_mutex to detect if conf_mutex is held by the caller.
The idea for this patch stemmed from coming across the comment block above the ath10k_drain_tx() while reviewing the conf_mutex holds during to debug the conf_mutex lock assert in ath10k_debug_fw_stats_request().
Adding detection to assert on conf_mutex hold will help detect incorrect usages that could lead to locking problems when async worker routines try to call this routine.
--- drivers/net/wireless/ath/ath10k/mac.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/wireless/ath/ath10k/mac.c +2 -0
@@ -4727,6 +4727,8 @@ static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw,/* Must not be called with conf_mutex held as workers can use that also. */ void ath10k_drain_tx (struct ath10k *ar) { +lockdep_assert_not_held (&ar->conf_mutex); +/* make sure rcu-protected mac80211 tx path itself is drained */ synchronize_net ();
Signature · 7 lines
2.27.0 _______________________________________________ ath10k mailing list [email protected] http://lists.infradead.org/mailman/listinfo/ath10k
Peter Zijlstra
maintainerQuoted 4 lines · Shuah Khan
Shuah Khan (3):
lockdep: addlockdep_assert_not_held()
lockdep: add lockdep lock state defines
ath10k: detectconf_mutexheldath10k_drain_tx()calls
Thanks!
_______________________________________________
ath10k mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/ath10k
Quoted 7 lines · Peter Zijlstra
Quoted 4 lines · Shuah Khan
Shuah Khan (3):
lockdep: addlockdep_assert_not_held()
lockdep: add lockdep lock state defines
ath10k: detectconf_mutexheldath10k_drain_tx()callsThanks!
Via which tree should these go?
Signature · 8 lines
https://patchwork.kernel.org/project/linux-wireless/list/ https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches _______________________________________________ ath10k mailing list [email protected] http://lists.infradead.org/mailman/listinfo/ath10k
Peter Zijlstra
maintainerQuoted 11 lines · Kalle Valo
Quoted 7 lines · Peter Zijlstra
Quoted 4 lines · Shuah Khan
Shuah Khan (3):
lockdep: addlockdep_assert_not_held()
lockdep: add lockdep lock state defines
ath10k: detectconf_mutexheldath10k_drain_tx()callsThanks!
Via which tree should these go?
I've just queued the lot for locking/core, which will show up in tip when the robots don't hate on it.
Does that work for you?
_______________________________________________
ath10k mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/ath10k
Quoted 9 lines · Peter Zijlstra
Quoted 8 lines · Kalle Valo
Quoted 6 lines · Peter Zijlstra
Quoted 4 lines · Shuah Khan
Shuah Khan (3):
lockdep: addlockdep_assert_not_held()
lockdep: add lockdep lock state defines
ath10k: detectconf_mutexheldath10k_drain_tx()calls
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
Thanks!
Via which tree should these go?
I've just queued the lot for locking/core, which will show up in tip when the robots don't hate on it.
Does that work for you?
That's perfect, thanks! Just making sure that the patches don't get lost.
Signature · 8 lines
https://patchwork.kernel.org/project/linux-wireless/list/ https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches _______________________________________________ ath10k mailing list [email protected] http://lists.infradead.org/mailman/listinfo/ath10k
Quoted 15 lines · Kalle Valo
Quoted 13 lines · Peter Zijlstra
Quoted 11 lines · Kalle Valo
Quoted 7 lines · Peter Zijlstra
Quoted 4 lines · Shuah Khan
Shuah Khan (3):
lockdep: addlockdep_assert_not_held()
lockdep: add lockdep lock state defines
ath10k: detectconf_mutexheldath10k_drain_tx()callsThanks!
Via which tree should these go?
Quoted 8 lines
Quoted 4 lines
I've just queued the lot for locking/core, which will show up in tip when the robots don't hate on it.
Does that work for you?
That's perfect, thanks! Just making sure that the patches don't get lost.
Awesome. Thank you.
thanks,
-- Shuah
_______________________________________________
ath10k mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/ath10k