Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 28 Feb 2017 06:29:45 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r314377 - stable/11/sys/dev/iscsi
Message-ID:  <201702280629.v1S6Tjpx088667@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Tue Feb 28 06:29:44 2017
New Revision: 314377
URL: https://svnweb.freebsd.org/changeset/base/314377

Log:
  MFC r313731: Do not rely on data alignment after m_pullup().
  
  In general case m_pullup() does not really guarantee any data alignment.
  Instead of depenting on side effects caused by data being always copied
  out of mbuf cluster (which is probably a bug by itself), always allocate
  aligned BHS buffer and read data there directly from socket.
  
  While there, reuse new icl_conn_receive_buf() function to read digests.
  The code could probably be even more optimized to aggregate those reads,
  but until that done, this is still easier then the way it was before.

Modified:
  stable/11/sys/dev/iscsi/icl_soft.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/dev/iscsi/icl_soft.c
==============================================================================
--- stable/11/sys/dev/iscsi/icl_soft.c	Tue Feb 28 06:28:17 2017	(r314376)
+++ stable/11/sys/dev/iscsi/icl_soft.c	Tue Feb 28 06:29:44 2017	(r314377)
@@ -169,6 +169,40 @@ icl_conn_receive(struct icl_conn *ic, si
 	return (m);
 }
 
+static int
+icl_conn_receive_buf(struct icl_conn *ic, void *buf, size_t len)
+{
+	struct iovec iov[1];
+	struct uio uio;
+	struct socket *so;
+	int error, flags;
+
+	so = ic->ic_socket;
+
+	memset(&uio, 0, sizeof(uio));
+	iov[0].iov_base = buf;
+	iov[0].iov_len = len;
+	uio.uio_iov = iov;
+	uio.uio_iovcnt = 1;
+	uio.uio_offset = 0;
+	uio.uio_resid = len;
+	uio.uio_segflg = UIO_SYSSPACE;
+	uio.uio_rw = UIO_READ;
+
+	flags = MSG_DONTWAIT;
+	error = soreceive(so, NULL, &uio, NULL, NULL, &flags);
+	if (error != 0) {
+		ICL_DEBUG("soreceive error %d", error);
+		return (-1);
+	}
+	if (uio.uio_resid != 0) {
+		ICL_DEBUG("short read");
+		return (-1);
+	}
+
+	return (0);
+}
+
 static struct icl_pdu *
 icl_pdu_new_empty(struct icl_conn *ic, int flags)
 {
@@ -229,7 +263,7 @@ icl_soft_conn_new_pdu(struct icl_conn *i
 	ip->ip_bhs_mbuf = m_getm2(NULL, sizeof(struct iscsi_bhs),
 	    flags, MT_DATA, M_PKTHDR);
 	if (ip->ip_bhs_mbuf == NULL) {
-		ICL_WARN("failed to allocate %zd bytes", sizeof(*ip));
+		ICL_WARN("failed to allocate BHS mbuf");
 		icl_pdu_free(ip);
 		return (NULL);
 	}
@@ -308,28 +342,13 @@ icl_pdu_size(const struct icl_pdu *respo
 static int
 icl_pdu_receive_bhs(struct icl_pdu *request, size_t *availablep)
 {
-	struct mbuf *m;
 
-	m = icl_conn_receive(request->ip_conn, sizeof(struct iscsi_bhs));
-	if (m == NULL) {
+	if (icl_conn_receive_buf(request->ip_conn,
+	    request->ip_bhs, sizeof(struct iscsi_bhs))) {
 		ICL_DEBUG("failed to receive BHS");
 		return (-1);
 	}
 
-	request->ip_bhs_mbuf = m_pullup(m, sizeof(struct iscsi_bhs));
-	if (request->ip_bhs_mbuf == NULL) {
-		ICL_WARN("m_pullup failed");
-		return (-1);
-	}
-	request->ip_bhs = mtod(request->ip_bhs_mbuf, struct iscsi_bhs *);
-
-	/*
-	 * XXX: For architectures with strict alignment requirements
-	 * 	we may need to allocate ip_bhs and copy the data into it.
-	 * 	For some reason, though, not doing this doesn't seem
-	 * 	to cause problems; tested on sparc64.
-	 */
-
 	*availablep -= sizeof(struct iscsi_bhs);
 	return (0);
 }
@@ -371,22 +390,17 @@ icl_mbuf_to_crc32c(const struct mbuf *m0
 static int
 icl_pdu_check_header_digest(struct icl_pdu *request, size_t *availablep)
 {
-	struct mbuf *m;
 	uint32_t received_digest, valid_digest;
 
 	if (request->ip_conn->ic_header_crc32c == false)
 		return (0);
 
-	m = icl_conn_receive(request->ip_conn, ISCSI_HEADER_DIGEST_SIZE);
-	if (m == NULL) {
+	CTASSERT(sizeof(received_digest) == ISCSI_HEADER_DIGEST_SIZE);
+	if (icl_conn_receive_buf(request->ip_conn,
+	    &received_digest, ISCSI_HEADER_DIGEST_SIZE)) {
 		ICL_DEBUG("failed to receive header digest");
 		return (-1);
 	}
-
-	CTASSERT(sizeof(received_digest) == ISCSI_HEADER_DIGEST_SIZE);
-	m_copydata(m, 0, ISCSI_HEADER_DIGEST_SIZE, (void *)&received_digest);
-	m_freem(m);
-
 	*availablep -= ISCSI_HEADER_DIGEST_SIZE;
 
 	/* Temporary attach AHS to BHS to calculate header digest. */
@@ -526,7 +540,6 @@ icl_pdu_receive_data_segment(struct icl_
 static int
 icl_pdu_check_data_digest(struct icl_pdu *request, size_t *availablep)
 {
-	struct mbuf *m;
 	uint32_t received_digest, valid_digest;
 
 	if (request->ip_conn->ic_data_crc32c == false)
@@ -535,16 +548,12 @@ icl_pdu_check_data_digest(struct icl_pdu
 	if (request->ip_data_len == 0)
 		return (0);
 
-	m = icl_conn_receive(request->ip_conn, ISCSI_DATA_DIGEST_SIZE);
-	if (m == NULL) {
+	CTASSERT(sizeof(received_digest) == ISCSI_DATA_DIGEST_SIZE);
+	if (icl_conn_receive_buf(request->ip_conn,
+	    &received_digest, ISCSI_DATA_DIGEST_SIZE)) {
 		ICL_DEBUG("failed to receive data digest");
 		return (-1);
 	}
-
-	CTASSERT(sizeof(received_digest) == ISCSI_DATA_DIGEST_SIZE);
-	m_copydata(m, 0, ISCSI_DATA_DIGEST_SIZE, (void *)&received_digest);
-	m_freem(m);
-
 	*availablep -= ISCSI_DATA_DIGEST_SIZE;
 
 	/*
@@ -580,7 +589,7 @@ icl_conn_receive_pdu(struct icl_conn *ic
 	if (ic->ic_receive_state == ICL_CONN_STATE_BHS) {
 		KASSERT(ic->ic_receive_pdu == NULL,
 		    ("ic->ic_receive_pdu != NULL"));
-		request = icl_pdu_new_empty(ic, M_NOWAIT);
+		request = icl_soft_conn_new_pdu(ic, M_NOWAIT);
 		if (request == NULL) {
 			ICL_DEBUG("failed to allocate PDU; "
 			    "dropping connection");



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201702280629.v1S6Tjpx088667>