usr/src/uts/common/fs/zfs/vdev_raidz.c
author gw25295
Mon, 29 Oct 2007 17:24:59 -0700
changeset 5369 27c1235ef9a4
parent 5329 33cb98223b2d
child 5530 4ed96167d864
permissions -rw-r--r--
6621355 panic in vdev_disk_io_start when trying to write to a faulted device 6622732 Assertion failed: !(zio->io_flags & ZIO_FLAG_WRITE_RETRY), file ../../../uts/com mon/fs/zfs/zio.c 6623221 CIFS breaks ZFS root
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     1
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     2
 * CDDL HEADER START
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     3
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
     5
 * Common Development and Distribution License (the "License").
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
     6
 * You may not use this file except in compliance with the License.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     7
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     8
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     9
 * or http://www.opensolaris.org/os/licensing.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    10
 * See the License for the specific language governing permissions
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    11
 * and limitations under the License.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    12
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    13
 * When distributing Covered Code, include this CDDL HEADER in each
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    14
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    15
 * If applicable, add the following below this CDDL HEADER, with the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    16
 * fields enclosed by brackets "[]" replaced with your own identifying
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    17
 * information: Portions Copyright [yyyy] [name of copyright owner]
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    18
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    19
 * CDDL HEADER END
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    20
 */
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    21
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    22
/*
3456
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
    23
 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    24
 * Use is subject to license terms.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    25
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    26
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    27
#pragma ident	"%Z%%M%	%I%	%E% SMI"
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    28
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    29
#include <sys/zfs_context.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    30
#include <sys/spa.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    31
#include <sys/vdev_impl.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    32
#include <sys/zio.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    33
#include <sys/zio_checksum.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    34
#include <sys/fs/zfs.h>
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
    35
#include <sys/fm/fs/zfs.h>
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    36
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    37
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    38
 * Virtual device vector for RAID-Z.
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    39
 *
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    40
 * This vdev supports both single and double parity. For single parity, we
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    41
 * use a simple XOR of all the data columns. For double parity, we use both
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    42
 * the simple XOR as well as a technique described in "The mathematics of
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    43
 * RAID-6" by H. Peter Anvin. This technique defines a Galois field, GF(2^8),
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    44
 * over the integers expressable in a single byte. Briefly, the operations on
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    45
 * the field are defined as follows:
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    46
 *
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    47
 *   o addition (+) is represented by a bitwise XOR
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    48
 *   o subtraction (-) is therefore identical to addition: A + B = A - B
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    49
 *   o multiplication of A by 2 is defined by the following bitwise expression:
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    50
 *	(A * 2)_7 = A_6
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    51
 *	(A * 2)_6 = A_5
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    52
 *	(A * 2)_5 = A_4
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    53
 *	(A * 2)_4 = A_3 + A_7
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    54
 *	(A * 2)_3 = A_2 + A_7
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    55
 *	(A * 2)_2 = A_1 + A_7
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    56
 *	(A * 2)_1 = A_0
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    57
 *	(A * 2)_0 = A_7
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    58
 *
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    59
 * In C, multiplying by 2 is therefore ((a << 1) ^ ((a & 0x80) ? 0x1d : 0)).
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    60
 *
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    61
 * Observe that any number in the field (except for 0) can be expressed as a
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    62
 * power of 2 -- a generator for the field. We store a table of the powers of
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    63
 * 2 and logs base 2 for quick look ups, and exploit the fact that A * B can
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    64
 * be rewritten as 2^(log_2(A) + log_2(B)) (where '+' is normal addition rather
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    65
 * than field addition). The inverse of a field element A (A^-1) is A^254.
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    66
 *
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    67
 * The two parity columns, P and Q, over several data columns, D_0, ... D_n-1,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    68
 * can be expressed by field operations:
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    69
 *
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    70
 *	P = D_0 + D_1 + ... + D_n-2 + D_n-1
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    71
 *	Q = 2^n-1 * D_0 + 2^n-2 * D_1 + ... + 2^1 * D_n-2 + 2^0 * D_n-1
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    72
 *	  = ((...((D_0) * 2 + D_1) * 2 + ...) * 2 + D_n-2) * 2 + D_n-1
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    73
 *
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    74
 * See the reconstruction code below for how P and Q can used individually or
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    75
 * in concert to recover missing data columns.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    76
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    77
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    78
typedef struct raidz_col {
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    79
	uint64_t rc_devidx;		/* child device index for I/O */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    80
	uint64_t rc_offset;		/* device offset */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    81
	uint64_t rc_size;		/* I/O size */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    82
	void *rc_data;			/* I/O data */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    83
	int rc_error;			/* I/O error for this device */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    84
	uint8_t rc_tried;		/* Did we attempt this I/O column? */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    85
	uint8_t rc_skipped;		/* Did we skip this I/O column? */
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    86
} raidz_col_t;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    87
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    88
typedef struct raidz_map {
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    89
	uint64_t rm_cols;		/* Column count */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    90
	uint64_t rm_bigcols;		/* Number of oversized columns */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    91
	uint64_t rm_asize;		/* Actual total I/O size */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    92
	uint64_t rm_missingdata;	/* Count of missing data devices */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    93
	uint64_t rm_missingparity;	/* Count of missing parity devices */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    94
	uint64_t rm_firstdatacol;	/* First data column/parity count */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    95
	raidz_col_t rm_col[1];		/* Flexible array of I/O columns */
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    96
} raidz_map_t;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    97
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    98
#define	VDEV_RAIDZ_P		0
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
    99
#define	VDEV_RAIDZ_Q		1
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   100
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   101
#define	VDEV_RAIDZ_MAXPARITY	2
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   102
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   103
#define	VDEV_RAIDZ_MUL_2(a)	(((a) << 1) ^ (((a) & 0x80) ? 0x1d : 0))
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   104
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   105
/*
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   106
 * These two tables represent powers and logs of 2 in the Galois field defined
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   107
 * above. These values were computed by repeatedly multiplying by 2 as above.
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   108
 */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   109
static const uint8_t vdev_raidz_pow2[256] = {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   110
	0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   111
	0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   112
	0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   113
	0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   114
	0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   115
	0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   116
	0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   117
	0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   118
	0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   119
	0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   120
	0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   121
	0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   122
	0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   123
	0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   124
	0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   125
	0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   126
	0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   127
	0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   128
	0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   129
	0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   130
	0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   131
	0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   132
	0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   133
	0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   134
	0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   135
	0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   136
	0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   137
	0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   138
	0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   139
	0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   140
	0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   141
	0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x01
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   142
};
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   143
static const uint8_t vdev_raidz_log2[256] = {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   144
	0x00, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   145
	0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   146
	0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   147
	0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   148
	0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   149
	0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   150
	0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   151
	0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   152
	0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   153
	0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   154
	0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   155
	0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   156
	0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   157
	0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   158
	0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   159
	0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   160
	0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   161
	0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   162
	0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   163
	0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   164
	0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   165
	0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   166
	0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   167
	0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   168
	0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   169
	0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   170
	0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   171
	0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   172
	0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   173
	0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   174
	0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   175
	0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   176
};
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   177
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   178
/*
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   179
 * Multiply a given number by 2 raised to the given power.
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   180
 */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   181
static uint8_t
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   182
vdev_raidz_exp2(uint_t a, int exp)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   183
{
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   184
	if (a == 0)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   185
		return (0);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   186
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   187
	ASSERT(exp >= 0);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   188
	ASSERT(vdev_raidz_log2[a] > 0 || a == 1);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   189
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   190
	exp += vdev_raidz_log2[a];
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   191
	if (exp > 255)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   192
		exp -= 255;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   193
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   194
	return (vdev_raidz_pow2[exp]);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   195
}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   196
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   197
static raidz_map_t *
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   198
vdev_raidz_map_alloc(zio_t *zio, uint64_t unit_shift, uint64_t dcols,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   199
    uint64_t nparity)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   200
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   201
	raidz_map_t *rm;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   202
	uint64_t b = zio->io_offset >> unit_shift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   203
	uint64_t s = zio->io_size >> unit_shift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   204
	uint64_t f = b % dcols;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   205
	uint64_t o = (b / dcols) << unit_shift;
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   206
	uint64_t q, r, c, bc, col, acols, coff, devidx;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   207
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   208
	q = s / (dcols - nparity);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   209
	r = s - q * (dcols - nparity);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   210
	bc = (r == 0 ? 0 : r + nparity);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   211
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   212
	acols = (q == 0 ? bc : dcols);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   213
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   214
	rm = kmem_alloc(offsetof(raidz_map_t, rm_col[acols]), KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   215
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   216
	rm->rm_cols = acols;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   217
	rm->rm_bigcols = bc;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   218
	rm->rm_asize = 0;
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   219
	rm->rm_missingdata = 0;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   220
	rm->rm_missingparity = 0;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   221
	rm->rm_firstdatacol = nparity;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   222
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   223
	for (c = 0; c < acols; c++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   224
		col = f + c;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   225
		coff = o;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   226
		if (col >= dcols) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   227
			col -= dcols;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   228
			coff += 1ULL << unit_shift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   229
		}
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   230
		rm->rm_col[c].rc_devidx = col;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   231
		rm->rm_col[c].rc_offset = coff;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   232
		rm->rm_col[c].rc_size = (q + (c < bc)) << unit_shift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   233
		rm->rm_col[c].rc_data = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   234
		rm->rm_col[c].rc_error = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   235
		rm->rm_col[c].rc_tried = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   236
		rm->rm_col[c].rc_skipped = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   237
		rm->rm_asize += rm->rm_col[c].rc_size;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   238
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   239
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   240
	rm->rm_asize = roundup(rm->rm_asize, (nparity + 1) << unit_shift);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   241
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   242
	for (c = 0; c < rm->rm_firstdatacol; c++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   243
		rm->rm_col[c].rc_data = zio_buf_alloc(rm->rm_col[c].rc_size);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   244
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   245
	rm->rm_col[c].rc_data = zio->io_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   246
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   247
	for (c = c + 1; c < acols; c++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   248
		rm->rm_col[c].rc_data = (char *)rm->rm_col[c - 1].rc_data +
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   249
		    rm->rm_col[c - 1].rc_size;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   250
1133
335d069294d1 6357470 vdev_raidz.c has unused RAIDZ_SINGLE define, code
eschrock
parents: 789
diff changeset
   251
	/*
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   252
	 * If all data stored spans all columns, there's a danger that parity
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   253
	 * will always be on the same device and, since parity isn't read
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   254
	 * during normal operation, that that device's I/O bandwidth won't be
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   255
	 * used effectively. We therefore switch the parity every 1MB.
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   256
	 *
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   257
	 * ... at least that was, ostensibly, the theory. As a practical
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   258
	 * matter unless we juggle the parity between all devices evenly, we
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   259
	 * won't see any benefit. Further, occasional writes that aren't a
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   260
	 * multiple of the LCM of the number of children and the minimum
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   261
	 * stripe width are sufficient to avoid pessimal behavior.
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   262
	 * Unfortunately, this decision created an implicit on-disk format
3456
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   263
	 * requirement that we need to support for all eternity, but only
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   264
	 * for single-parity RAID-Z.
1133
335d069294d1 6357470 vdev_raidz.c has unused RAIDZ_SINGLE define, code
eschrock
parents: 789
diff changeset
   265
	 */
335d069294d1 6357470 vdev_raidz.c has unused RAIDZ_SINGLE define, code
eschrock
parents: 789
diff changeset
   266
	ASSERT(rm->rm_cols >= 2);
335d069294d1 6357470 vdev_raidz.c has unused RAIDZ_SINGLE define, code
eschrock
parents: 789
diff changeset
   267
	ASSERT(rm->rm_col[0].rc_size == rm->rm_col[1].rc_size);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   268
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   269
	if (rm->rm_firstdatacol == 1 && (zio->io_offset & (1ULL << 20))) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   270
		devidx = rm->rm_col[0].rc_devidx;
1133
335d069294d1 6357470 vdev_raidz.c has unused RAIDZ_SINGLE define, code
eschrock
parents: 789
diff changeset
   271
		o = rm->rm_col[0].rc_offset;
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   272
		rm->rm_col[0].rc_devidx = rm->rm_col[1].rc_devidx;
1133
335d069294d1 6357470 vdev_raidz.c has unused RAIDZ_SINGLE define, code
eschrock
parents: 789
diff changeset
   273
		rm->rm_col[0].rc_offset = rm->rm_col[1].rc_offset;
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   274
		rm->rm_col[1].rc_devidx = devidx;
1133
335d069294d1 6357470 vdev_raidz.c has unused RAIDZ_SINGLE define, code
eschrock
parents: 789
diff changeset
   275
		rm->rm_col[1].rc_offset = o;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   276
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   277
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   278
	zio->io_vsd = rm;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   279
	return (rm);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   280
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   281
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   282
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   283
vdev_raidz_map_free(zio_t *zio)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   284
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   285
	raidz_map_t *rm = zio->io_vsd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   286
	int c;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   287
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   288
	for (c = 0; c < rm->rm_firstdatacol; c++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   289
		zio_buf_free(rm->rm_col[c].rc_data, rm->rm_col[c].rc_size);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   290
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   291
	kmem_free(rm, offsetof(raidz_map_t, rm_col[rm->rm_cols]));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   292
	zio->io_vsd = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   293
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   294
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   295
static void
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   296
vdev_raidz_generate_parity_p(raidz_map_t *rm)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   297
{
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   298
	uint64_t *p, *src, pcount, ccount, i;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   299
	int c;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   300
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   301
	pcount = rm->rm_col[VDEV_RAIDZ_P].rc_size / sizeof (src[0]);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   302
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   303
	for (c = rm->rm_firstdatacol; c < rm->rm_cols; c++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   304
		src = rm->rm_col[c].rc_data;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   305
		p = rm->rm_col[VDEV_RAIDZ_P].rc_data;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   306
		ccount = rm->rm_col[c].rc_size / sizeof (src[0]);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   307
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   308
		if (c == rm->rm_firstdatacol) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   309
			ASSERT(ccount == pcount);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   310
			for (i = 0; i < ccount; i++, p++, src++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   311
				*p = *src;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   312
			}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   313
		} else {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   314
			ASSERT(ccount <= pcount);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   315
			for (i = 0; i < ccount; i++, p++, src++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   316
				*p ^= *src;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   317
			}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   318
		}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   319
	}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   320
}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   321
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   322
static void
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   323
vdev_raidz_generate_parity_pq(raidz_map_t *rm)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   324
{
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   325
	uint64_t *q, *p, *src, pcount, ccount, mask, i;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   326
	int c;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   327
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   328
	pcount = rm->rm_col[VDEV_RAIDZ_P].rc_size / sizeof (src[0]);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   329
	ASSERT(rm->rm_col[VDEV_RAIDZ_P].rc_size ==
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   330
	    rm->rm_col[VDEV_RAIDZ_Q].rc_size);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   331
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   332
	for (c = rm->rm_firstdatacol; c < rm->rm_cols; c++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   333
		src = rm->rm_col[c].rc_data;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   334
		p = rm->rm_col[VDEV_RAIDZ_P].rc_data;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   335
		q = rm->rm_col[VDEV_RAIDZ_Q].rc_data;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   336
		ccount = rm->rm_col[c].rc_size / sizeof (src[0]);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   337
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   338
		if (c == rm->rm_firstdatacol) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   339
			ASSERT(ccount == pcount || ccount == 0);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   340
			for (i = 0; i < ccount; i++, p++, q++, src++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   341
				*q = *src;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   342
				*p = *src;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   343
			}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   344
			for (; i < pcount; i++, p++, q++, src++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   345
				*q = 0;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   346
				*p = 0;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   347
			}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   348
		} else {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   349
			ASSERT(ccount <= pcount);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   350
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   351
			/*
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   352
			 * Rather than multiplying each byte individually (as
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   353
			 * described above), we are able to handle 8 at once
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   354
			 * by generating a mask based on the high bit in each
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   355
			 * byte and using that to conditionally XOR in 0x1d.
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   356
			 */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   357
			for (i = 0; i < ccount; i++, p++, q++, src++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   358
				mask = *q & 0x8080808080808080ULL;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   359
				mask = (mask << 1) - (mask >> 7);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   360
				*q = ((*q << 1) & 0xfefefefefefefefeULL) ^
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   361
				    (mask & 0x1d1d1d1d1d1d1d1dULL);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   362
				*q ^= *src;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   363
				*p ^= *src;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   364
			}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   365
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   366
			/*
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   367
			 * Treat short columns as though they are full of 0s.
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   368
			 */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   369
			for (; i < pcount; i++, q++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   370
				mask = *q & 0x8080808080808080ULL;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   371
				mask = (mask << 1) - (mask >> 7);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   372
				*q = ((*q << 1) & 0xfefefefefefefefeULL) ^
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   373
				    (mask & 0x1d1d1d1d1d1d1d1dULL);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   374
			}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   375
		}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   376
	}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   377
}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   378
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   379
static void
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   380
vdev_raidz_reconstruct_p(raidz_map_t *rm, int x)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   381
{
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   382
	uint64_t *dst, *src, xcount, ccount, count, i;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   383
	int c;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   384
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   385
	xcount = rm->rm_col[x].rc_size / sizeof (src[0]);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   386
	ASSERT(xcount <= rm->rm_col[VDEV_RAIDZ_P].rc_size / sizeof (src[0]));
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   387
	ASSERT(xcount > 0);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   388
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   389
	src = rm->rm_col[VDEV_RAIDZ_P].rc_data;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   390
	dst = rm->rm_col[x].rc_data;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   391
	for (i = 0; i < xcount; i++, dst++, src++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   392
		*dst = *src;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   393
	}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   394
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   395
	for (c = rm->rm_firstdatacol; c < rm->rm_cols; c++) {
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   396
		src = rm->rm_col[c].rc_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   397
		dst = rm->rm_col[x].rc_data;
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   398
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   399
		if (c == x)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   400
			continue;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   401
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   402
		ccount = rm->rm_col[c].rc_size / sizeof (src[0]);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   403
		count = MIN(ccount, xcount);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   404
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   405
		for (i = 0; i < count; i++, dst++, src++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   406
			*dst ^= *src;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   407
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   408
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   409
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   410
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   411
static void
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   412
vdev_raidz_reconstruct_q(raidz_map_t *rm, int x)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   413
{
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   414
	uint64_t *dst, *src, xcount, ccount, count, mask, i;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   415
	uint8_t *b;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   416
	int c, j, exp;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   417
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   418
	xcount = rm->rm_col[x].rc_size / sizeof (src[0]);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   419
	ASSERT(xcount <= rm->rm_col[VDEV_RAIDZ_Q].rc_size / sizeof (src[0]));
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   420
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   421
	for (c = rm->rm_firstdatacol; c < rm->rm_cols; c++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   422
		src = rm->rm_col[c].rc_data;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   423
		dst = rm->rm_col[x].rc_data;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   424
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   425
		if (c == x)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   426
			ccount = 0;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   427
		else
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   428
			ccount = rm->rm_col[c].rc_size / sizeof (src[0]);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   429
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   430
		count = MIN(ccount, xcount);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   431
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   432
		if (c == rm->rm_firstdatacol) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   433
			for (i = 0; i < count; i++, dst++, src++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   434
				*dst = *src;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   435
			}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   436
			for (; i < xcount; i++, dst++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   437
				*dst = 0;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   438
			}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   439
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   440
		} else {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   441
			/*
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   442
			 * For an explanation of this, see the comment in
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   443
			 * vdev_raidz_generate_parity_pq() above.
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   444
			 */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   445
			for (i = 0; i < count; i++, dst++, src++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   446
				mask = *dst & 0x8080808080808080ULL;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   447
				mask = (mask << 1) - (mask >> 7);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   448
				*dst = ((*dst << 1) & 0xfefefefefefefefeULL) ^
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   449
				    (mask & 0x1d1d1d1d1d1d1d1dULL);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   450
				*dst ^= *src;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   451
			}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   452
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   453
			for (; i < xcount; i++, dst++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   454
				mask = *dst & 0x8080808080808080ULL;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   455
				mask = (mask << 1) - (mask >> 7);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   456
				*dst = ((*dst << 1) & 0xfefefefefefefefeULL) ^
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   457
				    (mask & 0x1d1d1d1d1d1d1d1dULL);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   458
			}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   459
		}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   460
	}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   461
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   462
	src = rm->rm_col[VDEV_RAIDZ_Q].rc_data;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   463
	dst = rm->rm_col[x].rc_data;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   464
	exp = 255 - (rm->rm_cols - 1 - x);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   465
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   466
	for (i = 0; i < xcount; i++, dst++, src++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   467
		*dst ^= *src;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   468
		for (j = 0, b = (uint8_t *)dst; j < 8; j++, b++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   469
			*b = vdev_raidz_exp2(*b, exp);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   470
		}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   471
	}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   472
}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   473
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   474
static void
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   475
vdev_raidz_reconstruct_pq(raidz_map_t *rm, int x, int y)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   476
{
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   477
	uint8_t *p, *q, *pxy, *qxy, *xd, *yd, tmp, a, b, aexp, bexp;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   478
	void *pdata, *qdata;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   479
	uint64_t xsize, ysize, i;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   480
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   481
	ASSERT(x < y);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   482
	ASSERT(x >= rm->rm_firstdatacol);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   483
	ASSERT(y < rm->rm_cols);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   484
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   485
	ASSERT(rm->rm_col[x].rc_size >= rm->rm_col[y].rc_size);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   486
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   487
	/*
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   488
	 * Move the parity data aside -- we're going to compute parity as
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   489
	 * though columns x and y were full of zeros -- Pxy and Qxy. We want to
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   490
	 * reuse the parity generation mechanism without trashing the actual
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   491
	 * parity so we make those columns appear to be full of zeros by
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   492
	 * setting their lengths to zero.
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   493
	 */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   494
	pdata = rm->rm_col[VDEV_RAIDZ_P].rc_data;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   495
	qdata = rm->rm_col[VDEV_RAIDZ_Q].rc_data;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   496
	xsize = rm->rm_col[x].rc_size;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   497
	ysize = rm->rm_col[y].rc_size;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   498
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   499
	rm->rm_col[VDEV_RAIDZ_P].rc_data =
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   500
	    zio_buf_alloc(rm->rm_col[VDEV_RAIDZ_P].rc_size);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   501
	rm->rm_col[VDEV_RAIDZ_Q].rc_data =
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   502
	    zio_buf_alloc(rm->rm_col[VDEV_RAIDZ_Q].rc_size);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   503
	rm->rm_col[x].rc_size = 0;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   504
	rm->rm_col[y].rc_size = 0;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   505
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   506
	vdev_raidz_generate_parity_pq(rm);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   507
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   508
	rm->rm_col[x].rc_size = xsize;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   509
	rm->rm_col[y].rc_size = ysize;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   510
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   511
	p = pdata;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   512
	q = qdata;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   513
	pxy = rm->rm_col[VDEV_RAIDZ_P].rc_data;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   514
	qxy = rm->rm_col[VDEV_RAIDZ_Q].rc_data;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   515
	xd = rm->rm_col[x].rc_data;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   516
	yd = rm->rm_col[y].rc_data;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   517
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   518
	/*
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   519
	 * We now have:
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   520
	 *	Pxy = P + D_x + D_y
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   521
	 *	Qxy = Q + 2^(ndevs - 1 - x) * D_x + 2^(ndevs - 1 - y) * D_y
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   522
	 *
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   523
	 * We can then solve for D_x:
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   524
	 *	D_x = A * (P + Pxy) + B * (Q + Qxy)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   525
	 * where
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   526
	 *	A = 2^(x - y) * (2^(x - y) + 1)^-1
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   527
	 *	B = 2^(ndevs - 1 - x) * (2^(x - y) + 1)^-1
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   528
	 *
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   529
	 * With D_x in hand, we can easily solve for D_y:
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   530
	 *	D_y = P + Pxy + D_x
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   531
	 */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   532
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   533
	a = vdev_raidz_pow2[255 + x - y];
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   534
	b = vdev_raidz_pow2[255 - (rm->rm_cols - 1 - x)];
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   535
	tmp = 255 - vdev_raidz_log2[a ^ 1];
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   536
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   537
	aexp = vdev_raidz_log2[vdev_raidz_exp2(a, tmp)];
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   538
	bexp = vdev_raidz_log2[vdev_raidz_exp2(b, tmp)];
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   539
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   540
	for (i = 0; i < xsize; i++, p++, q++, pxy++, qxy++, xd++, yd++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   541
		*xd = vdev_raidz_exp2(*p ^ *pxy, aexp) ^
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   542
		    vdev_raidz_exp2(*q ^ *qxy, bexp);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   543
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   544
		if (i < ysize)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   545
			*yd = *p ^ *pxy ^ *xd;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   546
	}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   547
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   548
	zio_buf_free(rm->rm_col[VDEV_RAIDZ_P].rc_data,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   549
	    rm->rm_col[VDEV_RAIDZ_P].rc_size);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   550
	zio_buf_free(rm->rm_col[VDEV_RAIDZ_Q].rc_data,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   551
	    rm->rm_col[VDEV_RAIDZ_Q].rc_size);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   552
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   553
	/*
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   554
	 * Restore the saved parity data.
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   555
	 */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   556
	rm->rm_col[VDEV_RAIDZ_P].rc_data = pdata;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   557
	rm->rm_col[VDEV_RAIDZ_Q].rc_data = qdata;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   558
}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   559
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   560
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   561
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   562
vdev_raidz_open(vdev_t *vd, uint64_t *asize, uint64_t *ashift)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   563
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   564
	vdev_t *cvd;
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   565
	uint64_t nparity = vd->vdev_nparity;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   566
	int c, error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   567
	int lasterror = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   568
	int numerrors = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   569
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   570
	ASSERT(nparity > 0);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   571
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   572
	if (nparity > VDEV_RAIDZ_MAXPARITY ||
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   573
	    vd->vdev_children < nparity + 1) {
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   574
		vd->vdev_stat.vs_aux = VDEV_AUX_BAD_LABEL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   575
		return (EINVAL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   576
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   577
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   578
	for (c = 0; c < vd->vdev_children; c++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   579
		cvd = vd->vdev_child[c];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   580
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   581
		if ((error = vdev_open(cvd)) != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   582
			lasterror = error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   583
			numerrors++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   584
			continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   585
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   586
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   587
		*asize = MIN(*asize - 1, cvd->vdev_asize - 1) + 1;
1732
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   588
		*ashift = MAX(*ashift, cvd->vdev_ashift);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   589
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   590
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   591
	*asize *= vd->vdev_children;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   592
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   593
	if (numerrors > nparity) {
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   594
		vd->vdev_stat.vs_aux = VDEV_AUX_NO_REPLICAS;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   595
		return (lasterror);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   596
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   597
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   598
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   599
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   600
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   601
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   602
vdev_raidz_close(vdev_t *vd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   603
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   604
	int c;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   605
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   606
	for (c = 0; c < vd->vdev_children; c++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   607
		vdev_close(vd->vdev_child[c]);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   608
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   609
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   610
static uint64_t
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   611
vdev_raidz_asize(vdev_t *vd, uint64_t psize)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   612
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   613
	uint64_t asize;
1732
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   614
	uint64_t ashift = vd->vdev_top->vdev_ashift;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   615
	uint64_t cols = vd->vdev_children;
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   616
	uint64_t nparity = vd->vdev_nparity;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   617
1732
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   618
	asize = ((psize - 1) >> ashift) + 1;
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   619
	asize += nparity * ((asize + cols - nparity - 1) / (cols - nparity));
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   620
	asize = roundup(asize, nparity + 1) << ashift;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   621
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   622
	return (asize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   623
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   624
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   625
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   626
vdev_raidz_child_done(zio_t *zio)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   627
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   628
	raidz_col_t *rc = zio->io_private;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   629
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   630
	rc->rc_error = zio->io_error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   631
	rc->rc_tried = 1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   632
	rc->rc_skipped = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   633
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   634
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   635
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   636
vdev_raidz_repair_done(zio_t *zio)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   637
{
1732
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   638
	ASSERT(zio->io_private == zio->io_parent);
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   639
	vdev_raidz_map_free(zio->io_private);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   640
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   641
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   642
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   643
vdev_raidz_io_start(zio_t *zio)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   644
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   645
	vdev_t *vd = zio->io_vd;
1732
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   646
	vdev_t *tvd = vd->vdev_top;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   647
	vdev_t *cvd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   648
	blkptr_t *bp = zio->io_bp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   649
	raidz_map_t *rm;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   650
	raidz_col_t *rc;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   651
	int c;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   652
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   653
	rm = vdev_raidz_map_alloc(zio, tvd->vdev_ashift, vd->vdev_children,
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   654
	    vd->vdev_nparity);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   655
1775
e51e26b432c0 6410698 ZFS metadata needs to be more highly replicated (ditto blocks)
billm
parents: 1732
diff changeset
   656
	ASSERT3U(rm->rm_asize, ==, vdev_psize_to_asize(vd, zio->io_size));
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   657
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   658
	if (zio->io_type == ZIO_TYPE_WRITE) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   659
		/*
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   660
		 * Generate RAID parity in the first virtual columns.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   661
		 */
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   662
		if (rm->rm_firstdatacol == 1)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   663
			vdev_raidz_generate_parity_p(rm);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   664
		else
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   665
			vdev_raidz_generate_parity_pq(rm);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   666
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   667
		for (c = 0; c < rm->rm_cols; c++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   668
			rc = &rm->rm_col[c];
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   669
			cvd = vd->vdev_child[rc->rc_devidx];
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   670
			zio_nowait(zio_vdev_child_io(zio, NULL, cvd,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   671
			    rc->rc_offset, rc->rc_data, rc->rc_size,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   672
			    zio->io_type, zio->io_priority, ZIO_FLAG_CANFAIL,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   673
			    vdev_raidz_child_done, rc));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   674
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   675
		zio_wait_children_done(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   676
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   677
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   678
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   679
	ASSERT(zio->io_type == ZIO_TYPE_READ);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   680
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   681
	/*
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   682
	 * Iterate over the columns in reverse order so that we hit the parity
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   683
	 * last -- any errors along the way will force us to read the parity
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   684
	 * data.
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   685
	 */
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   686
	for (c = rm->rm_cols - 1; c >= 0; c--) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   687
		rc = &rm->rm_col[c];
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   688
		cvd = vd->vdev_child[rc->rc_devidx];
5329
33cb98223b2d PSARC 2007/567 zpool failmode property
gw25295
parents: 4034
diff changeset
   689
		if (!vdev_readable(cvd)) {
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   690
			if (c >= rm->rm_firstdatacol)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   691
				rm->rm_missingdata++;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   692
			else
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   693
				rm->rm_missingparity++;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   694
			rc->rc_error = ENXIO;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   695
			rc->rc_tried = 1;	/* don't even try */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   696
			rc->rc_skipped = 1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   697
			continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   698
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   699
		if (vdev_dtl_contains(&cvd->vdev_dtl_map, bp->blk_birth, 1)) {
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   700
			if (c >= rm->rm_firstdatacol)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   701
				rm->rm_missingdata++;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   702
			else
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   703
				rm->rm_missingparity++;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   704
			rc->rc_error = ESTALE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   705
			rc->rc_skipped = 1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   706
			continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   707
		}
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   708
		if (c >= rm->rm_firstdatacol || rm->rm_missingdata > 0 ||
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   709
		    (zio->io_flags & ZIO_FLAG_SCRUB)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   710
			zio_nowait(zio_vdev_child_io(zio, NULL, cvd,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   711
			    rc->rc_offset, rc->rc_data, rc->rc_size,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   712
			    zio->io_type, zio->io_priority, ZIO_FLAG_CANFAIL,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   713
			    vdev_raidz_child_done, rc));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   714
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   715
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   716
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   717
	zio_wait_children_done(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   718
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   719
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   720
/*
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   721
 * Report a checksum error for a child of a RAID-Z device.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   722
 */
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   723
static void
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   724
raidz_checksum_error(zio_t *zio, raidz_col_t *rc)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   725
{
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   726
	vdev_t *vd = zio->io_vd->vdev_child[rc->rc_devidx];
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   727
	dprintf_bp(zio->io_bp, "imputed checksum error on %s: ",
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   728
	    vdev_description(vd));
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   729
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   730
	if (!(zio->io_flags & ZIO_FLAG_SPECULATIVE)) {
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   731
		mutex_enter(&vd->vdev_stat_lock);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   732
		vd->vdev_stat.vs_checksum_errors++;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   733
		mutex_exit(&vd->vdev_stat_lock);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   734
	}
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   735
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   736
	if (!(zio->io_flags & ZIO_FLAG_SPECULATIVE))
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   737
		zfs_ereport_post(FM_EREPORT_ZFS_CHECKSUM,
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   738
		    zio->io_spa, vd, zio, rc->rc_offset, rc->rc_size);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   739
}
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   740
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   741
/*
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   742
 * Generate the parity from the data columns. If we tried and were able to
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   743
 * read the parity without error, verify that the generated parity matches the
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   744
 * data we read. If it doesn't, we fire off a checksum error. Return the
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   745
 * number such failures.
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   746
 */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   747
static int
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   748
raidz_parity_verify(zio_t *zio, raidz_map_t *rm)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   749
{
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   750
	void *orig[VDEV_RAIDZ_MAXPARITY];
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   751
	int c, ret = 0;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   752
	raidz_col_t *rc;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   753
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   754
	for (c = 0; c < rm->rm_firstdatacol; c++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   755
		rc = &rm->rm_col[c];
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   756
		if (!rc->rc_tried || rc->rc_error != 0)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   757
			continue;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   758
		orig[c] = zio_buf_alloc(rc->rc_size);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   759
		bcopy(rc->rc_data, orig[c], rc->rc_size);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   760
	}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   761
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   762
	if (rm->rm_firstdatacol == 1)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   763
		vdev_raidz_generate_parity_p(rm);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   764
	else
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   765
		vdev_raidz_generate_parity_pq(rm);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   766
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   767
	for (c = 0; c < rm->rm_firstdatacol; c++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   768
		rc = &rm->rm_col[c];
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   769
		if (!rc->rc_tried || rc->rc_error != 0)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   770
			continue;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   771
		if (bcmp(orig[c], rc->rc_data, rc->rc_size) != 0) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   772
			raidz_checksum_error(zio, rc);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   773
			rc->rc_error = ECKSUM;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   774
			ret++;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   775
		}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   776
		zio_buf_free(orig[c], rc->rc_size);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   777
	}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   778
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   779
	return (ret);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   780
}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   781
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   782
static uint64_t raidz_corrected_p;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   783
static uint64_t raidz_corrected_q;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   784
static uint64_t raidz_corrected_pq;
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   785
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   786
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   787
vdev_raidz_io_done(zio_t *zio)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   788
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   789
	vdev_t *vd = zio->io_vd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   790
	vdev_t *cvd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   791
	raidz_map_t *rm = zio->io_vsd;
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   792
	raidz_col_t *rc, *rc1;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   793
	int unexpected_errors = 0;
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   794
	int parity_errors = 0;
3456
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   795
	int parity_untried = 0;
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   796
	int data_errors = 0;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   797
	int n, c, c1;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   798
1775
e51e26b432c0 6410698 ZFS metadata needs to be more highly replicated (ditto blocks)
billm
parents: 1732
diff changeset
   799
	ASSERT(zio->io_bp != NULL);  /* XXX need to add code to enforce this */
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   800
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   801
	zio->io_error = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   802
	zio->io_numerrors = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   803
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   804
	ASSERT(rm->rm_missingparity <= rm->rm_firstdatacol);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   805
	ASSERT(rm->rm_missingdata <= rm->rm_cols - rm->rm_firstdatacol);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   806
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   807
	for (c = 0; c < rm->rm_cols; c++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   808
		rc = &rm->rm_col[c];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   809
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   810
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   811
		 * We preserve any EIOs because those may be worth retrying;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   812
		 * whereas ECKSUM and ENXIO are more likely to be persistent.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   813
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   814
		if (rc->rc_error) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   815
			if (zio->io_error != EIO)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   816
				zio->io_error = rc->rc_error;
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   817
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   818
			if (c < rm->rm_firstdatacol)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   819
				parity_errors++;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   820
			else
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   821
				data_errors++;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   822
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   823
			if (!rc->rc_skipped)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   824
				unexpected_errors++;
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   825
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   826
			zio->io_numerrors++;
3456
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   827
		} else if (c < rm->rm_firstdatacol && !rc->rc_tried) {
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   828
			parity_untried++;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   829
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   830
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   831
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   832
	if (zio->io_type == ZIO_TYPE_WRITE) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   833
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   834
		 * If this is not a failfast write, and we were able to
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   835
		 * write enough columns to reconstruct the data, good enough.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   836
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   837
		/* XXPOLICY */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   838
		if (zio->io_numerrors <= rm->rm_firstdatacol &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   839
		    !(zio->io_flags & ZIO_FLAG_FAILFAST))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   840
			zio->io_error = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   841
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   842
		vdev_raidz_map_free(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   843
		zio_next_stage(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   844
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   845
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   846
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   847
	ASSERT(zio->io_type == ZIO_TYPE_READ);
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   848
	/*
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   849
	 * There are three potential phases for a read:
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   850
	 *	1. produce valid data from the columns read
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   851
	 *	2. read all disks and try again
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   852
	 *	3. perform combinatorial reconstruction
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   853
	 *
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   854
	 * Each phase is progressively both more expensive and less likely to
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   855
	 * occur. If we encounter more errors than we can repair or all phases
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   856
	 * fail, we have no choice but to return an error.
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   857
	 */
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   858
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   859
	/*
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   860
	 * If the number of errors we saw was correctable -- less than or equal
3456
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   861
	 * to the number of parity disks read -- attempt to produce data that
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   862
	 * has a valid checksum. Naturally, this case applies in the absence of
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   863
	 * any errors.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   864
	 */
3456
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   865
	if (zio->io_numerrors <= rm->rm_firstdatacol - parity_untried) {
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   866
		switch (data_errors) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   867
		case 0:
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   868
			if (zio_checksum_error(zio) == 0) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   869
				zio->io_error = 0;
4034
b20b176bd1e8 6545015 RAID-Z resilver broken
ahl
parents: 3456
diff changeset
   870
b20b176bd1e8 6545015 RAID-Z resilver broken
ahl
parents: 3456
diff changeset
   871
				/*
b20b176bd1e8 6545015 RAID-Z resilver broken
ahl
parents: 3456
diff changeset
   872
				 * If we read parity information (unnecessarily
b20b176bd1e8 6545015 RAID-Z resilver broken
ahl
parents: 3456
diff changeset
   873
				 * as it happens since no reconstruction was
b20b176bd1e8 6545015 RAID-Z resilver broken
ahl
parents: 3456
diff changeset
   874
				 * needed) regenerate and verify the parity.
b20b176bd1e8 6545015 RAID-Z resilver broken
ahl
parents: 3456
diff changeset
   875
				 * We also regenerate parity when resilvering
b20b176bd1e8 6545015 RAID-Z resilver broken
ahl
parents: 3456
diff changeset
   876
				 * so we can write it out to the failed device
b20b176bd1e8 6545015 RAID-Z resilver broken
ahl
parents: 3456
diff changeset
   877
				 * later.
b20b176bd1e8 6545015 RAID-Z resilver broken
ahl
parents: 3456
diff changeset
   878
				 */
3456
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   879
				if (parity_errors + parity_untried <
4034
b20b176bd1e8 6545015 RAID-Z resilver broken
ahl
parents: 3456
diff changeset
   880
				    rm->rm_firstdatacol ||
b20b176bd1e8 6545015 RAID-Z resilver broken
ahl
parents: 3456
diff changeset
   881
				    (zio->io_flags & ZIO_FLAG_RESILVER)) {
3456
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   882
					n = raidz_parity_verify(zio, rm);
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   883
					unexpected_errors += n;
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   884
					ASSERT(parity_errors + n <=
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   885
					    rm->rm_firstdatacol);
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   886
				}
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   887
				goto done;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   888
			}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   889
			break;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   890
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   891
		case 1:
3456
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   892
			/*
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   893
			 * We either attempt to read all the parity columns or
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   894
			 * none of them. If we didn't try to read parity, we
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   895
			 * wouldn't be here in the correctable case. There must
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   896
			 * also have been fewer parity errors than parity
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   897
			 * columns or, again, we wouldn't be in this code path.
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   898
			 */
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   899
			ASSERT(parity_untried == 0);
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   900
			ASSERT(parity_errors < rm->rm_firstdatacol);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   901
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   902
			/*
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   903
			 * Find the column that reported the error.
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   904
			 */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   905
			for (c = rm->rm_firstdatacol; c < rm->rm_cols; c++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   906
				rc = &rm->rm_col[c];
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   907
				if (rc->rc_error != 0)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   908
					break;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   909
			}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   910
			ASSERT(c != rm->rm_cols);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   911
			ASSERT(!rc->rc_skipped || rc->rc_error == ENXIO ||
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   912
			    rc->rc_error == ESTALE);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   913
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   914
			if (rm->rm_col[VDEV_RAIDZ_P].rc_error == 0) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   915
				vdev_raidz_reconstruct_p(rm, c);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   916
			} else {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   917
				ASSERT(rm->rm_firstdatacol > 1);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   918
				vdev_raidz_reconstruct_q(rm, c);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   919
			}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   920
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   921
			if (zio_checksum_error(zio) == 0) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   922
				zio->io_error = 0;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   923
				if (rm->rm_col[VDEV_RAIDZ_P].rc_error == 0)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   924
					atomic_inc_64(&raidz_corrected_p);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   925
				else
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   926
					atomic_inc_64(&raidz_corrected_q);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   927
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   928
				/*
3456
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   929
				 * If there's more than one parity disk that
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   930
				 * was successfully read, confirm that the
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   931
				 * other parity disk produced the correct data.
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   932
				 * This routine is suboptimal in that it
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   933
				 * regenerates both the parity we wish to test
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   934
				 * as well as the parity we just used to
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   935
				 * perform the reconstruction, but this should
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   936
				 * be a relatively uncommon case, and can be
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   937
				 * optimized if it becomes a problem.
4034
b20b176bd1e8 6545015 RAID-Z resilver broken
ahl
parents: 3456
diff changeset
   938
				 * We also regenerate parity when resilvering
b20b176bd1e8 6545015 RAID-Z resilver broken
ahl
parents: 3456
diff changeset
   939
				 * so we can write it out to the failed device
b20b176bd1e8 6545015 RAID-Z resilver broken
ahl
parents: 3456
diff changeset
   940
				 * later.
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   941
				 */
4034
b20b176bd1e8 6545015 RAID-Z resilver broken
ahl
parents: 3456
diff changeset
   942
				if (parity_errors < rm->rm_firstdatacol - 1 ||
b20b176bd1e8 6545015 RAID-Z resilver broken
ahl
parents: 3456
diff changeset
   943
				    (zio->io_flags & ZIO_FLAG_RESILVER)) {
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   944
					n = raidz_parity_verify(zio, rm);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   945
					unexpected_errors += n;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   946
					ASSERT(parity_errors + n <=
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   947
					    rm->rm_firstdatacol);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   948
				}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   949
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   950
				goto done;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   951
			}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   952
			break;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   953
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   954
		case 2:
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   955
			/*
3456
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   956
			 * Two data column errors require double parity.
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   957
			 */
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   958
			ASSERT(rm->rm_firstdatacol == 2);
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   959
95c16947e4af 6509749 RAIDZ reads unnecessarily generate parity
ahl
parents: 2082
diff changeset
   960
			/*
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   961
			 * Find the two columns that reported errors.
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   962
			 */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   963
			for (c = rm->rm_firstdatacol; c < rm->rm_cols; c++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   964
				rc = &rm->rm_col[c];
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   965
				if (rc->rc_error != 0)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   966
					break;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   967
			}
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   968
			ASSERT(c != rm->rm_cols);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   969
			ASSERT(!rc->rc_skipped || rc->rc_error == ENXIO ||
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   970
			    rc->rc_error == ESTALE);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   971
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   972
			for (c1 = c++; c < rm->rm_cols; c++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   973
				rc = &rm->rm_col[c];
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   974
				if (rc->rc_error != 0)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   975
					break;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   976
			}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   977
			ASSERT(c != rm->rm_cols);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   978
			ASSERT(!rc->rc_skipped || rc->rc_error == ENXIO ||
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   979
			    rc->rc_error == ESTALE);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   980
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   981
			vdev_raidz_reconstruct_pq(rm, c1, c);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   982
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   983
			if (zio_checksum_error(zio) == 0) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   984
				zio->io_error = 0;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   985
				atomic_inc_64(&raidz_corrected_pq);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   986
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   987
				goto done;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   988
			}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   989
			break;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   990
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   991
		default:
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   992
			ASSERT(rm->rm_firstdatacol <= 2);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   993
			ASSERT(0);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   994
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   995
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   996
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   997
	/*
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   998
	 * This isn't a typical situation -- either we got a read error or
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
   999
	 * a child silently returned bad data. Read every block so we can
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1000
	 * try again with as much data and parity as we can track down. If
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1001
	 * we've already been through once before, all children will be marked
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1002
	 * as tried so we'll proceed to combinatorial reconstruction.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1003
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1004
	unexpected_errors = 1;
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1005
	rm->rm_missingdata = 0;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1006
	rm->rm_missingparity = 0;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1007
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1008
	for (c = 0; c < rm->rm_cols; c++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1009
		if (rm->rm_col[c].rc_tried)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1010
			continue;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1011
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1012
		zio->io_error = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1013
		zio_vdev_io_redone(zio);
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1014
		do {
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1015
			rc = &rm->rm_col[c];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1016
			if (rc->rc_tried)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1017
				continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1018
			zio_nowait(zio_vdev_child_io(zio, NULL,
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1019
			    vd->vdev_child[rc->rc_devidx],
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1020
			    rc->rc_offset, rc->rc_data, rc->rc_size,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1021
			    zio->io_type, zio->io_priority, ZIO_FLAG_CANFAIL,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1022
			    vdev_raidz_child_done, rc));
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1023
		} while (++c < rm->rm_cols);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1024
		dprintf("rereading\n");
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1025
		zio_wait_children_done(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1026
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1027
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1028
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1029
	/*
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1030
	 * At this point we've attempted to reconstruct the data given the
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1031
	 * errors we detected, and we've attempted to read all columns. There
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1032
	 * must, therefore, be one or more additional problems -- silent errors
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1033
	 * resulting in invalid data rather than explicit I/O errors resulting
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1034
	 * in absent data. Before we attempt combinatorial reconstruction make
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1035
	 * sure we have a chance of coming up with the right answer.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1036
	 */
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1037
	if (zio->io_numerrors >= rm->rm_firstdatacol) {
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1038
		ASSERT(zio->io_error != 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1039
		goto done;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1040
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1041
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1042
	if (rm->rm_col[VDEV_RAIDZ_P].rc_error == 0) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1043
		/*
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1044
		 * Attempt to reconstruct the data from parity P.
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1045
		 */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1046
		for (c = rm->rm_firstdatacol; c < rm->rm_cols; c++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1047
			void *orig;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1048
			rc = &rm->rm_col[c];
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1049
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1050
			orig = zio_buf_alloc(rc->rc_size);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1051
			bcopy(rc->rc_data, orig, rc->rc_size);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1052
			vdev_raidz_reconstruct_p(rm, c);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1053
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1054
			if (zio_checksum_error(zio) == 0) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1055
				zio_buf_free(orig, rc->rc_size);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1056
				zio->io_error = 0;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1057
				atomic_inc_64(&raidz_corrected_p);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1058
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1059
				/*
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1060
				 * If this child didn't know that it returned
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1061
				 * bad data, inform it.
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1062
				 */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1063
				if (rc->rc_tried && rc->rc_error == 0)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1064
					raidz_checksum_error(zio, rc);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1065
				rc->rc_error = ECKSUM;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1066
				goto done;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1067
			}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1068
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1069
			bcopy(orig, rc->rc_data, rc->rc_size);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1070
			zio_buf_free(orig, rc->rc_size);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1071
		}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1072
	}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1073
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1074
	if (rm->rm_firstdatacol > 1 && rm->rm_col[VDEV_RAIDZ_Q].rc_error == 0) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1075
		/*
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1076
		 * Attempt to reconstruct the data from parity Q.
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1077
		 */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1078
		for (c = rm->rm_firstdatacol; c < rm->rm_cols; c++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1079
			void *orig;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1080
			rc = &rm->rm_col[c];
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1081
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1082
			orig = zio_buf_alloc(rc->rc_size);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1083
			bcopy(rc->rc_data, orig, rc->rc_size);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1084
			vdev_raidz_reconstruct_q(rm, c);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1085
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1086
			if (zio_checksum_error(zio) == 0) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1087
				zio_buf_free(orig, rc->rc_size);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1088
				zio->io_error = 0;
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1089
				atomic_inc_64(&raidz_corrected_q);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1090
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1091
				/*
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1092
				 * If this child didn't know that it returned
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1093
				 * bad data, inform it.
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1094
				 */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1095
				if (rc->rc_tried && rc->rc_error == 0)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1096
					raidz_checksum_error(zio, rc);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1097
				rc->rc_error = ECKSUM;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1098
				goto done;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1099
			}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1100
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1101
			bcopy(orig, rc->rc_data, rc->rc_size);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1102
			zio_buf_free(orig, rc->rc_size);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1103
		}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1104
	}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1105
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1106
	if (rm->rm_firstdatacol > 1 &&
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1107
	    rm->rm_col[VDEV_RAIDZ_P].rc_error == 0 &&
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1108
	    rm->rm_col[VDEV_RAIDZ_Q].rc_error == 0) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1109
		/*
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1110
		 * Attempt to reconstruct the data from both P and Q.
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1111
		 */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1112
		for (c = rm->rm_firstdatacol; c < rm->rm_cols - 1; c++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1113
			void *orig, *orig1;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1114
			rc = &rm->rm_col[c];
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1115
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1116
			orig = zio_buf_alloc(rc->rc_size);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1117
			bcopy(rc->rc_data, orig, rc->rc_size);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1118
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1119
			for (c1 = c + 1; c1 < rm->rm_cols; c1++) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1120
				rc1 = &rm->rm_col[c1];
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1121
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1122
				orig1 = zio_buf_alloc(rc1->rc_size);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1123
				bcopy(rc1->rc_data, orig1, rc1->rc_size);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1124
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1125
				vdev_raidz_reconstruct_pq(rm, c, c1);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1126
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1127
				if (zio_checksum_error(zio) == 0) {
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1128
					zio_buf_free(orig, rc->rc_size);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1129
					zio_buf_free(orig1, rc1->rc_size);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1130
					zio->io_error = 0;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1131
					atomic_inc_64(&raidz_corrected_pq);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1132
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1133
					/*
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1134
					 * If these children didn't know they
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1135
					 * returned bad data, inform them.
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1136
					 */
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1137
					if (rc->rc_tried && rc->rc_error == 0)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1138
						raidz_checksum_error(zio, rc);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1139
					if (rc1->rc_tried && rc1->rc_error == 0)
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1140
						raidz_checksum_error(zio, rc1);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1141
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1142
					rc->rc_error = ECKSUM;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1143
					rc1->rc_error = ECKSUM;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1144
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1145
					goto done;
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1146
				}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1147
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1148
				bcopy(orig1, rc1->rc_data, rc1->rc_size);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1149
				zio_buf_free(orig1, rc1->rc_size);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1150
			}
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1151
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1152
			bcopy(orig, rc->rc_data, rc->rc_size);
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1153
			zio_buf_free(orig, rc->rc_size);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1154
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1155
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1156
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1157
	/*
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1158
	 * All combinations failed to checksum. Generate checksum ereports for
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1159
	 * all children.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1160
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1161
	zio->io_error = ECKSUM;
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
  1162
	if (!(zio->io_flags & ZIO_FLAG_SPECULATIVE)) {
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
  1163
		for (c = 0; c < rm->rm_cols; c++) {
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
  1164
			rc = &rm->rm_col[c];
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
  1165
			zfs_ereport_post(FM_EREPORT_ZFS_CHECKSUM,
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1166
			    zio->io_spa, vd->vdev_child[rc->rc_devidx], zio,
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
  1167
			    rc->rc_offset, rc->rc_size);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
  1168
		}
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
  1169
	}
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1170
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1171
done:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1172
	zio_checksum_verified(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1173
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1174
	if (zio->io_error == 0 && (spa_mode & FWRITE) &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1175
	    (unexpected_errors || (zio->io_flags & ZIO_FLAG_RESILVER))) {
1732
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
  1176
		zio_t *rio;
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
  1177
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1178
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1179
		 * Use the good data we have in hand to repair damaged children.
1732
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
  1180
		 *
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
  1181
		 * We issue all repair I/Os as children of 'rio' to arrange
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
  1182
		 * that vdev_raidz_map_free(zio) will be invoked after all
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
  1183
		 * repairs complete, but before we advance to the next stage.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1184
		 */
1732
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
  1185
		rio = zio_null(zio, zio->io_spa,
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
  1186
		    vdev_raidz_repair_done, zio, ZIO_FLAG_CANFAIL);
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
  1187
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1188
		for (c = 0; c < rm->rm_cols; c++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1189
			rc = &rm->rm_col[c];
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1190
			cvd = vd->vdev_child[rc->rc_devidx];
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1191
1732
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
  1192
			if (rc->rc_error == 0)
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
  1193
				continue;
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
  1194
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
  1195
			dprintf("%s resilvered %s @ 0x%llx error %d\n",
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
  1196
			    vdev_description(vd),
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
  1197
			    vdev_description(cvd),
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
  1198
			    zio->io_offset, rc->rc_error);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1199
1732
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
  1200
			zio_nowait(zio_vdev_child_io(rio, NULL, cvd,
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
  1201
			    rc->rc_offset, rc->rc_data, rc->rc_size,
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
  1202
			    ZIO_TYPE_WRITE, zio->io_priority,
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1203
			    ZIO_FLAG_IO_REPAIR | ZIO_FLAG_DONT_PROPAGATE |
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1204
			    ZIO_FLAG_CANFAIL, NULL, NULL));
1732
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
  1205
		}
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1206
1732
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
  1207
		zio_nowait(rio);
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
  1208
		zio_wait_children_done(zio);
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
  1209
		return;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1210
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1211
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1212
	vdev_raidz_map_free(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1213
	zio_next_stage(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1214
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1215
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1216
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1217
vdev_raidz_state_change(vdev_t *vd, int faulted, int degraded)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1218
{
2082
76b439ec3ac1 PSARC 2006/223 ZFS Hot Spares
eschrock
parents: 1775
diff changeset
  1219
	if (faulted > vd->vdev_nparity)
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
  1220
		vdev_set_state(vd, B_FALSE, VDEV_STATE_CANT_OPEN,
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
  1221
		    VDEV_AUX_NO_REPLICAS);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1222
	else if (degraded + faulted != 0)
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
  1223
		vdev_set_state(vd, B_FALSE, VDEV_STATE_DEGRADED, VDEV_AUX_NONE);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1224
	else
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
  1225
		vdev_set_state(vd, B_FALSE, VDEV_STATE_HEALTHY, VDEV_AUX_NONE);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1226
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1227
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1228
vdev_ops_t vdev_raidz_ops = {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1229
	vdev_raidz_open,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1230
	vdev_raidz_close,
5329
33cb98223b2d PSARC 2007/567 zpool failmode property
gw25295
parents: 4034
diff changeset
  1231
	NULL,
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1232
	vdev_raidz_asize,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1233
	vdev_raidz_io_start,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1234
	vdev_raidz_io_done,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1235
	vdev_raidz_state_change,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1236
	VDEV_TYPE_RAIDZ,	/* name of this vdev type */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1237
	B_FALSE			/* not a leaf vdev */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1238
};