diff options
Diffstat (limited to 'sys/contrib/openzfs/module/zfs/vdev_raidz.c')
| -rw-r--r-- | sys/contrib/openzfs/module/zfs/vdev_raidz.c | 55 |
1 files changed, 45 insertions, 10 deletions
diff --git a/sys/contrib/openzfs/module/zfs/vdev_raidz.c b/sys/contrib/openzfs/module/zfs/vdev_raidz.c index 2db7422e772e..ab9f62c3c2d0 100644 --- a/sys/contrib/openzfs/module/zfs/vdev_raidz.c +++ b/sys/contrib/openzfs/module/zfs/vdev_raidz.c @@ -419,7 +419,16 @@ static int zfs_scrub_partial_writes = 1; static void vdev_raidz_row_free(raidz_row_t *rr) { - for (int c = 0; c < rr->rr_cols; c++) { + abd_t *dabd = rr->rr_col[rr->rr_firstdatacol].rc_abd; + for (int c = 0; c < rr->rr_firstdatacol; c++) { + raidz_col_t *rc = &rr->rr_col[c]; + + if (rc->rc_size != 0 && rc->rc_abd != dabd) + abd_free(rc->rc_abd); + if (rc->rc_orig_data != NULL) + abd_free(rc->rc_orig_data); + } + for (int c = rr->rr_firstdatacol; c < rr->rr_cols; c++) { raidz_col_t *rc = &rr->rr_col[c]; if (rc->rc_size != 0) @@ -532,6 +541,22 @@ vdev_raidz_map_alloc_write(zio_t *zio, raidz_map_t *rm, uint64_t ashift) */ int skipped = rr->rr_scols - rr->rr_cols; + /* + * When there is only a single data column the parity is a copy of + * it, so point all parity columns at the data ABD directly to avoid + * allocating buffers and computing parity. + */ + if (rr->rr_cols == rr->rr_firstdatacol + 1) { + ASSERT0(nwrapped); + ASSERT0(rm->rm_nskip); + raidz_col_t *dc = &rr->rr_col[rr->rr_firstdatacol]; + dc->rc_abd = abd_get_offset_struct(&dc->rc_abdstruct, + zio->io_abd, 0, dc->rc_size); + for (c = 0; c < rr->rr_firstdatacol; c++) + rr->rr_col[c].rc_abd = dc->rc_abd; + return; + } + /* Allocate buffers for the parity columns */ for (c = 0; c < rr->rr_firstdatacol; c++) { raidz_col_t *rc = &rr->rr_col[c]; @@ -546,12 +571,13 @@ vdev_raidz_map_alloc_write(zio_t *zio, raidz_map_t *rm, uint64_t ashift) * VDEV queue locks (vq_lock). */ if (c < nwrapped) { - rc->rc_abd = abd_alloc_linear( + rc->rc_abd = abd_alloc_linear_struct(&rc->rc_abdstruct, rc->rc_size + (1ULL << ashift), B_FALSE); abd_zero_off(rc->rc_abd, rc->rc_size, 1ULL << ashift); skipped++; } else { - rc->rc_abd = abd_alloc_linear(rc->rc_size, B_FALSE); + rc->rc_abd = abd_alloc_linear_struct(&rc->rc_abdstruct, + rc->rc_size, B_FALSE); } } @@ -599,9 +625,11 @@ vdev_raidz_map_alloc_read(zio_t *zio, raidz_map_t *rm) ASSERT3U(rm->rm_nrows, ==, 1); /* Allocate buffers for the parity columns */ - for (c = 0; c < rr->rr_firstdatacol; c++) - rr->rr_col[c].rc_abd = - abd_alloc_linear(rr->rr_col[c].rc_size, B_FALSE); + for (c = 0; c < rr->rr_firstdatacol; c++) { + raidz_col_t *rc = &rr->rr_col[c]; + rc->rc_abd = abd_alloc_linear_struct(&rc->rc_abdstruct, + rc->rc_size, B_FALSE); + } for (uint64_t off = 0; c < rr->rr_cols; c++) { raidz_col_t *rc = &rr->rr_col[c]; @@ -1046,8 +1074,8 @@ vdev_raidz_map_alloc_expanded(zio_t *zio, continue; prc->rc_abd = - abd_alloc_linear(rm->rm_phys_col[i].rc_size, - B_FALSE); + abd_alloc_linear_struct(&prc->rc_abdstruct, + prc->rc_size, B_FALSE); } /* @@ -1075,8 +1103,8 @@ vdev_raidz_map_alloc_expanded(zio_t *zio, for (int c = 0; c < rr->rr_firstdatacol; c++) { raidz_col_t *rc = &rr->rr_col[c]; rc->rc_abd = - abd_alloc_linear(rc->rc_size, - B_TRUE); + abd_alloc_linear_struct(&rc->rc_abdstruct, + rc->rc_size, B_TRUE); } } } @@ -1272,6 +1300,13 @@ vdev_raidz_generate_parity_row(raidz_map_t *rm, raidz_row_t *rr) return; } + /* + * Single data column: parity is the data itself. + */ + if (rr->rr_col[VDEV_RAIDZ_P].rc_abd == + rr->rr_col[rr->rr_firstdatacol].rc_abd) + return; + /* Generate using the new math implementation */ if (vdev_raidz_math_generate(rm, rr) != RAIDZ_ORIGINAL_IMPL) return; |
