git: 156e41c4b772 - stable/13 - iscsi: Handle unmapped I/O requests.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 11 May 2022 21:04:37 UTC
The branch stable/13 has been updated by jhb: URL: https://cgit.FreeBSD.org/src/commit/?id=156e41c4b772c80c0ab5f36fced54072d3dd70d8 commit 156e41c4b772c80c0ab5f36fced54072d3dd70d8 Author: John Baldwin <jhb@FreeBSD.org> AuthorDate: 2022-03-10 23:49:53 +0000 Commit: John Baldwin <jhb@FreeBSD.org> CommitDate: 2022-05-11 20:52:17 +0000 iscsi: Handle unmapped I/O requests. Don't assume that csio->data_ptr is pointer to a data buffer that can be passed to icl_get_pdu_data and icl_append_data. For unmapped I/O requests, csio->data_ptr is instead a pointer to a struct bio as indicated by CAM_DATA_BIO. To support these requests, add icl_pdu_append_bio and icl_pdu_get_bio methods which pass a pointer to the bio and an offset and length relative to the bio's buffer. Note that only backends supporting unmapped requests need to implement these hooks. Implement simple no-op hooks for the iser backend. Reviewed by: mav Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D34382 (cherry picked from commit 7aab9c14a462e0871394bbc4e276affb79c8d173) --- sys/dev/iscsi/icl_conn_if.m | 19 +++++++++++++++++++ sys/dev/iscsi/icl_wrappers.h | 18 ++++++++++++++++++ sys/dev/iscsi/iscsi.c | 41 ++++++++++++++++++++++++++++++++++++++--- sys/dev/iser/icl_iser.c | 24 ++++++++++++++++++++++++ 4 files changed, 99 insertions(+), 3 deletions(-) diff --git a/sys/dev/iscsi/icl_conn_if.m b/sys/dev/iscsi/icl_conn_if.m index e46b8cdc20dc..1b424b0b0f31 100644 --- a/sys/dev/iscsi/icl_conn_if.m +++ b/sys/dev/iscsi/icl_conn_if.m @@ -30,6 +30,7 @@ # $FreeBSD$ # +#include <sys/bio.h> #include <sys/socket.h> #include <dev/iscsi/icl.h> @@ -50,6 +51,15 @@ METHOD size_t pdu_data_segment_length { 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 @@ METHOD int pdu_append_data { 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 index cc37771c7dba..c2f215c10607 100644 --- 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 <sys/bio.h> #include <sys/kobj.h> #include <dev/iscsi/icl.h> @@ -57,6 +58,15 @@ icl_pdu_data_segment_length(const struct icl_pdu *ip) 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 @@ icl_pdu_append_data(struct icl_pdu *ip, const void *addr, size_t len, int flags) 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 index 155faa0910e4..e4bfb6a353d2 100644 --- a/sys/dev/iscsi/iscsi.c +++ b/sys/dev/iscsi/iscsi.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> +#include <sys/bio.h> #include <sys/condvar.h> #include <sys/conf.h> #include <sys/endian.h> @@ -1059,6 +1060,24 @@ iscsi_pdu_handle_task_response(struct icl_pdu *response) 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) { @@ -1137,7 +1156,7 @@ iscsi_pdu_handle_data_in(struct icl_pdu *response) 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. @@ -1188,6 +1207,22 @@ iscsi_pdu_handle_logout_response(struct icl_pdu *response) 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) { @@ -1282,7 +1317,7 @@ iscsi_pdu_handle_r2t(struct icl_pdu *response) 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; " @@ -2387,7 +2422,7 @@ iscsi_action_scsiio(struct iscsi_session *is, union ccb *ccb) 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 index 2c2514a1422b..140b5622385d 100644 --- a/sys/dev/iser/icl_iser.c +++ b/sys/dev/iser/icl_iser.c @@ -43,6 +43,7 @@ static void iser_conn_release(struct icl_conn *ic); 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_close_t iser_conn_close; 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 @@ static kobj_method_t icl_iser_methods[] = { 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 @@ out: 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 @@ iser_conn_pdu_append_data(struct icl_conn *ic, struct icl_pdu *request, 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)