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>