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).
*/