Skip to content

Commit dee1535

Browse files
idryomovsmb49
authored andcommitted
rbd: don't assume RBD_LOCK_STATE_LOCKED for exclusive mappings
BugLink: https://bugs.launchpad.net/bugs/2078428 commit 2237ceb71f89837ac47c5dce2aaa2c2b3a337a3c upstream. Every time a watch is reestablished after getting lost, we need to update the cookie which involves quiescing exclusive lock. For this, we transition from RBD_LOCK_STATE_LOCKED to RBD_LOCK_STATE_QUIESCING roughly for the duration of rbd_reacquire_lock() call. If the mapping is exclusive and I/O happens to arrive in this time window, it's failed with EROFS (later translated to EIO) based on the wrong assumption in rbd_img_exclusive_lock() -- "lock got released?" check there stopped making sense with commit a2b1da0 ("rbd: lock should be quiesced on reacquire"). To make it worse, any such I/O is added to the acquiring list before EROFS is returned and this sets up for violating rbd_lock_del_request() precondition that the request is either on the running list or not on any list at all -- see commit ded080c ("rbd: don't move requests to the running list on errors"). rbd_lock_del_request() ends up processing these requests as if they were on the running list which screws up quiescing_wait completion counter and ultimately leads to rbd_assert(!completion_done(&rbd_dev->quiescing_wait)); being triggered on the next watch error. Cc: [email protected] # 06ef84c4e9c4: rbd: rename RBD_LOCK_STATE_RELEASING and releasing_wait Cc: [email protected] Fixes: 637cd06 ("rbd: new exclusive lock wait/wake code") Signed-off-by: Ilya Dryomov <[email protected]> Reviewed-by: Dongsheng Yang <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]> Signed-off-by: Koichiro Den <[email protected]> Signed-off-by: Stefan Bader <[email protected]>
1 parent 25a76b1 commit dee1535

File tree

1 file changed

+5
-5
lines changed

1 file changed

+5
-5
lines changed

drivers/block/rbd.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -3459,6 +3459,7 @@ static void rbd_lock_del_request(struct rbd_img_request *img_req)
34593459
lockdep_assert_held(&rbd_dev->lock_rwsem);
34603460
spin_lock(&rbd_dev->lock_lists_lock);
34613461
if (!list_empty(&img_req->lock_item)) {
3462+
rbd_assert(!list_empty(&rbd_dev->running_list));
34623463
list_del_init(&img_req->lock_item);
34633464
need_wakeup = (rbd_dev->lock_state == RBD_LOCK_STATE_QUIESCING &&
34643465
list_empty(&rbd_dev->running_list));
@@ -3478,11 +3479,6 @@ static int rbd_img_exclusive_lock(struct rbd_img_request *img_req)
34783479
if (rbd_lock_add_request(img_req))
34793480
return 1;
34803481

3481-
if (rbd_dev->opts->exclusive) {
3482-
WARN_ON(1); /* lock got released? */
3483-
return -EROFS;
3484-
}
3485-
34863482
/*
34873483
* Note the use of mod_delayed_work() in rbd_acquire_lock()
34883484
* and cancel_delayed_work() in wake_lock_waiters().
@@ -4603,6 +4599,10 @@ static void rbd_reacquire_lock(struct rbd_device *rbd_dev)
46034599
rbd_warn(rbd_dev, "failed to update lock cookie: %d",
46044600
ret);
46054601

4602+
if (rbd_dev->opts->exclusive)
4603+
rbd_warn(rbd_dev,
4604+
"temporarily releasing lock on exclusive mapping");
4605+
46064606
/*
46074607
* Lock cookie cannot be updated on older OSDs, so do
46084608
* a manual release and queue an acquire.

0 commit comments

Comments
 (0)