aboutsummaryrefslogtreecommitdiffstats
path: root/module/zfs/zio.c
diff options
context:
space:
mode:
Diffstat (limited to 'module/zfs/zio.c')
-rw-r--r--module/zfs/zio.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/module/zfs/zio.c b/module/zfs/zio.c
index 5d7ed6d58..d888a584a 100644
--- a/module/zfs/zio.c
+++ b/module/zfs/zio.c
@@ -2778,7 +2778,7 @@ zio_write_gang_member_ready(zio_t *zio)
ASSERT3U(zio->io_prop.zp_copies, ==, gio->io_prop.zp_copies);
ASSERT3U(zio->io_prop.zp_copies, <=, BP_GET_NDVAS(zio->io_bp));
ASSERT3U(pio->io_prop.zp_copies, <=, BP_GET_NDVAS(pio->io_bp));
- ASSERT3U(BP_GET_NDVAS(zio->io_bp), <=, BP_GET_NDVAS(pio->io_bp));
+ VERIFY3U(BP_GET_NDVAS(zio->io_bp), <=, BP_GET_NDVAS(pio->io_bp));
mutex_enter(&pio->io_lock);
for (int d = 0; d < BP_GET_NDVAS(zio->io_bp); d++) {
@@ -2816,18 +2816,20 @@ zio_write_gang_block(zio_t *pio, metaslab_class_t *mc)
uint64_t resid = pio->io_size;
uint64_t lsize;
int copies = gio->io_prop.zp_copies;
- int gbh_copies;
zio_prop_t zp;
int error;
boolean_t has_data = !(pio->io_flags & ZIO_FLAG_NODATA);
/*
- * encrypted blocks need DVA[2] free so encrypted gang headers can't
- * have a third copy.
+ * If one copy was requested, store 2 copies of the GBH, so that we
+ * can still traverse all the data (e.g. to free or scrub) even if a
+ * block is damaged. Note that we can't store 3 copies of the GBH in
+ * all cases, e.g. with encryption, which uses DVA[2] for the IV+salt.
*/
- gbh_copies = MIN(copies + 1, spa_max_replication(spa));
- if (BP_IS_ENCRYPTED(bp) && gbh_copies >= SPA_DVAS_PER_BP)
- gbh_copies = SPA_DVAS_PER_BP - 1;
+ int gbh_copies = copies;
+ if (gbh_copies == 1) {
+ gbh_copies = MIN(2, spa_max_replication(spa));
+ }
int flags = METASLAB_HINTBP_FAVOR | METASLAB_GANG_HEADER;
if (pio->io_flags & ZIO_FLAG_IO_ALLOCATING) {