Print this page
NEX-9981 Deadman timer panic from idm_refcnt_wait_ref thread while offlining iSCSI targets
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
NEX-6018 Return of the walking dead idm_refcnt_wait_ref comstar threads
Reviewed by:  Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by:  Evan Layton <evan.layton@nexenta.com>
NEX-3746 Panic seen if iSCSI Initiator sends a SCSI Response packet to target
NEX-3777 COMSTAR iscsi/io test can panic the target running 5.0
NEX-3785 This is on 5.0 release and iSCSI target can panic while running iSCSI mpxio disable test
Reviewed by: Steve Peng <steve.peng@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
NEX-2359 iSCSI target connection handling is missing refcount audit information
re #10417 rb2398 incorrect handling in iscsit of duplicate PDUs with cmdsn > expsn
re #9966: sysretq doesn't properly handle non-canonical addresses
re #9966: sysretq doesn't properly handle non-canonical addresses
--HG--
branch : stable-4.0
re #9822 - libiscsi test panics COMSTAR
--HG--
branch : stable-4.0
re #9822 - libiscsi test panics COMSTAR
        
*** 18,29 ****
   *
   * CDDL HEADER END
   */
  /*
   * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
!  *
!  * Copyright 2014, 2015 Nexenta Systems, Inc. All rights reserved.
   * Copyright (c) 2017, Joyent, Inc.  All rights reserved.
   */
  
  #include <sys/cpuvar.h>
  #include <sys/types.h>
--- 18,28 ----
   *
   * CDDL HEADER END
   */
  /*
   * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
!  * Copyright 2017 Nexenta Systems, Inc.
   * Copyright (c) 2017, Joyent, Inc.  All rights reserved.
   */
  
  #include <sys/cpuvar.h>
  #include <sys/types.h>
*** 562,571 ****
--- 561,571 ----
  cleanup:
                  if (cfg)
                          it_config_free_cmn(cfg);
                  if (cfg_pnvlist)
                          kmem_free(cfg_pnvlist, setcfg.set_cfg_pnvlist_len);
+                 if (cfg_nvlist)
                          nvlist_free(cfg_nvlist);
  
                  /*
                   * Now that the reconfig is complete set our state back to
                   * enabled.
*** 990,1000 ****
                           *
                           * STMF specification is wrong... says to return
                           * STMF_ABORTED, the code actually looks for
                           * STMF_ABORT_SUCCESS.
                           */
!                         stmf_task_lport_aborted(itask->it_stmf_task,
                              STMF_ABORT_SUCCESS, STMF_IOF_LPORT_DONE);
                          return;
                  } else {
                          mutex_exit(&itask->it_mutex);
                          /*
--- 990,1000 ----
                           *
                           * STMF specification is wrong... says to return
                           * STMF_ABORTED, the code actually looks for
                           * STMF_ABORT_SUCCESS.
                           */
!                         stmf_task_lport_aborted_unlocked(itask->it_stmf_task,
                              STMF_ABORT_SUCCESS, STMF_IOF_LPORT_DONE);
                          return;
                  } else {
                          mutex_exit(&itask->it_mutex);
                          /*
*** 1222,1231 ****
--- 1222,1232 ----
          ict->ict_keepalive_ttt = IDM_TASKIDS_MAX; /* Avoid IDM TT range */
          ic->ic_handle = ict;
          mutex_init(&ict->ict_mutex, NULL, MUTEX_DRIVER, NULL);
          mutex_init(&ict->ict_statsn_mutex, NULL, MUTEX_DRIVER, NULL);
          idm_refcnt_init(&ict->ict_refcnt, ict);
+         idm_refcnt_init(&ict->ict_dispatch_refcnt, ict);
  
          /*
           * Initialize login state machine
           */
          if (iscsit_login_sm_init(ict) != IDM_STATUS_SUCCESS) {
*** 1367,1376 ****
--- 1368,1380 ----
          }
          /*
           * Make sure there aren't any PDU's transitioning from the receive
           * handler to the dispatch taskq.
           */
+         if (idm_refcnt_is_held(&ict->ict_dispatch_refcnt) < 0) {
+                 cmn_err(CE_WARN, "Possible hang in iscsit_conn_lost");
+         }
          idm_refcnt_wait_ref(&ict->ict_dispatch_refcnt);
  
          return (IDM_STATUS_SUCCESS);
  }
  
*** 1383,1399 ****
          ict->ict_destroyed = B_TRUE;
          mutex_exit(&ict->ict_mutex);
  
          /* Generate session state machine event */
          if (ict->ict_sess != NULL) {
-                 /*
-                  * Session state machine will call iscsit_conn_destroy_done()
-                  * when it has removed references to this connection.
-                  */
                  iscsit_sess_sm_event(ict->ict_sess, SE_CONN_FAIL, ict);
          }
  
          idm_refcnt_wait_ref(&ict->ict_refcnt);
          /*
           * The session state machine does not need to post
           * events to IDM any longer, so it is safe to set
           * the idm connection reference to NULL
--- 1387,1400 ----
          ict->ict_destroyed = B_TRUE;
          mutex_exit(&ict->ict_mutex);
  
          /* Generate session state machine event */
          if (ict->ict_sess != NULL) {
                  iscsit_sess_sm_event(ict->ict_sess, SE_CONN_FAIL, ict);
          }
  
+         idm_refcnt_wait_ref(&ict->ict_dispatch_refcnt);
          idm_refcnt_wait_ref(&ict->ict_refcnt);
          /*
           * The session state machine does not need to post
           * events to IDM any longer, so it is safe to set
           * the idm connection reference to NULL
*** 1405,1414 ****
--- 1406,1416 ----
  
          /* Clean up any text command remnants */
          iscsit_text_cmd_fini(ict);
  
          mutex_destroy(&ict->ict_mutex);
+         idm_refcnt_destroy(&ict->ict_dispatch_refcnt);
          idm_refcnt_destroy(&ict->ict_refcnt);
          kmem_free(ict, sizeof (*ict));
  
          iscsit_global_rele();
  
*** 1886,1910 ****
                  mutex_exit(&iscsit_task->it_mutex);
                  /*
                   * Call IDM to abort the task.  Due to a variety of
                   * circumstances the task may already be in the process of
                   * aborting.
-                  * We'll let IDM worry about rationalizing all that except
-                  * for one particular instance.  If the state of the task
-                  * is TASK_COMPLETE, we need to indicate to the framework
-                  * that we are in fact done.  This typically happens with
-                  * framework-initiated task management type requests
-                  * (e.g. abort task).
                   */
!                 if (idt->idt_state == TASK_COMPLETE) {
!                         idm_refcnt_wait_ref(&idt->idt_refcnt);
!                         return (STMF_ABORT_SUCCESS);
!                 } else {
!                         idm_task_abort(idt->idt_ic, idt, AT_TASK_MGMT_ABORT);
!                         return (STMF_SUCCESS);
                  }
-         }
  
          /*NOTREACHED*/
  }
  
  /*ARGSUSED*/
--- 1888,1900 ----
                  mutex_exit(&iscsit_task->it_mutex);
                  /*
                   * Call IDM to abort the task.  Due to a variety of
                   * circumstances the task may already be in the process of
                   * aborting.
                   */
!                 return (idm_task_abort(idt->idt_ic, idt, AT_TASK_MGMT_ABORT));
          }
  
          /*NOTREACHED*/
  }
  
  /*ARGSUSED*/
*** 1960,1969 ****
--- 1950,1974 ----
                  iscsit_post_scsi_cmd(ic, rx_pdu);
          }
          iscsit_process_pdu_in_queue(ict->ict_sess);
  }
  
+ static int
+ iscsit_validate_idm_pdu(idm_pdu_t *rx_pdu)
+ {
+         iscsi_scsi_cmd_hdr_t    *iscsi_scsi =
+             (iscsi_scsi_cmd_hdr_t *)rx_pdu->isp_hdr;
+ 
+         if ((iscsi_scsi->scb[0] == SCMD_READ) ||
+             (iscsi_scsi->scb[0] == SCMD_READ_G1) ||
+             (iscsi_scsi->scb[0] == SCMD_READ_G4)) {
+                 if (iscsi_scsi->flags & ISCSI_FLAG_CMD_WRITE)
+                         return (IDM_STATUS_FAIL);
+         }
+         return (IDM_STATUS_SUCCESS);
+ }
+ 
  /*
   * ISCSI protocol
   */
  
  void
*** 1977,1987 ****
--- 1982,2001 ----
              (iscsi_scsi_cmd_hdr_t *)rx_pdu->isp_hdr;
          iscsi_addl_hdr_t        *ahs_hdr;
          uint16_t                addl_cdb_len = 0;
  
          ict = ic->ic_handle;
+         if (iscsit_validate_idm_pdu(rx_pdu) != IDM_STATUS_SUCCESS) {
+                 /* Finish processing request */
+                 iscsit_set_cmdsn(ict, rx_pdu);
  
+                 iscsit_send_direct_scsi_resp(ict, rx_pdu,
+                     ISCSI_STATUS_CMD_COMPLETED, STATUS_CHECK);
+                 idm_pdu_complete(rx_pdu, IDM_STATUS_PROTOCOL_ERROR);
+                 return;
+         }
+ 
          itask = iscsit_task_alloc(ict);
          if (itask == NULL) {
                  /* Finish processing request */
                  iscsit_set_cmdsn(ict, rx_pdu);