forked from Minki/linux
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 <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
This commit is contained in:
parent
03d63e1d1e
commit
615e087fbd
@ -1096,22 +1096,30 @@ static void drbd_flush(struct drbd_tconn *tconn)
|
|||||||
int vnr;
|
int vnr;
|
||||||
|
|
||||||
if (tconn->write_ordering >= WO_bdev_flush) {
|
if (tconn->write_ordering >= WO_bdev_flush) {
|
||||||
|
rcu_read_lock();
|
||||||
idr_for_each_entry(&tconn->volumes, mdev, vnr) {
|
idr_for_each_entry(&tconn->volumes, mdev, vnr) {
|
||||||
if (get_ldev(mdev)) {
|
if (!get_ldev(mdev))
|
||||||
rv = blkdev_issue_flush(mdev->ldev->backing_bdev, GFP_KERNEL,
|
continue;
|
||||||
NULL);
|
kref_get(&mdev->kref);
|
||||||
put_ldev(mdev);
|
rcu_read_unlock();
|
||||||
|
|
||||||
if (rv) {
|
rv = blkdev_issue_flush(mdev->ldev->backing_bdev,
|
||||||
dev_info(DEV, "local disk flush failed with status %d\n", rv);
|
GFP_NOIO, NULL);
|
||||||
/* would rather check on EOPNOTSUPP, but that is not reliable.
|
if (rv) {
|
||||||
* don't try again for ANY return value != 0
|
dev_info(DEV, "local disk flush failed with status %d\n", rv);
|
||||||
* if (rv == -EOPNOTSUPP) */
|
/* would rather check on EOPNOTSUPP, but that is not reliable.
|
||||||
drbd_bump_write_ordering(tconn, WO_drain_io);
|
* don't try again for ANY return value != 0
|
||||||
break;
|
* 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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user