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); } /*