* Divides the IO evenly across all child vdevs; usually, dcols is * the number of children in the target vdev. * * Avoid inlining the function to keep vdev_raidz_io_start(), which * is this functions only caller, as small as possible on the stack. */
| 366 | * is this functions only caller, as small as possible on the stack. |
| 367 | */ |
| 368 | noinline raidz_map_t * |
| 369 | vdev_raidz_map_alloc(zio_t *zio, uint64_t ashift, uint64_t dcols, |
| 370 | uint64_t nparity) |
| 371 | { |
| 372 | raidz_row_t *rr; |
| 373 | /* The starting RAIDZ (parent) vdev sector of the block. */ |
| 374 | uint64_t b = zio->io_offset >> ashift; |
| 375 | /* The zio's size in units of the vdev's minimum sector size. */ |
| 376 | uint64_t s = zio->io_size >> ashift; |
| 377 | /* The first column for this stripe. */ |
| 378 | uint64_t f = b % dcols; |
| 379 | /* The starting byte offset on each child vdev. */ |
| 380 | uint64_t o = (b / dcols) << ashift; |
| 381 | uint64_t q, r, c, bc, col, acols, scols, coff, devidx, asize, tot; |
| 382 | uint64_t off = 0; |
| 383 | |
| 384 | raidz_map_t *rm = |
| 385 | kmem_zalloc(offsetof(raidz_map_t, rm_row[1]), KM_SLEEP); |
| 386 | rm->rm_nrows = 1; |
| 387 | |
| 388 | /* |
| 389 | * "Quotient": The number of data sectors for this stripe on all but |
| 390 | * the "big column" child vdevs that also contain "remainder" data. |
| 391 | */ |
| 392 | q = s / (dcols - nparity); |
| 393 | |
| 394 | /* |
| 395 | * "Remainder": The number of partial stripe data sectors in this I/O. |
| 396 | * This will add a sector to some, but not all, child vdevs. |
| 397 | */ |
| 398 | r = s - q * (dcols - nparity); |
| 399 | |
| 400 | /* The number of "big columns" - those which contain remainder data. */ |
| 401 | bc = (r == 0 ? 0 : r + nparity); |
| 402 | |
| 403 | /* |
| 404 | * The total number of data and parity sectors associated with |
| 405 | * this I/O. |
| 406 | */ |
| 407 | tot = s + nparity * (q + (r == 0 ? 0 : 1)); |
| 408 | |
| 409 | /* |
| 410 | * acols: The columns that will be accessed. |
| 411 | * scols: The columns that will be accessed or skipped. |
| 412 | */ |
| 413 | if (q == 0) { |
| 414 | /* Our I/O request doesn't span all child vdevs. */ |
| 415 | acols = bc; |
| 416 | scols = MIN(dcols, roundup(bc, nparity + 1)); |
| 417 | } else { |
| 418 | acols = dcols; |
| 419 | scols = dcols; |
| 420 | } |
| 421 | |
| 422 | ASSERT3U(acols, <=, scols); |
| 423 | |
| 424 | rr = kmem_alloc(offsetof(raidz_row_t, rr_col[scols]), KM_SLEEP); |
| 425 | rm->rm_row[0] = rr; |