diff --git a/sys/dev/iscsi/icl_conn_if.m b/sys/dev/iscsi/icl_conn_if.m --- a/sys/dev/iscsi/icl_conn_if.m +++ b/sys/dev/iscsi/icl_conn_if.m @@ -30,6 +30,7 @@ # $FreeBSD$ # +#include #include #include @@ -50,6 +51,15 @@ const struct icl_pdu *_ip; }; +METHOD int pdu_append_bio { + struct icl_conn *_ic; + struct icl_pdu *_ip; + struct bio *_bp; + size_t _offset; + size_t _len; + int _flags; +}; + METHOD int pdu_append_data { struct icl_conn *_ic; struct icl_pdu *_ip; @@ -58,6 +68,15 @@ int _flags; }; +METHOD void pdu_get_bio { + struct icl_conn *_ic; + struct icl_pdu *_ip; + size_t _pdu_off; + struct bio *_bp; + size_t _bio_off; + size_t _len; +}; + METHOD void pdu_get_data { struct icl_conn *_ic; struct icl_pdu *_ip; diff --git a/sys/dev/iscsi/icl_wrappers.h b/sys/dev/iscsi/icl_wrappers.h --- a/sys/dev/iscsi/icl_wrappers.h +++ b/sys/dev/iscsi/icl_wrappers.h @@ -38,6 +38,7 @@ #ifndef ICL_WRAPPERS_H #define ICL_WRAPPERS_H +#include #include #include @@ -57,6 +58,15 @@ return (ICL_CONN_PDU_DATA_SEGMENT_LENGTH(ip->ip_conn, ip)); } +static inline int +icl_pdu_append_bio(struct icl_pdu *ip, struct bio *bp, size_t offset, + size_t len, int flags) +{ + + return (ICL_CONN_PDU_APPEND_BIO(ip->ip_conn, ip, bp, offset, len, + flags)); +} + static inline int icl_pdu_append_data(struct icl_pdu *ip, const void *addr, size_t len, int flags) { @@ -64,6 +74,14 @@ return (ICL_CONN_PDU_APPEND_DATA(ip->ip_conn, ip, addr, len, flags)); } +static inline void +icl_pdu_get_bio(struct icl_pdu *ip, size_t pdu_off, struct bio *bp, + size_t bio_off, size_t len) +{ + + ICL_CONN_PDU_GET_BIO(ip->ip_conn, ip, pdu_off, bp, bio_off, len); +} + static inline void icl_pdu_get_data(struct icl_pdu *ip, size_t off, void *addr, size_t len) { diff --git a/sys/dev/iscsi/iscsi.c b/sys/dev/iscsi/iscsi.c --- a/sys/dev/iscsi/iscsi.c +++ b/sys/dev/iscsi/iscsi.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include #include @@ -1085,6 +1086,24 @@ icl_pdu_free(response); } +static void +iscsi_pdu_get_data_csio(struct icl_pdu *response, size_t pdu_offset, + struct ccb_scsiio *csio, size_t oreceived, size_t data_segment_len) +{ + switch (csio->ccb_h.flags & CAM_DATA_MASK) { + case CAM_DATA_BIO: + icl_pdu_get_bio(response, pdu_offset, + (struct bio *)csio->data_ptr, oreceived, data_segment_len); + break; + case CAM_DATA_VADDR: + icl_pdu_get_data(response, pdu_offset, + csio->data_ptr + oreceived, data_segment_len); + break; + default: + __assert_unreachable(); + } +} + static void iscsi_pdu_handle_data_in(struct icl_pdu *response) { @@ -1163,7 +1182,7 @@ iscsi_outstanding_remove(is, io); ISCSI_SESSION_UNLOCK(is); - icl_pdu_get_data(response, 0, csio->data_ptr + oreceived, data_segment_len); + iscsi_pdu_get_data_csio(response, 0, csio, oreceived, data_segment_len); /* * XXX: Check F. @@ -1214,6 +1233,22 @@ icl_pdu_free(response); } +static int +iscsi_pdu_append_data_csio(struct icl_pdu *request, struct ccb_scsiio *csio, + size_t off, size_t len, int how) +{ + switch (csio->ccb_h.flags & CAM_DATA_MASK) { + case CAM_DATA_BIO: + return (icl_pdu_append_bio(request, + (struct bio *)csio->data_ptr, off, len, how)); + case CAM_DATA_VADDR: + return (icl_pdu_append_data(request, csio->data_ptr + off, len, + how)); + default: + __assert_unreachable(); + } +} + static void iscsi_pdu_handle_r2t(struct icl_pdu *response) { @@ -1308,7 +1343,7 @@ bhsr2t->bhsr2t_target_transfer_tag; bhsdo->bhsdo_datasn = htonl(datasn); bhsdo->bhsdo_buffer_offset = htonl(off); - error = icl_pdu_append_data(request, csio->data_ptr + off, len, + error = iscsi_pdu_append_data_csio(request, csio, off, len, M_NOWAIT | ICL_NOCOPY); if (error != 0) { ISCSI_SESSION_WARN(is, "failed to allocate memory; " @@ -2427,7 +2462,7 @@ len = is->is_conn->ic_max_send_data_segment_length; } - error = icl_pdu_append_data(request, csio->data_ptr, len, + error = iscsi_pdu_append_data_csio(request, csio, 0, len, M_NOWAIT | ICL_NOCOPY); if (error != 0) { iscsi_outstanding_remove(is, io); diff --git a/sys/dev/iser/icl_iser.c b/sys/dev/iser/icl_iser.c --- a/sys/dev/iser/icl_iser.c +++ b/sys/dev/iser/icl_iser.c @@ -43,6 +43,7 @@ static icl_conn_new_pdu_t iser_conn_new_pdu; static icl_conn_pdu_free_t iser_conn_pdu_free; static icl_conn_pdu_data_segment_length_t iser_conn_pdu_data_segment_length; +static icl_conn_pdu_append_bio_t iser_conn_pdu_append_bio; static icl_conn_pdu_append_data_t iser_conn_pdu_append_data; static icl_conn_pdu_queue_t iser_conn_pdu_queue; static icl_conn_handoff_t iser_conn_handoff; @@ -51,12 +52,14 @@ static icl_conn_connect_t iser_conn_connect; static icl_conn_task_setup_t iser_conn_task_setup; static icl_conn_task_done_t iser_conn_task_done; +static icl_conn_pdu_get_bio_t iser_conn_pdu_get_bio; static icl_conn_pdu_get_data_t iser_conn_pdu_get_data; static kobj_method_t icl_iser_methods[] = { KOBJMETHOD(icl_conn_new_pdu, iser_conn_new_pdu), KOBJMETHOD(icl_conn_pdu_free, iser_conn_pdu_free), KOBJMETHOD(icl_conn_pdu_data_segment_length, iser_conn_pdu_data_segment_length), + KOBJMETHOD(icl_conn_pdu_append_bio, iser_conn_pdu_append_bio), KOBJMETHOD(icl_conn_pdu_append_data, iser_conn_pdu_append_data), KOBJMETHOD(icl_conn_pdu_queue, iser_conn_pdu_queue), KOBJMETHOD(icl_conn_handoff, iser_conn_handoff), @@ -65,6 +68,7 @@ KOBJMETHOD(icl_conn_connect, iser_conn_connect), KOBJMETHOD(icl_conn_task_setup, iser_conn_task_setup), KOBJMETHOD(icl_conn_task_done, iser_conn_task_done), + KOBJMETHOD(icl_conn_pdu_get_bio, iser_conn_pdu_get_bio), KOBJMETHOD(icl_conn_pdu_get_data, iser_conn_pdu_get_data), { 0, 0 } }; @@ -108,6 +112,18 @@ return (ret); } +int +iser_conn_pdu_append_bio(struct icl_conn *ic, struct icl_pdu *request, + struct bio *bp, size_t offset, size_t len, int flags) +{ + MPASS(!((request->ip_bhs->bhs_opcode & ISCSI_OPCODE_MASK) == + ISCSI_BHS_OPCODE_LOGIN_REQUEST || + (request->ip_bhs->bhs_opcode & ISCSI_OPCODE_MASK) == + ISCSI_BHS_OPCODE_TEXT_REQUEST)); + + return (0); +} + int iser_conn_pdu_append_data(struct icl_conn *ic, struct icl_pdu *request, const void *addr, size_t len, int flags) @@ -126,6 +142,14 @@ return (0); } +void +iser_conn_pdu_get_bio(struct icl_conn *ic, struct icl_pdu *ip, + size_t pdu_off, struct bio *bp, size_t bio_off, + size_t len) +{ + MPASS(ip->ip_data_mbuf == NULL); +} + void iser_conn_pdu_get_data(struct icl_conn *ic, struct icl_pdu *ip, size_t off, void *addr, size_t len)