]> git.proxmox.com Git - mirror_zfs.git/blobdiff - module/zfs/zio.c
EIO caused by encryption + recursive gang
[mirror_zfs.git] / module / zfs / zio.c
index 5d7ed6d582a21a36ce5a8b33ed0e7446c38a0ee3..d888a584a93cab9320918a180eee936b69c37c70 100644 (file)
@@ -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) {