mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-12-26 03:09:34 +03:00
Fix vdev_open_child() race on updating vdev_parent->vdev_nonrot
Updating vd->vdev_parent->vdev_nonrot in vdev_open_child() is a race when vdev_open_child is called for many children from a task queue. vdev_open_child() is only called by vdev_open_children(), let the latter update the parent vdev_nonrot member. The update was already there, so done twice previously. Thus using the same logic at the end in vdev_open_children() to update vdev_nonrot, either we are vdev_uses_zvols() or not. Reviewed-by: Richard Elling <Richard.Elling@RichardElling.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Haakan T Johansson <f96hajo@chalmers.se> Closes #5162
This commit is contained in:
parent
ccc92611b1
commit
4770aa0643
@ -1124,7 +1124,6 @@ vdev_open_child(void *arg)
|
|||||||
vd->vdev_open_thread = curthread;
|
vd->vdev_open_thread = curthread;
|
||||||
vd->vdev_open_error = vdev_open(vd);
|
vd->vdev_open_error = vdev_open(vd);
|
||||||
vd->vdev_open_thread = NULL;
|
vd->vdev_open_thread = NULL;
|
||||||
vd->vdev_parent->vdev_nonrot &= vd->vdev_nonrot;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean_t
|
static boolean_t
|
||||||
@ -1151,29 +1150,27 @@ vdev_open_children(vdev_t *vd)
|
|||||||
int children = vd->vdev_children;
|
int children = vd->vdev_children;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
vd->vdev_nonrot = B_TRUE;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* in order to handle pools on top of zvols, do the opens
|
* in order to handle pools on top of zvols, do the opens
|
||||||
* in a single thread so that the same thread holds the
|
* in a single thread so that the same thread holds the
|
||||||
* spa_namespace_lock
|
* spa_namespace_lock
|
||||||
*/
|
*/
|
||||||
if (vdev_uses_zvols(vd)) {
|
if (vdev_uses_zvols(vd)) {
|
||||||
for (c = 0; c < children; c++) {
|
for (c = 0; c < children; c++)
|
||||||
vd->vdev_child[c]->vdev_open_error =
|
vd->vdev_child[c]->vdev_open_error =
|
||||||
vdev_open(vd->vdev_child[c]);
|
vdev_open(vd->vdev_child[c]);
|
||||||
vd->vdev_nonrot &= vd->vdev_child[c]->vdev_nonrot;
|
} else {
|
||||||
}
|
tq = taskq_create("vdev_open", children, minclsyspri,
|
||||||
return;
|
children, children, TASKQ_PREPOPULATE);
|
||||||
|
|
||||||
|
for (c = 0; c < children; c++)
|
||||||
|
VERIFY(taskq_dispatch(tq, vdev_open_child,
|
||||||
|
vd->vdev_child[c], TQ_SLEEP) != 0);
|
||||||
|
|
||||||
|
taskq_destroy(tq);
|
||||||
}
|
}
|
||||||
tq = taskq_create("vdev_open", children, minclsyspri,
|
|
||||||
children, children, TASKQ_PREPOPULATE);
|
|
||||||
|
|
||||||
for (c = 0; c < children; c++)
|
vd->vdev_nonrot = B_TRUE;
|
||||||
VERIFY(taskq_dispatch(tq, vdev_open_child, vd->vdev_child[c],
|
|
||||||
TQ_SLEEP) != 0);
|
|
||||||
|
|
||||||
taskq_destroy(tq);
|
|
||||||
|
|
||||||
for (c = 0; c < children; c++)
|
for (c = 0; c < children; c++)
|
||||||
vd->vdev_nonrot &= vd->vdev_child[c]->vdev_nonrot;
|
vd->vdev_nonrot &= vd->vdev_child[c]->vdev_nonrot;
|
||||||
|
Loading…
Reference in New Issue
Block a user