Changeset View
Changeset View
Standalone View
Standalone View
sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_raidz.c
Show First 20 Lines • Show All 2,578 Lines • ▼ Show 20 Lines | if (faulted > vd->vdev_nparity) | ||||
vdev_set_state(vd, B_FALSE, VDEV_STATE_CANT_OPEN, | vdev_set_state(vd, B_FALSE, VDEV_STATE_CANT_OPEN, | ||||
VDEV_AUX_NO_REPLICAS); | VDEV_AUX_NO_REPLICAS); | ||||
else if (degraded + faulted != 0) | else if (degraded + faulted != 0) | ||||
vdev_set_state(vd, B_FALSE, VDEV_STATE_DEGRADED, VDEV_AUX_NONE); | vdev_set_state(vd, B_FALSE, VDEV_STATE_DEGRADED, VDEV_AUX_NONE); | ||||
else | else | ||||
vdev_set_state(vd, B_FALSE, VDEV_STATE_HEALTHY, VDEV_AUX_NONE); | vdev_set_state(vd, B_FALSE, VDEV_STATE_HEALTHY, VDEV_AUX_NONE); | ||||
} | } | ||||
/* | |||||
* Determine if any portion of the provided block resides on a child vdev | |||||
* with a dirty DTL and therefore needs to be resilvered. The function | |||||
* assumes that at least one DTL is dirty which imples that full stripe | |||||
* width blocks must be resilvered. | |||||
*/ | |||||
static boolean_t | |||||
vdev_raidz_need_resilver(vdev_t *vd, uint64_t offset, size_t psize) | |||||
{ | |||||
uint64_t dcols = vd->vdev_children; | |||||
uint64_t nparity = vd->vdev_nparity; | |||||
uint64_t ashift = vd->vdev_top->vdev_ashift; | |||||
/* The starting RAIDZ (parent) vdev sector of the block. */ | |||||
uint64_t b = offset >> ashift; | |||||
/* The zio's size in units of the vdev's minimum sector size. */ | |||||
uint64_t s = ((psize - 1) >> ashift) + 1; | |||||
/* The first column for this stripe. */ | |||||
uint64_t f = b % dcols; | |||||
if (s + nparity >= dcols) | |||||
return (B_TRUE); | |||||
for (uint64_t c = 0; c < s + nparity; c++) { | |||||
uint64_t devidx = (f + c) % dcols; | |||||
vdev_t *cvd = vd->vdev_child[devidx]; | |||||
/* | |||||
* dsl_scan_need_resilver() already checked vd with | |||||
* vdev_dtl_contains(). So here just check cvd with | |||||
* vdev_dtl_empty(), cheaper and a good approximation. | |||||
*/ | |||||
if (!vdev_dtl_empty(cvd, DTL_PARTIAL)) | |||||
return (B_TRUE); | |||||
} | |||||
return (B_FALSE); | |||||
} | |||||
vdev_ops_t vdev_raidz_ops = { | vdev_ops_t vdev_raidz_ops = { | ||||
vdev_raidz_open, | vdev_raidz_open, | ||||
vdev_raidz_close, | vdev_raidz_close, | ||||
vdev_raidz_asize, | vdev_raidz_asize, | ||||
vdev_raidz_io_start, | vdev_raidz_io_start, | ||||
vdev_raidz_io_done, | vdev_raidz_io_done, | ||||
vdev_raidz_state_change, | vdev_raidz_state_change, | ||||
vdev_raidz_need_resilver, | |||||
NULL, | NULL, | ||||
NULL, | NULL, | ||||
NULL, | NULL, | ||||
VDEV_TYPE_RAIDZ, /* name of this vdev type */ | VDEV_TYPE_RAIDZ, /* name of this vdev type */ | ||||
B_FALSE /* not a leaf vdev */ | B_FALSE /* not a leaf vdev */ | ||||
}; | }; |