usr/src/uts/common/fs/zfs/vdev_raidz.c
author bonwick
Sun, 02 Apr 2006 00:47:06 -0800
changeset 1732 9e3ae798af31
parent 1544 938876158511
child 1775 e51e26b432c0
permissions -rw-r--r--
6280668 pluggable block allocation policy 6399301 initial read of space maps is super slow 6407365 large-sector disk support in ZFS 6407366 ADVANCE_NOLOCK gathers MOS 6407367 three-way deadlock between db_mtx, dbuf_hash[], and ms_lock
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
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    21
/*
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
    22
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    23
 * Use is subject to license terms.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    24
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    25
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    26
#pragma ident	"%Z%%M%	%I%	%E% SMI"
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    27
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    28
#include <sys/zfs_context.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    29
#include <sys/spa.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    30
#include <sys/vdev_impl.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    31
#include <sys/zio.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    32
#include <sys/zio_checksum.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    33
#include <sys/fs/zfs.h>
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
    34
#include <sys/fm/fs/zfs.h>
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    35
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    36
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    37
 * Virtual device vector for RAID-Z.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    38
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    39
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    40
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    41
 * We currently allow up to two-way replication (i.e. single-fault
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    42
 * reconstruction) models in RAID-Z vdevs.  The blocks in such vdevs
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    43
 * must all be multiples of two times the leaf vdev blocksize.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    44
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    45
#define	VDEV_RAIDZ_ALIGN	2ULL
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    46
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    47
typedef struct raidz_col {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    48
	uint64_t	rc_col;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    49
	uint64_t	rc_offset;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    50
	uint64_t	rc_size;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    51
	void		*rc_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    52
	int		rc_error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    53
	short		rc_tried;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    54
	short		rc_skipped;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    55
} raidz_col_t;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    56
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    57
typedef struct raidz_map {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    58
	uint64_t	rm_cols;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    59
	uint64_t	rm_bigcols;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    60
	uint64_t	rm_asize;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    61
	int		rm_missing_child;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    62
	int		rm_firstdatacol;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    63
	raidz_col_t	rm_col[1];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    64
} raidz_map_t;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    65
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    66
static raidz_map_t *
1133
335d069294d1 6357470 vdev_raidz.c has unused RAIDZ_SINGLE define, code
eschrock
parents: 789
diff changeset
    67
vdev_raidz_map_alloc(zio_t *zio, uint64_t unit_shift, uint64_t dcols)
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    68
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    69
	raidz_map_t *rm;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    70
	uint64_t b = zio->io_offset >> unit_shift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    71
	uint64_t s = zio->io_size >> unit_shift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    72
	uint64_t f = b % dcols;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    73
	uint64_t o = (b / dcols) << unit_shift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    74
	uint64_t q, r, c, bc, col, acols, coff;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    75
	int firstdatacol;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    76
1133
335d069294d1 6357470 vdev_raidz.c has unused RAIDZ_SINGLE define, code
eschrock
parents: 789
diff changeset
    77
	q = s / (dcols - 1);
335d069294d1 6357470 vdev_raidz.c has unused RAIDZ_SINGLE define, code
eschrock
parents: 789
diff changeset
    78
	r = s - q * (dcols - 1);
335d069294d1 6357470 vdev_raidz.c has unused RAIDZ_SINGLE define, code
eschrock
parents: 789
diff changeset
    79
	bc = r + !!r;
335d069294d1 6357470 vdev_raidz.c has unused RAIDZ_SINGLE define, code
eschrock
parents: 789
diff changeset
    80
	firstdatacol = 1;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    81
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    82
	acols = (q == 0 ? bc : dcols);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    83
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    84
	rm = kmem_alloc(offsetof(raidz_map_t, rm_col[acols]), KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    85
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    86
	rm->rm_cols = acols;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    87
	rm->rm_bigcols = bc;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    88
	rm->rm_asize = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    89
	rm->rm_missing_child = -1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    90
	rm->rm_firstdatacol = firstdatacol;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    91
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    92
	for (c = 0; c < acols; c++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    93
		col = f + c;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    94
		coff = o;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    95
		if (col >= dcols) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    96
			col -= dcols;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    97
			coff += 1ULL << unit_shift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    98
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    99
		rm->rm_col[c].rc_col = col;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   100
		rm->rm_col[c].rc_offset = coff;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   101
		rm->rm_col[c].rc_size = (q + (c < bc)) << unit_shift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   102
		rm->rm_col[c].rc_data = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   103
		rm->rm_col[c].rc_error = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   104
		rm->rm_col[c].rc_tried = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   105
		rm->rm_col[c].rc_skipped = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   106
		rm->rm_asize += rm->rm_col[c].rc_size;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   107
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   108
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   109
	rm->rm_asize = P2ROUNDUP(rm->rm_asize, VDEV_RAIDZ_ALIGN << unit_shift);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   110
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   111
	for (c = 0; c < rm->rm_firstdatacol; c++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   112
		rm->rm_col[c].rc_data = zio_buf_alloc(rm->rm_col[c].rc_size);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   113
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   114
	rm->rm_col[c].rc_data = zio->io_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   115
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   116
	for (c = c + 1; c < acols; c++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   117
		rm->rm_col[c].rc_data = (char *)rm->rm_col[c - 1].rc_data +
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   118
		    rm->rm_col[c - 1].rc_size;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   119
1133
335d069294d1 6357470 vdev_raidz.c has unused RAIDZ_SINGLE define, code
eschrock
parents: 789
diff changeset
   120
	/*
335d069294d1 6357470 vdev_raidz.c has unused RAIDZ_SINGLE define, code
eschrock
parents: 789
diff changeset
   121
	 * To prevent hot parity disks, switch the parity and data
335d069294d1 6357470 vdev_raidz.c has unused RAIDZ_SINGLE define, code
eschrock
parents: 789
diff changeset
   122
	 * columns every 1MB.
335d069294d1 6357470 vdev_raidz.c has unused RAIDZ_SINGLE define, code
eschrock
parents: 789
diff changeset
   123
	 */
335d069294d1 6357470 vdev_raidz.c has unused RAIDZ_SINGLE define, code
eschrock
parents: 789
diff changeset
   124
	ASSERT(rm->rm_cols >= 2);
335d069294d1 6357470 vdev_raidz.c has unused RAIDZ_SINGLE define, code
eschrock
parents: 789
diff changeset
   125
	ASSERT(rm->rm_col[0].rc_size == rm->rm_col[1].rc_size);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   126
1133
335d069294d1 6357470 vdev_raidz.c has unused RAIDZ_SINGLE define, code
eschrock
parents: 789
diff changeset
   127
	if (zio->io_offset & (1ULL << 20)) {
335d069294d1 6357470 vdev_raidz.c has unused RAIDZ_SINGLE define, code
eschrock
parents: 789
diff changeset
   128
		col = rm->rm_col[0].rc_col;
335d069294d1 6357470 vdev_raidz.c has unused RAIDZ_SINGLE define, code
eschrock
parents: 789
diff changeset
   129
		o = rm->rm_col[0].rc_offset;
335d069294d1 6357470 vdev_raidz.c has unused RAIDZ_SINGLE define, code
eschrock
parents: 789
diff changeset
   130
		rm->rm_col[0].rc_col = rm->rm_col[1].rc_col;
335d069294d1 6357470 vdev_raidz.c has unused RAIDZ_SINGLE define, code
eschrock
parents: 789
diff changeset
   131
		rm->rm_col[0].rc_offset = rm->rm_col[1].rc_offset;
335d069294d1 6357470 vdev_raidz.c has unused RAIDZ_SINGLE define, code
eschrock
parents: 789
diff changeset
   132
		rm->rm_col[1].rc_col = col;
335d069294d1 6357470 vdev_raidz.c has unused RAIDZ_SINGLE define, code
eschrock
parents: 789
diff changeset
   133
		rm->rm_col[1].rc_offset = o;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   134
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   135
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   136
	zio->io_vsd = rm;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   137
	return (rm);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   138
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   139
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   140
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   141
vdev_raidz_map_free(zio_t *zio)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   142
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   143
	raidz_map_t *rm = zio->io_vsd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   144
	int c;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   145
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   146
	for (c = 0; c < rm->rm_firstdatacol; c++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   147
		zio_buf_free(rm->rm_col[c].rc_data, rm->rm_col[c].rc_size);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   148
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   149
	kmem_free(rm, offsetof(raidz_map_t, rm_col[rm->rm_cols]));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   150
	zio->io_vsd = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   151
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   152
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   153
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   154
vdev_raidz_reconstruct(raidz_map_t *rm, int x)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   155
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   156
	uint64_t *dst, *src, count, xsize, csize;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   157
	int i, c;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   158
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   159
	for (c = 0; c < rm->rm_cols; c++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   160
		if (c == x)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   161
			continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   162
		src = rm->rm_col[c].rc_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   163
		dst = rm->rm_col[x].rc_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   164
		csize = rm->rm_col[c].rc_size;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   165
		xsize = rm->rm_col[x].rc_size;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   166
		count = MIN(csize, xsize) / sizeof (uint64_t);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   167
		if (c == !x) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   168
			/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   169
			 * The initial copy happens at either c == 0 or c == 1.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   170
			 * Both of these columns are 'big' columns, so we'll
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   171
			 * definitely initialize all of column x.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   172
			 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   173
			ASSERT3U(xsize, <=, csize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   174
			for (i = 0; i < count; i++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   175
				*dst++ = *src++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   176
		} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   177
			for (i = 0; i < count; i++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   178
				*dst++ ^= *src++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   179
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   180
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   181
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   182
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   183
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   184
vdev_raidz_open(vdev_t *vd, uint64_t *asize, uint64_t *ashift)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   185
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   186
	vdev_t *cvd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   187
	int c, error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   188
	int lasterror = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   189
	int numerrors = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   190
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   191
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   192
	 * XXX -- minimum children should be raid-type-specific
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   193
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   194
	if (vd->vdev_children < 2) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   195
		vd->vdev_stat.vs_aux = VDEV_AUX_BAD_LABEL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   196
		return (EINVAL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   197
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   198
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   199
	for (c = 0; c < vd->vdev_children; c++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   200
		cvd = vd->vdev_child[c];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   201
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   202
		if ((error = vdev_open(cvd)) != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   203
			lasterror = error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   204
			numerrors++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   205
			continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   206
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   207
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   208
		*asize = MIN(*asize - 1, cvd->vdev_asize - 1) + 1;
1732
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   209
		*ashift = MAX(*ashift, cvd->vdev_ashift);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   210
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   211
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   212
	*asize *= vd->vdev_children;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   213
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   214
	if (numerrors > 1) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   215
		vd->vdev_stat.vs_aux = VDEV_AUX_NO_REPLICAS;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   216
		return (lasterror);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   217
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   218
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   219
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   220
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   221
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   222
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   223
vdev_raidz_close(vdev_t *vd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   224
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   225
	int c;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   226
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   227
	for (c = 0; c < vd->vdev_children; c++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   228
		vdev_close(vd->vdev_child[c]);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   229
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   230
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   231
static uint64_t
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   232
vdev_raidz_asize(vdev_t *vd, uint64_t psize)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   233
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   234
	uint64_t asize;
1732
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   235
	uint64_t ashift = vd->vdev_top->vdev_ashift;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   236
	uint64_t cols = vd->vdev_children;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   237
1732
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   238
	asize = ((psize - 1) >> ashift) + 1;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   239
	asize += (asize + cols - 2) / (cols - 1);
1732
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   240
	asize = P2ROUNDUP(asize, VDEV_RAIDZ_ALIGN) << ashift;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   241
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   242
	return (asize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   243
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   244
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   245
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   246
vdev_raidz_child_done(zio_t *zio)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   247
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   248
	raidz_col_t *rc = zio->io_private;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   249
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   250
	rc->rc_error = zio->io_error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   251
	rc->rc_tried = 1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   252
	rc->rc_skipped = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   253
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   254
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   255
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   256
vdev_raidz_repair_done(zio_t *zio)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   257
{
1732
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   258
	ASSERT(zio->io_private == zio->io_parent);
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   259
	vdev_raidz_map_free(zio->io_private);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   260
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   261
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   262
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   263
vdev_raidz_io_start(zio_t *zio)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   264
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   265
	vdev_t *vd = zio->io_vd;
1732
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   266
	vdev_t *tvd = vd->vdev_top;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   267
	vdev_t *cvd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   268
	blkptr_t *bp = zio->io_bp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   269
	raidz_map_t *rm;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   270
	raidz_col_t *rc;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   271
	int c;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   272
1732
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   273
	rm = vdev_raidz_map_alloc(zio, tvd->vdev_ashift, vd->vdev_children);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   274
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   275
	if (DVA_GET_GANG(ZIO_GET_DVA(zio))) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   276
		ASSERT3U(rm->rm_asize, ==,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   277
		    vdev_psize_to_asize(vd, SPA_GANGBLOCKSIZE));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   278
	} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   279
		ASSERT3U(rm->rm_asize, ==, DVA_GET_ASIZE(ZIO_GET_DVA(zio)));
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
	if (zio->io_type == ZIO_TYPE_WRITE) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   283
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   284
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   285
		 * Generate RAID parity in virtual column 0.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   286
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   287
		vdev_raidz_reconstruct(rm, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   288
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   289
		for (c = 0; c < rm->rm_cols; c++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   290
			rc = &rm->rm_col[c];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   291
			cvd = vd->vdev_child[rc->rc_col];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   292
			zio_nowait(zio_vdev_child_io(zio, NULL, cvd,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   293
			    rc->rc_offset, rc->rc_data, rc->rc_size,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   294
			    zio->io_type, zio->io_priority, ZIO_FLAG_CANFAIL,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   295
			    vdev_raidz_child_done, rc));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   296
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   297
		zio_wait_children_done(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   298
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   299
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   300
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   301
	ASSERT(zio->io_type == ZIO_TYPE_READ);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   302
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   303
	for (c = rm->rm_cols - 1; c >= 0; c--) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   304
		rc = &rm->rm_col[c];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   305
		cvd = vd->vdev_child[rc->rc_col];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   306
		if (vdev_is_dead(cvd)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   307
			rm->rm_missing_child = c;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   308
			rc->rc_error = ENXIO;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   309
			rc->rc_tried = 1;	/* don't even try */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   310
			rc->rc_skipped = 1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   311
			continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   312
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   313
		if (vdev_dtl_contains(&cvd->vdev_dtl_map, bp->blk_birth, 1)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   314
			rm->rm_missing_child = c;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   315
			rc->rc_error = ESTALE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   316
			rc->rc_skipped = 1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   317
			continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   318
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   319
		if (c >= rm->rm_firstdatacol || rm->rm_missing_child != -1 ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   320
		    (zio->io_flags & ZIO_FLAG_SCRUB)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   321
			zio_nowait(zio_vdev_child_io(zio, NULL, cvd,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   322
			    rc->rc_offset, rc->rc_data, rc->rc_size,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   323
			    zio->io_type, zio->io_priority, ZIO_FLAG_CANFAIL,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   324
			    vdev_raidz_child_done, rc));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   325
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   326
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   327
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   328
	zio_wait_children_done(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   329
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   330
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   331
/*
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   332
 * Report a checksum error for a child of a RAID-Z device.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   333
 */
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   334
static void
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   335
raidz_checksum_error(zio_t *zio, raidz_col_t *rc)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   336
{
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   337
	vdev_t *vd = zio->io_vd->vdev_child[rc->rc_col];
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   338
	dprintf_bp(zio->io_bp, "imputed checksum error on %s: ",
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   339
	    vdev_description(vd));
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   340
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   341
	if (!(zio->io_flags & ZIO_FLAG_SPECULATIVE)) {
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   342
		mutex_enter(&vd->vdev_stat_lock);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   343
		vd->vdev_stat.vs_checksum_errors++;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   344
		mutex_exit(&vd->vdev_stat_lock);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   345
	}
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   346
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   347
	if (!(zio->io_flags & ZIO_FLAG_SPECULATIVE))
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   348
		zfs_ereport_post(FM_EREPORT_ZFS_CHECKSUM,
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   349
		    zio->io_spa, vd, zio, rc->rc_offset, rc->rc_size);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   350
}
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   351
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   352
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   353
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   354
vdev_raidz_io_done(zio_t *zio)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   355
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   356
	vdev_t *vd = zio->io_vd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   357
	vdev_t *cvd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   358
	raidz_map_t *rm = zio->io_vsd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   359
	raidz_col_t *rc;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   360
	blkptr_t *bp = zio->io_bp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   361
	int unexpected_errors = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   362
	int c;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   363
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   364
	ASSERT(bp != NULL);	/* XXX need to add code to enforce this */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   365
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   366
	zio->io_error = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   367
	zio->io_numerrors = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   368
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   369
	for (c = 0; c < rm->rm_cols; c++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   370
		rc = &rm->rm_col[c];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   371
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   372
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   373
		 * We preserve any EIOs because those may be worth retrying;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   374
		 * whereas ECKSUM and ENXIO are more likely to be persistent.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   375
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   376
		if (rc->rc_error) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   377
			if (zio->io_error != EIO)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   378
				zio->io_error = rc->rc_error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   379
			if (!rc->rc_skipped)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   380
				unexpected_errors++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   381
			zio->io_numerrors++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   382
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   383
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   384
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   385
	if (zio->io_type == ZIO_TYPE_WRITE) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   386
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   387
		 * If this is not a failfast write, and we were able to
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   388
		 * write enough columns to reconstruct the data, good enough.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   389
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   390
		/* XXPOLICY */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   391
		if (zio->io_numerrors <= rm->rm_firstdatacol &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   392
		    !(zio->io_flags & ZIO_FLAG_FAILFAST))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   393
			zio->io_error = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   394
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   395
		vdev_raidz_map_free(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   396
		zio_next_stage(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   397
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   398
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   399
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   400
	ASSERT(zio->io_type == ZIO_TYPE_READ);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   401
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   402
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   403
	 * If there were no I/O errors, and the data checksums correctly,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   404
	 * the read is complete.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   405
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   406
	/* XXPOLICY */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   407
	if (zio->io_numerrors == 0 && zio_checksum_error(zio) == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   408
		ASSERT(unexpected_errors == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   409
		ASSERT(zio->io_error == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   410
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   411
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   412
		 * We know the data's good.  If we read the parity,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   413
		 * verify that it's good as well.  If not, fix it.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   414
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   415
		for (c = 0; c < rm->rm_firstdatacol; c++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   416
			void *orig;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   417
			rc = &rm->rm_col[c];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   418
			if (!rc->rc_tried)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   419
				continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   420
			orig = zio_buf_alloc(rc->rc_size);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   421
			bcopy(rc->rc_data, orig, rc->rc_size);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   422
			vdev_raidz_reconstruct(rm, c);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   423
			if (bcmp(orig, rc->rc_data, rc->rc_size) != 0) {
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   424
				raidz_checksum_error(zio, rc);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   425
				rc->rc_error = ECKSUM;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   426
				unexpected_errors++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   427
			}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   428
			zio_buf_free(orig, rc->rc_size);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   429
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   430
		goto done;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   431
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   432
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   433
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   434
	 * If there was exactly one I/O error, it's the one we expected,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   435
	 * and the reconstructed data checksums, the read is complete.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   436
	 * This happens when one child is offline and vdev_fault_assess()
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   437
	 * knows it, or when one child has stale data and the DTL knows it.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   438
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   439
	if (zio->io_numerrors == 1 && (c = rm->rm_missing_child) != -1) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   440
		rc = &rm->rm_col[c];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   441
		ASSERT(unexpected_errors == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   442
		ASSERT(rc->rc_error == ENXIO || rc->rc_error == ESTALE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   443
		vdev_raidz_reconstruct(rm, c);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   444
		if (zio_checksum_error(zio) == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   445
			zio->io_error = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   446
			goto done;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   447
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   448
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   449
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   450
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   451
	 * This isn't a typical error -- either we got a read error or
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   452
	 * more than one child claimed a problem.  Read every block we
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   453
	 * haven't already so we can try combinatorial reconstruction.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   454
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   455
	unexpected_errors = 1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   456
	rm->rm_missing_child = -1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   457
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   458
	for (c = 0; c < rm->rm_cols; c++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   459
		if (!rm->rm_col[c].rc_tried)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   460
			break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   461
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   462
	if (c != rm->rm_cols) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   463
		zio->io_error = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   464
		zio_vdev_io_redone(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   465
		for (c = 0; c < rm->rm_cols; c++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   466
			rc = &rm->rm_col[c];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   467
			if (rc->rc_tried)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   468
				continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   469
			zio_nowait(zio_vdev_child_io(zio, NULL,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   470
			    vd->vdev_child[rc->rc_col],
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   471
			    rc->rc_offset, rc->rc_data, rc->rc_size,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   472
			    zio->io_type, zio->io_priority, ZIO_FLAG_CANFAIL,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   473
			    vdev_raidz_child_done, rc));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   474
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   475
		zio_wait_children_done(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   476
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   477
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   478
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   479
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   480
	 * If there were more errors than parity disks, give up.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   481
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   482
	if (zio->io_numerrors > rm->rm_firstdatacol) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   483
		ASSERT(zio->io_error != 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   484
		goto done;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   485
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   486
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   487
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   488
	 * The number of I/O errors is correctable.  Correct them here.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   489
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   490
	ASSERT(zio->io_numerrors <= rm->rm_firstdatacol);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   491
	for (c = 0; c < rm->rm_cols; c++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   492
		rc = &rm->rm_col[c];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   493
		ASSERT(rc->rc_tried);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   494
		if (rc->rc_error) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   495
			vdev_raidz_reconstruct(rm, c);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   496
			if (zio_checksum_error(zio) == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   497
				zio->io_error = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   498
			else
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   499
				zio->io_error = rc->rc_error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   500
			goto done;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   501
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   502
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   503
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   504
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   505
	 * There were no I/O errors, but the data doesn't checksum.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   506
	 * Try all permutations to see if we can find one that does.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   507
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   508
	ASSERT(zio->io_numerrors == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   509
	for (c = 0; c < rm->rm_cols; c++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   510
		void *orig;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   511
		rc = &rm->rm_col[c];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   512
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   513
		orig = zio_buf_alloc(rc->rc_size);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   514
		bcopy(rc->rc_data, orig, rc->rc_size);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   515
		vdev_raidz_reconstruct(rm, c);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   516
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   517
		if (zio_checksum_error(zio) == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   518
			zio_buf_free(orig, rc->rc_size);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   519
			zio->io_error = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   520
			/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   521
			 * If this child didn't know that it returned bad data,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   522
			 * inform it.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   523
			 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   524
			if (rc->rc_tried && rc->rc_error == 0)
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   525
				raidz_checksum_error(zio, rc);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   526
			rc->rc_error = ECKSUM;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   527
			goto done;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   528
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   529
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   530
		bcopy(orig, rc->rc_data, rc->rc_size);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   531
		zio_buf_free(orig, rc->rc_size);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   532
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   533
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   534
	/*
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   535
	 * All combinations failed to checksum.  Generate checksum ereports for
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   536
	 * every one.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   537
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   538
	zio->io_error = ECKSUM;
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   539
	if (!(zio->io_flags & ZIO_FLAG_SPECULATIVE)) {
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   540
		for (c = 0; c < rm->rm_cols; c++) {
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   541
			rc = &rm->rm_col[c];
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   542
			zfs_ereport_post(FM_EREPORT_ZFS_CHECKSUM,
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   543
			    zio->io_spa, vd->vdev_child[rc->rc_col], zio,
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   544
			    rc->rc_offset, rc->rc_size);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   545
		}
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   546
	}
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   547
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   548
done:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   549
	zio_checksum_verified(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   550
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   551
	if (zio->io_error == 0 && (spa_mode & FWRITE) &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   552
	    (unexpected_errors || (zio->io_flags & ZIO_FLAG_RESILVER))) {
1732
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   553
		zio_t *rio;
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   554
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   555
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   556
		 * Use the good data we have in hand to repair damaged children.
1732
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   557
		 *
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   558
		 * We issue all repair I/Os as children of 'rio' to arrange
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   559
		 * that vdev_raidz_map_free(zio) will be invoked after all
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   560
		 * repairs complete, but before we advance to the next stage.
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   561
		 */
1732
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   562
		rio = zio_null(zio, zio->io_spa,
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   563
		    vdev_raidz_repair_done, zio, ZIO_FLAG_CANFAIL);
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   564
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   565
		for (c = 0; c < rm->rm_cols; c++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   566
			rc = &rm->rm_col[c];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   567
			cvd = vd->vdev_child[rc->rc_col];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   568
1732
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   569
			if (rc->rc_error == 0)
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   570
				continue;
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   571
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   572
			dprintf("%s resilvered %s @ 0x%llx error %d\n",
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   573
			    vdev_description(vd),
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   574
			    vdev_description(cvd),
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   575
			    zio->io_offset, rc->rc_error);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   576
1732
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   577
			zio_nowait(zio_vdev_child_io(rio, NULL, cvd,
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   578
			    rc->rc_offset, rc->rc_data, rc->rc_size,
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   579
			    ZIO_TYPE_WRITE, zio->io_priority,
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   580
			    ZIO_FLAG_IO_REPAIR | ZIO_FLAG_CANFAIL |
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   581
			    ZIO_FLAG_DONT_PROPAGATE, NULL, NULL));
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   582
		}
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   583
1732
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   584
		zio_nowait(rio);
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   585
		zio_wait_children_done(zio);
9e3ae798af31 6280668 pluggable block allocation policy
bonwick
parents: 1544
diff changeset
   586
		return;
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   587
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   588
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   589
	vdev_raidz_map_free(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   590
	zio_next_stage(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   591
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   592
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   593
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   594
vdev_raidz_state_change(vdev_t *vd, int faulted, int degraded)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   595
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   596
	if (faulted > 1)
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   597
		vdev_set_state(vd, B_FALSE, VDEV_STATE_CANT_OPEN,
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   598
		    VDEV_AUX_NO_REPLICAS);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   599
	else if (degraded + faulted != 0)
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   600
		vdev_set_state(vd, B_FALSE, VDEV_STATE_DEGRADED, VDEV_AUX_NONE);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   601
	else
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents: 1133
diff changeset
   602
		vdev_set_state(vd, B_FALSE, VDEV_STATE_HEALTHY, VDEV_AUX_NONE);
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   603
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   604
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   605
vdev_ops_t vdev_raidz_ops = {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   606
	vdev_raidz_open,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   607
	vdev_raidz_close,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   608
	vdev_raidz_asize,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   609
	vdev_raidz_io_start,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   610
	vdev_raidz_io_done,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   611
	vdev_raidz_state_change,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   612
	VDEV_TYPE_RAIDZ,	/* name of this vdev type */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   613
	B_FALSE			/* not a leaf vdev */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   614
};