[Devel] [PATCH RHEL7 COMMIT] ploop: release plo->ctl_mutex for thaw_bdev in PLOOP_IOC_THAW handler

Vladimir Davydov vdavydov at virtuozzo.com
Fri Jul 15 02:34:36 PDT 2016


The commit is pushed to "branch-rh7-3.10.0-327.18.2.vz7.14.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-327.18.2.vz7.14.25
------>
commit b81bf870a6c314b664977ee9b6747cf93e78bcc3
Author: Vladimir Davydov <vdavydov at virtuozzo.com>
Date:   Fri Jul 15 13:34:36 2016 +0400

    ploop: release plo->ctl_mutex for thaw_bdev in PLOOP_IOC_THAW handler
    
    Recent patch to ploop 91a74e3b91a ("ploop: add PLOOP_IOC_FREEZE and
    PLOOP_IOC_THAW ioctls") introduced the follwing deadlock:
    
    Thread 1:
    [<ffffffff8122dc1e>] sleep_on_buffer+0xe/0x20
    [<ffffffff8122fd78>] __sync_dirty_buffer+0xb8/0xe0
    [<ffffffff8122fdb3>] sync_dirty_buffer+0x13/0x20
    [<ffffffffa01dc930>] ext4_commit_super+0x1b0/0x240 [ext4]
    [<ffffffffa01dc9ed>] ext4_unfreeze+0x2d/0x40 [ext4]
    [<ffffffff811fc63f>] thaw_super+0x3f/0xb0
    [<ffffffff812357d5>] thaw_bdev+0x65/0x80
    [<ffffffffa0380140>] ploop_ioctl+0x6d0/0x29f0 [ploop]
    [<ffffffff812d3d3f>] blkdev_ioctl+0x2df/0x770
    [<ffffffff81236131>] block_ioctl+0x41/0x50
    [<ffffffff8120d0c5>] do_vfs_ioctl+0x255/0x4f0
    [<ffffffff8120d3b4>] SyS_ioctl+0x54/0xa0
    [<ffffffff81642d09>] system_call_fastpath+0x16/0x1b
    [<ffffffffffffffff>] 0xffffffffffffffff
    
    Thread 2:
    [<ffffffffa038a4c3>] ploop_pb_get_pending+0x163/0x290 [ploop]
    [<ffffffffa03791a1>] ploop_push_backup_io_get.isra.26+0x81/0x1b0 [ploop]
    [<ffffffffa037a75b>] ploop_push_backup_io+0x15b/0x260 [ploop]
    [<ffffffffa0380906>] ploop_ioctl+0xe96/0x29f0 [ploop]
    [<ffffffff812d3d3f>] blkdev_ioctl+0x2df/0x770
    [<ffffffff81236131>] block_ioctl+0x41/0x50
    [<ffffffff8120d0c5>] do_vfs_ioctl+0x255/0x4f0
    [<ffffffff8120d3b4>] SyS_ioctl+0x54/0xa0
    [<ffffffff81642d09>] system_call_fastpath+0x16/0x1b
    [<ffffffffffffffff>] 0xffffffffffffffff
    
    E.g. thread 1 is thawing ploop with PLOOP_IOC_THAW ioctl which holds
    plo->ctl_mutex during its work. To thaw itself, ext4 has to commit some
    data. This commit triggers push backup out-of-order request which must
    be processed and acked by userspace to be completed. But userspace can't
    process it, because ploop_pb_get_pending() wants the same mutext. Thus,
    deadlock.
    
    Fix the deadlock by releasing the mutex before calling thaw_bdev and
    reaquiring it after thaw_bdev is done.
    
    https://jira.sw.ru/browse/PSBM-49699
    
    Reported-by: Pavel Borzenkov <pborzenkov at virtuozzo.com>
    Signed-off-by: Vladimir Davydov <vdavydov at virtuozzo.com>
    Cc: Maxim Patlasov <mpatlasov at virtuozzo.com>
---
 drivers/block/ploop/dev.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/block/ploop/dev.c b/drivers/block/ploop/dev.c
index d52975eaaa36..3dc94ca5c393 100644
--- a/drivers/block/ploop/dev.c
+++ b/drivers/block/ploop/dev.c
@@ -4839,11 +4839,12 @@ static int ploop_thaw(struct ploop_device *plo, struct block_device *bdev)
 	if (!test_bit(PLOOP_S_FROZEN, &plo->state))
 		return 0;
 
+	plo->sb = NULL;
+	clear_bit(PLOOP_S_FROZEN, &plo->state);
+
+	mutex_unlock(&plo->ctl_mutex);
 	err = thaw_bdev(bdev, sb);
-	if (!err) {
-		plo->sb = NULL;
-		clear_bit(PLOOP_S_FROZEN, &plo->state);
-	}
+	mutex_lock(&plo->ctl_mutex);
 
 	return err;
 }


More information about the Devel mailing list