usr/src/cmd/fm/modules/common/zfs-diagnosis/zfs_de.c
author lling
Wed, 19 Sep 2007 10:32:40 -0700
changeset 5094 71a3e95fb9e2
parent 4451 24fbf2d7a5d7
child 6523 c1d2a7f04573
permissions -rw-r--r--
PSARC 2007/342 Enhanced ZFS Pool Properties PSARC 2007/482 zpool upgrade -V 6565437 zpool property extensions 6561384 want 'zpool upgrade -V <version>' to upgrade to specific version number 6582755 zfs.h has some incorrect version macros 6595601 libzfs headers declare functions which don't exist 6603938 libzfs is using VERIFY() again 6538984 duplicated messages when get pool properties from an unsupported pool version
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
     1
/*
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
     2
 * CDDL HEADER START
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
     3
 *
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
     5
 * Common Development and Distribution License (the "License").
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
     6
 * You may not use this file except in compliance with the License.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
     7
 *
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
     8
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
     9
 * or http://www.opensolaris.org/os/licensing.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    10
 * See the License for the specific language governing permissions
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    11
 * and limitations under the License.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    12
 *
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    13
 * When distributing Covered Code, include this CDDL HEADER in each
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    14
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    15
 * If applicable, add the following below this CDDL HEADER, with the
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    16
 * fields enclosed by brackets "[]" replaced with your own identifying
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    17
 * information: Portions Copyright [yyyy] [name of copyright owner]
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    18
 *
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    19
 * CDDL HEADER END
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    20
 */
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    21
/*
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    22
 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    23
 * Use is subject to license terms.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    24
 */
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    25
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    26
#pragma ident	"%Z%%M%	%I%	%E% SMI"
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    27
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    28
#include <assert.h>
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    29
#include <stddef.h>
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    30
#include <strings.h>
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    31
#include <libuutil.h>
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    32
#include <libzfs.h>
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    33
#include <fm/fmd_api.h>
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    34
#include <sys/fs/zfs.h>
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    35
#include <sys/fm/protocol.h>
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    36
#include <sys/fm/fs/zfs.h>
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    37
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    38
/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    39
 * Our serd engines are named 'zfs_<pool_guid>_<vdev_guid>_{checksum,io}'.  This
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    40
 * #define reserves enough space for two 64-bit hex values plus the length of
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    41
 * the longest string.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    42
 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    43
#define	MAX_SERDLEN	(16 * 2 + sizeof ("zfs___checksum"))
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    44
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    45
typedef struct zfs_case_data {
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    46
	uint64_t	zc_version;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    47
	uint64_t	zc_ena;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    48
	uint64_t	zc_pool_guid;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    49
	uint64_t	zc_vdev_guid;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    50
	int		zc_has_timer;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    51
	int		zc_pool_state;
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    52
	char		zc_serd_checksum[MAX_SERDLEN];
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    53
	char		zc_serd_io[MAX_SERDLEN];
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    54
	int		zc_has_serd_timer;
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    55
} zfs_case_data_t;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    56
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    57
typedef struct zfs_case {
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    58
	boolean_t	zc_present;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    59
	uint32_t	zc_version;
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    60
	zfs_case_data_t	zc_data;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    61
	fmd_case_t	*zc_case;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    62
	uu_list_node_t	zc_node;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    63
	id_t		zc_timer;
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    64
	id_t		zc_serd_timer;
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    65
} zfs_case_t;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    66
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    67
#define	CASE_DATA			"data"
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    68
#define	CASE_DATA_VERSION_INITIAL	1
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    69
#define	CASE_DATA_VERSION_SERD		2
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    70
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    71
static hrtime_t zfs_case_timeout;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    72
static hrtime_t zfs_serd_timeout;
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    73
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    74
uu_list_pool_t *zfs_case_pool;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    75
uu_list_t *zfs_cases;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    76
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    77
/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    78
 * Write out the persistent representation of an active case.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    79
 */
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    80
static void
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    81
zfs_case_serialize(fmd_hdl_t *hdl, zfs_case_t *zcp)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    82
{
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    83
	/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    84
	 * Always update cases to the latest version, even if they were the
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    85
	 * previous version when unserialized.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    86
	 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    87
	zcp->zc_data.zc_version = CASE_DATA_VERSION_SERD;
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    88
	fmd_buf_write(hdl, zcp->zc_case, CASE_DATA, &zcp->zc_data,
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    89
	    sizeof (zcp->zc_data));
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    90
}
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    91
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    92
/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    93
 * Read back the persistent representation of an active case.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
    94
 */
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    95
static zfs_case_t *
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    96
zfs_case_unserialize(fmd_hdl_t *hdl, fmd_case_t *cp)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    97
{
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    98
	zfs_case_t *zcp;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
    99
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   100
	zcp = fmd_hdl_zalloc(hdl, sizeof (zfs_case_t), FMD_SLEEP);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   101
	zcp->zc_case = cp;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   102
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   103
	fmd_buf_read(hdl, cp, CASE_DATA, &zcp->zc_data,
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   104
	    sizeof (zcp->zc_data));
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   105
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   106
	if (zcp->zc_data.zc_version > CASE_DATA_VERSION_SERD) {
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   107
		fmd_hdl_free(hdl, zcp, sizeof (zfs_case_t));
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   108
		return (NULL);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   109
	}
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   110
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   111
	/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   112
	 * fmd_buf_read() will have already zeroed out the remainder of the
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   113
	 * buffer, so we don't have to do anything special if the version
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   114
	 * doesn't include the SERD engine name.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   115
	 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   116
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   117
	if (zcp->zc_data.zc_has_timer)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   118
		zcp->zc_timer = fmd_timer_install(hdl, zcp,
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   119
		    NULL, zfs_case_timeout);
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   120
	if (zcp->zc_data.zc_has_serd_timer)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   121
		zcp->zc_serd_timer = fmd_timer_install(hdl, zcp,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   122
		    NULL, zfs_serd_timeout);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   123
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   124
	(void) uu_list_insert_before(zfs_cases, NULL, zcp);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   125
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   126
	fmd_case_setspecific(hdl, cp, zcp);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   127
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   128
	return (zcp);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   129
}
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   130
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   131
/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   132
 * Iterate over any active cases.  If any cases are associated with a pool or
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   133
 * vdev which is no longer present on the system, close the associated case.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   134
 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   135
static void
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   136
zfs_mark_vdev(uint64_t pool_guid, nvlist_t *vd)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   137
{
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   138
	uint64_t vdev_guid;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   139
	uint_t c, children;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   140
	nvlist_t **child;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   141
	zfs_case_t *zcp;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   142
	int ret;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   143
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   144
	ret = nvlist_lookup_uint64(vd, ZPOOL_CONFIG_GUID, &vdev_guid);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   145
	assert(ret == 0);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   146
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   147
	/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   148
	 * Mark any cases associated with this (pool, vdev) pair.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   149
	 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   150
	for (zcp = uu_list_first(zfs_cases); zcp != NULL;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   151
	    zcp = uu_list_next(zfs_cases, zcp)) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   152
		if (zcp->zc_data.zc_pool_guid == pool_guid &&
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   153
		    zcp->zc_data.zc_vdev_guid == vdev_guid)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   154
			zcp->zc_present = B_TRUE;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   155
	}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   156
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   157
	/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   158
	 * Iterate over all children.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   159
	 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   160
	if (nvlist_lookup_nvlist_array(vd, ZPOOL_CONFIG_CHILDREN, &child,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   161
	    &children) != 0) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   162
		for (c = 0; c < children; c++)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   163
			zfs_mark_vdev(pool_guid, child[c]);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   164
	}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   165
}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   166
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   167
/*ARGSUSED*/
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   168
static int
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   169
zfs_mark_pool(zpool_handle_t *zhp, void *unused)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   170
{
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   171
	zfs_case_t *zcp;
5094
71a3e95fb9e2 PSARC 2007/342 Enhanced ZFS Pool Properties
lling
parents: 4451
diff changeset
   172
	uint64_t pool_guid;
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   173
	nvlist_t *config, *vd;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   174
	int ret;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   175
5094
71a3e95fb9e2 PSARC 2007/342 Enhanced ZFS Pool Properties
lling
parents: 4451
diff changeset
   176
	pool_guid = zpool_get_prop_int(zhp, ZPOOL_PROP_GUID, NULL);
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   177
	/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   178
	 * Mark any cases associated with just this pool.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   179
	 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   180
	for (zcp = uu_list_first(zfs_cases); zcp != NULL;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   181
	    zcp = uu_list_next(zfs_cases, zcp)) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   182
		if (zcp->zc_data.zc_pool_guid == pool_guid &&
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   183
		    zcp->zc_data.zc_vdev_guid == 0)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   184
			zcp->zc_present = B_TRUE;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   185
	}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   186
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   187
	if ((config = zpool_get_config(zhp, NULL)) == NULL)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   188
		return (-1);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   189
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   190
	ret = nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &vd);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   191
	assert(ret == 0);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   192
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   193
	zfs_mark_vdev(pool_guid, vd);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   194
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   195
	return (0);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   196
}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   197
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   198
static void
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   199
zfs_purge_cases(fmd_hdl_t *hdl)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   200
{
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   201
	zfs_case_t *zcp;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   202
	uu_list_walk_t *walk;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   203
	libzfs_handle_t *zhdl = fmd_hdl_getspecific(hdl);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   204
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   205
	/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   206
	 * There is no way to open a pool by GUID, or lookup a vdev by GUID.  No
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   207
	 * matter what we do, we're going to have to stomach a O(vdevs * cases)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   208
	 * algorithm.  In reality, both quantities are likely so small that
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   209
	 * neither will matter. Given that iterating over pools is more
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   210
	 * expensive than iterating over the in-memory case list, we opt for a
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   211
	 * 'present' flag in each case that starts off cleared.  We then iterate
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   212
	 * over all pools, marking those that are still present, and removing
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   213
	 * those that aren't found.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   214
	 *
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   215
	 * Note that we could also construct an FMRI and rely on
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   216
	 * fmd_nvl_fmri_present(), but this would end up doing the same search.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   217
	 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   218
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   219
	/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   220
	 * Mark the cases an not present.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   221
	 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   222
	for (zcp = uu_list_first(zfs_cases); zcp != NULL;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   223
	    zcp = uu_list_next(zfs_cases, zcp))
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   224
		zcp->zc_present = B_FALSE;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   225
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   226
	/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   227
	 * Iterate over all pools and mark the pools and vdevs found.  If this
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   228
	 * fails (most probably because we're out of memory), then don't close
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   229
	 * any of the cases and we cannot be sure they are accurate.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   230
	 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   231
	if (zpool_iter(zhdl, zfs_mark_pool, NULL) != 0)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   232
		return;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   233
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   234
	/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   235
	 * Remove those cases which were not found.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   236
	 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   237
	walk = uu_list_walk_start(zfs_cases, UU_WALK_ROBUST);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   238
	while ((zcp = uu_list_walk_next(walk)) != NULL) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   239
		if (!zcp->zc_present)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   240
			fmd_case_close(hdl, zcp->zc_case);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   241
	}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   242
	uu_list_walk_end(walk);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   243
}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   244
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   245
/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   246
 * Construct the name of a serd engine given the pool/vdev GUID and type (io or
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   247
 * checksum).
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   248
 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   249
static void
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   250
zfs_serd_name(char *buf, uint64_t pool_guid, uint64_t vdev_guid,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   251
    const char *type)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   252
{
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   253
	(void) snprintf(buf, MAX_SERDLEN, "zfs_%llx_%llx_%s", pool_guid,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   254
	    vdev_guid, type);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   255
}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   256
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   257
/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   258
 * Solve a given ZFS case.  This first checks to make sure the diagnosis is
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   259
 * still valid, as well as cleaning up any pending timer associated with the
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   260
 * case.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   261
 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   262
static void
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   263
zfs_case_solve(fmd_hdl_t *hdl, zfs_case_t *zcp, const char *faultname,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   264
    boolean_t checkunusable)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   265
{
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   266
	nvlist_t *detector, *fault;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   267
	boolean_t serialize;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   268
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   269
	/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   270
	 * Construct the detector from the case data.  The detector is in the
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   271
	 * ZFS scheme, and is either the pool or the vdev, depending on whether
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   272
	 * this is a vdev or pool fault.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   273
	 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   274
	if (nvlist_alloc(&detector, NV_UNIQUE_NAME, 0) != 0)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   275
		return;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   276
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   277
	if (nvlist_add_uint8(detector, FM_VERSION, ZFS_SCHEME_VERSION0) != 0 ||
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   278
	    nvlist_add_string(detector, FM_FMRI_SCHEME,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   279
	    FM_FMRI_SCHEME_ZFS) != 0 ||
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   280
	    nvlist_add_uint64(detector, FM_FMRI_ZFS_POOL,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   281
	    zcp->zc_data.zc_pool_guid) != 0 ||
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   282
	    (zcp->zc_data.zc_vdev_guid != 0 &&
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   283
	    nvlist_add_uint64(detector, FM_FMRI_ZFS_VDEV,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   284
	    zcp->zc_data.zc_vdev_guid) != 0)) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   285
		nvlist_free(detector);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   286
		return;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   287
	}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   288
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   289
	/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   290
	 * We also want to make sure that the detector (pool or vdev) properly
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   291
	 * reflects the diagnosed state, when the fault corresponds to internal
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   292
	 * ZFS state (i.e. not checksum or I/O error-induced).  Otherwise, a
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   293
	 * device which was unavailable early in boot (because the driver/file
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   294
	 * wasn't available) and is now healthy will be mis-diagnosed.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   295
	 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   296
	if (!fmd_nvl_fmri_present(hdl, detector) ||
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   297
	    (checkunusable && !fmd_nvl_fmri_unusable(hdl, detector))) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   298
		fmd_case_close(hdl, zcp->zc_case);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   299
		nvlist_free(detector);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   300
		return;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   301
	}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   302
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   303
	fault = fmd_nvl_create_fault(hdl, faultname, 100, detector, NULL,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   304
	    detector);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   305
	fmd_case_add_suspect(hdl, zcp->zc_case, fault);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   306
	fmd_case_solve(hdl, zcp->zc_case);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   307
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   308
	serialize = B_FALSE;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   309
	if (zcp->zc_data.zc_has_timer) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   310
		fmd_timer_remove(hdl, zcp->zc_timer);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   311
		zcp->zc_data.zc_has_timer = 0;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   312
		serialize = B_TRUE;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   313
	}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   314
	if (zcp->zc_data.zc_has_serd_timer) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   315
		fmd_timer_remove(hdl, zcp->zc_serd_timer);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   316
		zcp->zc_data.zc_has_serd_timer = 0;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   317
		serialize = B_TRUE;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   318
	}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   319
	if (serialize)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   320
		zfs_case_serialize(hdl, zcp);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   321
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   322
	nvlist_free(detector);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   323
}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   324
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   325
/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   326
 * Main fmd entry point.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   327
 */
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   328
/*ARGSUSED*/
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   329
static void
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   330
zfs_fm_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   331
{
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   332
	zfs_case_t *zcp;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   333
	int32_t pool_state;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   334
	uint64_t ena, pool_guid, vdev_guid;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   335
	nvlist_t *detector;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   336
	boolean_t isresource;
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   337
	const char *serd;
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   338
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   339
	isresource = fmd_nvl_class_match(hdl, nvl, "resource.fs.zfs.*");
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   340
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   341
	if (isresource) {
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   342
		/*
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   343
		 * For resources, we don't have a normal payload.
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   344
		 */
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   345
		if (nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_GUID,
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   346
		    &vdev_guid) != 0)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   347
			pool_state = SPA_LOAD_OPEN;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   348
		else
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   349
			pool_state = SPA_LOAD_NONE;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   350
		detector = NULL;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   351
	} else {
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   352
		(void) nvlist_lookup_nvlist(nvl,
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   353
		    FM_EREPORT_DETECTOR, &detector);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   354
		(void) nvlist_lookup_int32(nvl,
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   355
		    FM_EREPORT_PAYLOAD_ZFS_POOL_CONTEXT, &pool_state);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   356
	}
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   357
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   358
	/*
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   359
	 * We also ignore all ereports generated during an import of a pool,
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   360
	 * since the only possible fault (.pool) would result in import failure,
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   361
	 * and hence no persistent fault.  Some day we may want to do something
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   362
	 * with these ereports, so we continue generating them internally.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   363
	 */
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   364
	if (pool_state == SPA_LOAD_IMPORT)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   365
		return;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   366
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   367
	/*
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   368
	 * Determine if this ereport corresponds to an open case.  Cases are
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   369
	 * indexed by ENA, since ZFS does all the work of chaining together
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   370
	 * related ereports.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   371
	 *
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   372
	 * We also detect if an ereport corresponds to an open case by context,
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   373
	 * such as:
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   374
	 *
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   375
	 * 	- An error occurred during an open of a pool with an existing
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   376
	 *	  case.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   377
	 *
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   378
	 * 	- An error occurred for a device which already has an open
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   379
	 *	  case.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   380
	 */
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   381
	(void) nvlist_lookup_uint64(nvl,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   382
	    FM_EREPORT_PAYLOAD_ZFS_POOL_GUID, &pool_guid);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   383
	if (nvlist_lookup_uint64(nvl,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   384
	    FM_EREPORT_PAYLOAD_ZFS_VDEV_GUID, &vdev_guid) != 0)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   385
		vdev_guid = 0;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   386
	if (nvlist_lookup_uint64(nvl, FM_EREPORT_ENA, &ena) != 0)
1588
2eff456ae020 6395695 uninitialized ENA can confuse ZFS diagnosis
eschrock
parents: 1544
diff changeset
   387
		ena = 0;
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   388
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   389
	for (zcp = uu_list_first(zfs_cases); zcp != NULL;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   390
	    zcp = uu_list_next(zfs_cases, zcp)) {
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   391
		/*
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   392
		 * Matches a known ENA.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   393
		 */
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   394
		if (zcp->zc_data.zc_ena == ena)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   395
			break;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   396
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   397
		/*
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   398
		 * Matches a case involving load errors for this same pool.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   399
		 */
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   400
		if (zcp->zc_data.zc_pool_guid == pool_guid &&
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   401
		    zcp->zc_data.zc_pool_state == SPA_LOAD_OPEN &&
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   402
		    pool_state == SPA_LOAD_OPEN)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   403
			break;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   404
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   405
		/*
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   406
		 * Device errors for the same device.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   407
		 */
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   408
		if (vdev_guid != 0 && zcp->zc_data.zc_vdev_guid == vdev_guid)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   409
			break;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   410
	}
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   411
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   412
	if (zcp == NULL) {
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   413
		fmd_case_t *cs;
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   414
		zfs_case_data_t data = { 0 };
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   415
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   416
		/*
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   417
		 * If this is one of our 'fake' resource ereports, and there is
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   418
		 * no case open, simply discard it.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   419
		 */
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   420
		if (isresource)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   421
			return;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   422
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   423
		/*
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   424
		 * Open a new case.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   425
		 */
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   426
		cs = fmd_case_open(hdl, NULL);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   427
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   428
		/*
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   429
		 * Initialize the case buffer.  To commonize code, we actually
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   430
		 * create the buffer with existing data, and then call
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   431
		 * zfs_case_unserialize() to instantiate the in-core structure.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   432
		 */
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   433
		fmd_buf_create(hdl, cs, CASE_DATA,
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   434
		    sizeof (zfs_case_data_t));
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   435
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   436
		data.zc_version = CASE_DATA_VERSION_SERD;
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   437
		data.zc_ena = ena;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   438
		data.zc_pool_guid = pool_guid;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   439
		data.zc_vdev_guid = vdev_guid;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   440
		data.zc_pool_state = (int)pool_state;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   441
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   442
		fmd_buf_write(hdl, cs, CASE_DATA, &data, sizeof (data));
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   443
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   444
		zcp = zfs_case_unserialize(hdl, cs);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   445
		assert(zcp != NULL);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   446
	}
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   447
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   448
	if (isresource) {
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   449
		if (fmd_nvl_class_match(hdl, nvl, "resource.fs.zfs.ok")) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   450
			/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   451
			 * The 'resource.fs.zfs.ok' event is a special
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   452
			 * internal-only event that signifies that a pool or
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   453
			 * device that was previously faulted has now come
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   454
			 * online (as detected by ZFS).  This allows us to close
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   455
			 * the associated case.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   456
			 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   457
			fmd_case_close(hdl, zcp->zc_case);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   458
		} else if (fmd_nvl_class_match(hdl, nvl,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   459
		    "resource.fs.zfs.autoreplace")) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   460
			/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   461
			 * The 'resource.fs.zfs.autoreplace' event indicates
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   462
			 * that the pool was loaded with the 'autoreplace'
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   463
			 * property set.  In this case, any pending device
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   464
			 * failures should be ignored, as the asynchronous
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   465
			 * autoreplace handling will take care of them.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   466
			 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   467
			fmd_case_close(hdl, zcp->zc_case);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   468
		} else {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   469
			/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   470
			 * The 'resource.fs.zfs.removed' event indicates that
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   471
			 * device removal was detected, and the device was
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   472
			 * closed asynchronously.  If this is the case, we
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   473
			 * assume that any recent I/O errors were due to the
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   474
			 * device removal, not any fault of the device itself.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   475
			 * We reset the SERD engine, and cancel any pending
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   476
			 * timers.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   477
			 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   478
			if (zcp->zc_data.zc_has_serd_timer) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   479
				fmd_timer_remove(hdl, zcp->zc_serd_timer);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   480
				zcp->zc_data.zc_has_serd_timer = 0;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   481
				zfs_case_serialize(hdl, zcp);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   482
			}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   483
			if (zcp->zc_data.zc_serd_io[0] != '\0')
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   484
				fmd_serd_reset(hdl,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   485
				    zcp->zc_data.zc_serd_io);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   486
			if (zcp->zc_data.zc_serd_checksum[0] != '\0')
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   487
				fmd_serd_reset(hdl,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   488
				    zcp->zc_data.zc_serd_checksum);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   489
		}
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   490
		return;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   491
	}
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   492
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   493
	/*
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   494
	 * Associate the ereport with this case.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   495
	 */
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   496
	fmd_case_add_ereport(hdl, zcp->zc_case, ep);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   497
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   498
	/*
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   499
	 * Don't do anything else if this case is already solved.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   500
	 */
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   501
	if (fmd_case_solved(hdl, zcp->zc_case))
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   502
		return;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   503
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   504
	/*
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   505
	 * Determine if we should solve the case and generate a fault.  We solve
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   506
	 * a case if:
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   507
	 *
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   508
	 * 	a. A pool failed to open (ereport.fs.zfs.pool)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   509
	 * 	b. A device failed to open (ereport.fs.zfs.pool) while a pool
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   510
	 *	   was up and running.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   511
	 *
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   512
	 * We may see a series of ereports associated with a pool open, all
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   513
	 * chained together by the same ENA.  If the pool open succeeds, then
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   514
	 * we'll see no further ereports.  To detect when a pool open has
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   515
	 * succeeded, we associate a timer with the event.  When it expires, we
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   516
	 * close the case.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   517
	 */
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   518
	if (fmd_nvl_class_match(hdl, nvl, "ereport.fs.zfs.zpool")) {
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   519
		/*
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   520
		 * Pool level fault.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   521
		 */
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   522
		zfs_case_solve(hdl, zcp, "fault.fs.zfs.pool", B_TRUE);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   523
	} else if (fmd_nvl_class_match(hdl, nvl, "ereport.fs.zfs.vdev.*") &&
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   524
	    pool_state == SPA_LOAD_NONE) {
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   525
		/*
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   526
		 * Device fault.  Before solving the case, determine if the
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   527
		 * device failed during open, and the 'autoreplace' property is
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   528
		 * set.  If this is the case, then we post a sysevent which is
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   529
		 * picked up by the syseventd module, and any processing is done
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   530
		 * as needed.
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   531
		 */
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   532
		zfs_case_solve(hdl, zcp, "fault.fs.zfs.device",  B_TRUE);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   533
	} else {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   534
		if (pool_state == SPA_LOAD_OPEN) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   535
			/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   536
			 * Error incurred during a pool open.  Reset the timer
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   537
			 * associated with this case.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   538
			 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   539
			if (zcp->zc_data.zc_has_timer)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   540
				fmd_timer_remove(hdl, zcp->zc_timer);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   541
			zcp->zc_timer = fmd_timer_install(hdl, zcp, NULL,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   542
			    zfs_case_timeout);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   543
			if (!zcp->zc_data.zc_has_timer) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   544
				zcp->zc_data.zc_has_timer = 1;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   545
				zfs_case_serialize(hdl, zcp);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   546
			}
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   547
		}
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   548
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   549
		/*
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   550
		 * If this is a checksum or I/O error, then toss it into the
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   551
		 * appropriate SERD engine and check to see if it has fired.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   552
		 * Ideally, we want to do something more sophisticated,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   553
		 * (persistent errors for a single data block, etc).  For now,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   554
		 * a single SERD engine is sufficient.
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   555
		 */
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   556
		serd = NULL;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   557
		if (fmd_nvl_class_match(hdl, nvl, "ereport.fs.zfs.io")) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   558
			if (zcp->zc_data.zc_serd_io[0] == '\0') {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   559
				zfs_serd_name(zcp->zc_data.zc_serd_io,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   560
				    pool_guid, vdev_guid, "io");
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   561
				fmd_serd_create(hdl, zcp->zc_data.zc_serd_io,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   562
				    fmd_prop_get_int32(hdl, "io_N"),
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   563
				    fmd_prop_get_int64(hdl, "io_T"));
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   564
				zfs_case_serialize(hdl, zcp);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   565
			}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   566
			serd = zcp->zc_data.zc_serd_io;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   567
		} else if (fmd_nvl_class_match(hdl, nvl,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   568
		    "ereport.fs.zfs.checksum")) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   569
			if (zcp->zc_data.zc_serd_checksum[0] == '\0') {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   570
				zfs_serd_name(zcp->zc_data.zc_serd_checksum,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   571
				    pool_guid, vdev_guid, "checksum");
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   572
				fmd_serd_create(hdl,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   573
				    zcp->zc_data.zc_serd_checksum,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   574
				    fmd_prop_get_int32(hdl, "checksum_N"),
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   575
				    fmd_prop_get_int64(hdl, "checksum_T"));
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   576
				zfs_case_serialize(hdl, zcp);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   577
			}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   578
			serd = zcp->zc_data.zc_serd_checksum;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   579
		}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   580
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   581
		/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   582
		 * Because I/O errors may be due to device removal, we postpone
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   583
		 * any diagnosis until we're sure that we aren't about to
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   584
		 * receive a 'resource.fs.zfs.removed' event.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   585
		 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   586
		if (serd && fmd_serd_record(hdl, serd, ep)) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   587
			if (zcp->zc_data.zc_has_serd_timer)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   588
				fmd_timer_remove(hdl, zcp->zc_serd_timer);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   589
			zcp->zc_serd_timer = fmd_timer_install(hdl, zcp, NULL,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   590
			    zfs_serd_timeout);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   591
			if (!zcp->zc_data.zc_has_serd_timer) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   592
				zcp->zc_data.zc_has_serd_timer = 1;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   593
				zfs_case_serialize(hdl, zcp);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   594
			}
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   595
		}
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   596
	}
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   597
}
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   598
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   599
/*
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   600
 * Timeout indicates one of two scenarios:
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   601
 *
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   602
 * 	- The pool had faults but was eventually opened successfully.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   603
 *
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   604
 * 	- We diagnosed an I/O error, and it was not due to device removal (which
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   605
 *	  would cause the timeout to be cancelled).
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   606
 */
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   607
/* ARGSUSED */
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   608
static void
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   609
zfs_fm_timeout(fmd_hdl_t *hdl, id_t id, void *data)
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   610
{
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   611
	zfs_case_t *zcp = data;
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   612
	const char *faultname;
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   613
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   614
	if (id == zcp->zc_timer) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   615
		zcp->zc_data.zc_has_timer = 0;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   616
		fmd_case_close(hdl, zcp->zc_case);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   617
	}
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   618
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   619
	if (id == zcp->zc_serd_timer) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   620
		if (zcp->zc_data.zc_serd_io[0] != '\0' &&
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   621
		    fmd_serd_fired(hdl, zcp->zc_data.zc_serd_io)) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   622
			faultname = "fault.fs.zfs.vdev.io";
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   623
		} else {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   624
			assert(fmd_serd_fired(hdl,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   625
			    zcp->zc_data.zc_serd_checksum));
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   626
			faultname = "fault.fs.zfs.vdev.checksum";
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   627
		}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   628
		zfs_case_solve(hdl, zcp, faultname, B_FALSE);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   629
	}
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   630
}
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   631
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   632
static void
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   633
zfs_fm_close(fmd_hdl_t *hdl, fmd_case_t *cs)
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   634
{
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   635
	zfs_case_t *zcp = fmd_case_getspecific(hdl, cs);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   636
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   637
	if (zcp->zc_data.zc_serd_checksum[0] != '\0')
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   638
		fmd_serd_destroy(hdl, zcp->zc_data.zc_serd_checksum);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   639
	if (zcp->zc_data.zc_serd_io[0] != '\0')
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   640
		fmd_serd_destroy(hdl, zcp->zc_data.zc_serd_io);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   641
	if (zcp->zc_data.zc_has_timer)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   642
		fmd_timer_remove(hdl, zcp->zc_timer);
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   643
	if (zcp->zc_data.zc_has_serd_timer)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   644
		fmd_timer_remove(hdl, zcp->zc_serd_timer);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   645
	uu_list_remove(zfs_cases, zcp);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   646
	fmd_hdl_free(hdl, zcp, sizeof (zfs_case_t));
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   647
}
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   648
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   649
/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   650
 * We use the fmd gc entry point to look for old cases that no longer apply.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   651
 * This allows us to keep our set of case data small in a long running system.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   652
 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   653
static void
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   654
zfs_fm_gc(fmd_hdl_t *hdl)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   655
{
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   656
	zfs_purge_cases(hdl);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   657
}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   658
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   659
static const fmd_hdl_ops_t fmd_ops = {
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   660
	zfs_fm_recv,	/* fmdo_recv */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   661
	zfs_fm_timeout,	/* fmdo_timeout */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   662
	zfs_fm_close,	/* fmdo_close */
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   663
	NULL,		/* fmdo_stats */
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   664
	zfs_fm_gc,	/* fmdo_gc */
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   665
};
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   666
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   667
static const fmd_prop_t fmd_props[] = {
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   668
	{ "case_timeout", FMD_TYPE_TIME, "5sec" },
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   669
	{ "checksum_N", FMD_TYPE_UINT32, "10" },
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   670
	{ "checksum_T", FMD_TYPE_TIME, "10min" },
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   671
	{ "io_N", FMD_TYPE_UINT32, "10" },
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   672
	{ "io_T", FMD_TYPE_TIME, "10min" },
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   673
	{ "serd_timeout", FMD_TYPE_TIME, "5sec" },
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   674
	{ NULL, 0, NULL }
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   675
};
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   676
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   677
static const fmd_hdl_info_t fmd_info = {
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   678
	"ZFS Diagnosis Engine", "1.0", &fmd_ops, fmd_props
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   679
};
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   680
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   681
void
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   682
_fmd_init(fmd_hdl_t *hdl)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   683
{
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   684
	fmd_case_t *cp;
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   685
	libzfs_handle_t *zhdl;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   686
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   687
	if ((zhdl = libzfs_init()) == NULL)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   688
		return;
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   689
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   690
	if ((zfs_case_pool = uu_list_pool_create("zfs_case_pool",
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   691
	    sizeof (zfs_case_t), offsetof(zfs_case_t, zc_node),
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   692
	    NULL, 0)) == NULL) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   693
		libzfs_fini(zhdl);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   694
		return;
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   695
	}
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   696
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   697
	if ((zfs_cases = uu_list_create(zfs_case_pool, NULL, 0)) == NULL) {
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   698
		uu_list_pool_destroy(zfs_case_pool);
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   699
		libzfs_fini(zhdl);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   700
		return;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   701
	}
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   702
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   703
	if (fmd_hdl_register(hdl, FMD_API_VERSION, &fmd_info) != 0) {
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   704
		uu_list_destroy(zfs_cases);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   705
		uu_list_pool_destroy(zfs_case_pool);
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   706
		libzfs_fini(zhdl);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   707
		return;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   708
	}
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   709
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   710
	fmd_hdl_setspecific(hdl, zhdl);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   711
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   712
	/*
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   713
	 * Iterate over all active cases and unserialize the associated buffers,
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   714
	 * adding them to our list of open cases.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   715
	 */
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   716
	for (cp = fmd_case_next(hdl, NULL);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   717
	    cp != NULL; cp = fmd_case_next(hdl, cp))
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   718
		(void) zfs_case_unserialize(hdl, cp);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   719
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   720
	/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   721
	 * Clear out any old cases that are no longer valid.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   722
	 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   723
	zfs_purge_cases(hdl);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   724
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   725
	zfs_case_timeout = fmd_prop_get_int64(hdl, "case_timeout");
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   726
	zfs_serd_timeout = fmd_prop_get_int64(hdl, "serd_timeout");
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   727
}
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   728
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   729
void
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   730
_fmd_fini(fmd_hdl_t *hdl)
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   731
{
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   732
	zfs_case_t *zcp;
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   733
	uu_list_walk_t *walk;
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   734
	libzfs_handle_t *zhdl;
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   735
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   736
	/*
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   737
	 * Remove all active cases.
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   738
	 */
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   739
	walk = uu_list_walk_start(zfs_cases, UU_WALK_ROBUST);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   740
	while ((zcp = uu_list_walk_next(walk)) != NULL) {
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   741
		uu_list_remove(zfs_cases, zcp);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   742
		fmd_hdl_free(hdl, zcp, sizeof (zfs_case_t));
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   743
	}
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   744
	uu_list_walk_end(walk);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   745
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   746
	uu_list_destroy(zfs_cases);
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   747
	uu_list_pool_destroy(zfs_case_pool);
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   748
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   749
	zhdl = fmd_hdl_getspecific(hdl);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents: 1588
diff changeset
   750
	libzfs_fini(zhdl);
1544
938876158511 PSARC 2006/077 zpool clear
eschrock
parents:
diff changeset
   751
}