diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-05-21 14:17:28 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-05-21 14:17:28 -0700 |
| commit | 6d3b2673e1fd553395933b6f2bc88c9e9d2a2bc5 (patch) | |
| tree | f5bfe0752de92f43bc01f17f3b9581a90d5a7583 | |
| parent | 7acfa2c5f4366d63653380646ffa7dbd1bfaccc0 (diff) | |
| parent | 9fc75b71fdd38465c76c6f6a884cdd4ae3c72d90 (diff) | |
| download | linux-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.c | 20 |
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); } /* |
