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.
 -----BEGIN PGP SIGNATURE-----
 
 iQFHBAABCgAxFiEEydHwtzie9C7TfviiSn/eOAIR84sFAmoPOcUTHGlkcnlvbW92
 QGdtYWlsLmNvbQAKCRBKf944AhHzi6yvB/9+hm+IHQK1gib4gCHOPgq9cD1gj7j8
 oegjSmO0tIn3nP1K6wqQfTFnYkE6F37+dRqZTXOUjzi3NlefNJDnxwt9fymp2Y6S
 DEobTnRgXSKMxJQ4+cu7jphgbJC/OKYZ+fxJRrKI4hlgZOfQwpvUfQczZZgjWJRz
 WqJnSKLoF2k6JDgvokcmt1nyyQ7TrpPRB+6Jz2ATRtG0oxEzp1EN++FtiaRzn1mx
 e0WgCBZV/AEFey2YG+Zyhrrg+1nUDWrZI3NgIZz5Q5WU4q/8zF7S9qbNeBQVdzKJ
 aZFLxOdQvuRGbLs+g8f6dOMMlDSLnKl2rN2AAzcfwXcmmSQILqLH+ycp
 =+cb7
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Linus Torvalds 2026-05-21 14:17:28 -07:00
commit 6d3b2673e1

View File

@ -4565,24 +4565,12 @@ static int rbd_register_watch(struct rbd_device *rbd_dev)
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 @@ static int rbd_add_parse_args(const char *buf,
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);
}
/*