diff options
| author | Navdeep Parhar <np@FreeBSD.org> | 2016-08-25 05:22:53 +0000 |
|---|---|---|
| committer | Navdeep Parhar <np@FreeBSD.org> | 2016-08-25 05:22:53 +0000 |
| commit | 97b84d344d4a7bb9e34703948e31be5247318a71 (patch) | |
| tree | 956a2021fa5a85180b18e0c435a8cdcba6356718 /sys/dev | |
| parent | 02d99265593c8c13ae08eaa7a962531bcd9889a0 (diff) | |
Notes
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/cxgbe/cxgbei/icl_cxgbei.c | 7 | ||||
| -rw-r--r-- | sys/dev/iscsi/icl.c | 37 | ||||
| -rw-r--r-- | sys/dev/iscsi/icl.h | 14 | ||||
| -rw-r--r-- | sys/dev/iscsi/icl_soft.c | 4 | ||||
| -rw-r--r-- | sys/dev/iscsi/iscsi.c | 46 | ||||
| -rw-r--r-- | sys/dev/iscsi/iscsi.h | 7 | ||||
| -rw-r--r-- | sys/dev/iscsi/iscsi_ioctl.h | 22 | ||||
| -rw-r--r-- | sys/dev/iser/icl_iser.c | 4 |
8 files changed, 99 insertions, 42 deletions
diff --git a/sys/dev/cxgbe/cxgbei/icl_cxgbei.c b/sys/dev/cxgbe/cxgbei/icl_cxgbei.c index 8f29452196fe..288e8e692a9b 100644 --- a/sys/dev/cxgbe/cxgbei/icl_cxgbei.c +++ b/sys/dev/cxgbe/cxgbei/icl_cxgbei.c @@ -832,10 +832,13 @@ icl_cxgbei_conn_transfer_done(struct icl_conn *ic, void *prv) } static int -icl_cxgbei_limits(size_t *limitp) +icl_cxgbei_limits(struct icl_drv_limits *idl) { - *limitp = CXGBEI_MAX_DSL; + idl->idl_max_recv_data_segment_length = CXGBEI_MAX_DSL; + idl->idl_max_send_data_segment_length = CXGBEI_MAX_DSL; + idl->idl_max_burst_length = 2 * 1024 * 1024; + idl->idl_first_burst_length = CXGBEI_MAX_DSL; return (0); } diff --git a/sys/dev/iscsi/icl.c b/sys/dev/iscsi/icl.c index 2823074f2104..9a20b54a1f83 100644 --- a/sys/dev/iscsi/icl.c +++ b/sys/dev/iscsi/icl.c @@ -59,7 +59,7 @@ struct icl_module { char *im_name; bool im_iser; int im_priority; - int (*im_limits)(size_t *limitp); + int (*im_limits)(struct icl_drv_limits *idl); struct icl_conn *(*im_new_conn)(const char *name, struct mtx *lock); }; @@ -182,11 +182,12 @@ icl_new_conn(const char *offload, bool iser, const char *name, struct mtx *lock) } int -icl_limits(const char *offload, bool iser, size_t *limitp) +icl_limits(const char *offload, bool iser, struct icl_drv_limits *idl) { struct icl_module *im; int error; + bzero(idl, sizeof(*idl)); sx_slock(&sc->sc_lock); im = icl_find(offload, iser, false); if (im == NULL) { @@ -194,14 +195,42 @@ icl_limits(const char *offload, bool iser, size_t *limitp) return (ENXIO); } - error = im->im_limits(limitp); + error = im->im_limits(idl); sx_sunlock(&sc->sc_lock); + /* + * Validate the limits provided by the driver against values allowed by + * the iSCSI RFC. 0 means iscsid/ctld should pick a reasonable value. + * + * Note that max_send_dsl is an internal implementation detail and not + * part of the RFC. + */ +#define OUT_OF_RANGE(x, lo, hi) ((x) != 0 && ((x) < (lo) || (x) > (hi))) + if (error == 0 && + (OUT_OF_RANGE(idl->idl_max_recv_data_segment_length, 512, 16777215) || + OUT_OF_RANGE(idl->idl_max_send_data_segment_length, 512, 16777215) || + OUT_OF_RANGE(idl->idl_max_burst_length, 512, 16777215) || + OUT_OF_RANGE(idl->idl_first_burst_length, 512, 16777215))) { + error = EINVAL; + } +#undef OUT_OF_RANGE + + /* + * If both first_burst and max_burst are provided then first_burst must + * not exceed max_burst. + */ + if (error == 0 && idl->idl_first_burst_length > 0 && + idl->idl_max_burst_length > 0 && + idl->idl_first_burst_length > idl->idl_max_burst_length) { + error = EINVAL; + } + return (error); } int -icl_register(const char *offload, bool iser, int priority, int (*limits)(size_t *), +icl_register(const char *offload, bool iser, int priority, + int (*limits)(struct icl_drv_limits *), struct icl_conn *(*new_conn)(const char *, struct mtx *)) { struct icl_module *im; diff --git a/sys/dev/iscsi/icl.h b/sys/dev/iscsi/icl.h index 292fa6006657..0a1ee9414e4f 100644 --- a/sys/dev/iscsi/icl.h +++ b/sys/dev/iscsi/icl.h @@ -126,12 +126,20 @@ struct icl_conn { void *ic_prv0; }; +struct icl_drv_limits { + int idl_max_recv_data_segment_length; + int idl_max_send_data_segment_length; + int idl_max_burst_length; + int idl_first_burst_length; + int spare[4]; +}; + struct icl_conn *icl_new_conn(const char *offload, bool iser, const char *name, struct mtx *lock); -int icl_limits(const char *offload, bool iser, size_t *limitp); - +int icl_limits(const char *offload, bool iser, + struct icl_drv_limits *idl); int icl_register(const char *offload, bool iser, int priority, - int (*limits)(size_t *), + int (*limits)(struct icl_drv_limits *), struct icl_conn *(*new_conn)(const char *, struct mtx *)); int icl_unregister(const char *offload, bool rdma); diff --git a/sys/dev/iscsi/icl_soft.c b/sys/dev/iscsi/icl_soft.c index 4efae9fd9712..230a41456796 100644 --- a/sys/dev/iscsi/icl_soft.c +++ b/sys/dev/iscsi/icl_soft.c @@ -1474,10 +1474,10 @@ icl_soft_conn_transfer_done(struct icl_conn *ic, void *prv) } static int -icl_soft_limits(size_t *limitp) +icl_soft_limits(struct icl_drv_limits *idl) { - *limitp = 128 * 1024; + idl->idl_max_recv_data_segment_length = 128 * 1024; return (0); } diff --git a/sys/dev/iscsi/iscsi.c b/sys/dev/iscsi/iscsi.c index 5364584816c2..57b60bb8423f 100644 --- a/sys/dev/iscsi/iscsi.c +++ b/sys/dev/iscsi/iscsi.c @@ -1204,8 +1204,8 @@ iscsi_pdu_handle_r2t(struct icl_pdu *response) for (;;) { len = total_len; - if (len > is->is_max_data_segment_length) - len = is->is_max_data_segment_length; + if (len > is->is_max_send_data_segment_length) + len = is->is_max_send_data_segment_length; if (off + len > csio->dxfer_len) { ISCSI_SESSION_WARN(is, "target requested invalid " @@ -1313,6 +1313,7 @@ iscsi_ioctl_daemon_wait(struct iscsi_softc *sc, struct iscsi_daemon_request *request) { struct iscsi_session *is; + struct icl_drv_limits idl; int error; sx_slock(&sc->sc_lock); @@ -1352,10 +1353,9 @@ iscsi_ioctl_daemon_wait(struct iscsi_softc *sc, request->idr_tsih = 0; /* New or reinstated session. */ memcpy(&request->idr_conf, &is->is_conf, sizeof(request->idr_conf)); - + error = icl_limits(is->is_conf.isc_offload, - is->is_conf.isc_iser, - &request->idr_limits.isl_max_data_segment_length); + is->is_conf.isc_iser, &idl); if (error != 0) { ISCSI_SESSION_WARN(is, "icl_limits for offload \"%s\" " "failed with error %d", is->is_conf.isc_offload, @@ -1363,6 +1363,14 @@ iscsi_ioctl_daemon_wait(struct iscsi_softc *sc, sx_sunlock(&sc->sc_lock); return (error); } + request->idr_limits.isl_max_recv_data_segment_length = + idl.idl_max_recv_data_segment_length; + request->idr_limits.isl_max_send_data_segment_length = + idl.idl_max_recv_data_segment_length; + request->idr_limits.isl_max_burst_length = + idl.idl_max_burst_length; + request->idr_limits.isl_first_burst_length = + idl.idl_first_burst_length; sx_sunlock(&sc->sc_lock); return (0); @@ -1417,12 +1425,10 @@ iscsi_ioctl_daemon_handoff(struct iscsi_softc *sc, is->is_initial_r2t = handoff->idh_initial_r2t; is->is_immediate_data = handoff->idh_immediate_data; - /* - * Cap MaxRecvDataSegmentLength obtained from the target to the maximum - * size supported by our ICL module. - */ - is->is_max_data_segment_length = min(ic->ic_max_data_segment_length, - handoff->idh_max_data_segment_length); + is->is_max_recv_data_segment_length = + handoff->idh_max_recv_data_segment_length; + is->is_max_send_data_segment_length = + handoff->idh_max_send_data_segment_length; is->is_max_burst_length = handoff->idh_max_burst_length; is->is_first_burst_length = handoff->idh_first_burst_length; @@ -1634,7 +1640,7 @@ iscsi_ioctl_daemon_send(struct iscsi_softc *sc, return (EIO); datalen = ids->ids_data_segment_len; - if (datalen > ISCSI_MAX_DATA_SEGMENT_LENGTH) + if (datalen > is->is_max_send_data_segment_length) return (EINVAL); if (datalen > 0) { data = malloc(datalen, M_ISCSI, M_WAITOK); @@ -1933,12 +1939,15 @@ iscsi_ioctl_session_list(struct iscsi_softc *sc, struct iscsi_session_list *isl) else iss.iss_data_digest = ISCSI_DIGEST_NONE; - iss.iss_max_data_segment_length = is->is_max_data_segment_length; + iss.iss_max_send_data_segment_length = + is->is_max_send_data_segment_length; + iss.iss_max_recv_data_segment_length = + is->is_max_recv_data_segment_length; iss.iss_max_burst_length = is->is_max_burst_length; iss.iss_first_burst_length = is->is_first_burst_length; iss.iss_immediate_data = is->is_immediate_data; iss.iss_connected = is->is_connected; - + error = copyout(&iss, isl->isl_pstates + i, sizeof(iss)); if (error != 0) { sx_sunlock(&sc->sc_lock); @@ -2259,12 +2268,13 @@ iscsi_action_scsiio(struct iscsi_session *is, union ccb *ccb) len = csio->dxfer_len; //ISCSI_SESSION_DEBUG(is, "adding %zd of immediate data", len); if (len > is->is_first_burst_length) { - ISCSI_SESSION_DEBUG(is, "len %zd -> %zd", len, is->is_first_burst_length); + ISCSI_SESSION_DEBUG(is, "len %zd -> %d", len, is->is_first_burst_length); len = is->is_first_burst_length; } - if (len > is->is_max_data_segment_length) { - ISCSI_SESSION_DEBUG(is, "len %zd -> %zd", len, is->is_max_data_segment_length); - len = is->is_max_data_segment_length; + if (len > is->is_max_send_data_segment_length) { + ISCSI_SESSION_DEBUG(is, "len %zd -> %d", len, + is->is_max_send_data_segment_length); + len = is->is_max_send_data_segment_length; } error = icl_pdu_append_data(request, csio->data_ptr, len, M_NOWAIT); diff --git a/sys/dev/iscsi/iscsi.h b/sys/dev/iscsi/iscsi.h index 3225649cc464..d5bd79ab4140 100644 --- a/sys/dev/iscsi/iscsi.h +++ b/sys/dev/iscsi/iscsi.h @@ -62,12 +62,13 @@ struct iscsi_session { int is_header_digest; int is_data_digest; int is_initial_r2t; - size_t is_max_burst_length; - size_t is_first_burst_length; + int is_max_burst_length; + int is_first_burst_length; uint8_t is_isid[6]; uint16_t is_tsih; bool is_immediate_data; - size_t is_max_data_segment_length; + int is_max_recv_data_segment_length; + int is_max_send_data_segment_length; char is_target_alias[ISCSI_ALIAS_LEN]; TAILQ_HEAD(, iscsi_outstanding) is_outstanding; diff --git a/sys/dev/iscsi/iscsi_ioctl.h b/sys/dev/iscsi/iscsi_ioctl.h index a494cd558ed1..3767c45f99df 100644 --- a/sys/dev/iscsi/iscsi_ioctl.h +++ b/sys/dev/iscsi/iscsi_ioctl.h @@ -76,8 +76,12 @@ struct iscsi_session_conf { * iscsid(8) must obey those when negotiating operational parameters. */ struct iscsi_session_limits { - size_t isl_max_data_segment_length; - int isl_spare[8]; + size_t isl_spare0; + int isl_max_recv_data_segment_length; + int isl_max_send_data_segment_length; + int isl_max_burst_length; + int isl_first_burst_length; + int isl_spare[4]; }; /* @@ -89,14 +93,15 @@ struct iscsi_session_state { char iss_target_alias[ISCSI_ALIAS_LEN]; int iss_header_digest; int iss_data_digest; - int iss_max_data_segment_length; + int iss_max_recv_data_segment_length; int iss_max_burst_length; int iss_first_burst_length; int iss_immediate_data; int iss_connected; char iss_reason[ISCSI_REASON_LEN]; char iss_offload[ISCSI_OFFLOAD_LEN]; - int iss_spare[4]; + int iss_max_send_data_segment_length; + int iss_spare[3]; }; /* @@ -122,12 +127,13 @@ struct iscsi_daemon_handoff { uint32_t idh_statsn; int idh_header_digest; int idh_data_digest; - size_t idh_max_data_segment_length; - size_t idh_max_burst_length; - size_t idh_first_burst_length; + size_t spare[3]; int idh_immediate_data; int idh_initial_r2t; - int idh_spare[4]; + int idh_max_recv_data_segment_length; + int idh_max_send_data_segment_length; + int idh_max_burst_length; + int idh_first_burst_length; }; struct iscsi_daemon_fail { diff --git a/sys/dev/iser/icl_iser.c b/sys/dev/iser/icl_iser.c index a7c29d761035..0ebaee5977b0 100644 --- a/sys/dev/iser/icl_iser.c +++ b/sys/dev/iser/icl_iser.c @@ -483,9 +483,9 @@ iser_conn_task_done(struct icl_conn *ic, void *prv) } static int -iser_limits(size_t *limitp) +iser_limits(struct icl_drv_limits *idl) { - *limitp = 128 * 1024; + idl->idl_max_recv_data_segment_length = 128 * 1024; return (0); } |
