Mercurial > illumos > illumos-gate
changeset 10261:f3fec2334981
6740060 iscsit does not send or handle MaxRecvDataSegmentLength key properly
6862789 memory leak in stmfGetSessionList()
author | Charles Ting <Charles.Ting@Sun.COM> |
---|---|
date | Wed, 05 Aug 2009 15:31:33 -0400 |
parents | 2896314db48b |
children | f0a682e100e9 |
files | usr/src/lib/libstmf/common/stmf.c usr/src/uts/common/io/comstar/port/iscsit/iscsit.h usr/src/uts/common/io/comstar/port/iscsit/iscsit_login.c usr/src/uts/common/io/ib/clients/iser/iser_idm.c usr/src/uts/common/io/idm/idm.c usr/src/uts/common/io/idm/idm_so.c usr/src/uts/common/sys/idm/idm.h usr/src/uts/common/sys/idm/idm_impl.h usr/src/uts/common/sys/idm/idm_transport.h |
diffstat | 9 files changed, 206 insertions(+), 22 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/lib/libstmf/common/stmf.c Wed Aug 05 11:20:52 2009 -0700 +++ b/usr/src/lib/libstmf/common/stmf.c Wed Aug 05 15:31:33 2009 -0400 @@ -3541,7 +3541,7 @@ int cmd = STMF_IOCTL_SESSION_LIST; int i; stmf_iocdata_t stmfIoctl; - slist_scsi_session_t *fSessionList; + slist_scsi_session_t *fSessionList, *fSessionListP = NULL; uint8_t ident[260]; uint32_t fSessionListSize; @@ -3567,8 +3567,10 @@ fSessionListSize = ALLOC_SESSION; fSessionListSize = fSessionListSize * (sizeof (slist_scsi_session_t)); fSessionList = (slist_scsi_session_t *)calloc(1, fSessionListSize); + fSessionListP = fSessionList; if (fSessionList == NULL) { - return (STMF_ERROR_NOMEM); + ret = STMF_ERROR_NOMEM; + goto done; } ident[IDENT_LENGTH_BYTE] = devid->identLength; @@ -3611,8 +3613,10 @@ sizeof (slist_scsi_session_t); fSessionList = realloc(fSessionList, fSessionListSize); if (fSessionList == NULL) { - return (STMF_ERROR_NOMEM); + ret = STMF_ERROR_NOMEM; + goto done; } + fSessionListP = fSessionList; stmfIoctl.stmf_obuf_size = fSessionListSize; stmfIoctl.stmf_obuf = (uint64_t)(unsigned long)fSessionList; ioctlRet = ioctl(fd, cmd, &stmfIoctl); @@ -3667,6 +3671,7 @@ } done: (void) close(fd); + free(fSessionListP); return (ret); }
--- a/usr/src/uts/common/io/comstar/port/iscsit/iscsit.h Wed Aug 05 11:20:52 2009 -0700 +++ b/usr/src/uts/common/io/comstar/port/iscsit/iscsit.h Wed Aug 05 15:31:33 2009 -0400 @@ -44,6 +44,7 @@ #define ISCSIT_MAX_TIME2RETAIN ISCSI_DEFAULT_TIME_TO_RETAIN #define ISCSIT_MAX_OUTSTANDING_R2T ISCSI_DEFAULT_MAX_OUT_R2T #define ISCSIT_MAX_ERROR_RECOVERY_LEVEL 0 +#define ISCSIT_MAX_OUTSTANDING_UNEXPECTED_PDUS 0 #define ISCSIT_DEFAULT_TPG "iscsit-default-tpg" #define ISCSIT_DEFAULT_TPGT 1
--- a/usr/src/uts/common/io/comstar/port/iscsit/iscsit_login.c Wed Aug 05 11:20:52 2009 -0700 +++ b/usr/src/uts/common/io/comstar/port/iscsit/iscsit_login.c Wed Aug 05 15:31:33 2009 -0400 @@ -189,6 +189,11 @@ static void login_resp_complete_cb(idm_pdu_t *pdu, idm_status_t status); +static idm_status_t +iscsit_add_declarative_keys(iscsit_conn_t *ict); + +uint64_t max_dataseglen_target = ISCSIT_MAX_RECV_DATA_SEGMENT_LENGTH; + idm_status_t iscsit_login_sm_init(iscsit_conn_t *ict) { @@ -1000,6 +1005,10 @@ (void) iscsit_reply_numerical(ict, "TargetPortalGroupTag", (uint64_t)lsm->icl_tpgt_tag); + if (iscsit_add_declarative_keys(ict) != + IDM_STATUS_SUCCESS) { + goto request_fail; + } } ict->ict_op.op_initial_params_set = B_TRUE; @@ -2261,11 +2270,12 @@ ISCSI_MAX_CONNECTIONS, ISCSIT_MAX_CONNECTIONS); break; + /* this is a declartive param */ case KI_MAX_RECV_DATA_SEGMENT_LENGTH: kvrc = iscsit_handle_numerical(ict, nvp, num_val, ikvx, ISCSI_MIN_RECV_DATA_SEGMENT_LENGTH, ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH, - ISCSIT_MAX_RECV_DATA_SEGMENT_LENGTH); + ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH); break; case KI_MAX_BURST_LENGTH: kvrc = iscsit_handle_numerical(ict, nvp, num_val, ikvx, @@ -2412,22 +2422,27 @@ kv_status_t kvrc; int nvrc; - if (value != iscsit_value) { - /* Respond back to initiator with our value */ - value = iscsit_value; - lsm->icl_login_transit = B_FALSE; - nvrc = 0; + if (ikvx->ik_declarative) { + nvrc = nvlist_add_nvpair(lsm->icl_negotiated_values, nvp); } else { - /* Add this to our negotiated values */ - nvrc = nvlist_add_nvpair(lsm->icl_negotiated_values, - nvp); + if (value != iscsit_value) { + /* Respond back to initiator with our value */ + value = iscsit_value; + lsm->icl_login_transit = B_FALSE; + nvrc = 0; + } else { + /* Add this to our negotiated values */ + nvrc = nvlist_add_nvpair(lsm->icl_negotiated_values, + nvp); + } + + /* Response of Simple-value Negotiation */ + if (nvrc == 0) { + nvrc = nvlist_add_boolean_value( + lsm->icl_response_nvlist, ikvx->ik_key_name, value); + } } - /* Response of Simple-value Negotiation */ - if (nvrc == 0 && !ikvx->ik_declarative) { - nvrc = nvlist_add_boolean_value( - lsm->icl_response_nvlist, ikvx->ik_key_name, value); - } kvrc = idm_nvstat_to_kvstat(nvrc); return (kvrc); @@ -2446,6 +2461,9 @@ /* Validate against standard */ if ((value < iscsi_min_value) || (value > iscsi_max_value)) { kvrc = KV_VALUE_ERROR; + } else if (ikvx->ik_declarative) { + nvrc = nvlist_add_nvpair(lsm->icl_negotiated_values, nvp); + kvrc = idm_nvstat_to_kvstat(nvrc); } else { if (value > iscsit_max_value) { /* Respond back to initiator with our value */ @@ -2459,7 +2477,7 @@ } /* Response of Simple-value Negotiation */ - if (nvrc == 0 && !ikvx->ik_declarative) { + if (nvrc == 0) { nvrc = nvlist_add_uint64(lsm->icl_response_nvlist, ikvx->ik_key_name, value); } @@ -2577,3 +2595,44 @@ ict->ict_op.op_error_recovery_level = uint64_val; } } + +static idm_status_t +iscsit_add_declarative_keys(iscsit_conn_t *ict) +{ + nvlist_t *cfg_nv = NULL; + kv_status_t kvrc; + int nvrc; + iscsit_conn_login_t *lsm = &ict->ict_login_sm; + uint8_t error_class; + uint8_t error_detail; + idm_status_t idm_status; + + if ((nvrc = nvlist_alloc(&cfg_nv, NV_UNIQUE_NAME, KM_NOSLEEP)) != 0) { + kvrc = idm_nvstat_to_kvstat(nvrc); + goto alloc_fail; + } + if ((nvrc = nvlist_add_uint64(cfg_nv, "MaxRecvDataSegmentLength", + max_dataseglen_target)) != 0) { + kvrc = idm_nvstat_to_kvstat(nvrc); + goto done; + } + if ((nvrc = nvlist_add_uint64(cfg_nv, "MaxOutstandingUnexpectedPDUs", + ISCSIT_MAX_OUTSTANDING_UNEXPECTED_PDUS)) != 0) { + kvrc = idm_nvstat_to_kvstat(nvrc); + goto done; + } + + kvrc = idm_declare_key_values(ict->ict_ic, cfg_nv, + lsm->icl_response_nvlist); +done: + nvlist_free(cfg_nv); +alloc_fail: + idm_kvstat_to_error(kvrc, &error_class, &error_detail); + if (error_class == ISCSI_STATUS_CLASS_SUCCESS) { + idm_status = IDM_STATUS_SUCCESS; + } else { + SET_LOGIN_ERROR(ict, error_class, error_detail); + idm_status = IDM_STATUS_FAIL; + } + return (idm_status); +}
--- a/usr/src/uts/common/io/ib/clients/iser/iser_idm.c Wed Aug 05 11:20:52 2009 -0700 +++ b/usr/src/uts/common/io/ib/clients/iser/iser_idm.c Wed Aug 05 15:31:33 2009 -0400 @@ -48,6 +48,8 @@ static idm_status_t iser_ini_enable_datamover(idm_conn_t *ic); static void iser_notice_key_values(struct idm_conn_s *ic, nvlist_t *negotiated_nvl); +static kv_status_t iser_declare_key_values(struct idm_conn_s *ic, + nvlist_t *config_nvl, nvlist_t *outgoing_nvl); static idm_status_t iser_free_task_rsrcs(idm_task_t *idt); static kv_status_t iser_negotiate_key_values(idm_conn_t *ic, nvlist_t *request_nvl, nvlist_t *response_nvl, nvlist_t *negotiated_nvl); @@ -114,7 +116,8 @@ &iser_ini_conn_create, /* it_ini_conn_create */ &iser_conn_destroy, /* it_ini_conn_destroy */ &iser_ini_conn_connect, /* it_ini_conn_connect */ - &iser_conn_disconnect /* it_ini_conn_disconnect */ + &iser_conn_disconnect, /* it_ini_conn_disconnect */ + &iser_declare_key_values /* it_declare_key_values */ }; /* @@ -841,6 +844,31 @@ } /* + * iser_declare_key_values() declares the declarative key values for + * this connection. + */ +/* ARGSUSED */ +static kv_status_t +iser_declare_key_values(idm_conn_t *ic, nvlist_t *config_nvl, + nvlist_t *outgoing_nvl) +{ + kv_status_t kvrc; + int nvrc; + uint64_t uint64_val; + + if ((nvrc = nvlist_lookup_uint64(config_nvl, + ISER_KV_KEY_NAME_MAX_OUTSTANDING_PDU, &uint64_val)) != ENOENT) { + ASSERT(nvrc == 0); + if (outgoing_nvl) { + nvrc = nvlist_add_uint64(outgoing_nvl, + ISER_KV_KEY_NAME_MAX_OUTSTANDING_PDU, uint64_val); + } + } + kvrc = idm_nvstat_to_kvstat(nvrc); + return (kvrc); +} + +/* * iser_notice_key_values() activates the negotiated key values for * this connection. */
--- a/usr/src/uts/common/io/idm/idm.c Wed Aug 05 11:20:52 2009 -0700 +++ b/usr/src/uts/common/io/idm/idm.c Wed Aug 05 15:31:33 2009 -0400 @@ -656,6 +656,20 @@ } /* + * idm_declare_key_values() + * Activate an operational set of declarative parameters from the config_nvl, + * and return the selected values in the outgoing_nvl. + */ +kv_status_t +idm_declare_key_values(idm_conn_t *ic, nvlist_t *config_nvl, + nvlist_t *outgoing_nvl) +{ + ASSERT(ic->ic_transport_ops != NULL); + return (ic->ic_transport_ops->it_declare_key_values(ic, config_nvl, + outgoing_nvl)); +} + +/* * idm_buf_tx_to_ini * * This is IDM's implementation of the 'Put_Data' operational primitive.
--- a/usr/src/uts/common/io/idm/idm_so.c Wed Aug 05 11:20:52 2009 -0700 +++ b/usr/src/uts/common/io/idm/idm_so.c Wed Aug 05 15:31:33 2009 -0400 @@ -46,6 +46,7 @@ #include <net/if.h> #include <sys/sockio.h> #include <sys/ksocket.h> +#include <sys/iscsi_protocol.h> #include <sys/idm/idm.h> #include <sys/idm/idm_so.h> #include <sys/idm/idm_text.h> @@ -101,6 +102,8 @@ nvlist_t *request_nvl, nvlist_t *response_nvl, nvlist_t *negotiated_nvl); static void idm_so_notice_key_values(idm_conn_t *it, nvlist_t *negotiated_nvl); +static kv_status_t idm_so_declare_key_values(idm_conn_t *it, + nvlist_t *config_nvl, nvlist_t *outgoing_nvl); static boolean_t idm_so_conn_is_capable(idm_conn_req_t *ic, idm_transport_caps_t *caps); static idm_status_t idm_so_buf_alloc(idm_buf_t *idb, uint64_t buflen); @@ -152,7 +155,8 @@ idm_so_ini_conn_create, /* it_ini_conn_create */ idm_so_ini_conn_destroy, /* it_ini_conn_destroy */ idm_so_ini_conn_connect, /* it_ini_conn_connect */ - idm_so_conn_disconnect /* it_ini_conn_disconnect */ + idm_so_conn_disconnect, /* it_ini_conn_disconnect */ + idm_so_declare_key_values /* it_declare_key_values */ }; /* @@ -760,6 +764,12 @@ pdu->isp_hdrlen = sizeof (iscsi_hdr_t) + (bhs->hlength * sizeof (uint32_t)); pdu->isp_datalen = n2h24(bhs->dlength); + if (ic->ic_conn_type == CONN_TYPE_TGT && + pdu->isp_datalen > ic->ic_conn_params.max_recv_dataseglen) { + IDM_CONN_LOG(CE_WARN, + "idm_sorecvhdr: exceeded the max data segment length"); + return (IDM_STATUS_FAIL); + } if (bhs->hlength > IDM_SORX_CACHE_AHSLEN) { /* Allocate a new header segment and change the callback */ new_hdr = kmem_alloc(pdu->isp_hdrlen, KM_SLEEP); @@ -985,6 +995,10 @@ /* Set the scoreboarding flag on this connection */ ic->ic_conn_flags |= IDM_CONN_USE_SCOREBOARD; + ic->ic_conn_params.max_recv_dataseglen = + ISCSI_DEFAULT_MAX_RECV_SEG_LEN; + ic->ic_conn_params.max_xmit_dataseglen = + ISCSI_DEFAULT_MAX_XMIT_SEG_LEN; /* * Initialize tx thread mutex and list @@ -1380,6 +1394,7 @@ int nvrc; idm_status_t idm_status; const idm_kv_xlate_t *ikvx; + uint64_t num_val; for (nvp = nvlist_next_nvpair(negotiated_nvl, NULL); nvp != NULL; nvp = next_nvp) { @@ -1398,12 +1413,64 @@ negotiated_nvl, ikvx->ik_key_name); ASSERT(nvrc == 0); break; + case KI_MAX_RECV_DATA_SEGMENT_LENGTH: + /* + * Just pass the value down to idm layer. + * No need to remove it from negotiated_nvl list here. + */ + nvrc = nvpair_value_uint64(nvp, &num_val); + ASSERT(nvrc == 0); + it->ic_conn_params.max_xmit_dataseglen = + (uint32_t)num_val; + break; default: break; } } } +/* + * idm_so_declare_key_values() declares the key values for this connection + */ +/* ARGSUSED */ +static kv_status_t +idm_so_declare_key_values(idm_conn_t *it, nvlist_t *config_nvl, + nvlist_t *outgoing_nvl) +{ + char *nvp_name; + nvpair_t *nvp; + nvpair_t *next_nvp; + kv_status_t kvrc; + int nvrc = 0; + const idm_kv_xlate_t *ikvx; + uint64_t num_val; + + for (nvp = nvlist_next_nvpair(config_nvl, NULL); + nvp != NULL && nvrc == 0; nvp = next_nvp) { + next_nvp = nvlist_next_nvpair(config_nvl, nvp); + nvp_name = nvpair_name(nvp); + + ikvx = idm_lookup_kv_xlate(nvp_name, strlen(nvp_name)); + switch (ikvx->ik_key_id) { + case KI_MAX_RECV_DATA_SEGMENT_LENGTH: + if ((nvrc = nvpair_value_uint64(nvp, &num_val)) != 0) { + break; + } + if (outgoing_nvl && + (nvrc = nvlist_add_uint64(outgoing_nvl, + nvp_name, num_val)) != 0) { + break; + } + it->ic_conn_params.max_recv_dataseglen = + (uint32_t)num_val; + break; + default: + break; + } + } + kvrc = idm_nvstat_to_kvstat(nvrc); + return (kvrc); +} static idm_status_t idm_so_handle_digest(idm_conn_t *it, nvpair_t *digest_choice, @@ -2489,7 +2556,7 @@ ic = idt->idt_ic; - max_dataseglen = 8192; /* Need value from login negotiation */ + max_dataseglen = ic->ic_conn_params.max_xmit_dataseglen; remainder = buf_region_length; while (remainder) {
--- a/usr/src/uts/common/sys/idm/idm.h Wed Aug 05 11:20:52 2009 -0700 +++ b/usr/src/uts/common/sys/idm/idm.h Wed Aug 05 15:31:33 2009 -0400 @@ -380,6 +380,10 @@ void idm_notice_key_values(idm_conn_t *ic, nvlist_t *negotiated_nvl); +kv_status_t +idm_declare_key_values(idm_conn_t *ic, nvlist_t *config_nvl, + nvlist_t *outgoing_nvl); + /* * Buffer services */
--- a/usr/src/uts/common/sys/idm/idm_impl.h Wed Aug 05 11:20:52 2009 -0700 +++ b/usr/src/uts/common/sys/idm/idm_impl.h Wed Aug 05 15:31:33 2009 -0400 @@ -122,7 +122,8 @@ * connection create, or during key-value negotiation at login */ typedef struct idm_conn_params_s { - uint32_t max_dataseglen; + uint32_t max_recv_dataseglen; + uint32_t max_xmit_dataseglen; uint32_t conn_login_max; uint32_t conn_login_interval; boolean_t nonblock_socket;
--- a/usr/src/uts/common/sys/idm/idm_transport.h Wed Aug 05 11:20:52 2009 -0700 +++ b/usr/src/uts/common/sys/idm/idm_transport.h Wed Aug 05 15:31:33 2009 -0400 @@ -109,6 +109,10 @@ typedef void (transport_notice_key_values_op_t)(struct idm_conn_s *ic, nvlist_t *negotiated_nvl); +/* Declare the declarative key value pairs */ +typedef kv_status_t (transport_declare_key_values_op_t)(struct idm_conn_s *ic, + nvlist_t *config_nvl, nvlist_t *outgoing_nvl); + /* Transport capability probe */ typedef boolean_t (transport_conn_is_capable_op_t)(idm_conn_req_t *ic, struct idm_transport_caps_s *caps); @@ -178,6 +182,7 @@ transport_ini_conn_destroy_op_t *it_ini_conn_destroy; transport_ini_conn_connect_op_t *it_ini_conn_connect; transport_ini_conn_disconnect_op_t *it_ini_conn_disconnect; + transport_declare_key_values_op_t *it_declare_key_values; } idm_transport_ops_t; /*