Print this page
4780 comstar iSCSI target shouldn't abuse ddi_get_time(9f)
Reviewed by: Eric Diven <eric.diven@delphix.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  23  *
  24  * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
  25  */
  26 
  27 #include <sys/cpuvar.h>
  28 #include <sys/types.h>
  29 #include <sys/conf.h>
  30 #include <sys/stat.h>
  31 #include <sys/file.h>
  32 #include <sys/ddi.h>
  33 #include <sys/sunddi.h>
  34 #include <sys/modctl.h>
  35 #include <sys/sysmacros.h>
  36 #include <sys/socket.h>
  37 #include <sys/strsubr.h>
  38 #include <sys/nvpair.h>
  39 
  40 #include <sys/stmf.h>
  41 #include <sys/stmf_ioctl.h>
  42 #include <sys/portif.h>
  43 #include <sys/idm/idm.h>
  44 #include <sys/idm/idm_conn_sm.h>


3108         iscsit_sess_t           *ist = ict->ict_sess;
3109         iscsi_scsi_cmd_hdr_t    *hdr = (iscsi_scsi_cmd_hdr_t *)rx_pdu->isp_hdr;
3110 
3111         mutex_enter(&ist->ist_sn_mutex);
3112         if (hdr->opcode & ISCSI_OP_IMMEDIATE) {
3113                 /* do not queue, handle it immediately */
3114                 DTRACE_PROBE2(immediate__cmd, iscsit_sess_t *, ist,
3115                     idm_pdu_t *, rx_pdu);
3116                 mutex_exit(&ist->ist_sn_mutex);
3117                 return (ISCSIT_CMDSN_EQ_EXPCMDSN);
3118         }
3119         if (iscsit_sna_lt(ist->ist_expcmdsn, ntohl(hdr->cmdsn))) {
3120                 /*
3121                  * Out-of-order commands (cmdSN higher than ExpCmdSN)
3122                  * are staged on a fixed-size circular buffer until
3123                  * the missing command is delivered to the SCSI layer.
3124                  * Irrespective of the order of insertion into the
3125                  * staging queue, the commands are processed out of the
3126                  * queue in cmdSN order only.
3127                  */
3128                 rx_pdu->isp_queue_time = ddi_get_time();
3129                 iscsit_add_pdu_to_queue(ist, rx_pdu);
3130                 mutex_exit(&ist->ist_sn_mutex);
3131                 return (ISCSIT_CMDSN_GT_EXPCMDSN);
3132         } else if (iscsit_sna_lt(ntohl(hdr->cmdsn), ist->ist_expcmdsn)) {
3133                 DTRACE_PROBE3(cmdsn__lt__expcmdsn, iscsit_sess_t *, ist,
3134                     iscsit_conn_t *, ict, idm_pdu_t *, rx_pdu);
3135                 mutex_exit(&ist->ist_sn_mutex);
3136                 return (ISCSIT_CMDSN_LT_EXPCMDSN);
3137         } else {
3138                 mutex_exit(&ist->ist_sn_mutex);
3139                 return (ISCSIT_CMDSN_EQ_EXPCMDSN);
3140         }
3141 }
3142 
3143 /*
3144  * iscsit_add_pdu_to_queue() adds PDUs into the array indexed by
3145  * their cmdsn value. The length of the array is kept above the
3146  * maximum window size. The window keeps the cmdsn within a range
3147  * such that there are no collisons. e.g. the assumption is that
3148  * the windowing checks make it impossible to receive PDUs that


3378          * wait time of 1004 > wait time of 1003, only 1003 will be considered
3379          * by the monitor thread. 1004 will be automatically processed by
3380          * iscsit_process_pdu_in_queue() once the scan is complete and the
3381          * expcmdsn becomes current.
3382          */
3383         mutex_enter(&ist->ist_sn_mutex);
3384         cbuf = ist->ist_rxpdu_queue;
3385         if (cbuf->cb_num_elems == 0) {
3386                 mutex_exit(&ist->ist_sn_mutex);
3387                 return;
3388         }
3389         for (next_pdu = NULL, i = 0; ; i++) {
3390                 next_cmdsn = ist->ist_expcmdsn + i; /* start at expcmdsn */
3391                 index = next_cmdsn % ISCSIT_RXPDU_QUEUE_LEN;
3392                 if ((next_pdu = cbuf->cb_buffer[index]) != NULL) {
3393                         /*
3394                          * If the PDU wait time has not exceeded threshold
3395                          * stop scanning the staging queue until the timer
3396                          * fires again
3397                          */
3398                         if ((ddi_get_time() - next_pdu->isp_queue_time)
3399                             < rxpdu_queue_threshold) {
3400                                 mutex_exit(&ist->ist_sn_mutex);
3401                                 return;
3402                         }
3403                         /*
3404                          * Remove the next PDU from the queue and post it
3405                          * to the SCSI layer, skipping over the missing
3406                          * PDU. Stop scanning the staging queue until
3407                          * the monitor timer fires again
3408                          */
3409                         (void) iscsit_remove_pdu_from_queue(ist, next_cmdsn);
3410                         mutex_exit(&ist->ist_sn_mutex);
3411                         DTRACE_PROBE3(advanced__to__blocked__cmdsn,
3412                             iscsit_sess_t *, ist, idm_pdu_t *, next_pdu,
3413                             uint32_t, next_cmdsn);
3414                         iscsit_post_staged_pdu(next_pdu);
3415                         /* Deliver any subsequent PDUs immediately */
3416                         iscsit_process_pdu_in_queue(ist);
3417                         return;
3418                 }
3419                 /*


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  23  *
  24  * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
  25  */
  26 
  27 #include <sys/cpuvar.h>
  28 #include <sys/types.h>
  29 #include <sys/conf.h>
  30 #include <sys/stat.h>
  31 #include <sys/file.h>
  32 #include <sys/ddi.h>
  33 #include <sys/sunddi.h>
  34 #include <sys/modctl.h>
  35 #include <sys/sysmacros.h>
  36 #include <sys/socket.h>
  37 #include <sys/strsubr.h>
  38 #include <sys/nvpair.h>
  39 
  40 #include <sys/stmf.h>
  41 #include <sys/stmf_ioctl.h>
  42 #include <sys/portif.h>
  43 #include <sys/idm/idm.h>
  44 #include <sys/idm/idm_conn_sm.h>


3108         iscsit_sess_t           *ist = ict->ict_sess;
3109         iscsi_scsi_cmd_hdr_t    *hdr = (iscsi_scsi_cmd_hdr_t *)rx_pdu->isp_hdr;
3110 
3111         mutex_enter(&ist->ist_sn_mutex);
3112         if (hdr->opcode & ISCSI_OP_IMMEDIATE) {
3113                 /* do not queue, handle it immediately */
3114                 DTRACE_PROBE2(immediate__cmd, iscsit_sess_t *, ist,
3115                     idm_pdu_t *, rx_pdu);
3116                 mutex_exit(&ist->ist_sn_mutex);
3117                 return (ISCSIT_CMDSN_EQ_EXPCMDSN);
3118         }
3119         if (iscsit_sna_lt(ist->ist_expcmdsn, ntohl(hdr->cmdsn))) {
3120                 /*
3121                  * Out-of-order commands (cmdSN higher than ExpCmdSN)
3122                  * are staged on a fixed-size circular buffer until
3123                  * the missing command is delivered to the SCSI layer.
3124                  * Irrespective of the order of insertion into the
3125                  * staging queue, the commands are processed out of the
3126                  * queue in cmdSN order only.
3127                  */
3128                 rx_pdu->isp_queue_time = gethrtime();
3129                 iscsit_add_pdu_to_queue(ist, rx_pdu);
3130                 mutex_exit(&ist->ist_sn_mutex);
3131                 return (ISCSIT_CMDSN_GT_EXPCMDSN);
3132         } else if (iscsit_sna_lt(ntohl(hdr->cmdsn), ist->ist_expcmdsn)) {
3133                 DTRACE_PROBE3(cmdsn__lt__expcmdsn, iscsit_sess_t *, ist,
3134                     iscsit_conn_t *, ict, idm_pdu_t *, rx_pdu);
3135                 mutex_exit(&ist->ist_sn_mutex);
3136                 return (ISCSIT_CMDSN_LT_EXPCMDSN);
3137         } else {
3138                 mutex_exit(&ist->ist_sn_mutex);
3139                 return (ISCSIT_CMDSN_EQ_EXPCMDSN);
3140         }
3141 }
3142 
3143 /*
3144  * iscsit_add_pdu_to_queue() adds PDUs into the array indexed by
3145  * their cmdsn value. The length of the array is kept above the
3146  * maximum window size. The window keeps the cmdsn within a range
3147  * such that there are no collisons. e.g. the assumption is that
3148  * the windowing checks make it impossible to receive PDUs that


3378          * wait time of 1004 > wait time of 1003, only 1003 will be considered
3379          * by the monitor thread. 1004 will be automatically processed by
3380          * iscsit_process_pdu_in_queue() once the scan is complete and the
3381          * expcmdsn becomes current.
3382          */
3383         mutex_enter(&ist->ist_sn_mutex);
3384         cbuf = ist->ist_rxpdu_queue;
3385         if (cbuf->cb_num_elems == 0) {
3386                 mutex_exit(&ist->ist_sn_mutex);
3387                 return;
3388         }
3389         for (next_pdu = NULL, i = 0; ; i++) {
3390                 next_cmdsn = ist->ist_expcmdsn + i; /* start at expcmdsn */
3391                 index = next_cmdsn % ISCSIT_RXPDU_QUEUE_LEN;
3392                 if ((next_pdu = cbuf->cb_buffer[index]) != NULL) {
3393                         /*
3394                          * If the PDU wait time has not exceeded threshold
3395                          * stop scanning the staging queue until the timer
3396                          * fires again
3397                          */
3398                         if ((gethrtime() - next_pdu->isp_queue_time)
3399                             < (rxpdu_queue_threshold * NANOSEC)) {
3400                                 mutex_exit(&ist->ist_sn_mutex);
3401                                 return;
3402                         }
3403                         /*
3404                          * Remove the next PDU from the queue and post it
3405                          * to the SCSI layer, skipping over the missing
3406                          * PDU. Stop scanning the staging queue until
3407                          * the monitor timer fires again
3408                          */
3409                         (void) iscsit_remove_pdu_from_queue(ist, next_cmdsn);
3410                         mutex_exit(&ist->ist_sn_mutex);
3411                         DTRACE_PROBE3(advanced__to__blocked__cmdsn,
3412                             iscsit_sess_t *, ist, idm_pdu_t *, next_pdu,
3413                             uint32_t, next_cmdsn);
3414                         iscsit_post_staged_pdu(next_pdu);
3415                         /* Deliver any subsequent PDUs immediately */
3416                         iscsit_process_pdu_in_queue(ist);
3417                         return;
3418                 }
3419                 /*