usr/src/cmd/syseventd/modules/zfs_mod/zfs_mod.c
author eschrock
Tue, 12 Jun 2007 13:18:17 -0700
changeset 4451 24fbf2d7a5d7
child 5094 71a3e95fb9e2
permissions -rw-r--r--
PSARC 2007/197 ZFS hotplug PSARC 2007/283 FMA for ZFS Phase 2 6401126 ZFS DE should verify that diagnosis is still valid before solving cases 6500545 ZFS does not handle changes in devids 6508521 zpool online should warn when it is being used incorrectly 6509807 ZFS checksum ereports are not being posted 6514712 zfs_nicenum() doesn't work with perfectly-sized buffers 6520510 media state doesn't get updated properly on device removal 6520513 ZFS should have better support for device removal 6520514 vdev state should be controlled through a single ioctl() 6520519 ZFS should diagnose faulty devices 6520947 ZFS DE should close cases which no longer apply 6521393 ZFS case timeout should be FMD_TYPE_TIME 6521624 fmd_hash_walk() can dump core when given a bad address 6521946 ZFS DE needlessly subscribes to faults 6522085 ZFS dictionary files contain spelling errors 6523185 vdev_reopen() doesn't correctly propagate state 6523555 'zpool online' should be less chatty unless something goes wrong 6527379 zpool(1M) should not try to open faulted devices 6527700 ZFS should post a sysevent when topology changes 6528194 lofi should support force unmap and DKIO_DEV_GONE 6528732 ZFS should store physical device path in addition to /dev path 6532635 ZFS keeps devices open unnecessarily 6532979 bad argument to ZFS_IOC_VDEV_ATTACH can panic system 6567983 deadlock with spa_scrub_thread() and spa_namespace_lock
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
4451
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
     1
/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
     2
 * CDDL HEADER START
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
     3
 *
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
     5
 * Common Development and Distribution License (the "License").
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
     6
 * You may not use this file except in compliance with the License.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
     7
 *
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
     8
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
     9
 * or http://www.opensolaris.org/os/licensing.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    10
 * See the License for the specific language governing permissions
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    11
 * and limitations under the License.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    12
 *
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    13
 * When distributing Covered Code, include this CDDL HEADER in each
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    14
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    15
 * If applicable, add the following below this CDDL HEADER, with the
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    16
 * fields enclosed by brackets "[]" replaced with your own identifying
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    17
 * information: Portions Copyright [yyyy] [name of copyright owner]
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    18
 *
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    19
 * CDDL HEADER END
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    20
 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    21
/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    22
 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    23
 * Use is subject to license terms.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    24
 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    25
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    26
#pragma ident	"%Z%%M%	%I%	%E% SMI"
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    27
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    28
/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    29
 * ZFS syseventd module.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    30
 *
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    31
 * The purpose of this module is to identify when devices are added to the
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    32
 * system, and appropriately online or replace the affected vdevs.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    33
 *
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    34
 * When a device is added to the system:
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    35
 *
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    36
 * 	1. Search for any vdevs whose devid matches that of the newly added
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    37
 *	   device.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    38
 *
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    39
 * 	2. If no vdevs are found, then search for any vdevs whose devfs path
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    40
 *	   matches that of the new device.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    41
 *
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    42
 *	3. If no vdevs match by either method, then ignore the event.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    43
 *
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    44
 * 	4. Attempt to online the device with a flag to indicate that it should
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    45
 *	   be unspared when resilvering completes.  If this succeeds, then the
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    46
 *	   same device was inserted and we should continue normally.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    47
 *
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    48
 *	5. If the pool does not have the 'autoreplace' property set, attempt to
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    49
 *	   online the device again without the unspare flag, which will
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    50
 *	   generate a FMA fault.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    51
 *
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    52
 *	6. If the pool has the 'autoreplace' property set, and the matching vdev
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    53
 *	   is a whole disk, then label the new disk and attempt a 'zpool
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    54
 *	   replace'.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    55
 *
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    56
 * The module responds to EC_DEV_ADD events for both disks and lofi devices,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    57
 * with the latter used for testing.  The special ESC_ZFS_VDEV_CHECK event
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    58
 * indicates that a device failed to open during pool load, but the autoreplace
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    59
 * property was set.  In this case, we deferred the associated FMA fault until
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    60
 * our module had a chance to process the autoreplace logic.  If the device
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    61
 * could not be replaced, then the second online attempt will trigger the FMA
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    62
 * fault that we skipped earlier.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    63
 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    64
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    65
#include <alloca.h>
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    66
#include <devid.h>
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    67
#include <fcntl.h>
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    68
#include <libnvpair.h>
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    69
#include <libsysevent.h>
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    70
#include <libzfs.h>
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    71
#include <limits.h>
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    72
#include <stdlib.h>
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    73
#include <string.h>
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    74
#include <syslog.h>
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    75
#include <sys/sunddi.h>
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    76
#include <sys/sysevent/eventdefs.h>
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    77
#include <sys/sysevent/dev.h>
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    78
#include <unistd.h>
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    79
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    80
#if defined(__i386) || defined(__amd64)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    81
#define	PHYS_PATH	":q"
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    82
#define	RAW_SLICE	"p0"
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    83
#elif defined(__sparc)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    84
#define	PHYS_PATH	":c"
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    85
#define	RAW_SLICE	"s2"
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    86
#else
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    87
#error Unknown architecture
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    88
#endif
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    89
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    90
typedef void (*zfs_process_func_t)(zpool_handle_t *, nvlist_t *, boolean_t);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    91
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    92
libzfs_handle_t *g_zfshdl;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    93
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    94
/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    95
 * The device associated with the given vdev (either by devid or physical path)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    96
 * has been added to the system.  If 'isdisk' is set, then we only attempt a
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    97
 * replacement if it's a whole disk.  This also implies that we should label the
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    98
 * disk first.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
    99
 *
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   100
 * First, we attempt to online the device (making sure to undo any spare
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   101
 * operation when finished).  If this succeeds, then we're done.  If it fails,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   102
 * and the new state is VDEV_CANT_OPEN, it indicates that the device was opened,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   103
 * but that the label was not what we expected.  If the 'autoreplace' property
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   104
 * is not set, then we relabel the disk (if specified), and attempt a 'zpool
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   105
 * replace'.  If the online is successful, but the new state is something else
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   106
 * (REMOVED or FAULTED), it indicates that we're out of sync or in some sort of
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   107
 * race, and we should avoid attempting to relabel the disk.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   108
 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   109
static void
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   110
zfs_process_add(zpool_handle_t *zhp, nvlist_t *vdev, boolean_t isdisk)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   111
{
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   112
	char *path;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   113
	vdev_state_t newstate;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   114
	nvlist_t *nvroot, *newvd;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   115
	uint64_t wholedisk = 0ULL;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   116
	char *devid = NULL;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   117
	char rawpath[PATH_MAX], fullpath[PATH_MAX];
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   118
	size_t len;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   119
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   120
	if (nvlist_lookup_string(vdev, ZPOOL_CONFIG_PATH, &path) != 0)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   121
		return;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   122
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   123
	(void) nvlist_lookup_string(vdev, ZPOOL_CONFIG_DEVID, &devid);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   124
	(void) nvlist_lookup_uint64(vdev, ZPOOL_CONFIG_WHOLE_DISK, &wholedisk);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   125
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   126
	/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   127
	 * We should have a way to online a device by guid.  With the current
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   128
	 * interface, we are forced to chop off the 's0' for whole disks.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   129
	 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   130
	(void) strlcpy(fullpath, path, sizeof (fullpath));
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   131
	if (wholedisk)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   132
		fullpath[strlen(fullpath) - 2] = '\0';
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   133
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   134
	/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   135
	 * Attempt to online the device.  It would be nice to online this by
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   136
	 * GUID, but the current interface only supports lookup by path.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   137
	 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   138
	if (zpool_vdev_online(zhp, fullpath,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   139
	    ZFS_ONLINE_CHECKREMOVE | ZFS_ONLINE_UNSPARE, &newstate) == 0 &&
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   140
	    newstate != VDEV_STATE_CANT_OPEN)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   141
		return;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   142
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   143
	/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   144
	 * If the pool doesn't have the autoreplace property set, then attempt a
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   145
	 * true online (without the unspare flag), which will trigger a FMA
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   146
	 * fault.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   147
	 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   148
	if (!zpool_get_prop_int(zhp, ZPOOL_PROP_AUTOREPLACE) ||
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   149
	    (isdisk && !wholedisk)) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   150
		(void) zpool_vdev_online(zhp, fullpath, ZFS_ONLINE_FORCEFAULT,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   151
		    &newstate);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   152
		return;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   153
	}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   154
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   155
	if (isdisk) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   156
		/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   157
		 * If this is a request to label a whole disk, then attempt to
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   158
		 * write out the label.  Before we can label the disk, we need
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   159
		 * access to a raw node.  Ideally, we'd like to walk the devinfo
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   160
		 * tree and find a raw node from the corresponding parent node.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   161
		 * This is overly complicated, and since we know how we labeled
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   162
		 * this device in the first place, we know it's save to switch
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   163
		 * from /dev/dsk to /dev/rdsk and append the backup slice.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   164
		 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   165
		if (strncmp(path, "/dev/dsk/", 9) != 0)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   166
			return;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   167
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   168
		(void) strlcpy(rawpath, path + 9, sizeof (rawpath));
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   169
		len = strlen(rawpath);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   170
		rawpath[len - 2] = '\0';
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   171
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   172
		if (zpool_label_disk(g_zfshdl, zhp, rawpath) != 0)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   173
			return;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   174
	}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   175
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   176
	/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   177
	 * Cosntruct the root vdev to pass to zpool_vdev_attach().  While adding
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   178
	 * the entire vdev structure is harmless, we construct a reduced set of
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   179
	 * path/devid/wholedisk to keep it simple.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   180
	 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   181
	if (nvlist_alloc(&nvroot, NV_UNIQUE_NAME, 0) != 0)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   182
		return;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   183
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   184
	if (nvlist_alloc(&newvd, NV_UNIQUE_NAME, 0) != 0) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   185
		nvlist_free(nvroot);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   186
		return;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   187
	}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   188
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   189
	if (nvlist_add_string(newvd, ZPOOL_CONFIG_TYPE, VDEV_TYPE_DISK) != 0 ||
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   190
	    nvlist_add_string(newvd, ZPOOL_CONFIG_PATH, path) != 0 ||
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   191
	    (devid && nvlist_add_string(newvd, ZPOOL_CONFIG_DEVID,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   192
	    devid) != 0) ||
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   193
	    nvlist_add_uint64(newvd, ZPOOL_CONFIG_WHOLE_DISK, wholedisk) != 0 ||
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   194
	    nvlist_add_string(nvroot, ZPOOL_CONFIG_TYPE, VDEV_TYPE_ROOT) != 0 ||
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   195
	    nvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, &newvd,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   196
	    1) != 0) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   197
		nvlist_free(newvd);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   198
		nvlist_free(nvroot);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   199
		return;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   200
	}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   201
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   202
	nvlist_free(newvd);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   203
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   204
	(void) zpool_vdev_attach(zhp, fullpath, path, nvroot, B_TRUE);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   205
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   206
	nvlist_free(nvroot);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   207
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   208
}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   209
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   210
/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   211
 * Utility functions to find a vdev matching given criteria.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   212
 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   213
typedef struct dev_data {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   214
	const char		*dd_compare;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   215
	const char		*dd_prop;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   216
	zfs_process_func_t	dd_func;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   217
	boolean_t		dd_found;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   218
	boolean_t		dd_isdisk;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   219
	uint64_t		dd_pool_guid;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   220
	uint64_t		dd_vdev_guid;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   221
} dev_data_t;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   222
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   223
static void
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   224
zfs_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *data)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   225
{
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   226
	dev_data_t *dp = data;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   227
	char *path;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   228
	uint_t c, children;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   229
	nvlist_t **child;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   230
	size_t len = strlen(dp->dd_compare);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   231
	uint64_t wholedisk = 0ULL;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   232
	uint64_t guid;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   233
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   234
	/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   235
	 * First iterate over any children.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   236
	 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   237
	if (nvlist_lookup_nvlist_array(nvl, ZPOOL_CONFIG_CHILDREN,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   238
	    &child, &children) == 0) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   239
		for (c = 0; c < children; c++)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   240
			zfs_iter_vdev(zhp, child[c], data);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   241
		return;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   242
	}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   243
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   244
	(void) nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_WHOLE_DISK,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   245
	    &wholedisk);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   246
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   247
	if (dp->dd_vdev_guid != 0) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   248
		if (nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_GUID,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   249
		    &guid) != 0 || guid != dp->dd_vdev_guid)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   250
			return;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   251
	} else {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   252
		if (nvlist_lookup_string(nvl, dp->dd_prop, &path) != 0 ||
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   253
		    strncmp(dp->dd_compare, path, len) != 0)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   254
			return;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   255
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   256
		/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   257
		 * Normally, we want to have an exact match for the comparison
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   258
		 * string.  However, we allow substring matches in the following
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   259
		 * cases:
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   260
		 *
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   261
		 * 	<path>:		This is a devpath, and the target is one
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   262
		 * 			of its children.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   263
		 *
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   264
		 * 	<path/>		This is a devid for a whole disk, and
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   265
		 * 			the target is one of its children.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   266
		 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   267
		if (path[len] != '\0' && path[len] != ':' &&
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   268
		    path[len - 1] != '/')
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   269
			return;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   270
	}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   271
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   272
	(dp->dd_func)(zhp, nvl, dp->dd_isdisk);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   273
}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   274
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   275
static int
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   276
zfs_iter_pool(zpool_handle_t *zhp, void *data)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   277
{
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   278
	nvlist_t *config, *nvl;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   279
	dev_data_t *dp = data;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   280
	uint64_t pool_guid;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   281
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   282
	if ((config = zpool_get_config(zhp, NULL)) != NULL) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   283
		if (dp->dd_pool_guid == 0 ||
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   284
		    (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   285
		    &pool_guid) == 0 && pool_guid == dp->dd_pool_guid)) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   286
			(void) nvlist_lookup_nvlist(config,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   287
			    ZPOOL_CONFIG_VDEV_TREE, &nvl);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   288
			zfs_iter_vdev(zhp, nvl, data);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   289
		}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   290
	}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   291
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   292
	zpool_close(zhp);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   293
	return (0);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   294
}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   295
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   296
/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   297
 * Given a physical device path, iterate over all (pool, vdev) pairs which
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   298
 * correspond to the given path.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   299
 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   300
static boolean_t
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   301
devpath_iter(const char *devpath, zfs_process_func_t func, boolean_t wholedisk)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   302
{
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   303
	dev_data_t data = { 0 };
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   304
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   305
	data.dd_compare = devpath;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   306
	data.dd_func = func;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   307
	data.dd_prop = ZPOOL_CONFIG_PHYS_PATH;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   308
	data.dd_found = B_FALSE;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   309
	data.dd_isdisk = wholedisk;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   310
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   311
	(void) zpool_iter(g_zfshdl, zfs_iter_pool, &data);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   312
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   313
	return (data.dd_found);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   314
}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   315
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   316
/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   317
 * Given a /devices path, lookup the corresponding devid for each minor node,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   318
 * and find any vdevs with matching devids.  Doing this straight up would be
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   319
 * rather inefficient, O(minor nodes * vdevs in system), so we take advantage of
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   320
 * the fact that each devid ends with "/<minornode>".  Once we find any valid
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   321
 * minor node, we chop off the portion after the last slash, and then search for
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   322
 * matching vdevs, which is O(vdevs in system).
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   323
 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   324
static boolean_t
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   325
devid_iter(const char *devpath, zfs_process_func_t func, boolean_t wholedisk)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   326
{
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   327
	size_t len = strlen(devpath) + sizeof ("/devices") +
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   328
	    sizeof (PHYS_PATH) - 1;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   329
	char *fullpath;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   330
	int fd;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   331
	ddi_devid_t devid;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   332
	char *devidstr, *fulldevid;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   333
	dev_data_t data = { 0 };
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   334
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   335
	/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   336
	 * Try to open a known minor node.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   337
	 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   338
	fullpath = alloca(len);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   339
	(void) snprintf(fullpath, len, "/devices%s%s", devpath, PHYS_PATH);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   340
	if ((fd = open(fullpath, O_RDONLY)) < 0)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   341
		return (B_FALSE);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   342
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   343
	/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   344
	 * Determine the devid as a string, with no trailing slash for the minor
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   345
	 * node.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   346
	 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   347
	if (devid_get(fd, &devid) != 0) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   348
		(void) close(fd);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   349
		return (B_FALSE);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   350
	}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   351
	(void) close(fd);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   352
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   353
	if ((devidstr = devid_str_encode(devid, NULL)) == NULL) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   354
		devid_free(devid);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   355
		return (B_FALSE);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   356
	}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   357
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   358
	len = strlen(devidstr) + 2;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   359
	fulldevid = alloca(len);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   360
	(void) snprintf(fulldevid, len, "%s/", devidstr);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   361
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   362
	data.dd_compare = fulldevid;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   363
	data.dd_func = func;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   364
	data.dd_prop = ZPOOL_CONFIG_DEVID;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   365
	data.dd_found = B_FALSE;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   366
	data.dd_isdisk = wholedisk;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   367
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   368
	(void) zpool_iter(g_zfshdl, zfs_iter_pool, &data);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   369
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   370
	devid_str_free(devidstr);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   371
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   372
	return (data.dd_found);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   373
}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   374
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   375
/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   376
 * This function is called when we receive a devfs add event.  This can be
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   377
 * either a disk event or a lofi event, and the behavior is slightly different
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   378
 * depending on which it is.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   379
 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   380
static int
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   381
zfs_deliver_add(nvlist_t *nvl, boolean_t is_lofi)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   382
{
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   383
	char *devpath, *devname;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   384
	char path[PATH_MAX], realpath[PATH_MAX];
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   385
	char *colon, *raw;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   386
	int ret;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   387
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   388
	/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   389
	 * The main unit of operation is the physical device path.  For disks,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   390
	 * this is the device node, as all minor nodes are affected.  For lofi
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   391
	 * devices, this includes the minor path.  Unfortunately, this isn't
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   392
	 * represented in the DEV_PHYS_PATH for various reasons.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   393
	 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   394
	if (nvlist_lookup_string(nvl, DEV_PHYS_PATH, &devpath) != 0)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   395
		return (-1);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   396
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   397
	/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   398
	 * If this is a lofi device, then also get the minor instance name.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   399
	 * Unfortunately, the current payload doesn't include an easy way to get
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   400
	 * this information.  So we cheat by resolving the 'dev_name' (which
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   401
	 * refers to the raw device) and taking the portion between ':(*),raw'.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   402
	 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   403
	(void) strlcpy(realpath, devpath, sizeof (realpath));
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   404
	if (is_lofi) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   405
		if (nvlist_lookup_string(nvl, DEV_NAME,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   406
		    &devname) == 0 &&
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   407
		    (ret = resolvepath(devname, path,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   408
		    sizeof (path))) > 0) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   409
			path[ret] = '\0';
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   410
			colon = strchr(path, ':');
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   411
			if (colon != NULL)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   412
				raw = strstr(colon + 1, ",raw");
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   413
			if (colon != NULL && raw != NULL) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   414
				*raw = '\0';
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   415
				(void) snprintf(realpath,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   416
				    sizeof (realpath), "%s%s",
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   417
				    devpath, colon);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   418
				*raw = ',';
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   419
			}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   420
		}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   421
	}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   422
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   423
	/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   424
	 * Iterate over all vdevs with a matching devid, and then those with a
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   425
	 * matching /devices path.  For disks, we only want to pay attention to
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   426
	 * vdevs marked as whole disks.  For lofi, we don't care (because we're
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   427
	 * matching an exact minor name).
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   428
	 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   429
	if (!devid_iter(realpath, zfs_process_add, !is_lofi))
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   430
		(void) devpath_iter(realpath, zfs_process_add, !is_lofi);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   431
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   432
	return (0);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   433
}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   434
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   435
/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   436
 * Called when we receive a VDEV_CHECK event, which indicates a device could not
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   437
 * be opened during initial pool open, but the autoreplace property was set on
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   438
 * the pool.  In this case, we treat it as if it were an add event.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   439
 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   440
static int
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   441
zfs_deliver_check(nvlist_t *nvl)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   442
{
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   443
	dev_data_t data = { 0 };
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   444
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   445
	if (nvlist_lookup_uint64(nvl, ZFS_EV_POOL_GUID,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   446
	    &data.dd_pool_guid) != 0 ||
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   447
	    nvlist_lookup_uint64(nvl, ZFS_EV_VDEV_GUID,
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   448
	    &data.dd_vdev_guid) != 0)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   449
		return (0);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   450
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   451
	data.dd_isdisk = B_TRUE;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   452
	data.dd_func = zfs_process_add;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   453
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   454
	(void) zpool_iter(g_zfshdl, zfs_iter_pool, &data);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   455
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   456
	return (0);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   457
}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   458
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   459
/*ARGSUSED*/
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   460
static int
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   461
zfs_deliver_event(sysevent_t *ev, int unused)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   462
{
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   463
	const char *class = sysevent_get_class_name(ev);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   464
	const char *subclass = sysevent_get_subclass_name(ev);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   465
	nvlist_t *nvl;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   466
	int ret;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   467
	boolean_t is_lofi, is_check;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   468
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   469
	if (strcmp(class, EC_DEV_ADD) == 0) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   470
		/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   471
		 * We're mainly interested in disk additions, but we also listen
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   472
		 * for new lofi devices, to allow for simplified testing.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   473
		 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   474
		if (strcmp(subclass, ESC_DISK) == 0)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   475
			is_lofi = B_FALSE;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   476
		else if (strcmp(subclass, ESC_LOFI) == 0)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   477
			is_lofi = B_TRUE;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   478
		else
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   479
			return (0);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   480
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   481
		is_check = B_FALSE;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   482
	} else if (strcmp(class, EC_ZFS) == 0 &&
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   483
	    strcmp(subclass, ESC_ZFS_VDEV_CHECK) == 0) {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   484
		/*
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   485
		 * This event signifies that a device failed to open during pool
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   486
		 * load, but the 'autoreplace' property was set, so we should
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   487
		 * pretend it's just been added.
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   488
		 */
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   489
		is_check = B_TRUE;
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   490
	} else {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   491
		return (0);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   492
	}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   493
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   494
	if (sysevent_get_attr_list(ev, &nvl) != 0)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   495
		return (-1);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   496
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   497
	if (is_check)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   498
		ret = zfs_deliver_check(nvl);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   499
	else
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   500
		ret = zfs_deliver_add(nvl, is_lofi);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   501
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   502
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   503
	nvlist_free(nvl);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   504
	return (ret);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   505
}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   506
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   507
static struct slm_mod_ops zfs_mod_ops = {
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   508
	SE_MAJOR_VERSION, SE_MINOR_VERSION, 10, zfs_deliver_event
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   509
};
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   510
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   511
struct slm_mod_ops *
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   512
slm_init()
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   513
{
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   514
	if ((g_zfshdl = libzfs_init()) == NULL)
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   515
		return (NULL);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   516
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   517
	return (&zfs_mod_ops);
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   518
}
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   519
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   520
void
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   521
slm_fini()
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   522
{
24fbf2d7a5d7 PSARC 2007/197 ZFS hotplug
eschrock
parents:
diff changeset
   523
}