* Iterate over all combinations of N bad vdevs and attempt a reconstruction. * Note that the algorithm below is non-optimal because it doesn't take into * account how reconstruction is actually performed. For example, with * triple-parity RAID-Z the reconstruction procedure is the same if column 4 * is targeted as invalid as if columns 1 and 4 are targeted since in both * cases we'd only use
| 2201 | * a future improvement. |
| 2202 | */ |
| 2203 | static int |
| 2204 | vdev_raidz_combrec(zio_t *zio) |
| 2205 | { |
| 2206 | int nparity = vdev_get_nparity(zio->io_vd); |
| 2207 | raidz_map_t *rm = zio->io_vsd; |
| 2208 | |
| 2209 | /* Check if there's enough data to attempt reconstrution. */ |
| 2210 | for (int i = 0; i < rm->rm_nrows; i++) { |
| 2211 | raidz_row_t *rr = rm->rm_row[i]; |
| 2212 | int total_errors = 0; |
| 2213 | |
| 2214 | for (int c = 0; c < rr->rr_cols; c++) { |
| 2215 | if (rr->rr_col[c].rc_error) |
| 2216 | total_errors++; |
| 2217 | } |
| 2218 | |
| 2219 | if (total_errors > nparity) |
| 2220 | return (vdev_raidz_worst_error(rr)); |
| 2221 | } |
| 2222 | |
| 2223 | for (int num_failures = 1; num_failures <= nparity; num_failures++) { |
| 2224 | int tstore[VDEV_RAIDZ_MAXPARITY + 2]; |
| 2225 | int *ltgts = &tstore[1]; /* value is logical child ID */ |
| 2226 | |
| 2227 | /* Determine number of logical children, n */ |
| 2228 | int n = zio->io_vd->vdev_children; |
| 2229 | |
| 2230 | ASSERT3U(num_failures, <=, nparity); |
| 2231 | ASSERT3U(num_failures, <=, VDEV_RAIDZ_MAXPARITY); |
| 2232 | |
| 2233 | /* Handle corner cases in combrec logic */ |
| 2234 | ltgts[-1] = -1; |
| 2235 | for (int i = 0; i < num_failures; i++) { |
| 2236 | ltgts[i] = i; |
| 2237 | } |
| 2238 | ltgts[num_failures] = n; |
| 2239 | |
| 2240 | for (;;) { |
| 2241 | int err = raidz_reconstruct(zio, ltgts, num_failures, |
| 2242 | nparity); |
| 2243 | if (err == EINVAL) { |
| 2244 | /* |
| 2245 | * Reconstruction not possible with this # |
| 2246 | * failures; try more failures. |
| 2247 | */ |
| 2248 | break; |
| 2249 | } else if (err == 0) |
| 2250 | return (0); |
| 2251 | |
| 2252 | /* Compute next targets to try */ |
| 2253 | for (int t = 0; ; t++) { |
| 2254 | ASSERT3U(t, <, num_failures); |
| 2255 | ltgts[t]++; |
| 2256 | if (ltgts[t] == n) { |
| 2257 | /* try more failures */ |
| 2258 | ASSERT3U(t, ==, num_failures - 1); |
| 2259 | break; |
| 2260 | } |
no test coverage detected