changeset 25179:774e1bce00ad

12924 blkdev needs to be better at handling attach failures Reviewed by: Toomas Soome <tsoome@me.com> Reviewed by: Paul Winder <paul@winders.demon.co.uk> Approved by: Dan McDonald <danmcd@joyent.com>
author Jason King <jason.king@joyent.com>
date Fri, 03 Jul 2020 00:42:14 -0500
parents e3294d77da91
children 8e476c6cec39
files usr/src/uts/common/io/blkdev/blkdev.c
diffstat 1 files changed, 32 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/io/blkdev/blkdev.c	Tue Jan 31 01:33:09 2017 +0000
+++ b/usr/src/uts/common/io/blkdev/blkdev.c	Fri Jul 03 00:42:14 2020 -0500
@@ -25,6 +25,7 @@
  * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  * Copyright 2017 The MathWorks, Inc.  All rights reserved.
  * Copyright 2019 Western Digital Corporation.
+ * Copyright 2020 Joyent, Inc.
  */
 
 #include <sys/types.h>
@@ -228,8 +229,10 @@
 static void bd_prop_update_inqstring(dev_info_t *, char *, char *, size_t);
 static void bd_create_inquiry_props(dev_info_t *, bd_drive_t *);
 static void bd_create_errstats(bd_t *, int, bd_drive_t *);
+static void bd_destroy_errstats(bd_t *);
 static void bd_errstats_setstr(kstat_named_t *, char *, size_t, char *);
 static void bd_init_errstats(bd_t *, bd_drive_t *);
+static void bd_fini_errstats(bd_t *);
 
 static int bd_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
 static int bd_attach(dev_info_t *, ddi_attach_cmd_t);
@@ -490,6 +493,21 @@
 	bd->d_errstats->ks_private = bd;
 
 	kstat_install(bd->d_errstats);
+	bd_init_errstats(bd, drive);
+}
+
+static void
+bd_destroy_errstats(bd_t *bd)
+{
+	if (bd->d_errstats != NULL) {
+		bd_fini_errstats(bd);
+		kstat_delete(bd->d_errstats);
+		bd->d_errstats = NULL;
+	} else {
+		kmem_free(bd->d_kerr, sizeof (struct bd_errstats));
+		bd->d_kerr = NULL;
+		mutex_destroy(&bd->d_errmutex);
+	}
 }
 
 static void
@@ -707,7 +725,6 @@
 	bd_create_inquiry_props(dip, &drive);
 
 	bd_create_errstats(bd, inst, &drive);
-	bd_init_errstats(bd, &drive);
 	bd_update_state(bd);
 
 	bd->d_queues = kmem_alloc(sizeof (*bd->d_queues) * bd->d_qcount,
@@ -732,19 +749,23 @@
 	    drive.d_lun >= 0 ? DDI_NT_BLOCK_CHAN : DDI_NT_BLOCK,
 	    CMLB_FAKE_LABEL_ONE_PARTITION, bd->d_cmlbh, 0);
 	if (rv != 0) {
+		bd_queues_free(bd);
+		bd_destroy_errstats(bd);
 		cmlb_free_handle(&bd->d_cmlbh);
-		kmem_cache_destroy(bd->d_cache);
-		mutex_destroy(&bd->d_ksmutex);
-		mutex_destroy(&bd->d_ocmutex);
-		mutex_destroy(&bd->d_statemutex);
-		cv_destroy(&bd->d_statecv);
-		bd_queues_free(bd);
+
 		if (bd->d_ksp != NULL) {
 			kstat_delete(bd->d_ksp);
 			bd->d_ksp = NULL;
 		} else {
 			kmem_free(bd->d_kiop, sizeof (kstat_io_t));
+			bd->d_kiop = NULL;
 		}
+
+		kmem_cache_destroy(bd->d_cache);
+		cv_destroy(&bd->d_statecv);
+		mutex_destroy(&bd->d_statemutex);
+		mutex_destroy(&bd->d_ocmutex);
+		mutex_destroy(&bd->d_ksmutex);
 		ddi_soft_state_free(bd_state, inst);
 		return (DDI_FAILURE);
 	}
@@ -797,6 +818,7 @@
 	default:
 		return (DDI_FAILURE);
 	}
+
 	if (bd->d_ksp != NULL) {
 		kstat_delete(bd->d_ksp);
 		bd->d_ksp = NULL;
@@ -804,15 +826,7 @@
 		kmem_free(bd->d_kiop, sizeof (kstat_io_t));
 	}
 
-	if (bd->d_errstats != NULL) {
-		bd_fini_errstats(bd);
-		kstat_delete(bd->d_errstats);
-		bd->d_errstats = NULL;
-	} else {
-		kmem_free(bd->d_kerr, sizeof (struct bd_errstats));
-		mutex_destroy(&bd->d_errmutex);
-	}
-
+	bd_destroy_errstats(bd);
 	cmlb_detach(bd->d_cmlbh, 0);
 	cmlb_free_handle(&bd->d_cmlbh);
 	if (bd->d_devid)
@@ -2052,11 +2066,12 @@
 	ddi_set_parent_data(child, hdl);
 	hdl->h_child = child;
 
-	if (ndi_devi_online(child, 0) == NDI_FAILURE) {
+	if (ndi_devi_online(child, 0) != NDI_SUCCESS) {
 		cmn_err(CE_WARN, "%s%d: failed bringing node %s@%s online",
 		    ddi_driver_name(dip), ddi_get_instance(dip),
 		    hdl->h_name, hdl->h_addr);
 		(void) ndi_devi_free(child);
+		hdl->h_child = NULL;
 		return (DDI_FAILURE);
 	}