Print this page
XXXX don't fail device detach when it's physically removed
*** 8549,8578 ****
int i;
int tgt;
dev_t dev;
dev_info_t *pdip = ddi_get_parent(devi);
int instance = ddi_get_instance(devi);
mutex_enter(&sd_detach_mutex);
/*
* Fail the detach for any of the following:
* - Unable to get the sd_lun struct for the instance
- * - A layered driver has an outstanding open on the instance
* - Another thread is already detaching this instance
* - Another thread is currently performing an open
*/
devp = ddi_get_driver_private(devi);
! if ((devp == NULL) ||
! ((un = (struct sd_lun *)devp->sd_private) == NULL) ||
! (un->un_ncmds_in_driver != 0) || (un->un_layer_count != 0) ||
! (un->un_detach_count != 0) || (un->un_opens_in_progress != 0)) {
mutex_exit(&sd_detach_mutex);
return (DDI_FAILURE);
}
! SD_TRACE(SD_LOG_ATTACH_DETACH, un, "sd_unit_detach: entry 0x%p\n", un);
/*
* Mark this instance as currently in a detach, to inhibit any
* opens from a layered driver.
*/
--- 8549,8583 ----
int i;
int tgt;
dev_t dev;
dev_info_t *pdip = ddi_get_parent(devi);
int instance = ddi_get_instance(devi);
+ int devigone = DEVI(devi)->devi_gone;
mutex_enter(&sd_detach_mutex);
/*
* Fail the detach for any of the following:
* - Unable to get the sd_lun struct for the instance
* - Another thread is already detaching this instance
* - Another thread is currently performing an open
+ *
+ * Additionaly, if "device gone" flag is not set:
+ * - There are outstanding commands in driver
+ * - There are outstanding commands in transport
*/
devp = ddi_get_driver_private(devi);
! if (devp == NULL || (un = (struct sd_lun *)devp->sd_private) == NULL ||
! un->un_detach_count != 0 || un->un_opens_in_progress != 0 ||
! (!devigone && (un->un_ncmds_in_driver != 0 ||
! un->un_ncmds_in_transport != 0 ||
! un->un_state == SD_STATE_RWAIT))) {
mutex_exit(&sd_detach_mutex);
return (DDI_FAILURE);
}
! SD_TRACE(SD_LOG_ATTACH_DETACH, un, "%s: entry 0x%p\n", __func__, un);
/*
* Mark this instance as currently in a detach, to inhibit any
* opens from a layered driver.
*/
*** 8582,8595 ****
tgt = ddi_prop_get_int(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS,
SCSI_ADDR_PROP_TARGET, -1);
dev = sd_make_device(SD_DEVINFO(un));
- #ifndef lint
- _NOTE(COMPETING_THREADS_NOW);
- #endif
-
mutex_enter(SD_MUTEX(un));
/*
* Fail the detach if there are any outstanding layered
* opens on this device.
--- 8587,8596 ----
*** 8599,8635 ****
goto err_notclosed;
}
}
/*
- * Verify there are NO outstanding commands issued to this device.
- * ie, un_ncmds_in_transport == 0.
- * It's possible to have outstanding commands through the physio
- * code path, even though everything's closed.
- */
- if ((un->un_ncmds_in_transport != 0) || (un->un_retry_timeid != NULL) ||
- (un->un_direct_priority_timeid != NULL) ||
- (un->un_state == SD_STATE_RWAIT)) {
- mutex_exit(SD_MUTEX(un));
- SD_ERROR(SD_LOG_ATTACH_DETACH, un,
- "sd_dr_detach: Detach failure due to outstanding cmds\n");
- goto err_stillbusy;
- }
-
- /*
* If we have the device reserved, release the reservation.
*/
! if ((un->un_resvd_status & SD_RESERVE) &&
!(un->un_resvd_status & SD_LOST_RESERVE)) {
mutex_exit(SD_MUTEX(un));
/*
* Note: sd_reserve_release sends a command to the device
* via the sd_ioctlcmd() path, and can sleep.
*/
if (sd_reserve_release(dev, SD_RELEASE) != 0) {
SD_ERROR(SD_LOG_ATTACH_DETACH, un,
! "sd_dr_detach: Cannot release reservation \n");
}
} else {
mutex_exit(SD_MUTEX(un));
}
--- 8600,8622 ----
goto err_notclosed;
}
}
/*
* If we have the device reserved, release the reservation.
*/
! if (!devigone &&
! (un->un_resvd_status & SD_RESERVE) &&
!(un->un_resvd_status & SD_LOST_RESERVE)) {
mutex_exit(SD_MUTEX(un));
/*
* Note: sd_reserve_release sends a command to the device
* via the sd_ioctlcmd() path, and can sleep.
*/
if (sd_reserve_release(dev, SD_RELEASE) != 0) {
SD_ERROR(SD_LOG_ATTACH_DETACH, un,
! "%s: cannot release reservation\n", __func__);
}
} else {
mutex_exit(SD_MUTEX(un));
}
*** 8682,8691 ****
--- 8669,8685 ----
/* Remove any pending reservation reclaim requests for this device */
sd_rmv_resv_reclaim_req(dev);
mutex_enter(SD_MUTEX(un));
+ if (un->un_retry_timeid != NULL) {
+ timeout_id_t temp_id = un->un_retry_timeid;
+ un->un_retry_timeid = NULL;
+ mutex_exit(SD_MUTEX(un));
+ (void) untimeout(temp_id);
+ mutex_enter(SD_MUTEX(un));
+ }
/* Cancel any pending callbacks for SD_PATH_DIRECT_PRIORITY cmd. */
if (un->un_direct_priority_timeid != NULL) {
timeout_id_t temp_id = un->un_direct_priority_timeid;
un->un_direct_priority_timeid = NULL;
*** 8699,8709 ****
mutex_exit(SD_MUTEX(un));
_NOTE(DATA_READABLE_WITHOUT_LOCK(sd_lun::un_mhd_token));
if (scsi_watch_request_terminate(un->un_mhd_token,
SCSI_WATCH_TERMINATE_NOWAIT)) {
SD_ERROR(SD_LOG_ATTACH_DETACH, un,
! "sd_dr_detach: Cannot cancel mhd watch request\n");
/*
* Note: We are returning here after having removed
* some driver timeouts above. This is consistent with
* the legacy implementation but perhaps the watch
* terminate call should be made with the wait flag set.
--- 8693,8703 ----
mutex_exit(SD_MUTEX(un));
_NOTE(DATA_READABLE_WITHOUT_LOCK(sd_lun::un_mhd_token));
if (scsi_watch_request_terminate(un->un_mhd_token,
SCSI_WATCH_TERMINATE_NOWAIT)) {
SD_ERROR(SD_LOG_ATTACH_DETACH, un,
! "%s: cannot cancel mhd watch request\n", __func__);
/*
* Note: We are returning here after having removed
* some driver timeouts above. This is consistent with
* the legacy implementation but perhaps the watch
* terminate call should be made with the wait flag set.
*** 8718,8728 ****
mutex_exit(SD_MUTEX(un));
_NOTE(DATA_READABLE_WITHOUT_LOCK(sd_lun::un_swr_token));
if (scsi_watch_request_terminate(un->un_swr_token,
SCSI_WATCH_TERMINATE_NOWAIT)) {
SD_ERROR(SD_LOG_ATTACH_DETACH, un,
! "sd_dr_detach: Cannot cancel swr watch request\n");
/*
* Note: We are returning here after having removed
* some driver timeouts above. This is consistent with
* the legacy implementation but perhaps the watch
* terminate call should be made with the wait flag set.
--- 8712,8722 ----
mutex_exit(SD_MUTEX(un));
_NOTE(DATA_READABLE_WITHOUT_LOCK(sd_lun::un_swr_token));
if (scsi_watch_request_terminate(un->un_swr_token,
SCSI_WATCH_TERMINATE_NOWAIT)) {
SD_ERROR(SD_LOG_ATTACH_DETACH, un,
! "%s: cannot cancel swr watch request\n", __func__);
/*
* Note: We are returning here after having removed
* some driver timeouts above. This is consistent with
* the legacy implementation but perhaps the watch
* terminate call should be made with the wait flag set.
*** 8731,8747 ****
}
mutex_enter(SD_MUTEX(un));
un->un_swr_token = NULL;
}
- mutex_exit(SD_MUTEX(un));
-
/*
* Clear any scsi_reset_notifies. We clear the reset notifies
* if we have not registered one.
* Note: The sd_mhd_reset_notify_cb() fn tries to acquire SD_MUTEX!
*/
(void) scsi_reset_notify(SD_ADDRESS(un), SCSI_RESET_CANCEL,
sd_mhd_reset_notify_cb, (caddr_t)un);
/*
* protect the timeout pointers from getting nulled by
--- 8725,8740 ----
}
mutex_enter(SD_MUTEX(un));
un->un_swr_token = NULL;
}
/*
* Clear any scsi_reset_notifies. We clear the reset notifies
* if we have not registered one.
* Note: The sd_mhd_reset_notify_cb() fn tries to acquire SD_MUTEX!
*/
+ mutex_exit(SD_MUTEX(un));
(void) scsi_reset_notify(SD_ADDRESS(un), SCSI_RESET_CANCEL,
sd_mhd_reset_notify_cb, (caddr_t)un);
/*
* protect the timeout pointers from getting nulled by
*** 8789,8801 ****
mutex_exit(&un->un_pm_mutex);
if ((un->un_f_pm_is_enabled == TRUE) &&
(pm_lower_power(SD_DEVINFO(un), 0, SD_PM_STATE_STOPPED(un))
!= DDI_SUCCESS)) {
SD_ERROR(SD_LOG_ATTACH_DETACH, un,
! "sd_dr_detach: Lower power request failed, ignoring.\n");
/*
- * Fix for bug: 4297749, item # 13
* The above test now includes a check to see if PM is
* supported by this device before call
* pm_lower_power().
* Note, the following is not dead code. The call to
* pm_lower_power above will generate a call back into
--- 8782,8794 ----
mutex_exit(&un->un_pm_mutex);
if ((un->un_f_pm_is_enabled == TRUE) &&
(pm_lower_power(SD_DEVINFO(un), 0, SD_PM_STATE_STOPPED(un))
!= DDI_SUCCESS)) {
SD_ERROR(SD_LOG_ATTACH_DETACH, un,
! "%s: lower power request failed, ignoring\n",
! __func__);
/*
* The above test now includes a check to see if PM is
* supported by this device before call
* pm_lower_power().
* Note, the following is not dead code. The call to
* pm_lower_power above will generate a call back into
*** 8854,8864 ****
* substantial cleanup above. This is consistent
* with the legacy implementation but this may not
* be the right thing to do.
*/
SD_ERROR(SD_LOG_ATTACH_DETACH, un,
! "sd_dr_detach: Cannot cancel insert event\n");
goto err_remove_event;
}
un->un_insert_event = NULL;
if ((un->un_remove_event != NULL) &&
--- 8847,8857 ----
* substantial cleanup above. This is consistent
* with the legacy implementation but this may not
* be the right thing to do.
*/
SD_ERROR(SD_LOG_ATTACH_DETACH, un,
! "%s: cannot cancel insert event\n", __func__);
goto err_remove_event;
}
un->un_insert_event = NULL;
if ((un->un_remove_event != NULL) &&
*** 8869,8879 ****
* substantial cleanup above. This is consistent
* with the legacy implementation but this may not
* be the right thing to do.
*/
SD_ERROR(SD_LOG_ATTACH_DETACH, un,
! "sd_dr_detach: Cannot cancel remove event\n");
goto err_remove_event;
}
un->un_remove_event = NULL;
}
--- 8862,8872 ----
* substantial cleanup above. This is consistent
* with the legacy implementation but this may not
* be the right thing to do.
*/
SD_ERROR(SD_LOG_ATTACH_DETACH, un,
! "%s: cannot cancel remove event\n", __func__);
goto err_remove_event;
}
un->un_remove_event = NULL;
}
*** 9012,9022 ****
err_remove_event:
mutex_enter(&sd_detach_mutex);
un->un_detach_count--;
mutex_exit(&sd_detach_mutex);
! SD_TRACE(SD_LOG_ATTACH_DETACH, un, "sd_unit_detach: exit failure\n");
return (DDI_FAILURE);
}
/*
--- 9005,9015 ----
err_remove_event:
mutex_enter(&sd_detach_mutex);
un->un_detach_count--;
mutex_exit(&sd_detach_mutex);
! SD_TRACE(SD_LOG_ATTACH_DETACH, un, "%s: exit failure\n", __func__);
return (DDI_FAILURE);
}
/*