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,30 ****
* 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 (c) 2016 by Delphix. All rights reserved.
*/
#include <sys/note.h>
#include <sys/t_lock.h>
--- 16,31 ----
* 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 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,182 ****
* 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.
*/
! int retire_prevents_attach = 1;
int mtc_off; /* turn off mt config */
int quiesce_debug = 0;
--- 170,182 ----
* 3rd party driver depends on identify(9e) being called.
*/
int identify_9e = 0;
/*
! * Don't prevent attaching retired devices by default.
*/
! int retire_prevents_attach = 0;
int mtc_off; /* turn off mt config */
int quiesce_debug = 0;
*** 483,497 ****
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);
}
/*
--- 483,492 ----
*** 1358,1369 ****
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)
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)));
--- 1353,1364 ----
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 != 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,1470 ****
--- 1456,1467 ----
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,3830 ****
* 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)
{
int error;
dev_info_t *parent, *child;
struct pathname pn;
char *component, *config_name;
--- 3816,3827 ----
* 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)
{
int error;
dev_info_t *parent, *child;
struct pathname pn;
char *component, *config_name;
*** 4598,4610 ****
/*
* report device status
*/
static void
! i_ndi_devi_report_status_change(dev_info_t *dip, char *path)
{
! char *status;
if (!DEVI_NEED_REPORT(dip) ||
(i_ddi_node_state(dip) < DS_INITIALIZED) ||
ndi_dev_is_hidden_node(dip)) {
return;
--- 4595,4607 ----
/*
* report device status
*/
static void
! i_ndi_devi_report_status_change(dev_info_t *dip)
{
! const char *status;
if (!DEVI_NEED_REPORT(dip) ||
(i_ddi_node_state(dip) < DS_INITIALIZED) ||
ndi_dev_is_hidden_node(dip)) {
return;
*** 4627,4647 ****
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),
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));
}
--- 4624,4635 ----
status = "online";
} else {
status = "unknown";
}
! cmn_err(CE_CONT, "?%s%d %s\n", 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,5235 ****
(void) ddi_remove_child(dip, 0);
}
return (NDI_FAILURE);
}
! i_ndi_devi_report_status_change(dip, NULL);
/*
* log an event, but not during devfs lookups in which case
* NDI_NO_EVENT is set.
*/
--- 5213,5223 ----
(void) ddi_remove_child(dip, 0);
}
return (NDI_FAILURE);
}
! i_ndi_devi_report_status_change(dip);
/*
* log an event, but not during devfs lookups in which case
* NDI_NO_EVENT is set.
*/
*** 5763,5772 ****
--- 5751,5771 ----
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,5959 ****
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);
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));
}
}
if (flags & (NDI_UNCONFIG | NDI_DEVI_REMOVE)) {
ret = ddi_uninitchild(dip);
if (ret == NDI_SUCCESS) {
/*
--- 5927,5961 ----
DEVI_SET_DEVICE_OFFLINE(dip);
mutex_exit(&(DEVI(dip)->devi_lock));
}
if (i_ddi_node_state(dip) == DS_INITIALIZED) {
if (flags & NDI_DEVI_OFFLINE)
! i_ndi_devi_report_status_change(dip);
if (need_remove_event(dip, flags)) {
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,6011 ****
* 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;
}
! ret = ddi_remove_child(dip, 0);
! if (post_event && ret == NDI_SUCCESS) {
! /* Generate EC_DEVFS_DEVI_REMOVE */
(void) i_log_devfs_remove_devinfo(path,
class, driver, instance, flags);
}
- }
! }
! }
!
! if (path)
! strfree(path);
! if (class)
strfree(class);
! if (driver)
strfree(driver);
return (ret);
}
/*
* unconfigure immediate children of bus nexus device
--- 5964,5995 ----
* reattached.
*/
if (!ndi_dev_is_persistent_node(dip))
flags |= NDI_DEVI_REMOVE;
! if (flags & NDI_DEVI_REMOVE)
! ret = ddi_remove_child(dip, 0);
}
+ }
! 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 != NULL)
! kmem_free(path, MAXPATHLEN);
! if (class != NULL)
strfree(class);
! 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,6586 ****
--- 6561,6573 ----
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,8108 ****
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);
return (dip);
}
/*
--- 8085,8095 ----
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);
return (dip);
}
/*
*** 8145,8155 ****
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);
/*
* Invalidate the cache to ensure accurate
* (di_state() & DI_DEVICE_REMOVED).
*/
--- 8132,8142 ----
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);
/*
* Invalidate the cache to ensure accurate
* (di_state() & DI_DEVICE_REMOVED).
*/
*** 8182,8192 ****
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);
/*
* Invalidate the cache to ensure accurate
* (di_state() & DI_DEVICE_REMOVED).
*/
--- 8169,8179 ----
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);
/*
* Invalidate the cache to ensure accurate
* (di_state() & DI_DEVICE_REMOVED).
*/