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
This commit is contained in:
parent
c6a43f7f10
commit
7aab9c14a4
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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>
|
||||
@ -1085,6 +1086,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)
|
||||
{
|
||||
@ -1163,7 +1182,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.
|
||||
@ -1214,6 +1233,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)
|
||||
{
|
||||
@ -1308,7 +1343,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; "
|
||||
@ -2427,7 +2462,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);
|
||||
|
@ -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 @@ iser_initialize_headers(struct icl_iser_pdu *pdu, struct iser_conn *iser_conn)
|
||||
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)
|
||||
|
Loading…
Reference in New Issue
Block a user