498
499 iscsit_global.global_isns_cfg.isns_state = B_FALSE;
500 list_create(&iscsit_global.global_isns_cfg.isns_svrs,
501 sizeof (iscsit_isns_svr_t), offsetof(iscsit_isns_svr_t, svr_ln));
502 avl_create(&isns_tpg_portals, isnst_portal_avl_compare,
503 sizeof (isns_portal_t), offsetof(isns_portal_t, portal_node));
504 avl_create(&isns_all_portals, isnst_portal_avl_compare,
505 sizeof (isns_portal_t), offsetof(isns_portal_t, portal_node));
506 num_default_portals = 0;
507 if (hostinfo->length > ISCSIT_MAX_HOSTNAME_LEN)
508 hostinfo->length = ISCSIT_MAX_HOSTNAME_LEN;
509 isns_eid = kmem_alloc(hostinfo->length, KM_SLEEP);
510 (void) strlcpy(isns_eid, hostinfo->fqhn, hostinfo->length);
511 avl_create(&isns_target_list, isnst_tgt_avl_compare,
512 sizeof (isns_target_t), offsetof(isns_target_t, target_node));
513
514 /* initialize isns client */
515 mutex_init(&isns_monitor_mutex, NULL, MUTEX_DEFAULT, NULL);
516 mutex_init(&esi.esi_mutex, NULL, MUTEX_DEFAULT, NULL);
517 isns_monitor_thr_id = NULL;
518 monitor_idle_interval = ISNS_IDLE_TIME * drv_usectohz(1000000);
519 cv_init(&isns_idle_cv, NULL, CV_DEFAULT, NULL);
520 cv_init(&esi.esi_cv, NULL, CV_DEFAULT, NULL);
521 xid = 0;
522 ISNS_GLOBAL_UNLOCK();
523
524 return (0);
525 }
526
527 void
528 iscsit_isns_fini()
529 {
530 ISNS_GLOBAL_LOCK();
531
532 /*
533 * The following call to iscsit_set_isns waits until all the
534 * iSNS servers have been fully deactivated and the monitor and esi
535 * threads have stopped.
536 */
537 iscsit_set_isns(B_FALSE);
538
1061
1062 /*
1063 * isnst_monitor -- the monitor thread for iSNS
1064 */
1065 /*ARGSUSED*/
1066 static void
1067 isnst_monitor(void *arg)
1068 {
1069 mutex_enter(&isns_monitor_mutex);
1070 isns_monitor_thr_did = curthread->t_did;
1071 isns_monitor_thr_running = B_TRUE;
1072 cv_signal(&isns_idle_cv);
1073
1074 /*
1075 * Start with a short pause (5 sec) to allow all targets
1076 * to be registered before we send register-all. This is
1077 * purely an optimization to cut down on the number of
1078 * messages we send to the iSNS server.
1079 */
1080 mutex_exit(&isns_monitor_mutex);
1081 delay(drv_usectohz(isns_initial_delay * 1000000));
1082 mutex_enter(&isns_monitor_mutex);
1083
1084 /* Force an initialization of isns_all_portals */
1085 mutex_enter(&iscsit_isns_mutex);
1086 isns_portals_changed = B_TRUE;
1087 mutex_exit(&iscsit_isns_mutex);
1088
1089 while (isns_monitor_thr_running) {
1090
1091 /* Update servers */
1092 mutex_exit(&isns_monitor_mutex);
1093 isnst_monitor_all_servers();
1094 mutex_enter(&isns_monitor_mutex);
1095
1096 /* If something needs attention, go right to the top */
1097 mutex_enter(&iscsit_isns_mutex);
1098 if (isns_targets_changed || isns_portals_changed) {
1099 DTRACE_PROBE(iscsit__isns__monitor__reenter);
1100 mutex_exit(&iscsit_isns_mutex);
1101 /* isns_monitor_mutex still held */
2857 /* receive the pdu header */
2858 rcv_timer = timeout(isnst_so_timeout, so,
2859 drv_usectohz(isns_timeout_usec));
2860 if (idm_sorecv(so, &tmp_pdu_hdr, ISNSP_HEADER_SIZE) != 0 ||
2861 ntohs(tmp_pdu_hdr.seq) != seq) {
2862 (void) untimeout(rcv_timer);
2863 goto rcv_error;
2864 }
2865 (void) untimeout(rcv_timer);
2866
2867 /* receive the payload */
2868 payload_len = ntohs(tmp_pdu_hdr.payload_len);
2869 if (payload_len > ISNST_MAX_MSG_SIZE) {
2870 goto rcv_error;
2871 }
2872 payload = kmem_alloc(payload_len, KM_NOSLEEP);
2873 if (payload == NULL) {
2874 goto rcv_error;
2875 }
2876 rcv_timer = timeout(isnst_so_timeout, so,
2877 drv_usectohz(ISNS_RCV_TIMER_SECONDS * 1000000));
2878 if (idm_sorecv(so, payload, payload_len) != 0) {
2879 (void) untimeout(rcv_timer);
2880 goto rcv_error;
2881 }
2882 (void) untimeout(rcv_timer);
2883
2884 /* combine the pdu if it is not the first one */
2885 if (total_pdu_len > 0) {
2886 combined_len = total_pdu_len + payload_len;
2887 combined_pdu = kmem_alloc(combined_len, KM_SLEEP);
2888 if (combined_pdu == NULL) {
2889 goto rcv_error;
2890 }
2891 bcopy(*pdu, combined_pdu, total_pdu_len);
2892 combined_payload =
2893 &combined_pdu->payload[total_payload_len];
2894 bcopy(payload, combined_payload, payload_len);
2895 kmem_free(*pdu, total_pdu_len);
2896 kmem_free(payload, payload_len);
2897 *pdu = combined_pdu;
3068
3069 esi.esi_thread_did = curthread->t_did;
3070
3071 mutex_enter(&esi.esi_mutex);
3072
3073 /*
3074 * Mark the thread as running and the portal as no longer new.
3075 */
3076 esi.esi_thread_running = B_TRUE;
3077 cv_signal(&esi.esi_cv);
3078
3079 while (esi.esi_enabled) {
3080 /*
3081 * Create a socket to listen for requests from the iSNS server.
3082 */
3083 if ((esi.esi_so = idm_socreate(PF_INET6, SOCK_STREAM, 0)) ==
3084 NULL) {
3085 ISNST_LOG(CE_WARN,
3086 "isnst_esi_thread: Unable to create socket");
3087 mutex_exit(&esi.esi_mutex);
3088 delay(drv_usectohz(1000000));
3089 mutex_enter(&esi.esi_mutex);
3090 continue;
3091 }
3092
3093 /*
3094 * Set options, bind, and listen until we're told to stop
3095 */
3096 bzero(&sin6, sizeof (sin6));
3097 sin6.sin6_family = AF_INET6;
3098 sin6.sin6_port = htons(0);
3099 sin6.sin6_addr = in6addr_any;
3100
3101 (void) ksocket_setsockopt(esi.esi_so, SOL_SOCKET,
3102 SO_REUSEADDR, (char *)&on, sizeof (on), CRED());
3103
3104 if (ksocket_bind(esi.esi_so, (struct sockaddr *)&sin6,
3105 sizeof (sin6), CRED()) != 0) {
3106 ISNST_LOG(CE_WARN, "Unable to bind socket for ESI");
3107 idm_sodestroy(esi.esi_so);
3108 mutex_exit(&esi.esi_mutex);
3109 delay(drv_usectohz(1000000));
3110 mutex_enter(&esi.esi_mutex);
3111 continue;
3112 }
3113
3114 /*
3115 * Get the port (sin6 is meaningless at this point)
3116 */
3117 (void) ksocket_getsockname(esi.esi_so,
3118 (struct sockaddr *)(&sin6), &sin_addrlen, CRED());
3119 esi.esi_port =
3120 ntohs(((struct sockaddr_in6 *)(&sin6))->sin6_port);
3121
3122 if ((rc = ksocket_listen(esi.esi_so, 5, CRED())) != 0) {
3123 ISNST_LOG(CE_WARN, "isnst_esi_thread: listen "
3124 "failure 0x%x", rc);
3125 idm_sodestroy(esi.esi_so);
3126 mutex_exit(&esi.esi_mutex);
3127 delay(drv_usectohz(1000000));
3128 mutex_enter(&esi.esi_mutex);
3129 continue;
3130 }
3131
3132 ksocket_hold(esi.esi_so);
3133 esi.esi_valid = B_TRUE;
3134 while (esi.esi_enabled) {
3135 mutex_exit(&esi.esi_mutex);
3136
3137 DTRACE_PROBE3(iscsit__isns__esi__accept__wait,
3138 boolean_t, esi.esi_enabled,
3139 ksocket_t, esi.esi_so,
3140 struct sockaddr_in6, &sin6);
3141 if ((rc = ksocket_accept(esi.esi_so, NULL, NULL,
3142 &newso, CRED())) != 0) {
3143 mutex_enter(&esi.esi_mutex);
3144 DTRACE_PROBE2(iscsit__isns__esi__accept__fail,
3145 int, rc, boolean_t, esi.esi_enabled);
3146 /*
3147 * If we were interrupted with EINTR
|
498
499 iscsit_global.global_isns_cfg.isns_state = B_FALSE;
500 list_create(&iscsit_global.global_isns_cfg.isns_svrs,
501 sizeof (iscsit_isns_svr_t), offsetof(iscsit_isns_svr_t, svr_ln));
502 avl_create(&isns_tpg_portals, isnst_portal_avl_compare,
503 sizeof (isns_portal_t), offsetof(isns_portal_t, portal_node));
504 avl_create(&isns_all_portals, isnst_portal_avl_compare,
505 sizeof (isns_portal_t), offsetof(isns_portal_t, portal_node));
506 num_default_portals = 0;
507 if (hostinfo->length > ISCSIT_MAX_HOSTNAME_LEN)
508 hostinfo->length = ISCSIT_MAX_HOSTNAME_LEN;
509 isns_eid = kmem_alloc(hostinfo->length, KM_SLEEP);
510 (void) strlcpy(isns_eid, hostinfo->fqhn, hostinfo->length);
511 avl_create(&isns_target_list, isnst_tgt_avl_compare,
512 sizeof (isns_target_t), offsetof(isns_target_t, target_node));
513
514 /* initialize isns client */
515 mutex_init(&isns_monitor_mutex, NULL, MUTEX_DEFAULT, NULL);
516 mutex_init(&esi.esi_mutex, NULL, MUTEX_DEFAULT, NULL);
517 isns_monitor_thr_id = NULL;
518 monitor_idle_interval = drv_sectohz(ISNS_IDLE_TIME);
519 cv_init(&isns_idle_cv, NULL, CV_DEFAULT, NULL);
520 cv_init(&esi.esi_cv, NULL, CV_DEFAULT, NULL);
521 xid = 0;
522 ISNS_GLOBAL_UNLOCK();
523
524 return (0);
525 }
526
527 void
528 iscsit_isns_fini()
529 {
530 ISNS_GLOBAL_LOCK();
531
532 /*
533 * The following call to iscsit_set_isns waits until all the
534 * iSNS servers have been fully deactivated and the monitor and esi
535 * threads have stopped.
536 */
537 iscsit_set_isns(B_FALSE);
538
1061
1062 /*
1063 * isnst_monitor -- the monitor thread for iSNS
1064 */
1065 /*ARGSUSED*/
1066 static void
1067 isnst_monitor(void *arg)
1068 {
1069 mutex_enter(&isns_monitor_mutex);
1070 isns_monitor_thr_did = curthread->t_did;
1071 isns_monitor_thr_running = B_TRUE;
1072 cv_signal(&isns_idle_cv);
1073
1074 /*
1075 * Start with a short pause (5 sec) to allow all targets
1076 * to be registered before we send register-all. This is
1077 * purely an optimization to cut down on the number of
1078 * messages we send to the iSNS server.
1079 */
1080 mutex_exit(&isns_monitor_mutex);
1081 delay(drv_sectohz(isns_initial_delay));
1082 mutex_enter(&isns_monitor_mutex);
1083
1084 /* Force an initialization of isns_all_portals */
1085 mutex_enter(&iscsit_isns_mutex);
1086 isns_portals_changed = B_TRUE;
1087 mutex_exit(&iscsit_isns_mutex);
1088
1089 while (isns_monitor_thr_running) {
1090
1091 /* Update servers */
1092 mutex_exit(&isns_monitor_mutex);
1093 isnst_monitor_all_servers();
1094 mutex_enter(&isns_monitor_mutex);
1095
1096 /* If something needs attention, go right to the top */
1097 mutex_enter(&iscsit_isns_mutex);
1098 if (isns_targets_changed || isns_portals_changed) {
1099 DTRACE_PROBE(iscsit__isns__monitor__reenter);
1100 mutex_exit(&iscsit_isns_mutex);
1101 /* isns_monitor_mutex still held */
2857 /* receive the pdu header */
2858 rcv_timer = timeout(isnst_so_timeout, so,
2859 drv_usectohz(isns_timeout_usec));
2860 if (idm_sorecv(so, &tmp_pdu_hdr, ISNSP_HEADER_SIZE) != 0 ||
2861 ntohs(tmp_pdu_hdr.seq) != seq) {
2862 (void) untimeout(rcv_timer);
2863 goto rcv_error;
2864 }
2865 (void) untimeout(rcv_timer);
2866
2867 /* receive the payload */
2868 payload_len = ntohs(tmp_pdu_hdr.payload_len);
2869 if (payload_len > ISNST_MAX_MSG_SIZE) {
2870 goto rcv_error;
2871 }
2872 payload = kmem_alloc(payload_len, KM_NOSLEEP);
2873 if (payload == NULL) {
2874 goto rcv_error;
2875 }
2876 rcv_timer = timeout(isnst_so_timeout, so,
2877 drv_sectohz(ISNS_RCV_TIMER_SECONDS));
2878 if (idm_sorecv(so, payload, payload_len) != 0) {
2879 (void) untimeout(rcv_timer);
2880 goto rcv_error;
2881 }
2882 (void) untimeout(rcv_timer);
2883
2884 /* combine the pdu if it is not the first one */
2885 if (total_pdu_len > 0) {
2886 combined_len = total_pdu_len + payload_len;
2887 combined_pdu = kmem_alloc(combined_len, KM_SLEEP);
2888 if (combined_pdu == NULL) {
2889 goto rcv_error;
2890 }
2891 bcopy(*pdu, combined_pdu, total_pdu_len);
2892 combined_payload =
2893 &combined_pdu->payload[total_payload_len];
2894 bcopy(payload, combined_payload, payload_len);
2895 kmem_free(*pdu, total_pdu_len);
2896 kmem_free(payload, payload_len);
2897 *pdu = combined_pdu;
3068
3069 esi.esi_thread_did = curthread->t_did;
3070
3071 mutex_enter(&esi.esi_mutex);
3072
3073 /*
3074 * Mark the thread as running and the portal as no longer new.
3075 */
3076 esi.esi_thread_running = B_TRUE;
3077 cv_signal(&esi.esi_cv);
3078
3079 while (esi.esi_enabled) {
3080 /*
3081 * Create a socket to listen for requests from the iSNS server.
3082 */
3083 if ((esi.esi_so = idm_socreate(PF_INET6, SOCK_STREAM, 0)) ==
3084 NULL) {
3085 ISNST_LOG(CE_WARN,
3086 "isnst_esi_thread: Unable to create socket");
3087 mutex_exit(&esi.esi_mutex);
3088 delay(drv_sectohz(1));
3089 mutex_enter(&esi.esi_mutex);
3090 continue;
3091 }
3092
3093 /*
3094 * Set options, bind, and listen until we're told to stop
3095 */
3096 bzero(&sin6, sizeof (sin6));
3097 sin6.sin6_family = AF_INET6;
3098 sin6.sin6_port = htons(0);
3099 sin6.sin6_addr = in6addr_any;
3100
3101 (void) ksocket_setsockopt(esi.esi_so, SOL_SOCKET,
3102 SO_REUSEADDR, (char *)&on, sizeof (on), CRED());
3103
3104 if (ksocket_bind(esi.esi_so, (struct sockaddr *)&sin6,
3105 sizeof (sin6), CRED()) != 0) {
3106 ISNST_LOG(CE_WARN, "Unable to bind socket for ESI");
3107 idm_sodestroy(esi.esi_so);
3108 mutex_exit(&esi.esi_mutex);
3109 delay(drv_sectohz(1));
3110 mutex_enter(&esi.esi_mutex);
3111 continue;
3112 }
3113
3114 /*
3115 * Get the port (sin6 is meaningless at this point)
3116 */
3117 (void) ksocket_getsockname(esi.esi_so,
3118 (struct sockaddr *)(&sin6), &sin_addrlen, CRED());
3119 esi.esi_port =
3120 ntohs(((struct sockaddr_in6 *)(&sin6))->sin6_port);
3121
3122 if ((rc = ksocket_listen(esi.esi_so, 5, CRED())) != 0) {
3123 ISNST_LOG(CE_WARN, "isnst_esi_thread: listen "
3124 "failure 0x%x", rc);
3125 idm_sodestroy(esi.esi_so);
3126 mutex_exit(&esi.esi_mutex);
3127 delay(drv_sectohz(1));
3128 mutex_enter(&esi.esi_mutex);
3129 continue;
3130 }
3131
3132 ksocket_hold(esi.esi_so);
3133 esi.esi_valid = B_TRUE;
3134 while (esi.esi_enabled) {
3135 mutex_exit(&esi.esi_mutex);
3136
3137 DTRACE_PROBE3(iscsit__isns__esi__accept__wait,
3138 boolean_t, esi.esi_enabled,
3139 ksocket_t, esi.esi_so,
3140 struct sockaddr_in6, &sin6);
3141 if ((rc = ksocket_accept(esi.esi_so, NULL, NULL,
3142 &newso, CRED())) != 0) {
3143 mutex_enter(&esi.esi_mutex);
3144 DTRACE_PROBE2(iscsit__isns__esi__accept__fail,
3145 int, rc, boolean_t, esi.esi_enabled);
3146 /*
3147 * If we were interrupted with EINTR
|