Print this page
NEX-18492 Disk can't be restored in pool if disappeared under active I/O
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-18264 devi_detach_node() should be aware that device class can be NULL
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-18214 unplug of multipathed disks doesn't produce EC_DEV_REMOVE/ESC_DISK event (fix build)
NEX-18214 unplug of multipathed disks doesn't produce EC_DEV_REMOVE/ESC_DISK event
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Revert "NEX-18214 unplug of multipathed disks doesn't produce EC_DEV_REMOVE/ESC_DISK event"
This reverts commit b0f7e47b60b115c1bb6c07dc5aa150cc519790e7.
NEX-18214 unplug of multipathed disks doesn't produce EC_DEV_REMOVE/ESC_DISK event
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Dan Fields <dan.fields@nexenta.com>
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-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>
NEX-15146 Retired device is not listed after appliance reboot
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Dmitry Savitsky <dmitry.savitsky@nexenta.com>
OS-164 Add ddi property to allow device
retire to succeed when device is in use

@@ -16,15 +16,16 @@
  * 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 2012 Nexenta Systems, Inc. All rights reserved.
  * Copyright 2012 Garrett D'Amore <garrett@damore.org>.  All rights reserved.
  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright 2018 Nexenta Systems, Inc.
  * Copyright (c) 2016 by Delphix. All rights reserved.
  */
 
 #include <sys/note.h>
 #include <sys/t_lock.h>

@@ -169,14 +170,13 @@
  * 3rd party driver depends on identify(9e) being called.
  */
 int identify_9e = 0;
 
 /*
- * Add flag so behaviour of preventing attach for retired persistant nodes
- * can be disabled.
+ * Don't prevent attaching retired devices by default.
  */
-int retire_prevents_attach = 1;
+int retire_prevents_attach = 0;
 
 int mtc_off;                                    /* turn off mt config */
 
 int quiesce_debug = 0;
 

@@ -483,15 +483,10 @@
         mutex_destroy(&(devi->devi_ct_lock));
         RIO_TRACE((CE_NOTE, "i_ddi_free_node: destroyed all contract fields: "
             "dip=%p, name=%s", (void *)dip, devi->devi_node_name));
 
         kmem_free(devi->devi_node_name, strlen(devi->devi_node_name) + 1);
-
-        /* free event data */
-        if (devi->devi_ev_path)
-                kmem_free(devi->devi_ev_path, MAXPATHLEN);
-
         kmem_cache_free(ddi_node_cache, devi);
 }
 
 
 /*

@@ -1358,12 +1353,12 @@
         int             rv;
 
         ASSERT(DEVI_BUSY_OWNED(ddi_get_parent(dip)));
         ASSERT(i_ddi_node_state(dip) == DS_ATTACHED);
 
-        /* check references */
-        if (DEVI(dip)->devi_ref)
+        /* Check references */
+        if (DEVI(dip)->devi_ref != 0 && !DEVI_IS_GONE(dip))
                 return (DDI_FAILURE);
 
         NDI_CONFIG_DEBUG((CE_CONT, "detach_node: 0x%p(%s%d)\n",
             (void *)dip, ddi_driver_name(dip), ddi_get_instance(dip)));
 

@@ -1461,10 +1456,12 @@
 static int
 postattach_node(dev_info_t *dip)
 {
         int rval;
 
+        DEVI_UNSET_GONE(dip);
+
         /*
          * For hotplug busses like USB, it's possible that devices
          * are removed but dip is still around. We don't want to
          * run dacf routines as part of detach failure recovery.
          *

@@ -3819,12 +3816,12 @@
  * with argument "ioc@xxxxxxx,yyyyyyy:port=1". After configuring
  * the ioc, look for minor node dhcp. If not found, pass ":dhcp"
  * to ioc's bus_config entry point.
  */
 int
-resolve_pathname(char *pathname,
-        dev_info_t **dipp, dev_t *devtp, int *spectypep)
+resolve_pathname(char *pathname, dev_info_t **dipp, dev_t *devtp,
+    int *spectypep)
 {
         int                     error;
         dev_info_t              *parent, *child;
         struct pathname         pn;
         char                    *component, *config_name;

@@ -4598,13 +4595,13 @@
 
 /*
  * report device status
  */
 static void
-i_ndi_devi_report_status_change(dev_info_t *dip, char *path)
+i_ndi_devi_report_status_change(dev_info_t *dip)
 {
-        char *status;
+        const char *status;
 
         if (!DEVI_NEED_REPORT(dip) ||
             (i_ddi_node_state(dip) < DS_INITIALIZED) ||
             ndi_dev_is_hidden_node(dip)) {
                 return;

@@ -4627,21 +4624,12 @@
                 status = "online";
         } else {
                 status = "unknown";
         }
 
-        if (path == NULL) {
-                path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
-                cmn_err(CE_CONT, "?%s (%s%d) %s\n",
-                    ddi_pathname(dip, path), ddi_driver_name(dip),
+        cmn_err(CE_CONT, "?%s%d %s\n", ddi_driver_name(dip),
                     ddi_get_instance(dip), status);
-                kmem_free(path, MAXPATHLEN);
-        } else {
-                cmn_err(CE_CONT, "?%s (%s%d) %s\n",
-                    path, ddi_driver_name(dip),
-                    ddi_get_instance(dip), status);
-        }
 
         mutex_enter(&(DEVI(dip)->devi_lock));
         DEVI_REPORT_DONE(dip);
         mutex_exit(&(DEVI(dip)->devi_lock));
 }

@@ -5225,11 +5213,11 @@
                         (void) ddi_remove_child(dip, 0);
                 }
                 return (NDI_FAILURE);
         }
 
-        i_ndi_devi_report_status_change(dip, NULL);
+        i_ndi_devi_report_status_change(dip);
 
         /*
          * log an event, but not during devfs lookups in which case
          * NDI_NO_EVENT is set.
          */

@@ -5763,10 +5751,21 @@
                 break;
         default:
                 ASSERT(retval == LDI_EV_NONE);
         }
 
+        /*
+         * In order to allow a device retire to succeed that is in use
+         */
+
+        if (ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
+            "allow-unconstrained-retire", 0) == 1 && failure == 0) {
+                RIO_VERBOSE((CE_NOTE, "e_ddi_offline_notify(): setting "
+                    "constraint flag due to 'allow-unconstrained-retire' "
+                    "property on dip=%p", (void *)dip));
+                constraint = 1;
+        }
 out:
         mutex_enter(&(DEVI(dip)->devi_lock));
         if ((DEVI(dip)->devi_flags & DEVI_RETIRING) && failure) {
                 RIO_VERBOSE((CE_NOTE, "e_ddi_offline_notify(): setting "
                     "BLOCKED flag. dip=%p", (void *)dip));

@@ -5928,32 +5927,35 @@
                 DEVI_SET_DEVICE_OFFLINE(dip);
                 mutex_exit(&(DEVI(dip)->devi_lock));
         }
 
         if (i_ddi_node_state(dip) == DS_INITIALIZED) {
-                struct dev_info *devi = DEVI(dip);
-
-                if (devi->devi_ev_path == NULL) {
-                        devi->devi_ev_path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
-                        (void) ddi_pathname(dip, devi->devi_ev_path);
-                }
                 if (flags & NDI_DEVI_OFFLINE)
-                        i_ndi_devi_report_status_change(dip,
-                            devi->devi_ev_path);
+                        i_ndi_devi_report_status_change(dip);
 
                 if (need_remove_event(dip, flags)) {
-                        /*
-                         * instance and path data are lost in call to
-                         * ddi_uninitchild
-                         */
-                        devi->devi_ev_instance = ddi_get_instance(dip);
-
                         mutex_enter(&(DEVI(dip)->devi_lock));
                         DEVI_SET_EVREMOVE(dip);
                         mutex_exit(&(DEVI(dip)->devi_lock));
+
+                        post_event = (flags & NDI_DEVI_REMOVE) ||
+                            DEVI_IS_GONE(dip);
                 }
+
+                if (post_event) {
+                        /*
+                         * Instance and path data are lost in call to
+                         * ddi_uninitchild.
+                         */
+                        path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
+                        (void) ddi_pathname(dip, path);
+                        class = i_ddi_strdup(i_ddi_devi_class(dip), KM_SLEEP);
+                        driver = i_ddi_strdup((char *)ddi_driver_name(dip),
+                            KM_SLEEP);
+                        instance = ddi_get_instance(dip);
         }
+        }
 
         if (flags & (NDI_UNCONFIG | NDI_DEVI_REMOVE)) {
                 ret = ddi_uninitchild(dip);
                 if (ret == NDI_SUCCESS) {
                         /*

@@ -5962,50 +5964,32 @@
                          * reattached.
                          */
                         if (!ndi_dev_is_persistent_node(dip))
                                 flags |= NDI_DEVI_REMOVE;
 
-                        if (flags & NDI_DEVI_REMOVE) {
-                                /*
-                                 * NOTE: If there is a consumer of LDI events,
-                                 * ddi_uninitchild above would have failed
-                                 * because of active devi_ref from ldi_open().
-                                 */
-
-                                if (DEVI_EVREMOVE(dip)) {
-                                        path = i_ddi_strdup(
-                                            DEVI(dip)->devi_ev_path,
-                                            KM_SLEEP);
-                                        class =
-                                            i_ddi_strdup(i_ddi_devi_class(dip),
-                                            KM_SLEEP);
-                                        driver =
-                                            i_ddi_strdup(
-                                            (char *)ddi_driver_name(dip),
-                                            KM_SLEEP);
-                                        instance = DEVI(dip)->devi_ev_instance;
-                                        post_event = 1;
+                        if (flags & NDI_DEVI_REMOVE)
+                                ret = ddi_remove_child(dip, 0);
                                 }
+        }
 
-                                ret = ddi_remove_child(dip, 0);
-                                if (post_event && ret == NDI_SUCCESS) {
-                                        /* Generate EC_DEVFS_DEVI_REMOVE */
+        if (ret == NDI_SUCCESS && post_event) {
+                /* Generate EC_DEVFS/ESC_DEVFS_DEVI_REMOVE */
                                         (void) i_log_devfs_remove_devinfo(path,
                                             class, driver, instance, flags);
                                 }
-                        }
 
-                }
-        }
-
-        if (path)
-                strfree(path);
-        if (class)
+        if (path != NULL)
+                kmem_free(path, MAXPATHLEN);
+        if (class != NULL)
                 strfree(class);
-        if (driver)
+        if (driver != NULL)
                 strfree(driver);
 
+        /* Clean the flag on successful detach */
+        if (ret == NDI_SUCCESS)
+                DEVI_UNSET_GONE(dip);
+
         return (ret);
 }
 
 /*
  * unconfigure immediate children of bus nexus device

@@ -6577,10 +6561,13 @@
 
         ASSERT(pdip);
 
         flags |= NDI_DEVI_OFFLINE;
 
+        if (flags & NDI_DEVI_GONE)
+                DEVI_SET_GONE(dip);
+
         /*
          * If child is pHCI and vHCI and pHCI are not siblings then enter vHCI
          * before parent(pHCI) to avoid deadlock with mpxio Client power
          * management operations.
          */

@@ -8098,11 +8085,11 @@
         LOCK_DEV_OPS(&dnp->dn_lock);
         dnp->dn_flags |= DN_DRIVER_HELD;
         dnp->dn_head = dip;
         UNLOCK_DEV_OPS(&dnp->dn_lock);
 
-        i_ndi_devi_report_status_change(dip, NULL);
+        i_ndi_devi_report_status_change(dip);
 
         return (dip);
 }
 
 /*

@@ -8145,11 +8132,11 @@
         DEVI_SET_DEVICE_REMOVED(dip);
         DEVI_SET_EVREMOVE(dip);         /* this clears EVADD too */
         mutex_exit(&(DEVI(dip)->devi_lock));
 
         /* report remove (as 'removed') */
-        i_ndi_devi_report_status_change(dip, NULL);
+        i_ndi_devi_report_status_change(dip);
 
         /*
          * Invalidate the cache to ensure accurate
          * (di_state() & DI_DEVICE_REMOVED).
          */

@@ -8182,11 +8169,11 @@
         DEVI_SET_DEVICE_REINSERTED(dip);
         DEVI_SET_EVADD(dip);            /* this clears EVREMOVE too */
         mutex_exit(&(DEVI(dip)->devi_lock));
 
         /* report insert (as 'online') */
-        i_ndi_devi_report_status_change(dip, NULL);
+        i_ndi_devi_report_status_change(dip);
 
         /*
          * Invalidate the cache to ensure accurate
          * (di_state() & DI_DEVICE_REMOVED).
          */