Skip to content

Commit 17df4fd

Browse files
committed
rbd: don't assume RBD_LOCK_STATE_LOCKED for exclusive mappings
jira LE-1907 Rebuild_History Non-Buildable kernel-5.14.0-427.35.1.el9_4 commit-author Ilya Dryomov <idryomov@gmail.com> commit 2237ceb 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: stable@vger.kernel.org # 06ef84c4e9c4: rbd: rename RBD_LOCK_STATE_RELEASING and releasing_wait Cc: stable@vger.kernel.org Fixes: 637cd06 ("rbd: new exclusive lock wait/wake code") Signed-off-by: Ilya Dryomov <idryomov@gmail.com> Reviewed-by: Dongsheng Yang <dongsheng.yang@easystack.cn> (cherry picked from commit 2237ceb) Signed-off-by: Jonathan Maple <jmaple@ciq.com>
1 parent fab21c5 commit 17df4fd

File tree

1 file changed

+5
-5
lines changed

1 file changed

+5
-5
lines changed

drivers/block/rbd.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3457,6 +3457,7 @@ static void rbd_lock_del_request(struct rbd_img_request *img_req)
34573457
lockdep_assert_held(&rbd_dev->lock_rwsem);
34583458
spin_lock(&rbd_dev->lock_lists_lock);
34593459
if (!list_empty(&img_req->lock_item)) {
3460+
rbd_assert(!list_empty(&rbd_dev->running_list));
34603461
list_del_init(&img_req->lock_item);
34613462
need_wakeup = (rbd_dev->lock_state == RBD_LOCK_STATE_QUIESCING &&
34623463
list_empty(&rbd_dev->running_list));
@@ -3476,11 +3477,6 @@ static int rbd_img_exclusive_lock(struct rbd_img_request *img_req)
34763477
if (rbd_lock_add_request(img_req))
34773478
return 1;
34783479

3479-
if (rbd_dev->opts->exclusive) {
3480-
WARN_ON(1); /* lock got released? */
3481-
return -EROFS;
3482-
}
3483-
34843480
/*
34853481
* Note the use of mod_delayed_work() in rbd_acquire_lock()
34863482
* and cancel_delayed_work() in wake_lock_waiters().
@@ -4601,6 +4597,10 @@ static void rbd_reacquire_lock(struct rbd_device *rbd_dev)
46014597
rbd_warn(rbd_dev, "failed to update lock cookie: %d",
46024598
ret);
46034599

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

0 commit comments

Comments
 (0)