changeset 7041:b4c5fe87fad8

6721901 uninitialized variable in zfs_fm_recv() can confuse diagnosis 6721906 probe failure should be ignored during pool open 6721920 cache device failure should not trigger pool I/O failure 6722096 ZFS DE case clearing logic for vdevs is busted 6722098 ZFS DE should avoid ereports against non-leaf vdevs 6722100 replacing a hot spare with an idle spare doesn't work
author eschrock
date Fri, 04 Jul 2008 13:08:26 -0700
parents eeae3015c35e
children 46fc4b6db23e
files usr/src/cmd/fm/modules/common/zfs-diagnosis/zfs_de.c usr/src/lib/libzfs/common/libzfs_pool.c usr/src/uts/common/fs/zfs/vdev_label.c
diffstat 3 files changed, 46 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/fm/modules/common/zfs-diagnosis/zfs_de.c	Fri Jul 04 06:02:33 2008 -0700
+++ b/usr/src/cmd/fm/modules/common/zfs-diagnosis/zfs_de.c	Fri Jul 04 13:08:26 2008 -0700
@@ -166,7 +166,19 @@
 	 * Iterate over all children.
 	 */
 	if (nvlist_lookup_nvlist_array(vd, ZPOOL_CONFIG_CHILDREN, &child,
-	    &children) != 0) {
+	    &children) == 0) {
+		for (c = 0; c < children; c++)
+			zfs_mark_vdev(pool_guid, child[c]);
+	}
+
+	if (nvlist_lookup_nvlist_array(vd, ZPOOL_CONFIG_L2CACHE, &child,
+	    &children) == 0) {
+		for (c = 0; c < children; c++)
+			zfs_mark_vdev(pool_guid, child[c]);
+	}
+
+	if (nvlist_lookup_nvlist_array(vd, ZPOOL_CONFIG_SPARES, &child,
+	    &children) == 0) {
 		for (c = 0; c < children; c++)
 			zfs_mark_vdev(pool_guid, child[c]);
 	}
@@ -341,7 +353,7 @@
 	uint64_t ena, pool_guid, vdev_guid;
 	nvlist_t *detector;
 	boolean_t isresource;
-	boolean_t checkremove;
+	char *type;
 
 	isresource = fmd_nvl_class_match(hdl, nvl, "resource.fs.zfs.*");
 
@@ -375,11 +387,25 @@
 	 * Device I/O errors are ignored during pool open.
 	 */
 	if (pool_state == SPA_LOAD_OPEN &&
-	    (fmd_nvl_class_match(hdl, nvl, "ereport.fs.zfs.checksum") ||
-	    fmd_nvl_class_match(hdl, nvl, "ereport.fs.zfs.io")))
+	    (fmd_nvl_class_match(hdl, nvl,
+	    ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_CHECKSUM)) ||
+	    fmd_nvl_class_match(hdl, nvl,
+	    ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_IO)) ||
+	    fmd_nvl_class_match(hdl, nvl,
+	    ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_PROBE_FAILURE))))
 		return;
 
 	/*
+	 * We ignore ereports for anything except disks and files.
+	 */
+	if (nvlist_lookup_string(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_TYPE,
+	    &type) == 0) {
+		if (strcmp(type, VDEV_TYPE_DISK) != 0 &&
+		    strcmp(type, VDEV_TYPE_FILE) != 0)
+			return;
+	}
+
+	/*
 	 * Determine if this ereport corresponds to an open case.  Cases are
 	 * indexed by ENA, since ZFS does all the work of chaining together
 	 * related ereports.
@@ -555,6 +581,7 @@
 	    fmd_nvl_class_match(hdl, nvl,
 	    ZFS_MAKE_EREPORT(FM_EREPORT_ZFS_PROBE_FAILURE))) {
 		char *failmode = NULL;
+		boolean_t checkremove = B_FALSE;
 
 		/*
 		 * If this is a checksum or I/O error, then toss it into the
--- a/usr/src/lib/libzfs/common/libzfs_pool.c	Fri Jul 04 06:02:33 2008 -0700
+++ b/usr/src/lib/libzfs/common/libzfs_pool.c	Fri Jul 04 13:08:26 2008 -0700
@@ -1502,7 +1502,7 @@
 	nvlist_t *tgt;
 	boolean_t avail_spare, l2cache;
 	uint64_t val, is_log;
-	char *path;
+	char *path, *newname;
 	nvlist_t **child;
 	uint_t children;
 	nvlist_t *config_root;
@@ -1538,17 +1538,20 @@
 	verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
 	    ZPOOL_CONFIG_VDEV_TREE, &config_root) == 0);
 
+	if ((newname = zpool_vdev_name(NULL, NULL, child[0])) == NULL)
+		return (-1);
+
 	/*
 	 * If the target is a hot spare that has been swapped in, we can only
 	 * replace it with another hot spare.
 	 */
 	if (replacing &&
 	    nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_IS_SPARE, &val) == 0 &&
-	    nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 &&
-	    (zpool_find_vdev(zhp, path, &avail_spare, &l2cache) == NULL ||
+	    (zpool_find_vdev(zhp, newname, &avail_spare, &l2cache) == NULL ||
 	    !avail_spare) && is_replacing_spare(config_root, tgt, 1)) {
 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 		    "can only be replaced by another hot spare"));
+		free(newname);
 		return (zfs_error(hdl, EZFS_BADTARGET, msg));
 	}
 
@@ -1558,13 +1561,16 @@
 	 */
 	if (replacing &&
 	    nvlist_lookup_string(child[0], ZPOOL_CONFIG_PATH, &path) == 0 &&
-	    zpool_find_vdev(zhp, path, &avail_spare, &l2cache) != NULL &&
+	    zpool_find_vdev(zhp, newname, &avail_spare, &l2cache) != NULL &&
 	    avail_spare && is_replacing_spare(config_root, tgt, 0)) {
 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 		    "device has already been replaced with a spare"));
+		free(newname);
 		return (zfs_error(hdl, EZFS_BADTARGET, msg));
 	}
 
+	free(newname);
+
 	if (zcmd_write_conf_nvlist(hdl, &zc, nvroot) != 0)
 		return (-1);
 
--- a/usr/src/uts/common/fs/zfs/vdev_label.c	Fri Jul 04 06:02:33 2008 -0700
+++ b/usr/src/uts/common/fs/zfs/vdev_label.c	Fri Jul 04 13:08:26 2008 -0700
@@ -913,10 +913,10 @@
 }
 
 /*
- * We ignore errors for log devices, simply free the private data.
+ * We ignore errors for log and cache devices, simply free the private data.
  */
 static void
-vdev_label_sync_log_done(zio_t *zio)
+vdev_label_sync_ignore_done(zio_t *zio)
 {
 	kmem_free(zio->io_private, sizeof (uint64_t));
 }
@@ -993,8 +993,9 @@
 	for (vd = list_head(dl); vd != NULL; vd = list_next(dl, vd)) {
 		uint64_t *good_writes = kmem_zalloc(sizeof (uint64_t),
 		    KM_SLEEP);
-		zio_t *vio = zio_null(nio, spa, vd->vdev_islog ?
-		    vdev_label_sync_log_done : vdev_label_sync_top_done,
+		zio_t *vio = zio_null(nio, spa,
+		    (vd->vdev_islog || vd->vdev_aux != NULL) ?
+		    vdev_label_sync_ignore_done : vdev_label_sync_top_done,
 		    good_writes, flags);
 		vdev_label_sync(vio, vd, l, txg);
 		zio_nowait(vio);