When we are going to open journal, we don't want to release exclusive-lock in the whole process. But we can release it after opening. So introduce a lock_flag in rbd_dev to say, wait, we don't want to release exclusive-lock currently, please wait for this flag cleared. Signed-off-by: Dongsheng Yang <dongsheng.yang@xxxxxxxxxxxx> --- drivers/block/rbd.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index cc9ee8d..8db4c36 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -316,6 +316,10 @@ enum rbd_lock_state { RBD_LOCK_STATE_RELEASING, }; +enum rbd_lock_flags { + RBD_LOCK_FLAG_RELEASE_WAIT, // wait until this flag cleared in lock releasing +}; + /* WatchNotify::ClientId */ struct rbd_client_id { u64 gid; @@ -363,6 +367,8 @@ struct rbd_device { struct rw_semaphore lock_rwsem; enum rbd_lock_state lock_state; + unsigned long lock_flags; + struct completion lock_wait; char lock_cookie[32]; struct rbd_client_id owner_cid; struct work_struct acquired_lock_work; @@ -3080,6 +3086,19 @@ static void rbd_acquire_lock(struct work_struct *work) } } +static int rbd_lock_wait(struct rbd_device *rbd_dev) +{ + int ret = 0; + + while (test_bit(RBD_LOCK_FLAG_RELEASE_WAIT, &rbd_dev->lock_flags)) { + ret = wait_for_completion_interruptible(&rbd_dev->lock_wait); + if (ret) + break; + } + + return ret; +} + static int rbd_inflight_wait(struct rbd_device *rbd_dev) { int ret = 0; @@ -3108,6 +3127,12 @@ static bool rbd_release_lock(struct rbd_device *rbd_dev) rbd_dev->lock_state = RBD_LOCK_STATE_RELEASING; up_write(&rbd_dev->lock_rwsem); + ret = rbd_lock_wait(rbd_dev); + if (ret) { + down_write(&rbd_dev->lock_rwsem); + return false; + } + ret = rbd_inflight_wait(rbd_dev); if (ret) { down_write(&rbd_dev->lock_rwsem); @@ -4428,6 +4453,7 @@ static struct rbd_device *__rbd_dev_create(struct rbd_client *rbdc, init_rwsem(&rbd_dev->lock_rwsem); rbd_dev->lock_state = RBD_LOCK_STATE_UNLOCKED; + init_completion(&rbd_dev->lock_wait); INIT_WORK(&rbd_dev->acquired_lock_work, rbd_notify_acquired_lock); INIT_WORK(&rbd_dev->released_lock_work, rbd_notify_released_lock); INIT_DELAYED_WORK(&rbd_dev->lock_dwork, rbd_acquire_lock); -- 1.8.3.1