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);