diff options
author | John Baldwin <jhb@FreeBSD.org> | 2022-04-18 19:48:42 +0000 |
---|---|---|
committer | John Baldwin <jhb@FreeBSD.org> | 2022-04-18 19:53:28 +0000 |
commit | 7b02c1e8c6a17d11b69988f3e1b449b783785415 (patch) | |
tree | 5fe0254825c92853733bef0d1c1fedc59e6c5942 /sys/dev/iscsi/iscsi.c | |
parent | f0df72273377daf5e1e97b80a4e542362b261a1d (diff) | |
download | src-7b02c1e8c6a17d11b69988f3e1b449b783785415.tar.gz src-7b02c1e8c6a17d11b69988f3e1b449b783785415.zip |
iscsi: Fetch limits based on a socket rather than assuming global limits.
cxgbei needs the ability to return different limits based on the
connection (e.g. if the connection is over a T5 adapter or a T6
adapter as well as factoring in the MTU).
This change plumbs through the changes in the ioctls without changing
any of the backends. The limits callback passed to icl_register now
accepts a second socket argument which holds the integer file
descriptor. To support ABI compatiblity for old binaries, the
callback should return "global" values if the socket fd is zero.
The CTL_ISCSI_LIMITS argument used with CTL_ISCSI by ctld(8) now
accepts the socket fd in a field that was previously part of a
reserved spare field. Old binaries zero this request which results in
passing a socket fd of 0 to the limits callback.
The ISCSIDREQUEST ioctl no longer returns limits. Instead, iscsid(8)
invokes a new ISCSIDLIMITS ioctl after establishing the connection via
connect(2). For ABI compat, if the old ISCSIDREQUEST is invoked, the
global limits are still fetched (with a socket fd of 0) and returned.
Reviewed by: mav
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D34928
Diffstat (limited to 'sys/dev/iscsi/iscsi.c')
-rw-r--r-- | sys/dev/iscsi/iscsi.c | 110 |
1 files changed, 90 insertions, 20 deletions
diff --git a/sys/dev/iscsi/iscsi.c b/sys/dev/iscsi/iscsi.c index 9535aa9b9e2a..f7a585c02545 100644 --- a/sys/dev/iscsi/iscsi.c +++ b/sys/dev/iscsi/iscsi.c @@ -78,6 +78,20 @@ __FBSDID("$FreeBSD$"); FEATURE(iscsi_kernel_proxy, "iSCSI initiator built with ICL_KERNEL_PROXY"); #endif +#ifdef COMPAT_FREEBSD13 +struct iscsi_daemon_request13 { + unsigned int idr_session_id; + struct iscsi_session_conf idr_conf; + uint8_t idr_isid[6]; + uint16_t idr_tsih; + uint16_t idr_spare_cid; + struct iscsi_session_limits idr_limits; + int idr_spare[4]; +}; + +#define ISCSIDWAIT13 _IOR('I', 0x01, struct iscsi_daemon_request13) +#endif + /* * XXX: This is global so the iscsi_unload() can access it. * Think about how to do this properly. @@ -1423,10 +1437,9 @@ iscsi_pdu_handle_reject(struct icl_pdu *response) static int iscsi_ioctl_daemon_wait(struct iscsi_softc *sc, - struct iscsi_daemon_request *request) + struct iscsi_daemon_request *request, bool freebsd13) { struct iscsi_session *is; - struct icl_drv_limits idl; int error; sx_slock(&sc->sc_lock); @@ -1472,30 +1485,79 @@ iscsi_ioctl_daemon_wait(struct iscsi_softc *sc, memcpy(&request->idr_conf, &is->is_conf, sizeof(request->idr_conf)); - error = icl_limits(is->is_conf.isc_offload, - 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, - error); - 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_send_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; +#ifdef COMPAT_FREEBSD13 + if (freebsd13) { + struct icl_drv_limits idl; + struct iscsi_daemon_request13 *request13; + error = icl_limits(is->is_conf.isc_offload, + is->is_conf.isc_iser, 0, &idl); + if (error != 0) { + ISCSI_SESSION_WARN(is, "icl_limits for " + "offload \"%s\" failed with error %d", + is->is_conf.isc_offload, error); + sx_sunlock(&sc->sc_lock); + return (error); + } + request13 = (struct iscsi_daemon_request13 *)request; + request13->idr_limits.isl_max_recv_data_segment_length = + idl.idl_max_recv_data_segment_length; + request13->idr_limits.isl_max_send_data_segment_length = + idl.idl_max_send_data_segment_length; + request13->idr_limits.isl_max_burst_length = + idl.idl_max_burst_length; + request13->idr_limits.isl_first_burst_length = + idl.idl_first_burst_length; + } +#endif sx_sunlock(&sc->sc_lock); return (0); } } static int +iscsi_ioctl_daemon_limits(struct iscsi_softc *sc, + struct iscsi_daemon_limits *limits) +{ + struct icl_drv_limits idl; + struct iscsi_session *is; + int error; + + sx_slock(&sc->sc_lock); + + /* + * Find the session to fetch limits for. + */ + TAILQ_FOREACH(is, &sc->sc_sessions, is_next) { + if (is->is_id == limits->idl_session_id) + break; + } + if (is == NULL) { + sx_sunlock(&sc->sc_lock); + return (ESRCH); + } + + error = icl_limits(is->is_conf.isc_offload, is->is_conf.isc_iser, + limits->idl_socket, &idl); + sx_sunlock(&sc->sc_lock); + if (error != 0) { + ISCSI_SESSION_WARN(is, "icl_limits for offload \"%s\" " + "failed with error %d", is->is_conf.isc_offload, error); + return (error); + } + limits->idl_limits.isl_max_recv_data_segment_length = + idl.idl_max_recv_data_segment_length; + limits->idl_limits.isl_max_send_data_segment_length = + idl.idl_max_send_data_segment_length; + limits->idl_limits.isl_max_burst_length = + idl.idl_max_burst_length; + limits->idl_limits.isl_first_burst_length = + idl.idl_first_burst_length; + + return (0); +} + +static int iscsi_ioctl_daemon_handoff(struct iscsi_softc *sc, struct iscsi_daemon_handoff *handoff) { @@ -2179,7 +2241,15 @@ iscsi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int mode, switch (cmd) { case ISCSIDWAIT: return (iscsi_ioctl_daemon_wait(sc, - (struct iscsi_daemon_request *)arg)); + (struct iscsi_daemon_request *)arg, false)); +#ifdef COMPAT_FREEBSD13 + case ISCSIDWAIT13: + return (iscsi_ioctl_daemon_wait(sc, + (struct iscsi_daemon_request *)arg, true)); +#endif + case ISCSIDLIMITS: + return (iscsi_ioctl_daemon_limits(sc, + (struct iscsi_daemon_limits *)arg)); case ISCSIDHANDOFF: return (iscsi_ioctl_daemon_handoff(sc, (struct iscsi_daemon_handoff *)arg)); |