[dm-devel] [PATCH] dm-bufio: avoid a possible deadlock due to lock ordering
Mikulas Patocka
mpatocka at redhat.com
Sun Apr 30 21:33:26 UTC 2017
The function __get_memory_limit tests if dm_bufio_cache_size changed and
calls __cache_size_refresh if it did. It takes dm_bufio_clients_lock while
it already holds the client lock. However, lock ordering is violated
because in the function cleanup_old_buffers dm_bufio_clients_lock is taken
before the client lock.
This results in a possible deadlock and lockdep engine warning.
This patch fixes the deadlock by changing mutex_lock to mutex_trylock. If
the lock can't be taken, it will be re-checked next time when a new buffer
is be allocated. The patch also adds "unlikely" to the if confition, so
that the optimizer assumes that the condition is false.
Signed-off-by: Mikulas Patocka <mpatocka at redhat.com>
Cc: stable at vger.kernel.org
---
drivers/md/dm-bufio.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
Index: linux-2.6/drivers/md/dm-bufio.c
===================================================================
--- linux-2.6.orig/drivers/md/dm-bufio.c
+++ linux-2.6/drivers/md/dm-bufio.c
@@ -959,10 +959,11 @@ static void __get_memory_limit(struct dm
{
unsigned long buffers;
- if (ACCESS_ONCE(dm_bufio_cache_size) != dm_bufio_cache_size_latch) {
- mutex_lock(&dm_bufio_clients_lock);
- __cache_size_refresh();
- mutex_unlock(&dm_bufio_clients_lock);
+ if (unlikely(ACCESS_ONCE(dm_bufio_cache_size) != dm_bufio_cache_size_latch)) {
+ if (mutex_trylock(&dm_bufio_clients_lock)) {
+ __cache_size_refresh();
+ mutex_unlock(&dm_bufio_clients_lock);
+ }
}
buffers = dm_bufio_cache_size_per_client >>
More information about the dm-devel
mailing list