Print this page
NEX-17866
Release lun_mutex/port_mutex before logging an online/offline event, and only
do logging if online/offline operation was successful.
While here, follow the comment suggestion and only hold lun_mutex while checking
its state in fcp_scsi_start().


8196                         rval = NDI_SUCCESS;
8197                 }
8198                 return (rval);
8199         }
8200 
8201         if (fc_ulp_busy_port(pptr->port_fp_handle) != 0) {
8202                 return (NDI_FAILURE);
8203         }
8204 
8205         if (is_mpxio) {
8206                 mdi_devi_enter(pptr->port_dip, &circ);
8207         } else {
8208                 ndi_devi_enter(pptr->port_dip, &circ);
8209         }
8210 
8211         mutex_enter(&pptr->port_mutex);
8212         mutex_enter(&plun->lun_mutex);
8213 
8214         if (online == FCP_ONLINE) {
8215                 ccip = fcp_get_cip(plun, cip, lcount, tcount);
8216                 if (ccip == NULL) {
8217                         goto fail;
8218                 }
8219         } else {
8220                 if (fcp_is_child_present(plun, cip) != FC_SUCCESS) {
8221                         goto fail;
8222                 }
8223                 ccip = cip;
8224         }
8225 
8226         if (online == FCP_ONLINE) {
8227                 rval = fcp_online_child(plun, ccip, lcount, tcount, flags,
8228                     &circ);
8229                 fc_ulp_log_device_event(pptr->port_fp_handle,
8230                     FC_ULP_DEVICE_ONLINE);
8231         } else {
8232                 rval = fcp_offline_child(plun, ccip, lcount, tcount, flags,
8233                     &circ);
8234                 fc_ulp_log_device_event(pptr->port_fp_handle,
8235                     FC_ULP_DEVICE_OFFLINE);
8236         }
8237 
8238 fail:   mutex_exit(&plun->lun_mutex);

8239         mutex_exit(&pptr->port_mutex);
8240 






8241         if (is_mpxio) {
8242                 mdi_devi_exit(pptr->port_dip, circ);
8243         } else {
8244                 ndi_devi_exit(pptr->port_dip, circ);
8245         }
8246 
8247         fc_ulp_idle_port(pptr->port_fp_handle);
8248 
8249         return (rval);
8250 }
8251 
8252 
8253 /*
8254  * take a target offline by taking all of its LUNs offline
8255  */
8256 /*ARGSUSED*/
8257 static int
8258 fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt,
8259     int link_cnt, int tgt_cnt, int nowait, int flags)
8260 {


11027  *               TRAN_BADPKT
11028  *               TRAN_FATAL_ERROR
11029  */
11030 static int
11031 fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
11032 {
11033         struct fcp_port *pptr = ADDR2FCP(ap);
11034         struct fcp_lun  *plun = ADDR2LUN(ap);
11035         struct fcp_pkt  *cmd = PKT2CMD(pkt);
11036         struct fcp_tgt  *ptgt = plun->lun_tgt;
11037         int                     rval;
11038 
11039         /* ensure command isn't already issued */
11040         ASSERT(cmd->cmd_state != FCP_PKT_ISSUED);
11041 
11042         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11043             fcp_trace, FCP_BUF_LEVEL_9, 0,
11044             "fcp_transport Invoked for %x", plun->lun_tgt->tgt_d_id);
11045 
11046         /*
11047          * It is strange that we enter the fcp_port mutex and the target
11048          * mutex to check the lun state (which has a mutex of its own).
11049          */
11050         mutex_enter(&pptr->port_mutex);
11051         mutex_enter(&ptgt->tgt_mutex);
11052 
11053         /*
11054          * If the device is offline and is not in the process of coming
11055          * online, fail the request.
11056          */
11057 
11058         if ((plun->lun_state & FCP_LUN_OFFLINE) &&
11059             !(plun->lun_state & FCP_LUN_ONLINING)) {
11060                 mutex_exit(&ptgt->tgt_mutex);
11061                 mutex_exit(&pptr->port_mutex);
11062 
11063                 if (cmd->cmd_fp_pkt->pkt_pd == NULL) {
11064                         pkt->pkt_reason = CMD_DEV_GONE;
11065                 }
11066 
11067                 return (TRAN_FATAL_ERROR);
11068         }


11069         cmd->cmd_fp_pkt->pkt_timeout = pkt->pkt_time;
11070 
11071         /*
11072          * If we are suspended, kernel is trying to dump, so don't
11073          * block, fail or defer requests - send them down right away.
11074          * NOTE: If we are in panic (i.e. trying to dump), we can't
11075          * assume we have been suspended.  There is hardware such as
11076          * the v880 that doesn't do PM.  Thus, the check for
11077          * ddi_in_panic.
11078          *
11079          * If FCP_STATE_IN_CB_DEVC is set, devices are in the process
11080          * of changing.  So, if we can queue the packet, do it.  Eventually,
11081          * either the device will have gone away or changed and we can fail
11082          * the request, or we can proceed if the device didn't change.
11083          *
11084          * If the pd in the target or the packet is NULL it's probably
11085          * because the device has gone away, we allow the request to be
11086          * put on the internal queue here in case the device comes back within
11087          * the offline timeout. fctl will fix up the pd's if the tgt_pd_handle
11088          * has gone NULL, while fcp deals cases where pkt_pd is NULL. pkt_pd
11089          * could be NULL because the device was disappearing during or since
11090          * packet initialization.
11091          */
11092 



11093         if (((plun->lun_state & FCP_LUN_BUSY) && (!(pptr->port_state &
11094             FCP_STATE_SUSPENDED)) && !ddi_in_panic()) ||
11095             (pptr->port_state & (FCP_STATE_ONLINING | FCP_STATE_IN_CB_DEVC)) ||
11096             (ptgt->tgt_pd_handle == NULL) ||
11097             (cmd->cmd_fp_pkt->pkt_pd == NULL)) {
11098                 /*
11099                  * If ((LUN is busy AND
11100                  *      LUN not suspended AND
11101                  *      The system is not in panic state) OR
11102                  *      (The port is coming up))
11103                  *
11104                  * We check to see if the any of the flags FLAG_NOINTR or
11105                  * FLAG_NOQUEUE is set.  If one of them is set the value
11106                  * returned will be TRAN_BUSY.  If not, the request is queued.
11107                  */
11108                 mutex_exit(&ptgt->tgt_mutex);
11109                 mutex_exit(&pptr->port_mutex);
11110 
11111                 /* see if using interrupts is allowed (so queueing'll work) */
11112                 if (pkt->pkt_flags & FLAG_NOINTR) {




8196                         rval = NDI_SUCCESS;
8197                 }
8198                 return (rval);
8199         }
8200 
8201         if (fc_ulp_busy_port(pptr->port_fp_handle) != 0) {
8202                 return (NDI_FAILURE);
8203         }
8204 
8205         if (is_mpxio) {
8206                 mdi_devi_enter(pptr->port_dip, &circ);
8207         } else {
8208                 ndi_devi_enter(pptr->port_dip, &circ);
8209         }
8210 
8211         mutex_enter(&pptr->port_mutex);
8212         mutex_enter(&plun->lun_mutex);
8213 
8214         if (online == FCP_ONLINE) {
8215                 ccip = fcp_get_cip(plun, cip, lcount, tcount);
8216                 if (ccip == NULL)
8217                         goto skip;

8218         } else {
8219                 if (fcp_is_child_present(plun, cip) != FC_SUCCESS)
8220                         goto skip;

8221                 ccip = cip;
8222         }
8223 
8224         if (online == FCP_ONLINE) {
8225                 rval = fcp_online_child(plun, ccip, lcount, tcount, flags,
8226                     &circ);


8227         } else {
8228                 rval = fcp_offline_child(plun, ccip, lcount, tcount, flags,
8229                     &circ);


8230         }
8231 
8232 skip:
8233         mutex_exit(&plun->lun_mutex);
8234         mutex_exit(&pptr->port_mutex);
8235 
8236         if (rval == NDI_SUCCESS) {
8237                 fc_ulp_log_device_event(pptr->port_fp_handle,
8238                     online == FCP_ONLINE ?
8239                     FC_ULP_DEVICE_ONLINE : FC_ULP_DEVICE_OFFLINE);
8240         }
8241 
8242         if (is_mpxio) {
8243                 mdi_devi_exit(pptr->port_dip, circ);
8244         } else {
8245                 ndi_devi_exit(pptr->port_dip, circ);
8246         }
8247 
8248         fc_ulp_idle_port(pptr->port_fp_handle);
8249 
8250         return (rval);
8251 }
8252 
8253 
8254 /*
8255  * take a target offline by taking all of its LUNs offline
8256  */
8257 /*ARGSUSED*/
8258 static int
8259 fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt,
8260     int link_cnt, int tgt_cnt, int nowait, int flags)
8261 {


11028  *               TRAN_BADPKT
11029  *               TRAN_FATAL_ERROR
11030  */
11031 static int
11032 fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
11033 {
11034         struct fcp_port *pptr = ADDR2FCP(ap);
11035         struct fcp_lun  *plun = ADDR2LUN(ap);
11036         struct fcp_pkt  *cmd = PKT2CMD(pkt);
11037         struct fcp_tgt  *ptgt = plun->lun_tgt;
11038         int                     rval;
11039 
11040         /* ensure command isn't already issued */
11041         ASSERT(cmd->cmd_state != FCP_PKT_ISSUED);
11042 
11043         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11044             fcp_trace, FCP_BUF_LEVEL_9, 0,
11045             "fcp_transport Invoked for %x", plun->lun_tgt->tgt_d_id);
11046 
11047         /*







11048          * If the device is offline and is not in the process of coming
11049          * online, fail the request.
11050          */
11051         mutex_enter(&plun->lun_mutex);
11052         if ((plun->lun_state & FCP_LUN_OFFLINE) &&
11053             !(plun->lun_state & FCP_LUN_ONLINING)) {
11054                 mutex_exit(&plun->lun_mutex);
11055                 if (cmd->cmd_fp_pkt->pkt_pd == NULL)


11056                         pkt->pkt_reason = CMD_DEV_GONE;


11057                 return (TRAN_FATAL_ERROR);
11058         }
11059         mutex_exit(&plun->lun_mutex);
11060 
11061         cmd->cmd_fp_pkt->pkt_timeout = pkt->pkt_time;
11062 
11063         /*
11064          * If we are suspended, kernel is trying to dump, so don't
11065          * block, fail or defer requests - send them down right away.
11066          * NOTE: If we are in panic (i.e. trying to dump), we can't
11067          * assume we have been suspended.  There is hardware such as
11068          * the v880 that doesn't do PM.  Thus, the check for
11069          * ddi_in_panic.
11070          *
11071          * If FCP_STATE_IN_CB_DEVC is set, devices are in the process
11072          * of changing.  So, if we can queue the packet, do it.  Eventually,
11073          * either the device will have gone away or changed and we can fail
11074          * the request, or we can proceed if the device didn't change.
11075          *
11076          * If the pd in the target or the packet is NULL it's probably
11077          * because the device has gone away, we allow the request to be
11078          * put on the internal queue here in case the device comes back within
11079          * the offline timeout. fctl will fix up the pd's if the tgt_pd_handle
11080          * has gone NULL, while fcp deals cases where pkt_pd is NULL. pkt_pd
11081          * could be NULL because the device was disappearing during or since
11082          * packet initialization.
11083          */
11084 
11085         mutex_enter(&pptr->port_mutex);
11086         mutex_enter(&ptgt->tgt_mutex);
11087 
11088         if (((plun->lun_state & FCP_LUN_BUSY) && (!(pptr->port_state &
11089             FCP_STATE_SUSPENDED)) && !ddi_in_panic()) ||
11090             (pptr->port_state & (FCP_STATE_ONLINING | FCP_STATE_IN_CB_DEVC)) ||
11091             (ptgt->tgt_pd_handle == NULL) ||
11092             (cmd->cmd_fp_pkt->pkt_pd == NULL)) {
11093                 /*
11094                  * If ((LUN is busy AND
11095                  *      LUN not suspended AND
11096                  *      The system is not in panic state) OR
11097                  *      (The port is coming up))
11098                  *
11099                  * We check to see if the any of the flags FLAG_NOINTR or
11100                  * FLAG_NOQUEUE is set.  If one of them is set the value
11101                  * returned will be TRAN_BUSY.  If not, the request is queued.
11102                  */
11103                 mutex_exit(&ptgt->tgt_mutex);
11104                 mutex_exit(&pptr->port_mutex);
11105 
11106                 /* see if using interrupts is allowed (so queueing'll work) */
11107                 if (pkt->pkt_flags & FLAG_NOINTR) {