Print this page
XXXX don't fail device detach when it's physically removed

@@ -8549,30 +8549,35 @@
         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
-         *  - A layered driver has an outstanding open on 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_ncmds_in_driver != 0) || (un->un_layer_count != 0) ||
-            (un->un_detach_count != 0) || (un->un_opens_in_progress != 0)) {
+        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, "sd_unit_detach: entry 0x%p\n", un);
+        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,14 +8587,10 @@
         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.

@@ -8599,37 +8600,23 @@
                         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) &&
+        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,
-                            "sd_dr_detach: Cannot release reservation \n");
+                            "%s: cannot release reservation\n", __func__);
                 }
         } else {
                 mutex_exit(SD_MUTEX(un));
         }
 

@@ -8682,10 +8669,17 @@
 
         /* 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,11 +8693,11 @@
                 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");
+                            "%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,11 +8712,11 @@
                 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");
+                            "%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,17 +8725,16 @@
                 }
                 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!
          */
+        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,13 +8782,13 @@
                 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");
+                            "%s: lower power request failed, ignoring\n",
+                            __func__);
                         /*
-                         * 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

@@ -8854,11 +8847,11 @@
                          * 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");
+                            "%s: cannot cancel insert event\n", __func__);
                         goto err_remove_event;
                 }
                 un->un_insert_event = NULL;
 
                 if ((un->un_remove_event != NULL) &&

@@ -8869,11 +8862,11 @@
                          * 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");
+                            "%s: cannot cancel remove event\n", __func__);
                         goto err_remove_event;
                 }
                 un->un_remove_event = NULL;
         }
 

@@ -9012,11 +9005,11 @@
 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");
+        SD_TRACE(SD_LOG_ATTACH_DETACH, un, "%s: exit failure\n", __func__);
         return (DDI_FAILURE);
 }
 
 
 /*