Print this page
653 incorrect handling in iscsit of duplicate PDUs with cmdsn > expsn
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Jason King <jason.brian.king@gmail.com>
Reviewed by: Gary Mills <gary_mills@fastmail.fm>


   3  *
   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 /*
  25  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  26  */
  27 
  28 #include <sys/cpuvar.h>
  29 #include <sys/types.h>
  30 #include <sys/conf.h>
  31 #include <sys/stat.h>
  32 #include <sys/file.h>
  33 #include <sys/ddi.h>
  34 #include <sys/sunddi.h>
  35 #include <sys/modctl.h>
  36 #include <sys/sysmacros.h>
  37 #include <sys/socket.h>
  38 #include <sys/strsubr.h>
  39 #include <sys/nvpair.h>
  40 
  41 #include <sys/stmf.h>
  42 #include <sys/stmf_ioctl.h>
  43 #include <sys/portif.h>
  44 #include <sys/idm/idm.h>
  45 #include <sys/idm/idm_conn_sm.h>
  46 


3144         iscsit_conn_t   *ict    = rx_pdu->isp_ic->ic_handle;
3145         uint32_t        cmdsn   =
3146             ((iscsi_scsi_cmd_hdr_t *)rx_pdu->isp_hdr)->cmdsn;
3147         uint32_t        index;
3148 
3149         ASSERT(MUTEX_HELD(&ist->ist_sn_mutex));
3150         /*
3151          * If the connection is being torn down, then
3152          * don't add the PDU to the staging queue
3153          */
3154         mutex_enter(&ict->ict_mutex);
3155         if (ict->ict_lost) {
3156                 mutex_exit(&ict->ict_mutex);
3157                 idm_pdu_complete(rx_pdu, IDM_STATUS_FAIL);
3158                 return;
3159         }
3160         iscsit_conn_dispatch_hold(ict);
3161         mutex_exit(&ict->ict_mutex);
3162 
3163         index = ntohl(cmdsn) % ISCSIT_RXPDU_QUEUE_LEN;
3164         ASSERT(cbuf->cb_buffer[index] == NULL);











3165         cbuf->cb_buffer[index] = rx_pdu;
3166         cbuf->cb_num_elems++;

3167 }
3168 
3169 static idm_pdu_t *
3170 iscsit_remove_pdu_from_queue(iscsit_sess_t *ist, uint32_t cmdsn)
3171 {
3172         iscsit_cbuf_t   *cbuf   = ist->ist_rxpdu_queue;
3173         idm_pdu_t       *pdu    = NULL;
3174         uint32_t        index;
3175 
3176         ASSERT(MUTEX_HELD(&ist->ist_sn_mutex));
3177         index = cmdsn % ISCSIT_RXPDU_QUEUE_LEN;
3178         if ((pdu = cbuf->cb_buffer[index]) != NULL) {
3179                 ASSERT(cmdsn ==
3180                     ntohl(((iscsi_scsi_cmd_hdr_t *)pdu->isp_hdr)->cmdsn));
3181                 cbuf->cb_buffer[index] = NULL;
3182                 cbuf->cb_num_elems--;
3183                 return (pdu);
3184         }
3185         return (NULL);
3186 }




   3  *
   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 2012 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>
  45 


3143         iscsit_conn_t   *ict    = rx_pdu->isp_ic->ic_handle;
3144         uint32_t        cmdsn   =
3145             ((iscsi_scsi_cmd_hdr_t *)rx_pdu->isp_hdr)->cmdsn;
3146         uint32_t        index;
3147 
3148         ASSERT(MUTEX_HELD(&ist->ist_sn_mutex));
3149         /*
3150          * If the connection is being torn down, then
3151          * don't add the PDU to the staging queue
3152          */
3153         mutex_enter(&ict->ict_mutex);
3154         if (ict->ict_lost) {
3155                 mutex_exit(&ict->ict_mutex);
3156                 idm_pdu_complete(rx_pdu, IDM_STATUS_FAIL);
3157                 return;
3158         }
3159         iscsit_conn_dispatch_hold(ict);
3160         mutex_exit(&ict->ict_mutex);
3161 
3162         index = ntohl(cmdsn) % ISCSIT_RXPDU_QUEUE_LEN;
3163         /*
3164          * In the normal case, assuming that the Initiator is not
3165          * buggy and that we don't have packet duplication occuring,
3166          * the entry in the array will be NULL.  However, we may have
3167          * received a duplicate PDU with cmdsn > expsn , and in that
3168          * case we just ignore this PDU -- the previously received one
3169          * remains queued for processing.  We need to be careful not
3170          * to leak this one however.
3171          */
3172         if (cbuf->cb_buffer[index] != NULL) {
3173                 idm_pdu_complete(rx_pdu, IDM_STATUS_FAIL);
3174         } else {
3175                 cbuf->cb_buffer[index] = rx_pdu;
3176                 cbuf->cb_num_elems++;
3177         }
3178 }
3179 
3180 static idm_pdu_t *
3181 iscsit_remove_pdu_from_queue(iscsit_sess_t *ist, uint32_t cmdsn)
3182 {
3183         iscsit_cbuf_t   *cbuf   = ist->ist_rxpdu_queue;
3184         idm_pdu_t       *pdu    = NULL;
3185         uint32_t        index;
3186 
3187         ASSERT(MUTEX_HELD(&ist->ist_sn_mutex));
3188         index = cmdsn % ISCSIT_RXPDU_QUEUE_LEN;
3189         if ((pdu = cbuf->cb_buffer[index]) != NULL) {
3190                 ASSERT(cmdsn ==
3191                     ntohl(((iscsi_scsi_cmd_hdr_t *)pdu->isp_hdr)->cmdsn));
3192                 cbuf->cb_buffer[index] = NULL;
3193                 cbuf->cb_num_elems--;
3194                 return (pdu);
3195         }
3196         return (NULL);
3197 }