aboutsummaryrefslogtreecommitdiff
path: root/sys/contrib/openzfs/module/zfs/vdev_raidz.c
diff options
context:
space:
mode:
authorMartin Matuska <mm@FreeBSD.org>2026-06-27 06:15:42 +0000
committerMartin Matuska <mm@FreeBSD.org>2026-06-27 08:51:33 +0000
commitd0b3ecdc274930e190ea233b6b69ff03782eaf8d (patch)
tree8f7bc49621e339a1a9baa14a3221e2d90c7a0c5d /sys/contrib/openzfs/module/zfs/vdev_raidz.c
parent8e61d8707f8a10acc143210089fea2502a3f2922 (diff)
parent37af899488652c55c456d3f160fb8b295db2ec70 (diff)
zfs: merge openzfs/zfs@37af89948
Notable upstream pull request merges: #18509 f16b3744d zstream: refactor common functions #18573 -multiple Persist z_seq across znode eviction s18611 eb0c674c2 zfs_ioctl: fix EBUSY race between quota queries and mount #18637 77e64d86e Fix self-deadlock when setting the "allocating"/"path" vdev property #18645 e3082b923 freebsd: set mnt_time on the rootfs at mountroot time #18652 50d012b2a zbookmark_compare: handle "marker" bookmarks with negative levels #18664 520eeeaa6 Improve performance of "zpool offline" for log devices #18668 6b8f79877 Avoid more abd_t allocations in RAIDZ/dRAID #18669 99ab859c3 Optimize metaslab_set_selected_txg() #18673 97b9ba7a9 delegate: add 'send:encrypted' permission #18687 2ea519c2a Avoid lookup overhead for nonexistent xattr directories #18688 87593ea2b Fix handling of _PC_HAS_HIDDENSYSTEM for FreeBSD #18693 0483a8e0c Clean up embedded slog metaslab across txgs #18695 41311c665 RAIDZ: Optimize single data column writes #18706 37af89948 ddt_log: Fix refcount tagging for begin/commit Obtained from: OpenZFS OpenZFS commit: 37af899488652c55c456d3f160fb8b295db2ec70
Diffstat (limited to 'sys/contrib/openzfs/module/zfs/vdev_raidz.c')
-rw-r--r--sys/contrib/openzfs/module/zfs/vdev_raidz.c55
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;