From 615e087fbd7483fafa28c8a1a4d1656251e0604d Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Thu, 17 Nov 2011 14:32:12 +0100 Subject: [PATCH] drbd: add missing rcu locks around recently introduced idr_for_each Recent commit drbd: Move write_ordering from mdev to tconn introduced a new idr_for_each loop over all volumes, but did not take necessary rcu locks or krefs. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_receiver.c | 32 +++++++++++++++++++----------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index be8f469bc8f0..9c888e5b648f 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -1096,22 +1096,30 @@ static void drbd_flush(struct drbd_tconn *tconn) int vnr; if (tconn->write_ordering >= WO_bdev_flush) { + rcu_read_lock(); idr_for_each_entry(&tconn->volumes, mdev, vnr) { - if (get_ldev(mdev)) { - rv = blkdev_issue_flush(mdev->ldev->backing_bdev, GFP_KERNEL, - NULL); - put_ldev(mdev); + if (!get_ldev(mdev)) + continue; + kref_get(&mdev->kref); + rcu_read_unlock(); - if (rv) { - dev_info(DEV, "local disk flush failed with status %d\n", rv); - /* would rather check on EOPNOTSUPP, but that is not reliable. - * don't try again for ANY return value != 0 - * if (rv == -EOPNOTSUPP) */ - drbd_bump_write_ordering(tconn, WO_drain_io); - break; - } + rv = blkdev_issue_flush(mdev->ldev->backing_bdev, + GFP_NOIO, NULL); + if (rv) { + dev_info(DEV, "local disk flush failed with status %d\n", rv); + /* would rather check on EOPNOTSUPP, but that is not reliable. + * don't try again for ANY return value != 0 + * if (rv == -EOPNOTSUPP) */ + drbd_bump_write_ordering(tconn, WO_drain_io); } + put_ldev(mdev); + kref_put(&mdev->kref, &drbd_minor_destroy); + + rcu_read_lock(); + if (rv) + break; } + rcu_read_unlock(); } } -- 2.34.1