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 <[email protected]>
Cc: [email protected]

---
 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 >>

--
dm-devel mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/dm-devel

Reply via email to