Print this page
NEX-15497 Multiple iSCSI targets stuck offlining and an old thread in idm_refcnt_wait_ref
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15497 Multiple iSCSI targets stuck offlining and an old thread in idm_refcnt_wait_ref
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-7907 uts/common/sys/scsi/scsi_names.h should define IQN as 223 bytes, not utf-8 characters
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
NEX-2756 iscsit should fold the case of scsi names that we get from initiators
Reviewed by: Steve Peng <steve.peng@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-3622 COMSTAR should have per remote port kstats for I/O and latency
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
SUP-776 iSCSI target portals not isolating IQNs on different subnets


  29 #include <sys/conf.h>
  30 #include <sys/file.h>
  31 #include <sys/ddi.h>
  32 #include <sys/sunddi.h>
  33 #include <sys/modctl.h>
  34 #include <sys/scsi/generic/persist.h>
  35 #include <sys/scsi/scsi_names.h>
  36 
  37 #include <sys/socket.h>
  38 #include <sys/strsubr.h>
  39 #include <sys/sysmacros.h>
  40 #include <sys/note.h>
  41 #include <sys/sdt.h>
  42 #include <sys/errno.h>
  43 
  44 #include <sys/stmf.h>
  45 #include <sys/stmf_ioctl.h>
  46 #include <sys/portif.h>
  47 #include <sys/idm/idm.h>
  48 #include <sys/idm/idm_text.h>

  49 
  50 #define ISCSIT_LOGIN_SM_STRINGS
  51 #include "iscsit.h"
  52 #include "iscsit_auth.h"
  53 
  54 typedef struct {
  55         list_node_t             le_ctx_node;
  56         iscsit_login_event_t    le_ctx_event;
  57         idm_pdu_t               *le_pdu;
  58 } login_event_ctx_t;
  59 
  60 #ifndef TRUE
  61 #define TRUE B_TRUE
  62 #endif
  63 
  64 #ifndef FALSE
  65 #define FALSE B_FALSE
  66 #endif
  67 
  68 #define DEFAULT_RADIUS_PORT     1812


 715 
 716         new_state = (new_state < ILS_MAX_STATE) ?
 717             new_state : ILS_UNDEFINED;
 718 
 719         IDM_SM_LOG(CE_NOTE, "login_sm_new_state: conn %p "
 720             "%s (%d) --> %s (%d)\n", (void *)ict->ict_ic,
 721             iscsit_ils_name[lsm->icl_login_state], lsm->icl_login_state,
 722             iscsit_ils_name[new_state], new_state);
 723 
 724         DTRACE_PROBE3(login__state__change,
 725             iscsit_conn_t *, ict, login_event_ctx_t *, ctx,
 726             iscsit_login_state_t, new_state);
 727 
 728         mutex_enter(&lsm->icl_mutex);
 729         idm_sm_audit_state_change(&lsm->icl_state_audit, SAS_ISCSIT_LOGIN,
 730             (int)lsm->icl_login_state, (int)new_state);
 731         lsm->icl_login_last_state = lsm->icl_login_state;
 732         lsm->icl_login_state = new_state;
 733         mutex_exit(&lsm->icl_mutex);
 734 
 735         switch (lsm->icl_login_state) {






























 736         case ILS_LOGIN_WAITING:
 737                 /* Do nothing, waiting for more login PDU's */
 738                 break;
 739         case ILS_LOGIN_PROCESSING:
 740                 /* All login PDU's received, process login request */
 741                 login_sm_process_request(ict);
 742                 break;
 743         case ILS_LOGIN_RESPONDING:
 744                 rpdu = login_sm_build_login_response(ict);
 745                 login_sm_send_next_response(ict, rpdu);
 746                 break;
 747         case ILS_LOGIN_RESPONDED:
 748                 /* clean up the login response idm text buffer */
 749                 if (lsm->icl_login_resp_itb != NULL) {
 750                         idm_itextbuf_free(lsm->icl_login_resp_itb);
 751                         lsm->icl_login_resp_itb = NULL;
 752                 }
 753                 break;
 754         case ILS_LOGIN_FFP:
 755                 login_sm_ffp_actions(ict);


1731         } else if ((strcmp(auth, PA_AUTH_CHAP) == 0) &&
1732             (lsm->icl_auth.ca_ini_chapsecretlen == 0)) {
1733                 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_INITIATOR_ERR,
1734                     ISCSI_LOGIN_STATUS_AUTH_FAILED);
1735                 idmrc = IDM_STATUS_FAIL;
1736         }
1737 
1738         ISCSIT_GLOBAL_UNLOCK();
1739 
1740         return (idmrc);
1741 }
1742 
1743 
1744 static idm_status_t
1745 login_sm_session_register(iscsit_conn_t *ict)
1746 {
1747         iscsit_sess_t           *ist = ict->ict_sess;
1748         stmf_scsi_session_t     *ss;
1749         iscsi_transport_id_t    *iscsi_tptid;
1750         uint16_t                ident_len, adn_len, tptid_sz;


1751 
1752         /*
1753          * Hold target mutex until we have finished registering with STMF
1754          */
1755         mutex_enter(&ist->ist_tgt->target_mutex);
1756         if (ist->ist_tgt->target_state != TS_STMF_ONLINE) {
1757                 mutex_exit(&ist->ist_tgt->target_mutex);
1758                 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_INITIATOR_ERR,
1759                     ISCSI_LOGIN_STATUS_TGT_REMOVED);
1760                 return (IDM_STATUS_FAIL);
1761         }
1762 
1763         ss = stmf_alloc(STMF_STRUCT_SCSI_SESSION, 0,
1764             0);
1765         if (ss == NULL) {
1766                 mutex_exit(&ist->ist_tgt->target_mutex);
1767                 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_TARGET_ERR,
1768                     ISCSI_LOGIN_STATUS_NO_RESOURCES);
1769                 return (IDM_STATUS_FAIL);
1770         }


1791             ist->ist_initiator_name, ident_len);
1792 
1793         ss->ss_lport = ist->ist_lport;
1794 
1795         if (stmf_register_scsi_session(ict->ict_sess->ist_lport, ss) !=
1796             STMF_SUCCESS) {
1797                 mutex_exit(&ist->ist_tgt->target_mutex);
1798                 kmem_free(ss->ss_rport_id,
1799                     sizeof (scsi_devid_desc_t) +
1800                     strlen(ist->ist_initiator_name) + 1);
1801                 stmf_remote_port_free(ss->ss_rport);
1802                 stmf_free(ss);
1803                 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_TARGET_ERR,
1804                     ISCSI_LOGIN_STATUS_TARGET_ERROR);
1805                 return (IDM_STATUS_FAIL);
1806         }
1807 
1808         ss->ss_port_private = ict->ict_sess;
1809         ict->ict_sess->ist_stmf_sess = ss;
1810         mutex_exit(&ist->ist_tgt->target_mutex);





1811 
1812         return (IDM_STATUS_SUCCESS);
1813 }
1814 
1815 
1816 static idm_status_t
1817 login_sm_req_pdu_check(iscsit_conn_t *ict, idm_pdu_t *pdu)
1818 {
1819         uint8_t                 csg_req;
1820         iscsit_conn_login_t     *lsm = &ict->ict_login_sm;
1821         iscsi_login_hdr_t       *lh = (iscsi_login_hdr_t *)pdu->isp_hdr;
1822         iscsi_login_rsp_hdr_t *lh_resp = lsm->icl_login_resp_tmpl;
1823 
1824         /*
1825          * Check CSG
1826          */
1827         csg_req = ISCSI_LOGIN_CURRENT_STAGE(lh->flags);
1828         switch (csg_req) {
1829         case ISCSI_SECURITY_NEGOTIATION_STAGE:
1830         case ISCSI_OP_PARMS_NEGOTIATION_STAGE:


2709                 idm_status = IDM_STATUS_FAIL;
2710         }
2711         return (idm_status);
2712 }
2713 
2714 static char *
2715 iscsit_fold_name(char *name, size_t *buflen)
2716 {
2717         char            *ret;
2718         const char      *sns;
2719         int             errnum;
2720         int             flag = U8_TEXTPREP_NFKC;
2721         size_t          inlen, outlen, coff;
2722 
2723         if (name == NULL)
2724                 return (NULL);
2725 
2726         /* Check for one of the supported name types */
2727         if (strncasecmp(name, SNS_EUI ".", strlen(SNS_EUI) + 1) == 0) {
2728                 sns = SNS_EUI;
2729                 *buflen = SNS_EUI_U8_LEN_MAX + 1;
2730                 flag |= U8_TEXTPREP_TOUPPER;
2731         } else if (strncasecmp(name, SNS_IQN ".", strlen(SNS_IQN) + 1) == 0) {
2732                 sns = SNS_IQN;
2733                 *buflen = SNS_IQN_U8_LEN_MAX + 1;
2734                 flag |= U8_TEXTPREP_TOLOWER;
2735         } else if (strncasecmp(name, SNS_NAA ".", strlen(SNS_NAA) + 1) == 0) {
2736                 sns = SNS_NAA;
2737                 *buflen = SNS_NAA_U8_LEN_MAX + 1;
2738                 flag |= U8_TEXTPREP_TOUPPER;
2739         } else {
2740                 return (NULL);
2741         }
2742 
2743         ret = kmem_zalloc(*buflen, KM_SLEEP);
2744         coff = strlen(sns);
2745         inlen = strlen(name) - coff;
2746         outlen = *buflen - coff;
2747 
2748         /* Fold the case and normalize string */
2749         if (u8_textprep_str(name + coff, &inlen, ret + coff, &outlen, flag,
2750             U8_UNICODE_320, &errnum) == (size_t)-1) {
2751                 kmem_free(ret, *buflen);
2752                 return (NULL);
2753         }
2754 
2755         /* Copy the name type prefix */
2756         bcopy(sns, ret, coff);
2757 
2758         return (ret);
2759 }


  29 #include <sys/conf.h>
  30 #include <sys/file.h>
  31 #include <sys/ddi.h>
  32 #include <sys/sunddi.h>
  33 #include <sys/modctl.h>
  34 #include <sys/scsi/generic/persist.h>
  35 #include <sys/scsi/scsi_names.h>
  36 
  37 #include <sys/socket.h>
  38 #include <sys/strsubr.h>
  39 #include <sys/sysmacros.h>
  40 #include <sys/note.h>
  41 #include <sys/sdt.h>
  42 #include <sys/errno.h>
  43 
  44 #include <sys/stmf.h>
  45 #include <sys/stmf_ioctl.h>
  46 #include <sys/portif.h>
  47 #include <sys/idm/idm.h>
  48 #include <sys/idm/idm_text.h>
  49 #include <sys/idm/idm_so.h>
  50 
  51 #define ISCSIT_LOGIN_SM_STRINGS
  52 #include "iscsit.h"
  53 #include "iscsit_auth.h"
  54 
  55 typedef struct {
  56         list_node_t             le_ctx_node;
  57         iscsit_login_event_t    le_ctx_event;
  58         idm_pdu_t               *le_pdu;
  59 } login_event_ctx_t;
  60 
  61 #ifndef TRUE
  62 #define TRUE B_TRUE
  63 #endif
  64 
  65 #ifndef FALSE
  66 #define FALSE B_FALSE
  67 #endif
  68 
  69 #define DEFAULT_RADIUS_PORT     1812


 716 
 717         new_state = (new_state < ILS_MAX_STATE) ?
 718             new_state : ILS_UNDEFINED;
 719 
 720         IDM_SM_LOG(CE_NOTE, "login_sm_new_state: conn %p "
 721             "%s (%d) --> %s (%d)\n", (void *)ict->ict_ic,
 722             iscsit_ils_name[lsm->icl_login_state], lsm->icl_login_state,
 723             iscsit_ils_name[new_state], new_state);
 724 
 725         DTRACE_PROBE3(login__state__change,
 726             iscsit_conn_t *, ict, login_event_ctx_t *, ctx,
 727             iscsit_login_state_t, new_state);
 728 
 729         mutex_enter(&lsm->icl_mutex);
 730         idm_sm_audit_state_change(&lsm->icl_state_audit, SAS_ISCSIT_LOGIN,
 731             (int)lsm->icl_login_state, (int)new_state);
 732         lsm->icl_login_last_state = lsm->icl_login_state;
 733         lsm->icl_login_state = new_state;
 734         mutex_exit(&lsm->icl_mutex);
 735 
 736         /*
 737          * Tale of caution here. The use of new_state instead of using
 738          * lsm->icl_login_state is deliberate (which had been used originally).
 739          * Since the icl_mutex is dropped under the right circumstances
 740          * the login state changes between setting the state and examining
 741          * the state to proceed. No big surprise since the lock was being
 742          * used in the first place to prevent just that type of change.
 743          *
 744          * There has been a case where network errors occurred while a client
 745          * was attempting to reinstate the connection causing multiple
 746          * login packets to arrive into the state machine. Those multiple
 747          * packets which were processed incorrectly caused the reference
 748          * count on the connection to be one higher than it should be and
 749          * from then on the connection can't close correctly causing a hang.
 750          *
 751          * Upon examination of the core it was found that the connection
 752          * audit data had calls looking like:
 753          *    login_sm_event_dispatch
 754          *    login_sm_processing
 755          *    login_sm_new_state
 756          * That call sequence means the new state was/is ILS_LOGIN_ERROR
 757          * yet the audit trail continues with a call to
 758          *    login_sm_send_next_response
 759          * which could only occur if icl_login_state had changed. Had the
 760          * design of COMSTAR taken this into account the code would
 761          * originally have held the icl_mutex across the processing of the
 762          * state processing. Lock order and calls which sleep prevent that
 763          * from being possible. The next best solution is to use the local
 764          * variable which holds the state.
 765          */
 766         switch (new_state) {
 767         case ILS_LOGIN_WAITING:
 768                 /* Do nothing, waiting for more login PDU's */
 769                 break;
 770         case ILS_LOGIN_PROCESSING:
 771                 /* All login PDU's received, process login request */
 772                 login_sm_process_request(ict);
 773                 break;
 774         case ILS_LOGIN_RESPONDING:
 775                 rpdu = login_sm_build_login_response(ict);
 776                 login_sm_send_next_response(ict, rpdu);
 777                 break;
 778         case ILS_LOGIN_RESPONDED:
 779                 /* clean up the login response idm text buffer */
 780                 if (lsm->icl_login_resp_itb != NULL) {
 781                         idm_itextbuf_free(lsm->icl_login_resp_itb);
 782                         lsm->icl_login_resp_itb = NULL;
 783                 }
 784                 break;
 785         case ILS_LOGIN_FFP:
 786                 login_sm_ffp_actions(ict);


1762         } else if ((strcmp(auth, PA_AUTH_CHAP) == 0) &&
1763             (lsm->icl_auth.ca_ini_chapsecretlen == 0)) {
1764                 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_INITIATOR_ERR,
1765                     ISCSI_LOGIN_STATUS_AUTH_FAILED);
1766                 idmrc = IDM_STATUS_FAIL;
1767         }
1768 
1769         ISCSIT_GLOBAL_UNLOCK();
1770 
1771         return (idmrc);
1772 }
1773 
1774 
1775 static idm_status_t
1776 login_sm_session_register(iscsit_conn_t *ict)
1777 {
1778         iscsit_sess_t           *ist = ict->ict_sess;
1779         stmf_scsi_session_t     *ss;
1780         iscsi_transport_id_t    *iscsi_tptid;
1781         uint16_t                ident_len, adn_len, tptid_sz;
1782         char                    prop_buf[KSTAT_STRLEN + 1];
1783         char                    peer_buf[IDM_SA_NTOP_BUFSIZ];
1784 
1785         /*
1786          * Hold target mutex until we have finished registering with STMF
1787          */
1788         mutex_enter(&ist->ist_tgt->target_mutex);
1789         if (ist->ist_tgt->target_state != TS_STMF_ONLINE) {
1790                 mutex_exit(&ist->ist_tgt->target_mutex);
1791                 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_INITIATOR_ERR,
1792                     ISCSI_LOGIN_STATUS_TGT_REMOVED);
1793                 return (IDM_STATUS_FAIL);
1794         }
1795 
1796         ss = stmf_alloc(STMF_STRUCT_SCSI_SESSION, 0,
1797             0);
1798         if (ss == NULL) {
1799                 mutex_exit(&ist->ist_tgt->target_mutex);
1800                 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_TARGET_ERR,
1801                     ISCSI_LOGIN_STATUS_NO_RESOURCES);
1802                 return (IDM_STATUS_FAIL);
1803         }


1824             ist->ist_initiator_name, ident_len);
1825 
1826         ss->ss_lport = ist->ist_lport;
1827 
1828         if (stmf_register_scsi_session(ict->ict_sess->ist_lport, ss) !=
1829             STMF_SUCCESS) {
1830                 mutex_exit(&ist->ist_tgt->target_mutex);
1831                 kmem_free(ss->ss_rport_id,
1832                     sizeof (scsi_devid_desc_t) +
1833                     strlen(ist->ist_initiator_name) + 1);
1834                 stmf_remote_port_free(ss->ss_rport);
1835                 stmf_free(ss);
1836                 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_TARGET_ERR,
1837                     ISCSI_LOGIN_STATUS_TARGET_ERROR);
1838                 return (IDM_STATUS_FAIL);
1839         }
1840 
1841         ss->ss_port_private = ict->ict_sess;
1842         ict->ict_sess->ist_stmf_sess = ss;
1843         mutex_exit(&ist->ist_tgt->target_mutex);
1844         (void) snprintf(prop_buf, sizeof (prop_buf), "peername_%"PRIxPTR"",
1845             (uintptr_t)ict->ict_sess);
1846         (void) idm_sa_ntop(&ict->ict_ic->ic_raddr, peer_buf,
1847             sizeof (peer_buf));
1848         (void) stmf_add_rport_info(ss, prop_buf, peer_buf);
1849 
1850         return (IDM_STATUS_SUCCESS);
1851 }
1852 
1853 
1854 static idm_status_t
1855 login_sm_req_pdu_check(iscsit_conn_t *ict, idm_pdu_t *pdu)
1856 {
1857         uint8_t                 csg_req;
1858         iscsit_conn_login_t     *lsm = &ict->ict_login_sm;
1859         iscsi_login_hdr_t       *lh = (iscsi_login_hdr_t *)pdu->isp_hdr;
1860         iscsi_login_rsp_hdr_t *lh_resp = lsm->icl_login_resp_tmpl;
1861 
1862         /*
1863          * Check CSG
1864          */
1865         csg_req = ISCSI_LOGIN_CURRENT_STAGE(lh->flags);
1866         switch (csg_req) {
1867         case ISCSI_SECURITY_NEGOTIATION_STAGE:
1868         case ISCSI_OP_PARMS_NEGOTIATION_STAGE:


2747                 idm_status = IDM_STATUS_FAIL;
2748         }
2749         return (idm_status);
2750 }
2751 
2752 static char *
2753 iscsit_fold_name(char *name, size_t *buflen)
2754 {
2755         char            *ret;
2756         const char      *sns;
2757         int             errnum;
2758         int             flag = U8_TEXTPREP_NFKC;
2759         size_t          inlen, outlen, coff;
2760 
2761         if (name == NULL)
2762                 return (NULL);
2763 
2764         /* Check for one of the supported name types */
2765         if (strncasecmp(name, SNS_EUI ".", strlen(SNS_EUI) + 1) == 0) {
2766                 sns = SNS_EUI;
2767                 *buflen = SNS_EUI_LEN_MAX + 1;
2768                 flag |= U8_TEXTPREP_TOUPPER;
2769         } else if (strncasecmp(name, SNS_IQN ".", strlen(SNS_IQN) + 1) == 0) {
2770                 sns = SNS_IQN;
2771                 *buflen = SNS_IQN_LEN_MAX + 1;
2772                 flag |= U8_TEXTPREP_TOLOWER;
2773         } else if (strncasecmp(name, SNS_NAA ".", strlen(SNS_NAA) + 1) == 0) {
2774                 sns = SNS_NAA;
2775                 *buflen = SNS_NAA_LEN_MAX + 1;
2776                 flag |= U8_TEXTPREP_TOUPPER;
2777         } else {
2778                 return (NULL);
2779         }
2780 
2781         ret = kmem_zalloc(*buflen, KM_SLEEP);
2782         coff = strlen(sns);
2783         inlen = strlen(name) - coff;
2784         outlen = *buflen - coff - 1;
2785 
2786         /* Fold the case and normalize string */
2787         if (u8_textprep_str(name + coff, &inlen, ret + coff, &outlen, flag,
2788             U8_UNICODE_320, &errnum) == (size_t)-1) {
2789                 kmem_free(ret, *buflen);
2790                 return (NULL);
2791         }
2792 
2793         /* Copy the name type prefix */
2794         bcopy(sns, ret, coff);
2795 
2796         return (ret);
2797 }