Author: trasz
Date: Wed Oct  9 12:03:04 2013
New Revision: 256187
URL: http://svnweb.freebsd.org/changeset/base/256187

Log:
  Fix NOP-In/NOP-Out payload handling.  Previous way didn't work at all; 
fortunately
  nothing seems to actually use this feature, but it's required by standard.
  
  Approved by:  re (glebius)
  Sponsored by: FreeBSD Foundation

Modified:
  head/sys/cam/ctl/ctl_frontend_iscsi.c
  head/sys/dev/iscsi/iscsi.c

Modified: head/sys/cam/ctl/ctl_frontend_iscsi.c
==============================================================================
--- head/sys/cam/ctl/ctl_frontend_iscsi.c       Wed Oct  9 12:00:38 2013        
(r256186)
+++ head/sys/cam/ctl/ctl_frontend_iscsi.c       Wed Oct  9 12:03:04 2013        
(r256187)
@@ -455,6 +455,9 @@ cfiscsi_pdu_handle_nop_out(struct icl_pd
        struct iscsi_bhs_nop_out *bhsno;
        struct iscsi_bhs_nop_in *bhsni;
        struct icl_pdu *response;
+       void *data = NULL;
+       size_t datasize;
+       int error;
 
        cs = PDU_SESSION(request);
        bhsno = (struct iscsi_bhs_nop_out *)request->ip_bhs;
@@ -468,9 +471,26 @@ cfiscsi_pdu_handle_nop_out(struct icl_pd
                return;
        }
 
+       datasize = icl_pdu_data_segment_length(request);
+       if (datasize > 0) {
+               data = malloc(datasize, M_CFISCSI, M_NOWAIT | M_ZERO);
+               if (data == NULL) {
+                       CFISCSI_SESSION_WARN(cs, "failed to allocate memory; "
+                           "dropping connection");
+                       icl_pdu_free(request);
+                       cfiscsi_session_terminate(cs);
+                       return;
+               }
+               icl_pdu_get_data(request, 0, data, datasize);
+       }
+
        response = cfiscsi_pdu_new_response(request, M_NOWAIT);
        if (response == NULL) {
+               CFISCSI_SESSION_WARN(cs, "failed to allocate memory; "
+                   "droppping connection");
+               free(data, M_CFISCSI);
                icl_pdu_free(request);
+               cfiscsi_session_terminate(cs);
                return;
        }
        bhsni = (struct iscsi_bhs_nop_in *)response->ip_bhs;
@@ -478,14 +498,19 @@ cfiscsi_pdu_handle_nop_out(struct icl_pd
        bhsni->bhsni_flags = 0x80;
        bhsni->bhsni_initiator_task_tag = bhsno->bhsno_initiator_task_tag;
        bhsni->bhsni_target_transfer_tag = 0xffffffff;
-
-#if 0
-       /* XXX */
-       response->ip_data_len = request->ip_data_len;
-       response->ip_data_mbuf = request->ip_data_mbuf;
-       request->ip_data_len = 0;
-       request->ip_data_mbuf = NULL;
-#endif
+       if (datasize > 0) {
+               error = icl_pdu_append_data(response, data, datasize, M_NOWAIT);
+               if (error != 0) {
+                       CFISCSI_SESSION_WARN(cs, "failed to allocate memory; "
+                           "dropping connection");
+                       free(data, M_CFISCSI);
+                       icl_pdu_free(request);
+                       icl_pdu_free(response);
+                       cfiscsi_session_terminate(cs);
+                       return;
+               }
+               free(data, M_CFISCSI);
+       }
 
        icl_pdu_free(request);
        cfiscsi_pdu_queue(response);

Modified: head/sys/dev/iscsi/iscsi.c
==============================================================================
--- head/sys/dev/iscsi/iscsi.c  Wed Oct  9 12:00:38 2013        (r256186)
+++ head/sys/dev/iscsi/iscsi.c  Wed Oct  9 12:03:04 2013        (r256187)
@@ -726,10 +726,15 @@ iscsi_error_callback(struct icl_conn *ic
 static void
 iscsi_pdu_handle_nop_in(struct icl_pdu *response)
 {
+       struct iscsi_session *is;
        struct iscsi_bhs_nop_out *bhsno;
        struct iscsi_bhs_nop_in *bhsni;
        struct icl_pdu *request;
+       void *data = NULL;
+       size_t datasize;
+       int error;
 
+       is = PDU_SESSION(response);
        bhsni = (struct iscsi_bhs_nop_in *)response->ip_bhs;
 
        if (bhsni->bhsni_target_transfer_tag == 0xffffffff) {
@@ -741,22 +746,47 @@ iscsi_pdu_handle_nop_in(struct icl_pdu *
                return;
        }
 
+       datasize = icl_pdu_data_segment_length(response);
+       if (datasize > 0) {
+               data = malloc(datasize, M_ISCSI, M_NOWAIT | M_ZERO);
+               if (data == NULL) {
+                       ISCSI_SESSION_WARN(is, "failed to allocate memory; "
+                           "reconnecting");
+                       icl_pdu_free(response);
+                       iscsi_session_reconnect(is);
+                       return;
+               }
+               icl_pdu_get_data(response, 0, data, datasize);
+       }
+
        request = icl_pdu_new_bhs(response->ip_conn, M_NOWAIT);
        if (request == NULL) {
+               ISCSI_SESSION_WARN(is, "failed to allocate memory; "
+                   "reconnecting");
+               free(data, M_ISCSI);
                icl_pdu_free(response);
+               iscsi_session_reconnect(is);
                return;
        }
        bhsno = (struct iscsi_bhs_nop_out *)request->ip_bhs;
        bhsno->bhsno_opcode = ISCSI_BHS_OPCODE_NOP_OUT |
            ISCSI_BHS_OPCODE_IMMEDIATE;
        bhsno->bhsno_flags = 0x80;
-       bhsno->bhsno_initiator_task_tag = 0xffffffff; /* XXX */
+       bhsno->bhsno_initiator_task_tag = 0xffffffff;
        bhsno->bhsno_target_transfer_tag = bhsni->bhsni_target_transfer_tag;
-
-       request->ip_data_len = response->ip_data_len;
-       request->ip_data_mbuf = response->ip_data_mbuf;
-       response->ip_data_len = 0;
-       response->ip_data_mbuf = NULL;
+       if (datasize > 0) {
+               error = icl_pdu_append_data(request, data, datasize, M_NOWAIT);
+               if (error != 0) {
+                       ISCSI_SESSION_WARN(is, "failed to allocate memory; "
+                           "reconnecting");
+                       free(data, M_ISCSI);
+                       icl_pdu_free(request);
+                       icl_pdu_free(response);
+                       iscsi_session_reconnect(is);
+                       return;
+               }
+               free(data, M_ISCSI);
+       }
 
        icl_pdu_free(response);
        iscsi_pdu_queue_locked(request);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to