Print this page
NEX-17446 cleanup of hot unplugged disks fails intermittently
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-17944 HBA drivers don't need the redundant devfs_clean step
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-17934 NULL pointer reference in kstat_rele()
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-15288 getting kstat_create('mdi'...) errors on each reboot
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
NEX-15925 pseudonex, rootnex, and friends don't need to log useless device announcements
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
OS-253 we should not free mdi_pathinfo_t in mptsas when device(s) are retired
OS-126 Creating a LUN for retired device results in sysevent loop

@@ -16,28 +16,19 @@
  * fields enclosed by brackets "[]" replaced with your own identifying
  * information: Portions Copyright [yyyy] [name of copyright owner]
  *
  * CDDL HEADER END
  */
+
 /*
  * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2014 Nexenta Systems Inc. All rights reserved.
+ * Copyright 2018 Nexenta Systems, Inc.
  */
 
 /*
  * Multipath driver interface (MDI) implementation; see mdi_impldefs.h for a
  * more detailed discussion of the overall mpxio architecture.
- *
- * Default locking order:
- *
- * _NOTE(LOCK_ORDER(mdi_mutex, mdi_vhci:vh_phci_mutex);
- * _NOTE(LOCK_ORDER(mdi_mutex, mdi_vhci:vh_client_mutex);
- * _NOTE(LOCK_ORDER(mdi_vhci:vh_phci_mutex, mdi_phci::ph_mutex);
- * _NOTE(LOCK_ORDER(mdi_vhci:vh_client_mutex, mdi_client::ct_mutex);
- * _NOTE(LOCK_ORDER(mdi_phci::ph_mutex mdi_pathinfo::pi_mutex))
- * _NOTE(LOCK_ORDER(mdi_phci::ph_mutex mdi_client::ct_mutex))
- * _NOTE(LOCK_ORDER(mdi_client::ct_mutex mdi_pathinfo::pi_mutex))
  */
 
 #include <sys/note.h>
 #include <sys/types.h>
 #include <sys/varargs.h>

@@ -1194,11 +1185,16 @@
 {
         int     rv = MDI_SUCCESS;
 
         if (i_mdi_is_child_present(vdip, cdip) == MDI_SUCCESS ||
             (flags & MDI_CLIENT_FLAGS_DEV_NOT_SUPPORTED)) {
-                rv = ndi_devi_offline(cdip, NDI_DEVFS_CLEAN | NDI_DEVI_REMOVE);
+                int nflags = NDI_DEVFS_CLEAN | NDI_DEVI_REMOVE;
+
+                if (flags & MDI_CLIENT_FLAGS_NO_EVENT)
+                        nflags |= NDI_NO_EVENT;
+
+                rv = ndi_devi_offline(cdip, nflags);
                 if (rv != NDI_SUCCESS) {
                         MDI_DEBUG(1, (MDI_NOTE, cdip,
                             "!failed: cdip %p", (void *)cdip));
                 }
                 /*

@@ -3261,10 +3257,11 @@
                 if (ct->ct_path_count == 0) {
                         /*
                          * Client lost its last path.
                          * Clean up the client device
                          */
+                        ct->ct_flags |= flags;
                         MDI_CLIENT_UNLOCK(ct);
                         (void) i_mdi_client_free(ct->ct_vhci, ct);
                         MDI_VHCI_CLIENT_UNLOCK(vh);
                         return (rv);
                 }

@@ -3668,31 +3665,30 @@
                         case MDI_CLIENT_STATE_FAILED:
                                 /*
                                  * This is the last path case for
                                  * non-user initiated events.
                                  */
-                                if (((flag & NDI_USER_REQ) == 0) &&
-                                    cdip && (i_ddi_node_state(cdip) >=
-                                    DS_INITIALIZED)) {
+                                if ((flag & NDI_USER_REQ) ||
+                                    cdip == NULL || i_ddi_node_state(cdip) <
+                                    DS_INITIALIZED)
+                                        break;
+
                                         MDI_CLIENT_UNLOCK(ct);
-                                        rv = ndi_devi_offline(cdip,
-                                            NDI_DEVFS_CLEAN);
+                                rv = ndi_devi_offline(cdip, NDI_DEVFS_CLEAN |
+                                    NDI_DEVI_GONE);
                                         MDI_CLIENT_LOCK(ct);
 
                                         if (rv != NDI_SUCCESS) {
                                                 /*
-                                                 * ndi_devi_offline failed.
-                                                 * Reset client flags to
-                                                 * online as the path could not
-                                                 * be offlined.
+                                         * Reset client flags to online as the
+                                         * path could not be offlined.
                                                  */
                                                 MDI_DEBUG(1, (MDI_WARN, cdip,
-                                                    "!ndi_devi_offline failed: "
-                                                    "error %x", rv));
+                                            "!ndi_devi_offline failed: %d",
+                                            rv));
                                                 MDI_CLIENT_SET_ONLINE(ct);
                                         }
-                                }
                                 break;
                         }
                         /*
                          * Convert to MDI error code
                          */

@@ -4853,18 +4849,13 @@
                 status = "faulted";
         } else {
                 status = "unknown";
         }
 
-        if (cdip) {
+        if (cdip != NULL) {
                 ct_path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
 
-                /*
-                 * NOTE: Keeping "multipath status: %s" and
-                 * "Load balancing: %s" format unchanged in case someone
-                 * scrubs /var/adm/messages looking for these messages.
-                 */
                 if (report_lb_c && report_lb_p) {
                         if (ct->ct_lb == LOAD_BALANCE_LBA) {
                                 (void) snprintf(lb_buf, sizeof (lb_buf),
                                     "%s, region-size: %d", mdi_load_balance_lba,
                                     ct->ct_lb_args->region_size);

@@ -4874,24 +4865,18 @@
                         } else {
                                 (void) snprintf(lb_buf, sizeof (lb_buf), "%s",
                                     mdi_load_balance_rr);
                         }
 
-                        cmn_err(mdi_debug_consoleonly ? CE_NOTE : CE_CONT,
-                            "?%s (%s%d) multipath status: %s: "
-                            "path %d %s is %s: Load balancing: %s\n",
-                            ddi_pathname(cdip, ct_path), ddi_driver_name(cdip),
-                            ddi_get_instance(cdip), ct_status,
-                            mdi_pi_get_path_instance(pip),
+                        dev_err(cdip, CE_CONT, "!multipath status: %s: "
+                            "path %d %s is %s; load balancing: %s\n",
+                            ct_status, mdi_pi_get_path_instance(pip),
                             mdi_pi_spathname(pip), status, lb_buf);
                 } else {
-                        cmn_err(mdi_debug_consoleonly ? CE_NOTE : CE_CONT,
-                            "?%s (%s%d) multipath status: %s: "
-                            "path %d %s is %s\n",
-                            ddi_pathname(cdip, ct_path), ddi_driver_name(cdip),
-                            ddi_get_instance(cdip), ct_status,
-                            mdi_pi_get_path_instance(pip),
+                        dev_err(cdip, CE_CONT,
+                            "!multipath status: %s: path %d %s is %s\n",
+                            ct_status, mdi_pi_get_path_instance(pip),
                             mdi_pi_spathname(pip), status);
                 }
 
                 kmem_free(ct_path, MAXPATHLEN);
                 MDI_CLIENT_CLEAR_REPORT_DEV_NEEDED(ct);

@@ -6073,25 +6058,37 @@
 mdi_pi_kstat_create(mdi_pathinfo_t *pip, char *ksname)
 {
         kstat_t                 *kiosp, *kerrsp;
         struct pi_errs          *nsp;
         struct mdi_pi_kstats    *mdi_statp;
+        char                    *errksname;
+        size_t                  len;
 
-        if (MDI_PI(pip)->pi_kstats != NULL)
+        /*
+         * If the kstat name was already created nothing to do.
+         */
+        if ((kiosp = kstat_hold_byname("mdi", 0, ksname,
+            ALL_ZONES)) != NULL) {
+                kstat_rele(kiosp);
                 return (MDI_SUCCESS);
+        }
 
         if ((kiosp = kstat_create("mdi", 0, ksname, "iopath",
             KSTAT_TYPE_IO, 1, KSTAT_FLAG_PERSISTENT)) == NULL) {
                 return (MDI_FAILURE);
         }
 
-        (void) strcat(ksname, ",err");
-        kerrsp = kstat_create("mdi", 0, ksname, "iopath_errors",
+        len = strlen(ksname) + strlen(",err") + 1;
+        errksname = kmem_alloc(len, KM_SLEEP);
+        (void) snprintf(errksname, len, "%s,err", ksname);
+
+        kerrsp = kstat_create("mdi", 0, errksname, "iopath_errors",
             KSTAT_TYPE_NAMED,
             sizeof (struct pi_errs) / sizeof (kstat_named_t), 0);
         if (kerrsp == NULL) {
                 kstat_delete(kiosp);
+                kmem_free(errksname, len);
                 return (MDI_FAILURE);
         }
 
         nsp = (struct pi_errs *)kerrsp->ks_data;
         kstat_named_init(&nsp->pi_softerrs, "Soft Errors", KSTAT_DATA_UINT32);

@@ -6117,10 +6114,11 @@
         mdi_statp->pi_kstat_iostats = kiosp;
         mdi_statp->pi_kstat_errstats = kerrsp;
         kstat_install(kiosp);
         kstat_install(kerrsp);
         MDI_PI(pip)->pi_kstats = mdi_statp;
+        kmem_free(errksname, len);
         return (MDI_SUCCESS);
 }
 
 /*
  * destroy per-path properties