From owner-svn-src-stable-11@freebsd.org Tue Feb 28 06:29:46 2017 Return-Path: Delivered-To: svn-src-stable-11@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 37E6BCF11A6; Tue, 28 Feb 2017 06:29:46 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id EE20B3C3; Tue, 28 Feb 2017 06:29:45 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v1S6Tjfo088668; Tue, 28 Feb 2017 06:29:45 GMT (envelope-from mav@FreeBSD.org) Received: (from mav@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v1S6Tjpx088667; Tue, 28 Feb 2017 06:29:45 GMT (envelope-from mav@FreeBSD.org) Message-Id: <201702280629.v1S6Tjpx088667@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mav set sender to mav@FreeBSD.org using -f From: Alexander Motin Date: Tue, 28 Feb 2017 06:29:45 +0000 (UTC) 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 X-SVN-Group: stable-11 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-11@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for only the 11-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 28 Feb 2017 06:29:46 -0000 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");