changeset 13574:d0fde6cacaac

1951 leaking a vdev when removing an l2cache device 1952 memory leak when adding a file-based l2arc device 1954 leak in ZFS from metaslab_group_create and zfs_ereport_checksum Reviewed by: Adam Leventhal <ahl@delphix.com> Reviewed by: Matt Ahrens <matt@delphix.com> Reviewed by: Eric Schrock <eric.schrock@delphix.com> Reviewed by: Bill Pijewski <wdp@joyent.com> Reviewed by: Dan McDonald <danmcd@nexenta.com> Approved by: Eric Schrock <eric.schrock@delphix.com>
author George Wilson <george.wilson@delphix.com>
date Mon, 23 Jan 2012 19:46:52 -0800
parents 72c96cded60f
children 36d25dce128e
files usr/src/uts/common/fs/zfs/spa.c usr/src/uts/common/fs/zfs/sys/vdev_impl.h usr/src/uts/common/fs/zfs/vdev.c usr/src/uts/common/fs/zfs/zfs_fm.c
diffstat 4 files changed, 21 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/fs/zfs/spa.c	Mon Jan 23 19:08:40 2012 -0800
+++ b/usr/src/uts/common/fs/zfs/spa.c	Mon Jan 23 19:46:52 2012 -0800
@@ -1063,8 +1063,10 @@
 	}
 	spa->spa_spares.sav_count = 0;
 
-	for (i = 0; i < spa->spa_l2cache.sav_count; i++)
+	for (i = 0; i < spa->spa_l2cache.sav_count; i++) {
+		vdev_clear_stats(spa->spa_l2cache.sav_vdevs[i]);
 		vdev_free(spa->spa_l2cache.sav_vdevs[i]);
+	}
 	if (spa->spa_l2cache.sav_vdevs) {
 		kmem_free(spa->spa_l2cache.sav_vdevs,
 		    spa->spa_l2cache.sav_count * sizeof (void *));
@@ -1292,11 +1294,13 @@
 
 		vd = oldvdevs[i];
 		if (vd != NULL) {
+			ASSERT(vd->vdev_isl2cache);
+
 			if (spa_l2cache_exists(vd->vdev_guid, &pool) &&
 			    pool != 0ULL && l2arc_vdev_present(vd))
 				l2arc_remove_vdev(vd);
-			(void) vdev_close(vd);
-			spa_l2cache_remove(vd);
+			vdev_clear_stats(vd);
+			vdev_free(vd);
 		}
 	}
 
@@ -2797,6 +2801,7 @@
 		if ((strcmp(config, ZPOOL_CONFIG_L2CACHE) == 0) &&
 		    strcmp(vd->vdev_ops->vdev_op_type, VDEV_TYPE_DISK) != 0) {
 			error = ENOTBLK;
+			vdev_free(vd);
 			goto out;
 		}
 #endif
@@ -2906,10 +2911,6 @@
 		if (spa_l2cache_exists(vd->vdev_guid, &pool) &&
 		    pool != 0ULL && l2arc_vdev_present(vd))
 			l2arc_remove_vdev(vd);
-		if (vd->vdev_isl2cache)
-			spa_l2cache_remove(vd);
-		vdev_clear_stats(vd);
-		(void) vdev_close(vd);
 	}
 }
 
@@ -3901,7 +3902,7 @@
 	pvd = oldvd->vdev_parent;
 
 	if ((error = spa_config_parse(spa, &newrootvd, nvroot, NULL, 0,
-	    VDEV_ALLOC_ADD)) != 0)
+	    VDEV_ALLOC_ATTACH)) != 0)
 		return (spa_vdev_exit(spa, NULL, txg, EINVAL));
 
 	if (newrootvd->vdev_children != 1)
--- a/usr/src/uts/common/fs/zfs/sys/vdev_impl.h	Mon Jan 23 19:08:40 2012 -0800
+++ b/usr/src/uts/common/fs/zfs/sys/vdev_impl.h	Mon Jan 23 19:46:52 2012 -0800
@@ -264,6 +264,7 @@
 #define	VDEV_ALLOC_L2CACHE	3
 #define	VDEV_ALLOC_ROOTPOOL	4
 #define	VDEV_ALLOC_SPLIT	5
+#define	VDEV_ALLOC_ATTACH	6
 
 /*
  * Allocate or free a vdev
--- a/usr/src/uts/common/fs/zfs/vdev.c	Mon Jan 23 19:08:40 2012 -0800
+++ b/usr/src/uts/common/fs/zfs/vdev.c	Mon Jan 23 19:46:52 2012 -0800
@@ -488,7 +488,7 @@
 		    &vd->vdev_removing);
 	}
 
-	if (parent && !parent->vdev_parent) {
+	if (parent && !parent->vdev_parent && alloctype != VDEV_ALLOC_ATTACH) {
 		ASSERT(alloctype == VDEV_ALLOC_LOAD ||
 		    alloctype == VDEV_ALLOC_ADD ||
 		    alloctype == VDEV_ALLOC_SPLIT ||
@@ -664,6 +664,8 @@
 	svd->vdev_ms_shift = 0;
 	svd->vdev_ms_count = 0;
 
+	if (tvd->vdev_mg)
+		ASSERT3P(tvd->vdev_mg, ==, svd->vdev_mg);
 	tvd->vdev_mg = svd->vdev_mg;
 	tvd->vdev_ms = svd->vdev_ms;
 
--- a/usr/src/uts/common/fs/zfs/zfs_fm.c	Mon Jan 23 19:08:40 2012 -0800
+++ b/usr/src/uts/common/fs/zfs/zfs_fm.c	Mon Jan 23 19:46:52 2012 -0800
@@ -23,6 +23,10 @@
  * Use is subject to license terms.
  */
 
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
 #include <sys/spa.h>
 #include <sys/spa_impl.h>
 #include <sys/vdev.h>
@@ -709,6 +713,10 @@
 
 	if (report->zcr_ereport == NULL) {
 		report->zcr_free(report->zcr_cbdata, report->zcr_cbinfo);
+		if (report->zcr_ckinfo != NULL) {
+			kmem_free(report->zcr_ckinfo,
+			    sizeof (*report->zcr_ckinfo));
+		}
 		kmem_free(report, sizeof (*report));
 		return;
 	}