aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/iscsi/iscsi.c
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2022-04-18 19:48:42 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2022-04-18 19:53:28 +0000
commit7b02c1e8c6a17d11b69988f3e1b449b783785415 (patch)
tree5fe0254825c92853733bef0d1c1fedc59e6c5942 /sys/dev/iscsi/iscsi.c
parentf0df72273377daf5e1e97b80a4e542362b261a1d (diff)
downloadsrc-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.c110
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));