summaryrefslogtreecommitdiffstats
path: root/drivers/block/drbd/drbd_worker.c
diff options
context:
space:
mode:
authorPhilipp Reisner <philipp.reisner@linbit.com>2011-04-13 14:46:05 -0700
committerPhilipp Reisner <philipp.reisner@linbit.com>2012-11-08 16:45:17 +0100
commitd3fcb4908d8cce7f29cff16bbef3b08933148003 (patch)
treefc457ab337f19aa265a3b5cc4d5bcacc5b664315 /drivers/block/drbd/drbd_worker.c
parentef356262846eb49821db7b20a131b6573e4c7d2e (diff)
downloadlinux-d3fcb4908d8cce7f29cff16bbef3b08933148003.tar.gz
linux-d3fcb4908d8cce7f29cff16bbef3b08933148003.tar.bz2
linux-d3fcb4908d8cce7f29cff16bbef3b08933148003.zip
drbd: protect all idr accesses that might sleep with drbd_cfg_rwsem
With this commit the locking for all accesses to IDRs is complete: * Non sleeping read accesses are protected by RCU * sleeping read accesses are protocted by a read lock on drbd_cfg_rwsem * accesses that add anything are protected by a write lock * accesses that remove an object are protoected by a write lock and a call to synchronize_rcu() after it is removed from the IDR and before the object is actually free()ed. Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block/drbd/drbd_worker.c')
-rw-r--r--drivers/block/drbd/drbd_worker.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c
index 410900eb2fff..02cdff2b0814 100644
--- a/drivers/block/drbd/drbd_worker.c
+++ b/drivers/block/drbd/drbd_worker.c
@@ -1731,12 +1731,14 @@ int drbd_worker(struct drbd_thread *thi)
spin_unlock_irq(&tconn->data.work.q_lock);
drbd_thread_stop(&tconn->receiver);
+ down_read(&drbd_cfg_rwsem);
idr_for_each_entry(&tconn->volumes, mdev, vnr) {
D_ASSERT(mdev->state.disk == D_DISKLESS && mdev->state.conn == C_STANDALONE);
/* _drbd_set_state only uses stop_nowait.
* wait here for the exiting receiver. */
drbd_mdev_cleanup(mdev);
}
+ up_read(&drbd_cfg_rwsem);
clear_bit(OBJECT_DYING, &tconn->flags);
clear_bit(CONFIG_PENDING, &tconn->flags);
wake_up(&tconn->ping_wait);