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

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/io/comstar/port/iscsit/iscsit.c
          +++ new/usr/src/uts/common/io/comstar/port/iscsit/iscsit.c
↓ open down ↓ 12 lines elided ↑ open up ↑
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  23      - *
  24      - * Copyright 2014, 2015 Nexenta Systems, Inc. All rights reserved.
       23 + * Copyright 2017 Nexenta Systems, Inc.
  25   24   * Copyright (c) 2017, Joyent, Inc.  All rights reserved.
  26   25   */
  27   26  
  28   27  #include <sys/cpuvar.h>
  29   28  #include <sys/types.h>
  30   29  #include <sys/conf.h>
  31   30  #include <sys/stat.h>
  32   31  #include <sys/file.h>
  33   32  #include <sys/ddi.h>
  34   33  #include <sys/sunddi.h>
↓ open down ↓ 522 lines elided ↑ open up ↑
 557  556  
 558  557                  /* Update config */
 559  558                  rc = iscsit_config_merge(cfg);
 560  559                  /* FALLTHROUGH */
 561  560  
 562  561  cleanup:
 563  562                  if (cfg)
 564  563                          it_config_free_cmn(cfg);
 565  564                  if (cfg_pnvlist)
 566  565                          kmem_free(cfg_pnvlist, setcfg.set_cfg_pnvlist_len);
 567      -                nvlist_free(cfg_nvlist);
      566 +                if (cfg_nvlist)
      567 +                        nvlist_free(cfg_nvlist);
 568  568  
 569  569                  /*
 570  570                   * Now that the reconfig is complete set our state back to
 571  571                   * enabled.
 572  572                   */
 573  573                  mutex_enter(&iscsit_global.global_state_mutex);
 574  574                  iscsit_global.global_svc_state = ISE_ENABLED;
 575  575                  mutex_exit(&iscsit_global.global_state_mutex);
 576  576                  break;
 577  577          case ISCSIT_IOC_ENABLE_SVC: {
↓ open down ↓ 407 lines elided ↑ open up ↑
 985  985                           */
 986  986                          iscsit_task_done(itask);
 987  987  
 988  988                          /*
 989  989                           * STMF has already asked for this task to be aborted
 990  990                           *
 991  991                           * STMF specification is wrong... says to return
 992  992                           * STMF_ABORTED, the code actually looks for
 993  993                           * STMF_ABORT_SUCCESS.
 994  994                           */
 995      -                        stmf_task_lport_aborted(itask->it_stmf_task,
      995 +                        stmf_task_lport_aborted_unlocked(itask->it_stmf_task,
 996  996                              STMF_ABORT_SUCCESS, STMF_IOF_LPORT_DONE);
 997  997                          return;
 998  998                  } else {
 999  999                          mutex_exit(&itask->it_mutex);
1000 1000                          /*
1001 1001                           * Tell STMF to stop processing the task.
1002 1002                           */
1003 1003                          stmf_abort(STMF_QUEUE_TASK_ABORT, itask->it_stmf_task,
1004 1004                              STMF_ABORTED, NULL);
1005 1005                          return;
↓ open down ↓ 211 lines elided ↑ open up ↑
1217 1217           */
1218 1218          ict = kmem_zalloc(sizeof (*ict), KM_SLEEP);
1219 1219  
1220 1220          ict->ict_ic = ic;
1221 1221          ict->ict_statsn = 1;
1222 1222          ict->ict_keepalive_ttt = IDM_TASKIDS_MAX; /* Avoid IDM TT range */
1223 1223          ic->ic_handle = ict;
1224 1224          mutex_init(&ict->ict_mutex, NULL, MUTEX_DRIVER, NULL);
1225 1225          mutex_init(&ict->ict_statsn_mutex, NULL, MUTEX_DRIVER, NULL);
1226 1226          idm_refcnt_init(&ict->ict_refcnt, ict);
     1227 +        idm_refcnt_init(&ict->ict_dispatch_refcnt, ict);
1227 1228  
1228 1229          /*
1229 1230           * Initialize login state machine
1230 1231           */
1231 1232          if (iscsit_login_sm_init(ict) != IDM_STATUS_SUCCESS) {
1232 1233                  iscsit_global_rele();
1233 1234                  /*
1234 1235                   * Cleanup the ict after idm notifies us about this failure
1235 1236                   */
1236 1237                  return (IDM_STATUS_FAIL);
↓ open down ↓ 125 lines elided ↑ open up ↑
1362 1363                                  cbuf->cb_num_elems--;
1363 1364                                  iscsit_conn_dispatch_rele(ict);
1364 1365                          }
1365 1366                  }
1366 1367                  mutex_exit(&ist->ist_sn_mutex);
1367 1368          }
1368 1369          /*
1369 1370           * Make sure there aren't any PDU's transitioning from the receive
1370 1371           * handler to the dispatch taskq.
1371 1372           */
     1373 +        if (idm_refcnt_is_held(&ict->ict_dispatch_refcnt) < 0) {
     1374 +                cmn_err(CE_WARN, "Possible hang in iscsit_conn_lost");
     1375 +        }
1372 1376          idm_refcnt_wait_ref(&ict->ict_dispatch_refcnt);
1373 1377  
1374 1378          return (IDM_STATUS_SUCCESS);
1375 1379  }
1376 1380  
1377 1381  static idm_status_t
1378 1382  iscsit_conn_destroy(idm_conn_t *ic)
1379 1383  {
1380 1384          iscsit_conn_t *ict = ic->ic_handle;
1381 1385  
1382 1386          mutex_enter(&ict->ict_mutex);
1383 1387          ict->ict_destroyed = B_TRUE;
1384 1388          mutex_exit(&ict->ict_mutex);
1385 1389  
1386 1390          /* Generate session state machine event */
1387 1391          if (ict->ict_sess != NULL) {
1388      -                /*
1389      -                 * Session state machine will call iscsit_conn_destroy_done()
1390      -                 * when it has removed references to this connection.
1391      -                 */
1392 1392                  iscsit_sess_sm_event(ict->ict_sess, SE_CONN_FAIL, ict);
1393 1393          }
1394 1394  
     1395 +        idm_refcnt_wait_ref(&ict->ict_dispatch_refcnt);
1395 1396          idm_refcnt_wait_ref(&ict->ict_refcnt);
1396 1397          /*
1397 1398           * The session state machine does not need to post
1398 1399           * events to IDM any longer, so it is safe to set
1399 1400           * the idm connection reference to NULL
1400 1401           */
1401 1402          ict->ict_ic = NULL;
1402 1403  
1403 1404          /* Reap the login state machine */
1404 1405          iscsit_login_sm_fini(ict);
1405 1406  
1406 1407          /* Clean up any text command remnants */
1407 1408          iscsit_text_cmd_fini(ict);
1408 1409  
1409 1410          mutex_destroy(&ict->ict_mutex);
     1411 +        idm_refcnt_destroy(&ict->ict_dispatch_refcnt);
1410 1412          idm_refcnt_destroy(&ict->ict_refcnt);
1411 1413          kmem_free(ict, sizeof (*ict));
1412 1414  
1413 1415          iscsit_global_rele();
1414 1416  
1415 1417          return (IDM_STATUS_SUCCESS);
1416 1418  }
1417 1419  
1418 1420  void
1419 1421  iscsit_conn_logout(iscsit_conn_t *ict)
↓ open down ↓ 461 lines elided ↑ open up ↑
1881 1883                   * STMF_ABORTED, the code actually looks for
1882 1884                   * STMF_ABORT_SUCCESS.
1883 1885                   */
1884 1886                  return (STMF_ABORT_SUCCESS);
1885 1887          } else {
1886 1888                  mutex_exit(&iscsit_task->it_mutex);
1887 1889                  /*
1888 1890                   * Call IDM to abort the task.  Due to a variety of
1889 1891                   * circumstances the task may already be in the process of
1890 1892                   * aborting.
1891      -                 * We'll let IDM worry about rationalizing all that except
1892      -                 * for one particular instance.  If the state of the task
1893      -                 * is TASK_COMPLETE, we need to indicate to the framework
1894      -                 * that we are in fact done.  This typically happens with
1895      -                 * framework-initiated task management type requests
1896      -                 * (e.g. abort task).
1897 1893                   */
1898      -                if (idt->idt_state == TASK_COMPLETE) {
1899      -                        idm_refcnt_wait_ref(&idt->idt_refcnt);
1900      -                        return (STMF_ABORT_SUCCESS);
1901      -                } else {
1902      -                        idm_task_abort(idt->idt_ic, idt, AT_TASK_MGMT_ABORT);
1903      -                        return (STMF_SUCCESS);
1904      -                }
     1894 +                return (idm_task_abort(idt->idt_ic, idt, AT_TASK_MGMT_ABORT));
1905 1895          }
1906 1896  
1907 1897          /*NOTREACHED*/
1908 1898  }
1909 1899  
1910 1900  /*ARGSUSED*/
1911 1901  void
1912 1902  iscsit_ctl(stmf_local_port_t *lport, int cmd, void *arg)
1913 1903  {
1914 1904          iscsit_tgt_t            *iscsit_tgt;
↓ open down ↓ 40 lines elided ↑ open up ↑
1955 1945  iscsit_op_scsi_cmd(idm_conn_t *ic, idm_pdu_t *rx_pdu)
1956 1946  {
1957 1947          iscsit_conn_t           *ict = ic->ic_handle;
1958 1948  
1959 1949          if (iscsit_check_cmdsn_and_queue(rx_pdu)) {
1960 1950                  iscsit_post_scsi_cmd(ic, rx_pdu);
1961 1951          }
1962 1952          iscsit_process_pdu_in_queue(ict->ict_sess);
1963 1953  }
1964 1954  
     1955 +static int
     1956 +iscsit_validate_idm_pdu(idm_pdu_t *rx_pdu)
     1957 +{
     1958 +        iscsi_scsi_cmd_hdr_t    *iscsi_scsi =
     1959 +            (iscsi_scsi_cmd_hdr_t *)rx_pdu->isp_hdr;
     1960 +
     1961 +        if ((iscsi_scsi->scb[0] == SCMD_READ) ||
     1962 +            (iscsi_scsi->scb[0] == SCMD_READ_G1) ||
     1963 +            (iscsi_scsi->scb[0] == SCMD_READ_G4)) {
     1964 +                if (iscsi_scsi->flags & ISCSI_FLAG_CMD_WRITE)
     1965 +                        return (IDM_STATUS_FAIL);
     1966 +        }
     1967 +        return (IDM_STATUS_SUCCESS);
     1968 +}
     1969 +
1965 1970  /*
1966 1971   * ISCSI protocol
1967 1972   */
1968 1973  
1969 1974  void
1970 1975  iscsit_post_scsi_cmd(idm_conn_t *ic, idm_pdu_t *rx_pdu)
1971 1976  {
1972 1977          iscsit_conn_t           *ict;
1973 1978          iscsit_task_t           *itask;
1974 1979          scsi_task_t             *task;
1975 1980          iscsit_buf_t            *ibuf;
1976 1981          iscsi_scsi_cmd_hdr_t    *iscsi_scsi =
1977 1982              (iscsi_scsi_cmd_hdr_t *)rx_pdu->isp_hdr;
1978 1983          iscsi_addl_hdr_t        *ahs_hdr;
1979 1984          uint16_t                addl_cdb_len = 0;
1980 1985  
1981 1986          ict = ic->ic_handle;
     1987 +        if (iscsit_validate_idm_pdu(rx_pdu) != IDM_STATUS_SUCCESS) {
     1988 +                /* Finish processing request */
     1989 +                iscsit_set_cmdsn(ict, rx_pdu);
1982 1990  
     1991 +                iscsit_send_direct_scsi_resp(ict, rx_pdu,
     1992 +                    ISCSI_STATUS_CMD_COMPLETED, STATUS_CHECK);
     1993 +                idm_pdu_complete(rx_pdu, IDM_STATUS_PROTOCOL_ERROR);
     1994 +                return;
     1995 +        }
     1996 +
1983 1997          itask = iscsit_task_alloc(ict);
1984 1998          if (itask == NULL) {
1985 1999                  /* Finish processing request */
1986 2000                  iscsit_set_cmdsn(ict, rx_pdu);
1987 2001  
1988 2002                  iscsit_send_direct_scsi_resp(ict, rx_pdu,
1989 2003                      ISCSI_STATUS_CMD_COMPLETED, STATUS_BUSY);
1990 2004                  idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS);
1991 2005                  return;
1992 2006          }
↓ open down ↓ 1475 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX