Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ba378b79 authored by Ilya Dryomov's avatar Ilya Dryomov Committed by Greg Kroah-Hartman
Browse files

rbd: always kick acquire on "acquired" and "released" notifications



commit 8798d070d416d18a75770fc19787e96705073f43 upstream.

Skipping the "lock has been released" notification if the lock owner
is not what we expect based on owner_cid can lead to I/O hangs.
One example is our own notifications: because owner_cid is cleared
in rbd_unlock(), when we get our own notification it is processed as
unexpected/duplicate and maybe_kick_acquire() isn't called.  If a peer
that requested the lock then doesn't go through with acquiring it,
I/O requests that came in while the lock was being quiesced would
be stalled until another I/O request is submitted and kicks acquire
from rbd_img_exclusive_lock().

This makes the comment in rbd_release_lock() actually true: prior to
this change the canceled work was being requeued in response to the
"lock has been acquired" notification from rbd_handle_acquired_lock().

Cc: stable@vger.kernel.org # 5.3+
Signed-off-by: default avatarIlya Dryomov <idryomov@gmail.com>
Tested-by: default avatarRobin Geuze <robin.geuze@nl.team.blue>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 13066d66
Loading
Loading
Loading
Loading
+7 −13
Original line number Diff line number Diff line
@@ -4340,15 +4340,11 @@ static void rbd_handle_acquired_lock(struct rbd_device *rbd_dev, u8 struct_v,
	if (!rbd_cid_equal(&cid, &rbd_empty_cid)) {
		down_write(&rbd_dev->lock_rwsem);
		if (rbd_cid_equal(&cid, &rbd_dev->owner_cid)) {
			/*
			 * we already know that the remote client is
			 * the owner
			 */
			up_write(&rbd_dev->lock_rwsem);
			return;
		}

			dout("%s rbd_dev %p cid %llu-%llu == owner_cid\n",
			     __func__, rbd_dev, cid.gid, cid.handle);
		} else {
			rbd_set_owner_cid(rbd_dev, &cid);
		}
		downgrade_write(&rbd_dev->lock_rwsem);
	} else {
		down_read(&rbd_dev->lock_rwsem);
@@ -4373,14 +4369,12 @@ static void rbd_handle_released_lock(struct rbd_device *rbd_dev, u8 struct_v,
	if (!rbd_cid_equal(&cid, &rbd_empty_cid)) {
		down_write(&rbd_dev->lock_rwsem);
		if (!rbd_cid_equal(&cid, &rbd_dev->owner_cid)) {
			dout("%s rbd_dev %p unexpected owner, cid %llu-%llu != owner_cid %llu-%llu\n",
			dout("%s rbd_dev %p cid %llu-%llu != owner_cid %llu-%llu\n",
			     __func__, rbd_dev, cid.gid, cid.handle,
			     rbd_dev->owner_cid.gid, rbd_dev->owner_cid.handle);
			up_write(&rbd_dev->lock_rwsem);
			return;
		}

		} else {
			rbd_set_owner_cid(rbd_dev, &rbd_empty_cid);
		}
		downgrade_write(&rbd_dev->lock_rwsem);
	} else {
		down_read(&rbd_dev->lock_rwsem);