summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-05-21 14:17:28 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-05-21 14:17:28 -0700
commit6d3b2673e1fd553395933b6f2bc88c9e9d2a2bc5 (patch)
treef5bfe0752de92f43bc01f17f3b9581a90d5a7583
parent7acfa2c5f4366d63653380646ffa7dbd1bfaccc0 (diff)
parent9fc75b71fdd38465c76c6f6a884cdd4ae3c72d90 (diff)
downloadlinux-stable-6d3b2673e1fd553395933b6f2bc88c9e9d2a2bc5.tar.gz
linux-stable-6d3b2673e1fd553395933b6f2bc88c9e9d2a2bc5.zip
Merge tag 'ceph-for-7.1-rc5' of https://github.com/ceph/ceph-client
Pull ceph fix from Ilya Dryomov: "A fix for an 'rbd unmap' race condition which popped up on a production setup where many RBD devices are frequently mapped and unmapped, marked for stable" * tag 'ceph-for-7.1-rc5' of https://github.com/ceph/ceph-client: rbd: eliminate a race in lock_dwork draining on unmap
-rw-r--r--drivers/block/rbd.c20
1 files changed, 8 insertions, 12 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 4065336ebd1f..6c1e7347e6a7 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -4565,24 +4565,12 @@ out:
return ret;
}
-static void cancel_tasks_sync(struct rbd_device *rbd_dev)
-{
- dout("%s rbd_dev %p\n", __func__, rbd_dev);
-
- cancel_work_sync(&rbd_dev->acquired_lock_work);
- cancel_work_sync(&rbd_dev->released_lock_work);
- cancel_delayed_work_sync(&rbd_dev->lock_dwork);
- cancel_work_sync(&rbd_dev->unlock_work);
-}
-
/*
* header_rwsem must not be held to avoid a deadlock with
* rbd_dev_refresh() when flushing notifies.
*/
static void rbd_unregister_watch(struct rbd_device *rbd_dev)
{
- cancel_tasks_sync(rbd_dev);
-
mutex_lock(&rbd_dev->watch_mutex);
if (rbd_dev->watch_state == RBD_WATCH_STATE_REGISTERED)
__rbd_unregister_watch(rbd_dev);
@@ -6548,10 +6536,18 @@ out_err:
static void rbd_dev_image_unlock(struct rbd_device *rbd_dev)
{
+ dout("%s rbd_dev %p\n", __func__, rbd_dev);
+
+ disable_delayed_work_sync(&rbd_dev->lock_dwork);
+ disable_work_sync(&rbd_dev->unlock_work);
+
down_write(&rbd_dev->lock_rwsem);
if (__rbd_is_lock_owner(rbd_dev))
__rbd_release_lock(rbd_dev);
up_write(&rbd_dev->lock_rwsem);
+
+ flush_work(&rbd_dev->acquired_lock_work);
+ flush_work(&rbd_dev->released_lock_work);
}
/*