usr/src/uts/common/fs/zfs/vdev.c
author ahrens
Mon, 31 Oct 2005 11:33:35 -0800
changeset 789 b348f31ed315
child 1171 b501e9f31cab
permissions -rw-r--r--
PSARC 2002/240 ZFS 6338653 Integrate ZFS PSARC 2004/652 - DKIOCFLUSH 5096886 Write caching disks need mechanism to flush cache to physical media
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
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     5
 * Common Development and Distribution License, Version 1.0 only
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     6
 * (the "License").  You may not use this file except in compliance
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     7
 * with the License.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     8
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     9
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    10
 * or http://www.opensolaris.org/os/licensing.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    11
 * See the License for the specific language governing permissions
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    12
 * and limitations under the License.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    13
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    14
 * When distributing Covered Code, include this CDDL HEADER in each
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    15
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    16
 * If applicable, add the following below this CDDL HEADER, with the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    17
 * fields enclosed by brackets "[]" replaced with your own identifying
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    18
 * information: Portions Copyright [yyyy] [name of copyright owner]
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    19
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    20
 * CDDL HEADER END
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    21
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    22
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    23
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
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/spa_impl.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    32
#include <sys/dmu.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    33
#include <sys/dmu_tx.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    34
#include <sys/vdev_impl.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    35
#include <sys/uberblock_impl.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    36
#include <sys/metaslab.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    37
#include <sys/metaslab_impl.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    38
#include <sys/space_map.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    39
#include <sys/zio.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    40
#include <sys/zap.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    41
#include <sys/fs/zfs.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    42
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    43
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    44
 * Virtual device management.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    45
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    46
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    47
static vdev_ops_t *vdev_ops_table[] = {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    48
	&vdev_root_ops,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    49
	&vdev_raidz_ops,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    50
	&vdev_mirror_ops,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    51
	&vdev_replacing_ops,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    52
	&vdev_disk_ops,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    53
	&vdev_file_ops,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    54
	&vdev_missing_ops,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    55
	NULL
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    56
};
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    57
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    58
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    59
 * Given a vdev type, return the appropriate ops vector.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    60
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    61
static vdev_ops_t *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    62
vdev_getops(const char *type)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    63
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    64
	vdev_ops_t *ops, **opspp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    65
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    66
	for (opspp = vdev_ops_table; (ops = *opspp) != NULL; opspp++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    67
		if (strcmp(ops->vdev_op_type, type) == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    68
			break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    69
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    70
	return (ops);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    71
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    72
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    73
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    74
 * Default asize function: return the MAX of psize with the asize of
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    75
 * all children.  This is what's used by anything other than RAID-Z.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    76
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    77
uint64_t
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    78
vdev_default_asize(vdev_t *vd, uint64_t psize)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    79
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    80
	uint64_t asize = P2ROUNDUP(psize, 1ULL << vd->vdev_ashift);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    81
	uint64_t csize;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    82
	uint64_t c;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    83
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    84
	for (c = 0; c < vd->vdev_children; c++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    85
		csize = vdev_psize_to_asize(vd->vdev_child[c], psize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    86
		asize = MAX(asize, csize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    87
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    88
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    89
	return (asize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    90
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    91
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    92
vdev_t *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    93
vdev_lookup_top(spa_t *spa, uint64_t vdev)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    94
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    95
	vdev_t *rvd = spa->spa_root_vdev;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    96
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    97
	if (vdev < rvd->vdev_children)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    98
		return (rvd->vdev_child[vdev]);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    99
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   100
	return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   101
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   102
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   103
vdev_t *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   104
vdev_lookup_by_path(vdev_t *vd, const char *path)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   105
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   106
	int c;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   107
	vdev_t *mvd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   108
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   109
	if (vd->vdev_path != NULL && strcmp(path, vd->vdev_path) == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   110
		return (vd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   111
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   112
	for (c = 0; c < vd->vdev_children; c++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   113
		if ((mvd = vdev_lookup_by_path(vd->vdev_child[c], path)) !=
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   114
		    NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   115
			return (mvd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   116
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   117
	return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   118
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   119
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   120
vdev_t *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   121
vdev_lookup_by_guid(vdev_t *vd, uint64_t guid)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   122
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   123
	int c;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   124
	vdev_t *mvd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   125
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   126
	if (vd->vdev_children == 0 && vd->vdev_guid == guid)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   127
		return (vd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   128
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   129
	for (c = 0; c < vd->vdev_children; c++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   130
		if ((mvd = vdev_lookup_by_guid(vd->vdev_child[c], guid)) !=
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   131
		    NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   132
			return (mvd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   133
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   134
	return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   135
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   136
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   137
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   138
vdev_add_child(vdev_t *pvd, vdev_t *cvd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   139
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   140
	size_t oldsize, newsize;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   141
	uint64_t id = cvd->vdev_id;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   142
	vdev_t **newchild;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   143
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   144
	ASSERT(spa_config_held(cvd->vdev_spa, RW_WRITER));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   145
	ASSERT(cvd->vdev_parent == NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   146
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   147
	cvd->vdev_parent = pvd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   148
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   149
	if (pvd == NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   150
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   151
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   152
	ASSERT(id >= pvd->vdev_children || pvd->vdev_child[id] == NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   153
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   154
	oldsize = pvd->vdev_children * sizeof (vdev_t *);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   155
	pvd->vdev_children = MAX(pvd->vdev_children, id + 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   156
	newsize = pvd->vdev_children * sizeof (vdev_t *);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   157
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   158
	newchild = kmem_zalloc(newsize, KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   159
	if (pvd->vdev_child != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   160
		bcopy(pvd->vdev_child, newchild, oldsize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   161
		kmem_free(pvd->vdev_child, oldsize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   162
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   163
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   164
	pvd->vdev_child = newchild;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   165
	pvd->vdev_child[id] = cvd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   166
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   167
	cvd->vdev_top = (pvd->vdev_top ? pvd->vdev_top: cvd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   168
	ASSERT(cvd->vdev_top->vdev_parent->vdev_parent == NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   169
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   170
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   171
	 * Walk up all ancestors to update guid sum.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   172
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   173
	for (; pvd != NULL; pvd = pvd->vdev_parent)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   174
		pvd->vdev_guid_sum += cvd->vdev_guid_sum;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   175
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   176
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   177
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   178
vdev_remove_child(vdev_t *pvd, vdev_t *cvd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   179
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   180
	int c;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   181
	uint_t id = cvd->vdev_id;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   182
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   183
	ASSERT(cvd->vdev_parent == pvd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   184
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   185
	if (pvd == NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   186
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   187
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   188
	ASSERT(id < pvd->vdev_children);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   189
	ASSERT(pvd->vdev_child[id] == cvd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   190
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   191
	pvd->vdev_child[id] = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   192
	cvd->vdev_parent = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   193
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   194
	for (c = 0; c < pvd->vdev_children; c++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   195
		if (pvd->vdev_child[c])
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   196
			break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   197
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   198
	if (c == pvd->vdev_children) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   199
		kmem_free(pvd->vdev_child, c * sizeof (vdev_t *));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   200
		pvd->vdev_child = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   201
		pvd->vdev_children = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   202
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   203
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   204
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   205
	 * Walk up all ancestors to update guid sum.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   206
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   207
	for (; pvd != NULL; pvd = pvd->vdev_parent)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   208
		pvd->vdev_guid_sum -= cvd->vdev_guid_sum;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   209
}
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
 * Remove any holes in the child array.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   213
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   214
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   215
vdev_compact_children(vdev_t *pvd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   216
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   217
	vdev_t **newchild, *cvd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   218
	int oldc = pvd->vdev_children;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   219
	int newc, c;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   220
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   221
	ASSERT(spa_config_held(pvd->vdev_spa, RW_WRITER));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   222
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   223
	for (c = newc = 0; c < oldc; c++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   224
		if (pvd->vdev_child[c])
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   225
			newc++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   226
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   227
	newchild = kmem_alloc(newc * sizeof (vdev_t *), KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   228
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   229
	for (c = newc = 0; c < oldc; c++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   230
		if ((cvd = pvd->vdev_child[c]) != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   231
			newchild[newc] = cvd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   232
			cvd->vdev_id = newc++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   233
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   234
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   235
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   236
	kmem_free(pvd->vdev_child, oldc * sizeof (vdev_t *));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   237
	pvd->vdev_child = newchild;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   238
	pvd->vdev_children = newc;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   239
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   240
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   241
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   242
 * Allocate and minimally initialize a vdev_t.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   243
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   244
static vdev_t *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   245
vdev_alloc_common(spa_t *spa, uint_t id, uint64_t guid, vdev_ops_t *ops)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   246
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   247
	vdev_t *vd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   248
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   249
	while (guid == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   250
		guid = spa_get_random(-1ULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   251
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   252
	vd = kmem_zalloc(sizeof (vdev_t), KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   253
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   254
	vd->vdev_spa = spa;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   255
	vd->vdev_id = id;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   256
	vd->vdev_guid = guid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   257
	vd->vdev_guid_sum = guid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   258
	vd->vdev_ops = ops;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   259
	vd->vdev_state = VDEV_STATE_CLOSED;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   260
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   261
	mutex_init(&vd->vdev_io_lock, NULL, MUTEX_DEFAULT, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   262
	cv_init(&vd->vdev_io_cv, NULL, CV_DEFAULT, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   263
	list_create(&vd->vdev_io_pending, sizeof (zio_t),
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   264
	    offsetof(zio_t, io_pending));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   265
	mutex_init(&vd->vdev_dirty_lock, NULL, MUTEX_DEFAULT, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   266
	mutex_init(&vd->vdev_dtl_lock, NULL, MUTEX_DEFAULT, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   267
	space_map_create(&vd->vdev_dtl_map, 0, -1ULL, 0, &vd->vdev_dtl_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   268
	space_map_create(&vd->vdev_dtl_scrub, 0, -1ULL, 0, &vd->vdev_dtl_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   269
	txg_list_create(&vd->vdev_ms_list,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   270
	    offsetof(struct metaslab, ms_txg_node));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   271
	txg_list_create(&vd->vdev_dtl_list,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   272
	    offsetof(struct vdev, vdev_dtl_node));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   273
	vd->vdev_stat.vs_timestamp = gethrtime();
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   274
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   275
	return (vd);
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
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   279
 * Free a vdev_t that has been removed from service.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   280
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   281
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   282
vdev_free_common(vdev_t *vd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   283
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   284
	if (vd->vdev_path)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   285
		spa_strfree(vd->vdev_path);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   286
	if (vd->vdev_devid)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   287
		spa_strfree(vd->vdev_devid);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   288
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   289
	txg_list_destroy(&vd->vdev_ms_list);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   290
	txg_list_destroy(&vd->vdev_dtl_list);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   291
	mutex_enter(&vd->vdev_dtl_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   292
	space_map_vacate(&vd->vdev_dtl_map, NULL, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   293
	space_map_destroy(&vd->vdev_dtl_map);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   294
	space_map_vacate(&vd->vdev_dtl_scrub, NULL, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   295
	space_map_destroy(&vd->vdev_dtl_scrub);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   296
	mutex_exit(&vd->vdev_dtl_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   297
	mutex_destroy(&vd->vdev_dtl_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   298
	mutex_destroy(&vd->vdev_dirty_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   299
	list_destroy(&vd->vdev_io_pending);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   300
	mutex_destroy(&vd->vdev_io_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   301
	cv_destroy(&vd->vdev_io_cv);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   302
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   303
	kmem_free(vd, sizeof (vdev_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   304
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   305
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   306
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   307
 * Allocate a new vdev.  The 'alloctype' is used to control whether we are
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   308
 * creating a new vdev or loading an existing one - the behavior is slightly
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   309
 * different for each case.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   310
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   311
vdev_t *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   312
vdev_alloc(spa_t *spa, nvlist_t *nv, vdev_t *parent, uint_t id, int alloctype)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   313
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   314
	vdev_ops_t *ops;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   315
	char *type;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   316
	uint64_t guid = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   317
	vdev_t *vd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   318
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   319
	ASSERT(spa_config_held(spa, RW_WRITER));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   320
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   321
	if (nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) != 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   322
		return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   323
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   324
	if ((ops = vdev_getops(type)) == NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   325
		return (NULL);
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
	 * If this is a load, get the vdev guid from the nvlist.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   329
	 * Otherwise, vdev_alloc_common() will generate one for us.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   330
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   331
	if (alloctype == VDEV_ALLOC_LOAD) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   332
		uint64_t label_id;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   333
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   334
		if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ID, &label_id) ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   335
		    label_id != id)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   336
			return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   337
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   338
		if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) != 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   339
			return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   340
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   341
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   342
	vd = vdev_alloc_common(spa, id, guid, ops);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   343
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   344
	if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &vd->vdev_path) == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   345
		vd->vdev_path = spa_strdup(vd->vdev_path);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   346
	if (nvlist_lookup_string(nv, ZPOOL_CONFIG_DEVID, &vd->vdev_devid) == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   347
		vd->vdev_devid = spa_strdup(vd->vdev_devid);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   348
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   349
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   350
	 * If we're a top-level vdev, try to load the allocation parameters.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   351
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   352
	if (parent && !parent->vdev_parent && alloctype == VDEV_ALLOC_LOAD) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   353
		(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_METASLAB_ARRAY,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   354
		    &vd->vdev_ms_array);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   355
		(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_METASLAB_SHIFT,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   356
		    &vd->vdev_ms_shift);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   357
		(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ASHIFT,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   358
		    &vd->vdev_ashift);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   359
		(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ASIZE,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   360
		    &vd->vdev_asize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   361
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   362
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   363
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   364
	 * If we're a leaf vdev, try to load the DTL object.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   365
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   366
	if (vd->vdev_ops->vdev_op_leaf && alloctype == VDEV_ALLOC_LOAD) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   367
		(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_DTL,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   368
		    &vd->vdev_dtl.smo_object);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   369
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   370
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   371
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   372
	 * Add ourselves to the parent's list of children.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   373
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   374
	vdev_add_child(parent, vd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   375
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   376
	return (vd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   377
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   378
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   379
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   380
vdev_free(vdev_t *vd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   381
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   382
	int c;
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
	 * vdev_free() implies closing the vdev first.  This is simpler than
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   386
	 * trying to ensure complicated semantics for all callers.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   387
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   388
	vdev_close(vd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   389
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   390
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   391
	 * It's possible to free a vdev that's been added to the dirty
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   392
	 * list when in the middle of spa_vdev_add().  Handle that case
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   393
	 * correctly here.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   394
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   395
	if (vd->vdev_is_dirty)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   396
		vdev_config_clean(vd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   397
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   398
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   399
	 * Free all children.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   400
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   401
	for (c = 0; c < vd->vdev_children; c++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   402
		vdev_free(vd->vdev_child[c]);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   403
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   404
	ASSERT(vd->vdev_child == NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   405
	ASSERT(vd->vdev_guid_sum == vd->vdev_guid);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   406
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   407
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   408
	 * Discard allocation state.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   409
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   410
	if (vd == vd->vdev_top)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   411
		vdev_metaslab_fini(vd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   412
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   413
	ASSERT3U(vd->vdev_stat.vs_space, ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   414
	ASSERT3U(vd->vdev_stat.vs_alloc, ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   415
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   416
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   417
	 * Remove this vdev from its parent's child list.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   418
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   419
	vdev_remove_child(vd->vdev_parent, vd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   420
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   421
	ASSERT(vd->vdev_parent == NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   422
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   423
	vdev_free_common(vd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   424
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   425
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   426
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   427
 * Transfer top-level vdev state from svd to tvd.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   428
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   429
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   430
vdev_top_transfer(vdev_t *svd, vdev_t *tvd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   431
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   432
	spa_t *spa = svd->vdev_spa;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   433
	metaslab_t *msp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   434
	vdev_t *vd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   435
	int t;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   436
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   437
	ASSERT(tvd == tvd->vdev_top);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   438
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   439
	tvd->vdev_ms_array = svd->vdev_ms_array;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   440
	tvd->vdev_ms_shift = svd->vdev_ms_shift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   441
	tvd->vdev_ms_count = svd->vdev_ms_count;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   442
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   443
	svd->vdev_ms_array = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   444
	svd->vdev_ms_shift = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   445
	svd->vdev_ms_count = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   446
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   447
	tvd->vdev_mg = svd->vdev_mg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   448
	tvd->vdev_mg->mg_vd = tvd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   449
	tvd->vdev_ms = svd->vdev_ms;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   450
	tvd->vdev_smo = svd->vdev_smo;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   451
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   452
	svd->vdev_mg = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   453
	svd->vdev_ms = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   454
	svd->vdev_smo = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   455
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   456
	tvd->vdev_stat.vs_alloc = svd->vdev_stat.vs_alloc;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   457
	tvd->vdev_stat.vs_space = svd->vdev_stat.vs_space;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   458
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   459
	svd->vdev_stat.vs_alloc = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   460
	svd->vdev_stat.vs_space = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   461
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   462
	for (t = 0; t < TXG_SIZE; t++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   463
		while ((msp = txg_list_remove(&svd->vdev_ms_list, t)) != NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   464
			(void) txg_list_add(&tvd->vdev_ms_list, msp, t);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   465
		while ((vd = txg_list_remove(&svd->vdev_dtl_list, t)) != NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   466
			(void) txg_list_add(&tvd->vdev_dtl_list, vd, t);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   467
		if (txg_list_remove_this(&spa->spa_vdev_txg_list, svd, t))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   468
			(void) txg_list_add(&spa->spa_vdev_txg_list, tvd, t);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   469
		tvd->vdev_dirty[t] = svd->vdev_dirty[t];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   470
		svd->vdev_dirty[t] = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   471
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   472
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   473
	if (svd->vdev_is_dirty) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   474
		vdev_config_clean(svd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   475
		vdev_config_dirty(tvd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   476
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   477
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   478
	ASSERT(svd->vdev_io_retry == NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   479
	ASSERT(list_is_empty(&svd->vdev_io_pending));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   480
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   481
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   482
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   483
vdev_top_update(vdev_t *tvd, vdev_t *vd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   484
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   485
	int c;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   486
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   487
	if (vd == NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   488
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   489
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   490
	vd->vdev_top = tvd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   491
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   492
	for (c = 0; c < vd->vdev_children; c++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   493
		vdev_top_update(tvd, vd->vdev_child[c]);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   494
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   495
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   496
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   497
 * Add a mirror/replacing vdev above an existing vdev.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   498
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   499
vdev_t *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   500
vdev_add_parent(vdev_t *cvd, vdev_ops_t *ops)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   501
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   502
	spa_t *spa = cvd->vdev_spa;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   503
	vdev_t *pvd = cvd->vdev_parent;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   504
	vdev_t *mvd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   505
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   506
	ASSERT(spa_config_held(spa, RW_WRITER));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   507
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   508
	mvd = vdev_alloc_common(spa, cvd->vdev_id, 0, ops);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   509
	vdev_remove_child(pvd, cvd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   510
	vdev_add_child(pvd, mvd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   511
	cvd->vdev_id = mvd->vdev_children;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   512
	vdev_add_child(mvd, cvd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   513
	vdev_top_update(cvd->vdev_top, cvd->vdev_top);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   514
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   515
	mvd->vdev_asize = cvd->vdev_asize;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   516
	mvd->vdev_ashift = cvd->vdev_ashift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   517
	mvd->vdev_state = cvd->vdev_state;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   518
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   519
	if (mvd == mvd->vdev_top)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   520
		vdev_top_transfer(cvd, mvd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   521
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   522
	return (mvd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   523
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   524
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   525
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   526
 * Remove a 1-way mirror/replacing vdev from the tree.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   527
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   528
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   529
vdev_remove_parent(vdev_t *cvd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   530
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   531
	vdev_t *mvd = cvd->vdev_parent;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   532
	vdev_t *pvd = mvd->vdev_parent;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   533
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   534
	ASSERT(spa_config_held(cvd->vdev_spa, RW_WRITER));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   535
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   536
	ASSERT(mvd->vdev_children == 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   537
	ASSERT(mvd->vdev_ops == &vdev_mirror_ops ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   538
	    mvd->vdev_ops == &vdev_replacing_ops);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   539
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   540
	vdev_remove_child(mvd, cvd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   541
	vdev_remove_child(pvd, mvd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   542
	cvd->vdev_id = mvd->vdev_id;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   543
	vdev_add_child(pvd, cvd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   544
	vdev_top_update(cvd->vdev_top, cvd->vdev_top);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   545
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   546
	if (cvd == cvd->vdev_top)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   547
		vdev_top_transfer(mvd, cvd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   548
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   549
	ASSERT(mvd->vdev_children == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   550
	vdev_free(mvd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   551
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   552
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   553
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   554
vdev_metaslab_init(vdev_t *vd, uint64_t txg)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   555
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   556
	spa_t *spa = vd->vdev_spa;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   557
	metaslab_class_t *mc = spa_metaslab_class_select(spa);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   558
	uint64_t c;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   559
	uint64_t oldc = vd->vdev_ms_count;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   560
	uint64_t newc = vd->vdev_asize >> vd->vdev_ms_shift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   561
	space_map_obj_t *smo = vd->vdev_smo;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   562
	metaslab_t **mspp = vd->vdev_ms;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   563
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   564
	dprintf("%s oldc %llu newc %llu\n", vdev_description(vd), oldc, newc);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   565
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   566
	ASSERT(oldc <= newc);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   567
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   568
	vd->vdev_smo = kmem_zalloc(newc * sizeof (*smo), KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   569
	vd->vdev_ms = kmem_zalloc(newc * sizeof (*mspp), KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   570
	vd->vdev_ms_count = newc;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   571
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   572
	if (vd->vdev_mg == NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   573
		if (txg == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   574
			dmu_buf_t *db;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   575
			uint64_t *ms_array;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   576
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   577
			ms_array = kmem_zalloc(newc * sizeof (uint64_t),
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   578
			    KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   579
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   580
			dmu_read(spa->spa_meta_objset, vd->vdev_ms_array,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   581
			    0, newc * sizeof (uint64_t), ms_array);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   582
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   583
			for (c = 0; c < newc; c++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   584
				if (ms_array[c] == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   585
					continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   586
				db = dmu_bonus_hold(spa->spa_meta_objset,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   587
				    ms_array[c]);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   588
				dmu_buf_read(db);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   589
				ASSERT3U(db->db_size, ==, sizeof (*smo));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   590
				bcopy(db->db_data, &vd->vdev_smo[c],
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   591
				    db->db_size);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   592
				ASSERT3U(vd->vdev_smo[c].smo_object, ==,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   593
				    ms_array[c]);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   594
				dmu_buf_rele(db);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   595
			}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   596
			kmem_free(ms_array, newc * sizeof (uint64_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   597
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   598
		vd->vdev_mg = metaslab_group_create(mc, vd);
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
	for (c = 0; c < oldc; c++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   602
		vd->vdev_smo[c] = smo[c];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   603
		vd->vdev_ms[c] = mspp[c];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   604
		mspp[c]->ms_smo = &vd->vdev_smo[c];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   605
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   606
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   607
	for (c = oldc; c < newc; c++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   608
		metaslab_init(vd->vdev_mg, &vd->vdev_smo[c], &vd->vdev_ms[c],
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   609
		    c << vd->vdev_ms_shift, 1ULL << vd->vdev_ms_shift, txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   610
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   611
	if (oldc != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   612
		kmem_free(smo, oldc * sizeof (*smo));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   613
		kmem_free(mspp, oldc * sizeof (*mspp));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   614
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   615
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   616
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   617
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   618
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   619
vdev_metaslab_fini(vdev_t *vd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   620
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   621
	uint64_t m;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   622
	uint64_t count = vd->vdev_ms_count;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   623
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   624
	if (vd->vdev_ms != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   625
		for (m = 0; m < count; m++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   626
			metaslab_fini(vd->vdev_ms[m]);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   627
		kmem_free(vd->vdev_ms, count * sizeof (metaslab_t *));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   628
		vd->vdev_ms = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   629
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   630
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   631
	if (vd->vdev_smo != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   632
		kmem_free(vd->vdev_smo, count * sizeof (space_map_obj_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   633
		vd->vdev_smo = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   634
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   635
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   636
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   637
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   638
 * Prepare a virtual device for access.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   639
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   640
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   641
vdev_open(vdev_t *vd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   642
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   643
	int error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   644
	vdev_knob_t *vk;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   645
	int c;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   646
	uint64_t osize = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   647
	uint64_t asize, psize;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   648
	uint64_t ashift = -1ULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   649
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   650
	ASSERT(vd->vdev_state == VDEV_STATE_CLOSED ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   651
	    vd->vdev_state == VDEV_STATE_CANT_OPEN ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   652
	    vd->vdev_state == VDEV_STATE_OFFLINE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   653
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   654
	if (vd->vdev_fault_mode == VDEV_FAULT_COUNT)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   655
		vd->vdev_fault_arg >>= 1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   656
	else
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   657
		vd->vdev_fault_mode = VDEV_FAULT_NONE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   658
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   659
	vd->vdev_stat.vs_aux = VDEV_AUX_NONE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   660
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   661
	for (vk = vdev_knob_next(NULL); vk != NULL; vk = vdev_knob_next(vk)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   662
		uint64_t *valp = (uint64_t *)((char *)vd + vk->vk_offset);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   663
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   664
		*valp = vk->vk_default;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   665
		*valp = MAX(*valp, vk->vk_min);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   666
		*valp = MIN(*valp, vk->vk_max);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   667
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   668
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   669
	if (vd->vdev_ops->vdev_op_leaf) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   670
		vdev_cache_init(vd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   671
		vdev_queue_init(vd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   672
		vd->vdev_cache_active = B_TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   673
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   674
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   675
	if (vd->vdev_offline) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   676
		ASSERT(vd->vdev_children == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   677
		dprintf("OFFLINE: %s = ENXIO\n", vdev_description(vd));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   678
		vd->vdev_state = VDEV_STATE_OFFLINE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   679
		return (ENXIO);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   680
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   681
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   682
	error = vd->vdev_ops->vdev_op_open(vd, &osize, &ashift);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   683
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   684
	dprintf("%s = %d, osize %llu, state = %d\n",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   685
	    vdev_description(vd), error, osize, vd->vdev_state);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   686
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   687
	if (error) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   688
		dprintf("%s in %s failed to open, error %d, aux %d\n",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   689
		    vdev_description(vd),
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   690
		    vdev_description(vd->vdev_parent),
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   691
		    error,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   692
		    vd->vdev_stat.vs_aux);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   693
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   694
		vd->vdev_state = VDEV_STATE_CANT_OPEN;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   695
		return (error);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   696
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   697
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   698
	vd->vdev_state = VDEV_STATE_HEALTHY;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   699
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   700
	for (c = 0; c < vd->vdev_children; c++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   701
		if (vd->vdev_child[c]->vdev_state != VDEV_STATE_HEALTHY)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   702
			vd->vdev_state = VDEV_STATE_DEGRADED;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   703
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   704
	osize = P2ALIGN(osize, (uint64_t)sizeof (vdev_label_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   705
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   706
	if (vd->vdev_children == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   707
		if (osize < SPA_MINDEVSIZE) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   708
			vd->vdev_state = VDEV_STATE_CANT_OPEN;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   709
			vd->vdev_stat.vs_aux = VDEV_AUX_TOO_SMALL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   710
			return (EOVERFLOW);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   711
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   712
		psize = osize;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   713
		asize = osize - (VDEV_LABEL_START_SIZE + VDEV_LABEL_END_SIZE);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   714
	} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   715
		if (osize < SPA_MINDEVSIZE -
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   716
		    (VDEV_LABEL_START_SIZE + VDEV_LABEL_END_SIZE)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   717
			vd->vdev_state = VDEV_STATE_CANT_OPEN;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   718
			vd->vdev_stat.vs_aux = VDEV_AUX_TOO_SMALL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   719
			return (EOVERFLOW);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   720
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   721
		psize = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   722
		asize = osize;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   723
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   724
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   725
	vd->vdev_psize = psize;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   726
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   727
	if (vd->vdev_asize == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   728
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   729
		 * This is the first-ever open, so use the computed values.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   730
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   731
		vd->vdev_asize = asize;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   732
		vd->vdev_ashift = ashift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   733
	} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   734
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   735
		 * Make sure the alignment requirement hasn't increased.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   736
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   737
		if (ashift > vd->vdev_ashift) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   738
			dprintf("%s: ashift grew\n", vdev_description(vd));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   739
			vd->vdev_state = VDEV_STATE_CANT_OPEN;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   740
			vd->vdev_stat.vs_aux = VDEV_AUX_BAD_LABEL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   741
			return (EINVAL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   742
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   743
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   744
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   745
		 * Make sure the device hasn't shrunk.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   746
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   747
		if (asize < vd->vdev_asize) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   748
			dprintf("%s: device shrank\n", vdev_description(vd));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   749
			vd->vdev_state = VDEV_STATE_CANT_OPEN;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   750
			vd->vdev_stat.vs_aux = VDEV_AUX_BAD_LABEL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   751
			return (EINVAL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   752
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   753
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   754
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   755
		 * If all children are healthy and the asize has increased,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   756
		 * then we've experienced dynamic LUN growth.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   757
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   758
		if (vd->vdev_state == VDEV_STATE_HEALTHY &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   759
		    asize > vd->vdev_asize) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   760
			dprintf("%s: device grew\n", vdev_description(vd));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   761
			vd->vdev_asize = asize;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   762
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   763
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   764
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   765
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   766
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   767
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   768
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   769
 * Close a virtual device.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   770
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   771
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   772
vdev_close(vdev_t *vd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   773
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   774
	ASSERT3P(list_head(&vd->vdev_io_pending), ==, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   775
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   776
	vd->vdev_ops->vdev_op_close(vd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   777
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   778
	if (vd->vdev_cache_active) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   779
		vdev_cache_fini(vd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   780
		vdev_queue_fini(vd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   781
		vd->vdev_cache_active = B_FALSE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   782
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   783
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   784
	if (vd->vdev_offline)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   785
		vd->vdev_state = VDEV_STATE_OFFLINE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   786
	else
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   787
		vd->vdev_state = VDEV_STATE_CLOSED;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   788
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   790
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   791
vdev_reopen(vdev_t *vd, zio_t **rq)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   792
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   793
	vdev_t *rvd = vd->vdev_spa->spa_root_vdev;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   794
	int c;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   795
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   796
	if (vd == rvd) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   797
		ASSERT(rq == NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   798
		for (c = 0; c < rvd->vdev_children; c++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   799
			vdev_reopen(rvd->vdev_child[c], NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   800
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   801
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   802
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   803
	/* only valid for top-level vdevs */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   804
	ASSERT3P(vd, ==, vd->vdev_top);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   805
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   806
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   807
	 * vdev_state can change when spa_config_lock is held as writer,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   808
	 * or when it's held as reader and we're doing a vdev_reopen().
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   809
	 * To handle the latter case, we grab rvd's io_lock to serialize
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   810
	 * reopens.  This ensures that there's never more than one vdev
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   811
	 * state changer active at a time.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   812
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   813
	mutex_enter(&rvd->vdev_io_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   814
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   815
	mutex_enter(&vd->vdev_io_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   816
	while (list_head(&vd->vdev_io_pending) != NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   817
		cv_wait(&vd->vdev_io_cv, &vd->vdev_io_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   818
	vdev_close(vd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   819
	(void) vdev_open(vd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   820
	if (rq != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   821
		*rq = vd->vdev_io_retry;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   822
		vd->vdev_io_retry = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   823
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   824
	mutex_exit(&vd->vdev_io_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   825
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   826
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   827
	 * Reassess root vdev's health.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   828
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   829
	rvd->vdev_state = VDEV_STATE_HEALTHY;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   830
	for (c = 0; c < rvd->vdev_children; c++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   831
		uint64_t state = rvd->vdev_child[c]->vdev_state;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   832
		rvd->vdev_state = MIN(rvd->vdev_state, state);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   833
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   834
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   835
	mutex_exit(&rvd->vdev_io_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   836
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   837
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   838
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   839
vdev_create(vdev_t *vd, uint64_t txg)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   840
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   841
	int error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   842
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   843
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   844
	 * Normally, partial opens (e.g. of a mirror) are allowed.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   845
	 * For a create, however, we want to fail the request if
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   846
	 * there are any components we can't open.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   847
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   848
	error = vdev_open(vd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   849
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   850
	if (error || vd->vdev_state != VDEV_STATE_HEALTHY) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   851
		vdev_close(vd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   852
		return (error ? error : ENXIO);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   853
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   854
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   855
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   856
	 * Recursively initialize all labels.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   857
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   858
	if ((error = vdev_label_init(vd, txg)) != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   859
		vdev_close(vd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   860
		return (error);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   861
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   862
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   863
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   864
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   865
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   866
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   867
 * The is the latter half of vdev_create().  It is distinct because it
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   868
 * involves initiating transactions in order to do metaslab creation.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   869
 * For creation, we want to try to create all vdevs at once and then undo it
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   870
 * if anything fails; this is much harder if we have pending transactions.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   871
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   872
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   873
vdev_init(vdev_t *vd, uint64_t txg)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   874
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   875
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   876
	 * Aim for roughly 200 metaslabs per vdev.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   877
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   878
	vd->vdev_ms_shift = highbit(vd->vdev_asize / 200);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   879
	vd->vdev_ms_shift = MAX(vd->vdev_ms_shift, SPA_MAXBLOCKSHIFT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   880
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   881
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   882
	 * Initialize the vdev's metaslabs.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   883
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   884
	vdev_metaslab_init(vd, txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   885
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   886
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   887
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   888
vdev_dirty(vdev_t *vd, uint8_t flags, uint64_t txg)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   889
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   890
	vdev_t *tvd = vd->vdev_top;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   891
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   892
	mutex_enter(&tvd->vdev_dirty_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   893
	if ((tvd->vdev_dirty[txg & TXG_MASK] & flags) != flags) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   894
		tvd->vdev_dirty[txg & TXG_MASK] |= flags;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   895
		(void) txg_list_add(&tvd->vdev_spa->spa_vdev_txg_list,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   896
		    tvd, txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   897
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   898
	mutex_exit(&tvd->vdev_dirty_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   899
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   900
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   901
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   902
vdev_dtl_dirty(space_map_t *sm, uint64_t txg, uint64_t size)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   903
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   904
	mutex_enter(sm->sm_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   905
	if (!space_map_contains(sm, txg, size))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   906
		space_map_add(sm, txg, size);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   907
	mutex_exit(sm->sm_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   908
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   909
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   910
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   911
vdev_dtl_contains(space_map_t *sm, uint64_t txg, uint64_t size)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   912
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   913
	int dirty;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   914
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   915
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   916
	 * Quick test without the lock -- covers the common case that
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   917
	 * there are no dirty time segments.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   918
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   919
	if (sm->sm_space == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   920
		return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   921
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   922
	mutex_enter(sm->sm_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   923
	dirty = space_map_contains(sm, txg, size);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   924
	mutex_exit(sm->sm_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   925
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   926
	return (dirty);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   927
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   928
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   929
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   930
 * Reassess DTLs after a config change or scrub completion.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   931
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   932
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   933
vdev_dtl_reassess(vdev_t *vd, uint64_t txg, uint64_t scrub_txg, int scrub_done)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   934
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   935
	int c;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   936
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   937
	ASSERT(spa_config_held(vd->vdev_spa, RW_WRITER));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   938
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   939
	if (vd->vdev_children == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   940
		mutex_enter(&vd->vdev_dtl_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   941
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   942
		 * We're successfully scrubbed everything up to scrub_txg.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   943
		 * Therefore, excise all old DTLs up to that point, then
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   944
		 * fold in the DTLs for everything we couldn't scrub.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   945
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   946
		if (scrub_txg != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   947
			space_map_excise(&vd->vdev_dtl_map, 0, scrub_txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   948
			space_map_union(&vd->vdev_dtl_map, &vd->vdev_dtl_scrub);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   949
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   950
		if (scrub_done)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   951
			space_map_vacate(&vd->vdev_dtl_scrub, NULL, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   952
		mutex_exit(&vd->vdev_dtl_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   953
		if (txg != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   954
			vdev_t *tvd = vd->vdev_top;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   955
			vdev_dirty(tvd, VDD_DTL, txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   956
			(void) txg_list_add(&tvd->vdev_dtl_list, vd, txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   957
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   958
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   959
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   960
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   961
	mutex_enter(&vd->vdev_dtl_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   962
	space_map_vacate(&vd->vdev_dtl_map, NULL, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   963
	space_map_vacate(&vd->vdev_dtl_scrub, NULL, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   964
	mutex_exit(&vd->vdev_dtl_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   965
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   966
	for (c = 0; c < vd->vdev_children; c++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   967
		vdev_t *cvd = vd->vdev_child[c];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   968
		vdev_dtl_reassess(cvd, txg, scrub_txg, scrub_done);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   969
		mutex_enter(&vd->vdev_dtl_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   970
		space_map_union(&vd->vdev_dtl_map, &cvd->vdev_dtl_map);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   971
		space_map_union(&vd->vdev_dtl_scrub, &cvd->vdev_dtl_scrub);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   972
		mutex_exit(&vd->vdev_dtl_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   973
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   974
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   975
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   976
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   977
vdev_dtl_load(vdev_t *vd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   978
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   979
	spa_t *spa = vd->vdev_spa;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   980
	space_map_obj_t *smo = &vd->vdev_dtl;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   981
	dmu_buf_t *db;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   982
	int error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   983
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   984
	ASSERT(vd->vdev_children == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   985
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   986
	if (smo->smo_object == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   987
		return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   988
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   989
	db = dmu_bonus_hold(spa->spa_meta_objset, smo->smo_object);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   990
	dmu_buf_read(db);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   991
	ASSERT3U(db->db_size, ==, sizeof (*smo));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   992
	bcopy(db->db_data, smo, db->db_size);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   993
	dmu_buf_rele(db);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   994
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   995
	mutex_enter(&vd->vdev_dtl_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   996
	error = space_map_load(&vd->vdev_dtl_map, smo, SM_ALLOC,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   997
	    spa->spa_meta_objset, smo->smo_objsize, smo->smo_alloc);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   998
	mutex_exit(&vd->vdev_dtl_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   999
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1000
	return (error);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1001
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1002
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1003
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1004
vdev_dtl_sync(vdev_t *vd, uint64_t txg)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1005
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1006
	spa_t *spa = vd->vdev_spa;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1007
	space_map_obj_t *smo = &vd->vdev_dtl;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1008
	space_map_t *sm = &vd->vdev_dtl_map;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1009
	space_map_t smsync;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1010
	kmutex_t smlock;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1011
	avl_tree_t *t = &sm->sm_root;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1012
	space_seg_t *ss;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1013
	dmu_buf_t *db;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1014
	dmu_tx_t *tx;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1015
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1016
	dprintf("%s in txg %llu pass %d\n",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1017
	    vdev_description(vd), (u_longlong_t)txg, spa_sync_pass(spa));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1018
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1019
	tx = dmu_tx_create_assigned(spa->spa_dsl_pool, txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1020
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1021
	if (vd->vdev_detached) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1022
		if (smo->smo_object != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1023
			int err = dmu_object_free(spa->spa_meta_objset,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1024
			    smo->smo_object, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1025
			ASSERT3U(err, ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1026
			smo->smo_object = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1027
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1028
		dmu_tx_commit(tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1029
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1030
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1031
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1032
	if (smo->smo_object == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1033
		ASSERT(smo->smo_objsize == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1034
		ASSERT(smo->smo_alloc == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1035
		smo->smo_object = dmu_object_alloc(spa->spa_meta_objset,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1036
		    DMU_OT_SPACE_MAP, 1 << SPACE_MAP_BLOCKSHIFT,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1037
		    DMU_OT_SPACE_MAP_HEADER, sizeof (*smo), tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1038
		ASSERT(smo->smo_object != 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1039
		vdev_config_dirty(vd->vdev_top);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1040
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1041
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1042
	dmu_free_range(spa->spa_meta_objset, smo->smo_object,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1043
	    0, smo->smo_objsize, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1044
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1045
	mutex_init(&smlock, NULL, MUTEX_DEFAULT, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1046
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1047
	space_map_create(&smsync, sm->sm_start, sm->sm_size, sm->sm_shift,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1048
	    &smlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1049
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1050
	mutex_enter(&smlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1051
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1052
	mutex_enter(&vd->vdev_dtl_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1053
	for (ss = avl_first(t); ss != NULL; ss = AVL_NEXT(t, ss))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1054
		space_map_add(&smsync, ss->ss_start, ss->ss_end - ss->ss_start);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1055
	mutex_exit(&vd->vdev_dtl_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1056
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1057
	smo->smo_objsize = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1058
	smo->smo_alloc = smsync.sm_space;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1059
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1060
	space_map_sync(&smsync, NULL, smo, SM_ALLOC, spa->spa_meta_objset, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1061
	space_map_destroy(&smsync);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1062
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1063
	mutex_exit(&smlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1064
	mutex_destroy(&smlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1065
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1066
	db = dmu_bonus_hold(spa->spa_meta_objset, smo->smo_object);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1067
	dmu_buf_will_dirty(db, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1068
	ASSERT3U(db->db_size, ==, sizeof (*smo));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1069
	bcopy(smo, db->db_data, db->db_size);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1070
	dmu_buf_rele(db);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1071
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1072
	dmu_tx_commit(tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1073
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1074
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1075
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1076
vdev_load(vdev_t *vd, int import)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1077
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1078
	spa_t *spa = vd->vdev_spa;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1079
	int c, error;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1080
	nvlist_t *label;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1081
	uint64_t guid, state;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1082
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1083
	dprintf("loading %s\n", vdev_description(vd));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1084
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1085
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1086
	 * Recursively load all children.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1087
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1088
	for (c = 0; c < vd->vdev_children; c++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1089
		if ((error = vdev_load(vd->vdev_child[c], import)) != 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1090
			return (error);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1091
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1092
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1093
	 * If this is a leaf vdev, make sure its agrees with its disk labels.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1094
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1095
	if (vd->vdev_ops->vdev_op_leaf) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1096
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1097
		if (vdev_is_dead(vd))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1098
			return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1099
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1100
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1101
		 * XXX state transitions don't propagate to parent here.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1102
		 * Also, merely setting the state isn't sufficient because
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1103
		 * it's not persistent; a vdev_reopen() would make us
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1104
		 * forget all about it.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1105
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1106
		if ((label = vdev_label_read_config(vd)) == NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1107
			dprintf("can't load label config\n");
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1108
			vdev_set_state(vd, VDEV_STATE_CANT_OPEN,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1109
			    VDEV_AUX_CORRUPT_DATA);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1110
			return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1111
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1112
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1113
		if (nvlist_lookup_uint64(label, ZPOOL_CONFIG_POOL_GUID,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1114
		    &guid) != 0 || guid != spa_guid(spa)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1115
			dprintf("bad or missing pool GUID (%llu)\n", guid);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1116
			vdev_set_state(vd, VDEV_STATE_CANT_OPEN,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1117
			    VDEV_AUX_CORRUPT_DATA);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1118
			nvlist_free(label);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1119
			return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1120
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1121
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1122
		if (nvlist_lookup_uint64(label, ZPOOL_CONFIG_GUID, &guid) ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1123
		    guid != vd->vdev_guid) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1124
			dprintf("bad or missing vdev guid (%llu != %llu)\n",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1125
			    guid, vd->vdev_guid);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1126
			vdev_set_state(vd, VDEV_STATE_CANT_OPEN,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1127
			    VDEV_AUX_CORRUPT_DATA);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1128
			nvlist_free(label);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1129
			return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1130
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1131
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1132
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1133
		 * If we find a vdev with a matching pool guid and vdev guid,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1134
		 * but the pool state is not active, it indicates that the user
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1135
		 * exported or destroyed the pool without affecting the config
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1136
		 * cache (if / was mounted readonly, for example).  In this
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1137
		 * case, immediately return EBADF so the caller can remove it
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1138
		 * from the config.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1139
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1140
		if (nvlist_lookup_uint64(label, ZPOOL_CONFIG_POOL_STATE,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1141
		    &state)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1142
			dprintf("missing pool state\n");
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1143
			vdev_set_state(vd, VDEV_STATE_CANT_OPEN,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1144
			    VDEV_AUX_CORRUPT_DATA);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1145
			nvlist_free(label);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1146
			return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1147
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1148
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1149
		if (state != POOL_STATE_ACTIVE &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1150
		    (!import || state != POOL_STATE_EXPORTED)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1151
			dprintf("pool state not active (%llu)\n", state);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1152
			nvlist_free(label);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1153
			return (EBADF);
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
		nvlist_free(label);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1157
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1158
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1159
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1160
	 * If this is a top-level vdev, make sure its allocation parameters
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1161
	 * exist and initialize its metaslabs.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1162
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1163
	if (vd == vd->vdev_top) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1164
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1165
		if (vd->vdev_ms_array == 0 ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1166
		    vd->vdev_ms_shift == 0 ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1167
		    vd->vdev_ashift == 0 ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1168
		    vd->vdev_asize == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1169
			vdev_set_state(vd, VDEV_STATE_CANT_OPEN,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1170
			    VDEV_AUX_CORRUPT_DATA);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1171
			return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1172
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1173
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1174
		vdev_metaslab_init(vd, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1175
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1176
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1177
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1178
	 * If this is a leaf vdev, load its DTL.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1179
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1180
	if (vd->vdev_ops->vdev_op_leaf) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1181
		error = vdev_dtl_load(vd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1182
		if (error) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1183
			dprintf("can't load DTL for %s, error %d\n",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1184
			    vdev_description(vd), error);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1185
			vdev_set_state(vd, VDEV_STATE_CANT_OPEN,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1186
			    VDEV_AUX_CORRUPT_DATA);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1187
			return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1188
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1189
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1190
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1191
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1192
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1193
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1194
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1195
vdev_sync_done(vdev_t *vd, uint64_t txg)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1196
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1197
	metaslab_t *msp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1198
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1199
	dprintf("%s txg %llu\n", vdev_description(vd), txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1200
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1201
	while (msp = txg_list_remove(&vd->vdev_ms_list, TXG_CLEAN(txg)))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1202
		metaslab_sync_done(msp, txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1203
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1204
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1205
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1206
vdev_add_sync(vdev_t *vd, uint64_t txg)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1207
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1208
	spa_t *spa = vd->vdev_spa;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1209
	dmu_tx_t *tx = dmu_tx_create_assigned(spa->spa_dsl_pool, txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1210
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1211
	ASSERT(vd == vd->vdev_top);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1212
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1213
	if (vd->vdev_ms_array == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1214
		vd->vdev_ms_array = dmu_object_alloc(spa->spa_meta_objset,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1215
		    DMU_OT_OBJECT_ARRAY, 0, DMU_OT_NONE, 0, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1216
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1217
	ASSERT(vd->vdev_ms_array != 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1218
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1219
	vdev_config_dirty(vd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1220
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1221
	dmu_tx_commit(tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1222
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1223
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1224
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1225
vdev_sync(vdev_t *vd, uint64_t txg)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1226
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1227
	spa_t *spa = vd->vdev_spa;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1228
	vdev_t *lvd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1229
	metaslab_t *msp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1230
	uint8_t *dirtyp = &vd->vdev_dirty[txg & TXG_MASK];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1231
	uint8_t dirty = *dirtyp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1232
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1233
	mutex_enter(&vd->vdev_dirty_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1234
	*dirtyp &= ~(VDD_ALLOC | VDD_FREE | VDD_ADD | VDD_DTL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1235
	mutex_exit(&vd->vdev_dirty_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1236
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1237
	dprintf("%s txg %llu pass %d\n",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1238
	    vdev_description(vd), (u_longlong_t)txg, spa_sync_pass(spa));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1239
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1240
	if (dirty & VDD_ADD)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1241
		vdev_add_sync(vd, txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1242
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1243
	while ((msp = txg_list_remove(&vd->vdev_ms_list, txg)) != NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1244
		metaslab_sync(msp, txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1245
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1246
	while ((lvd = txg_list_remove(&vd->vdev_dtl_list, txg)) != NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1247
		vdev_dtl_sync(lvd, txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1248
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1249
	(void) txg_list_add(&spa->spa_vdev_txg_list, vd, TXG_CLEAN(txg));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1250
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1251
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1252
uint64_t
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1253
vdev_psize_to_asize(vdev_t *vd, uint64_t psize)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1254
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1255
	return (vd->vdev_ops->vdev_op_asize(vd, psize));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1256
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1257
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1258
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1259
vdev_io_start(zio_t *zio)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1260
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1261
	zio->io_vd->vdev_ops->vdev_op_io_start(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1262
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1263
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1264
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1265
vdev_io_done(zio_t *zio)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1266
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1267
	zio->io_vd->vdev_ops->vdev_op_io_done(zio);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1268
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1269
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1270
const char *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1271
vdev_description(vdev_t *vd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1272
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1273
	if (vd == NULL || vd->vdev_ops == NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1274
		return ("<unknown>");
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1275
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1276
	if (vd->vdev_path != NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1277
		return (vd->vdev_path);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1278
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1279
	if (vd->vdev_parent == NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1280
		return (spa_name(vd->vdev_spa));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1281
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1282
	return (vd->vdev_ops->vdev_op_type);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1283
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1284
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1285
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1286
vdev_online(spa_t *spa, const char *path)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1287
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1288
	vdev_t *vd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1289
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1290
	spa_config_enter(spa, RW_WRITER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1291
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1292
	if ((vd = vdev_lookup_by_path(spa->spa_root_vdev, path)) == NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1293
		spa_config_exit(spa);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1294
		return (ENODEV);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1295
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1296
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1297
	dprintf("ONLINE: %s\n", vdev_description(vd));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1298
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1299
	vd->vdev_offline = B_FALSE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1300
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1301
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1302
	 * Clear the error counts.  The idea is that you expect to see all
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1303
	 * zeroes when everything is working, so if you've just onlined a
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1304
	 * device, you don't want to keep hearing about errors from before.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1305
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1306
	vd->vdev_stat.vs_read_errors = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1307
	vd->vdev_stat.vs_write_errors = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1308
	vd->vdev_stat.vs_checksum_errors = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1309
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1310
	vdev_reopen(vd->vdev_top, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1311
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1312
	spa_config_exit(spa);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1313
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1314
	VERIFY(spa_scrub(spa, POOL_SCRUB_RESILVER, B_TRUE) == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1315
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1316
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1317
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1318
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1319
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1320
vdev_offline(spa_t *spa, const char *path)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1321
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1322
	vdev_t *vd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1323
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1324
	spa_config_enter(spa, RW_WRITER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1325
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1326
	if ((vd = vdev_lookup_by_path(spa->spa_root_vdev, path)) == NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1327
		spa_config_exit(spa);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1328
		return (ENODEV);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1329
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1330
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1331
	dprintf("OFFLINE: %s\n", vdev_description(vd));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1332
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1333
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1334
	 * If this device's top-level vdev has a non-empty DTL,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1335
	 * don't allow the device to be offlined.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1336
	 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1337
	 * XXX -- we should make this more precise by allowing the offline
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1338
	 * as long as the remaining devices don't have any DTL holes.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1339
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1340
	if (vd->vdev_top->vdev_dtl_map.sm_space != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1341
		spa_config_exit(spa);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1342
		return (EBUSY);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1343
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1344
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1345
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1346
	 * Set this device to offline state and reopen its top-level vdev.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1347
	 * If this action results in the top-level vdev becoming unusable,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1348
	 * undo it and fail the request.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1349
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1350
	vd->vdev_offline = B_TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1351
	vdev_reopen(vd->vdev_top, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1352
	if (vdev_is_dead(vd->vdev_top)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1353
		vd->vdev_offline = B_FALSE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1354
		vdev_reopen(vd->vdev_top, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1355
		spa_config_exit(spa);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1356
		return (EBUSY);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1357
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1358
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1359
	spa_config_exit(spa);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1360
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1361
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1362
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1363
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1364
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1365
vdev_error_setup(spa_t *spa, const char *path, int mode, int mask, uint64_t arg)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1366
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1367
	vdev_t *vd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1368
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1369
	spa_config_enter(spa, RW_WRITER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1370
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1371
	if ((vd = vdev_lookup_by_path(spa->spa_root_vdev, path)) == NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1372
		spa_config_exit(spa);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1373
		return (ENODEV);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1374
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1375
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1376
	vd->vdev_fault_mode = mode;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1377
	vd->vdev_fault_mask = mask;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1378
	vd->vdev_fault_arg = arg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1379
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1380
	spa_config_exit(spa);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1381
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1382
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1383
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1384
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1385
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1386
vdev_is_dead(vdev_t *vd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1387
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1388
	return (vd->vdev_state <= VDEV_STATE_CANT_OPEN);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1389
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1390
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1391
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1392
vdev_error_inject(vdev_t *vd, zio_t *zio)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1393
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1394
	int error = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1395
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1396
	if (vd->vdev_fault_mode == VDEV_FAULT_NONE)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1397
		return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1398
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1399
	if (((1ULL << zio->io_type) & vd->vdev_fault_mask) == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1400
		return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1401
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1402
	switch (vd->vdev_fault_mode) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1403
	case VDEV_FAULT_RANDOM:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1404
		if (spa_get_random(vd->vdev_fault_arg) == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1405
			error = EIO;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1406
		break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1407
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1408
	case VDEV_FAULT_COUNT:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1409
		if ((int64_t)--vd->vdev_fault_arg <= 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1410
			vd->vdev_fault_mode = VDEV_FAULT_NONE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1411
		error = EIO;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1412
		break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1413
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1414
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1415
	if (error != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1416
		dprintf("returning %d for type %d on %s state %d offset %llx\n",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1417
		    error, zio->io_type, vdev_description(vd),
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1418
		    vd->vdev_state, zio->io_offset);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1419
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1420
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1421
	return (error);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1422
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1423
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1424
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1425
 * Get statistics for the given vdev.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1426
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1427
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1428
vdev_get_stats(vdev_t *vd, vdev_stat_t *vs)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1429
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1430
	vdev_t *rvd = vd->vdev_spa->spa_root_vdev;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1431
	int c, t;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1432
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1433
	mutex_enter(&vd->vdev_stat_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1434
	bcopy(&vd->vdev_stat, vs, sizeof (*vs));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1435
	vs->vs_timestamp = gethrtime() - vs->vs_timestamp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1436
	vs->vs_state = vd->vdev_state;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1437
	mutex_exit(&vd->vdev_stat_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1438
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1439
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1440
	 * If we're getting stats on the root vdev, aggregate the I/O counts
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1441
	 * over all top-level vdevs (i.e. the direct children of the root).
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1442
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1443
	if (vd == rvd) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1444
		for (c = 0; c < rvd->vdev_children; c++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1445
			vdev_t *cvd = rvd->vdev_child[c];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1446
			vdev_stat_t *cvs = &cvd->vdev_stat;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1447
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1448
			mutex_enter(&vd->vdev_stat_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1449
			for (t = 0; t < ZIO_TYPES; t++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1450
				vs->vs_ops[t] += cvs->vs_ops[t];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1451
				vs->vs_bytes[t] += cvs->vs_bytes[t];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1452
			}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1453
			vs->vs_read_errors += cvs->vs_read_errors;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1454
			vs->vs_write_errors += cvs->vs_write_errors;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1455
			vs->vs_checksum_errors += cvs->vs_checksum_errors;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1456
			vs->vs_scrub_examined += cvs->vs_scrub_examined;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1457
			vs->vs_scrub_errors += cvs->vs_scrub_errors;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1458
			mutex_exit(&vd->vdev_stat_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1459
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1460
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1461
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1462
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1463
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1464
vdev_stat_update(zio_t *zio)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1465
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1466
	vdev_t *vd = zio->io_vd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1467
	vdev_t *pvd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1468
	uint64_t txg = zio->io_txg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1469
	vdev_stat_t *vs = &vd->vdev_stat;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1470
	zio_type_t type = zio->io_type;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1471
	int flags = zio->io_flags;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1472
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1473
	if (zio->io_error == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1474
		if (!(flags & ZIO_FLAG_IO_BYPASS)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1475
			mutex_enter(&vd->vdev_stat_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1476
			vs->vs_ops[type]++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1477
			vs->vs_bytes[type] += zio->io_size;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1478
			mutex_exit(&vd->vdev_stat_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1479
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1480
		if ((flags & ZIO_FLAG_IO_REPAIR) &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1481
		    zio->io_delegate_list == NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1482
			mutex_enter(&vd->vdev_stat_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1483
			if (flags & (ZIO_FLAG_SCRUB | ZIO_FLAG_RESILVER))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1484
				vs->vs_scrub_repaired += zio->io_size;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1485
			else
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1486
				vs->vs_self_healed += zio->io_size;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1487
			mutex_exit(&vd->vdev_stat_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1488
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1489
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1490
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1491
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1492
	if (flags & ZIO_FLAG_SPECULATIVE)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1493
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1494
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1495
	if (!vdev_is_dead(vd)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1496
		mutex_enter(&vd->vdev_stat_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1497
		if (type == ZIO_TYPE_READ) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1498
			if (zio->io_error == ECKSUM)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1499
				vs->vs_checksum_errors++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1500
			else
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1501
				vs->vs_read_errors++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1502
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1503
		if (type == ZIO_TYPE_WRITE)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1504
			vs->vs_write_errors++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1505
		mutex_exit(&vd->vdev_stat_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1506
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1507
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1508
	if (type == ZIO_TYPE_WRITE) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1509
		if (txg == 0 || vd->vdev_children != 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1510
			return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1511
		if (flags & (ZIO_FLAG_SCRUB | ZIO_FLAG_RESILVER)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1512
			ASSERT(flags & ZIO_FLAG_IO_REPAIR);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1513
			for (pvd = vd; pvd != NULL; pvd = pvd->vdev_parent)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1514
				vdev_dtl_dirty(&pvd->vdev_dtl_scrub, txg, 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1515
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1516
		if (!(flags & ZIO_FLAG_IO_REPAIR)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1517
			vdev_t *tvd = vd->vdev_top;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1518
			if (vdev_dtl_contains(&vd->vdev_dtl_map, txg, 1))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1519
				return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1520
			vdev_dirty(tvd, VDD_DTL, txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1521
			(void) txg_list_add(&tvd->vdev_dtl_list, vd, txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1522
			for (pvd = vd; pvd != NULL; pvd = pvd->vdev_parent)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1523
				vdev_dtl_dirty(&pvd->vdev_dtl_map, txg, 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1524
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1525
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1526
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1527
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1528
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1529
vdev_scrub_stat_update(vdev_t *vd, pool_scrub_type_t type, boolean_t complete)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1530
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1531
	int c;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1532
	vdev_stat_t *vs = &vd->vdev_stat;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1533
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1534
	for (c = 0; c < vd->vdev_children; c++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1535
		vdev_scrub_stat_update(vd->vdev_child[c], type, complete);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1536
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1537
	mutex_enter(&vd->vdev_stat_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1538
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1539
	if (type == POOL_SCRUB_NONE) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1540
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1541
		 * Update completion and end time.  Leave everything else alone
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1542
		 * so we can report what happened during the previous scrub.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1543
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1544
		vs->vs_scrub_complete = complete;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1545
		vs->vs_scrub_end = gethrestime_sec();
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1546
	} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1547
		vs->vs_scrub_type = type;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1548
		vs->vs_scrub_complete = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1549
		vs->vs_scrub_examined = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1550
		vs->vs_scrub_repaired = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1551
		vs->vs_scrub_errors = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1552
		vs->vs_scrub_start = gethrestime_sec();
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1553
		vs->vs_scrub_end = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1554
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1555
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1556
	mutex_exit(&vd->vdev_stat_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1557
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1558
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1559
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1560
 * Report checksum errors that a vdev that didn't realize it made.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1561
 * This can happen, for example, when RAID-Z combinatorial reconstruction
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1562
 * infers that one of its components returned bad data.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1563
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1564
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1565
vdev_checksum_error(zio_t *zio, vdev_t *vd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1566
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1567
	dprintf_bp(zio->io_bp, "imputed checksum error on %s: ",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1568
	    vdev_description(vd));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1569
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1570
	if (!(zio->io_flags & ZIO_FLAG_SPECULATIVE)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1571
		mutex_enter(&vd->vdev_stat_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1572
		vd->vdev_stat.vs_checksum_errors++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1573
		mutex_exit(&vd->vdev_stat_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1574
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1575
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1576
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1577
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1578
 * Update the in-core space usage stats for this vdev and the root vdev.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1579
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1580
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1581
vdev_space_update(vdev_t *vd, uint64_t space_delta, uint64_t alloc_delta)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1582
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1583
	ASSERT(vd == vd->vdev_top);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1584
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1585
	do {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1586
		mutex_enter(&vd->vdev_stat_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1587
		vd->vdev_stat.vs_space += space_delta;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1588
		vd->vdev_stat.vs_alloc += alloc_delta;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1589
		mutex_exit(&vd->vdev_stat_lock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1590
	} while ((vd = vd->vdev_parent) != NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1591
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1592
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1593
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1594
 * Various knobs to tune a vdev.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1595
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1596
static vdev_knob_t vdev_knob[] = {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1597
	{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1598
		"cache_size",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1599
		"size of the read-ahead cache",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1600
		0,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1601
		1ULL << 30,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1602
		10ULL << 20,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1603
		offsetof(struct vdev, vdev_cache.vc_size)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1604
	},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1605
	{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1606
		"cache_bshift",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1607
		"log2 of cache blocksize",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1608
		SPA_MINBLOCKSHIFT,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1609
		SPA_MAXBLOCKSHIFT,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1610
		16,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1611
		offsetof(struct vdev, vdev_cache.vc_bshift)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1612
	},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1613
	{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1614
		"cache_max",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1615
		"largest block size to cache",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1616
		0,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1617
		SPA_MAXBLOCKSIZE,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1618
		1ULL << 14,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1619
		offsetof(struct vdev, vdev_cache.vc_max)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1620
	},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1621
	{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1622
		"min_pending",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1623
		"minimum pending I/Os to the disk",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1624
		1,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1625
		10000,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1626
		2,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1627
		offsetof(struct vdev, vdev_queue.vq_min_pending)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1628
	},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1629
	{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1630
		"max_pending",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1631
		"maximum pending I/Os to the disk",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1632
		1,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1633
		10000,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1634
		35,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1635
		offsetof(struct vdev, vdev_queue.vq_max_pending)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1636
	},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1637
	{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1638
		"agg_limit",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1639
		"maximum size of aggregated I/Os",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1640
		0,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1641
		SPA_MAXBLOCKSIZE,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1642
		SPA_MAXBLOCKSIZE,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1643
		offsetof(struct vdev, vdev_queue.vq_agg_limit)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1644
	},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1645
	{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1646
		"time_shift",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1647
		"deadline = pri + (lbolt >> time_shift)",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1648
		0,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1649
		63,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1650
		4,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1651
		offsetof(struct vdev, vdev_queue.vq_time_shift)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1652
	},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1653
	{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1654
		"ramp_rate",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1655
		"exponential I/O issue ramp-up rate",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1656
		1,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1657
		10000,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1658
		2,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1659
		offsetof(struct vdev, vdev_queue.vq_ramp_rate)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1660
	},
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1661
};
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1662
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1663
vdev_knob_t *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1664
vdev_knob_next(vdev_knob_t *vk)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1665
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1666
	if (vk == NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1667
		return (vdev_knob);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1668
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1669
	if (++vk == vdev_knob + sizeof (vdev_knob) / sizeof (vdev_knob_t))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1670
		return (NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1671
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1672
	return (vk);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1673
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1674
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1675
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1676
 * Mark a top-level vdev's config as dirty, placing it on the dirty list
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1677
 * so that it will be written out next time the vdev configuration is synced.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1678
 * If the root vdev is specified (vdev_top == NULL), dirty all top-level vdevs.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1679
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1680
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1681
vdev_config_dirty(vdev_t *vd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1682
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1683
	spa_t *spa = vd->vdev_spa;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1684
	vdev_t *rvd = spa->spa_root_vdev;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1685
	int c;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1686
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1687
	if (vd == rvd) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1688
		for (c = 0; c < rvd->vdev_children; c++)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1689
			vdev_config_dirty(rvd->vdev_child[c]);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1690
	} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1691
		ASSERT(vd == vd->vdev_top);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1692
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1693
		if (!vd->vdev_is_dirty) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1694
			list_insert_head(&spa->spa_dirty_list, vd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1695
			vd->vdev_is_dirty = B_TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1696
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1697
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1698
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1699
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1700
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1701
vdev_config_clean(vdev_t *vd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1702
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1703
	ASSERT(vd->vdev_is_dirty);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1704
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1705
	list_remove(&vd->vdev_spa->spa_dirty_list, vd);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1706
	vd->vdev_is_dirty = B_FALSE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1707
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1708
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1709
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1710
 * Set a vdev's state, updating any parent's state as well.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1711
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1712
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1713
vdev_set_state(vdev_t *vd, vdev_state_t state, vdev_aux_t aux)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1714
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1715
	if (state == vd->vdev_state)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1716
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1717
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1718
	vd->vdev_state = state;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1719
	vd->vdev_stat.vs_aux = aux;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1720
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1721
	if (vd->vdev_parent != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1722
		int c;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1723
		int degraded = 0, faulted = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1724
		vdev_t *parent, *child;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1725
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1726
		parent = vd->vdev_parent;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1727
		for (c = 0; c < parent->vdev_children; c++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1728
			child = parent->vdev_child[c];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1729
			if (child->vdev_state <= VDEV_STATE_CANT_OPEN)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1730
				faulted++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1731
			else if (child->vdev_state == VDEV_STATE_DEGRADED)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1732
				degraded++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1733
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1734
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1735
		vd->vdev_parent->vdev_ops->vdev_op_state_change(
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1736
		    vd->vdev_parent, faulted, degraded);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1737
	    }
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
  1738
}