Skip to content

Commit 2fb48d8

Browse files
ebiggersaxboe
authored andcommitted
blk-crypto: use dynamic lock class for blk_crypto_profile::lock
When a device-mapper device is passing through the inline encryption support of an underlying device, calls to blk_crypto_evict_key() take the blk_crypto_profile::lock of the device-mapper device, then take the blk_crypto_profile::lock of the underlying device (nested). This isn't a real deadlock, but it causes a lockdep report because there is only one lock class for all instances of this lock. Lockdep subclasses don't really work here because the hierarchy of block devices is dynamic and could have more than 2 levels. Instead, register a dynamic lock class for each blk_crypto_profile, and associate that with the lock. This avoids false-positive lockdep reports like the following: ============================================ WARNING: possible recursive locking detected 6.4.0-rc5 #2 Not tainted -------------------------------------------- fscryptctl/1421 is trying to acquire lock: ffffff80829ca418 (&profile->lock){++++}-{3:3}, at: __blk_crypto_evict_key+0x44/0x1c0 but task is already holding lock: ffffff8086b68ca8 (&profile->lock){++++}-{3:3}, at: __blk_crypto_evict_key+0xc8/0x1c0 other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(&profile->lock); lock(&profile->lock); *** DEADLOCK *** May be due to missing lock nesting notation Fixes: 1b26283 ("block: Keyslot Manager for Inline Encryption") Reported-by: Bart Van Assche <[email protected]> Signed-off-by: Eric Biggers <[email protected]> Reviewed-by: Bart Van Assche <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 7eb1e47 commit 2fb48d8

File tree

2 files changed

+11
-2
lines changed

2 files changed

+11
-2
lines changed

block/blk-crypto-profile.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,14 @@ int blk_crypto_profile_init(struct blk_crypto_profile *profile,
7979
unsigned int slot_hashtable_size;
8080

8181
memset(profile, 0, sizeof(*profile));
82-
init_rwsem(&profile->lock);
82+
83+
/*
84+
* profile->lock of an underlying device can nest inside profile->lock
85+
* of a device-mapper device, so use a dynamic lock class to avoid
86+
* false-positive lockdep reports.
87+
*/
88+
lockdep_register_key(&profile->lockdep_key);
89+
__init_rwsem(&profile->lock, "&profile->lock", &profile->lockdep_key);
8390

8491
if (num_slots == 0)
8592
return 0;
@@ -89,7 +96,7 @@ int blk_crypto_profile_init(struct blk_crypto_profile *profile,
8996
profile->slots = kvcalloc(num_slots, sizeof(profile->slots[0]),
9097
GFP_KERNEL);
9198
if (!profile->slots)
92-
return -ENOMEM;
99+
goto err_destroy;
93100

94101
profile->num_slots = num_slots;
95102

@@ -435,6 +442,7 @@ void blk_crypto_profile_destroy(struct blk_crypto_profile *profile)
435442
{
436443
if (!profile)
437444
return;
445+
lockdep_unregister_key(&profile->lockdep_key);
438446
kvfree(profile->slot_hashtable);
439447
kvfree_sensitive(profile->slots,
440448
sizeof(profile->slots[0]) * profile->num_slots);

include/linux/blk-crypto-profile.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ struct blk_crypto_profile {
111111
* keyslots while ensuring that they can't be changed concurrently.
112112
*/
113113
struct rw_semaphore lock;
114+
struct lock_class_key lockdep_key;
114115

115116
/* List of idle slots, with least recently used slot at front */
116117
wait_queue_head_t idle_slots_wait_queue;

0 commit comments

Comments
 (0)