Page MenuHomeFreeBSD

D30134.diff
No OneTemporary

D30134.diff

diff --git a/sys/opencrypto/criov.c b/sys/opencrypto/criov.c
--- a/sys/opencrypto/criov.c
+++ b/sys/opencrypto/criov.c
@@ -239,6 +239,99 @@
}
#endif /* CRYPTO_MAY_HAVE_VMPAGE */
+/*
+ * Given a starting page in an m_epg, determine the length of the
+ * current physically contiguous segment.
+ */
+static __inline size_t
+m_epg_pages_extent(struct mbuf *m, int idx, u_int pglen)
+{
+ size_t len;
+ u_int i;
+
+ len = pglen;
+ for (i = idx + 1; i < m->m_epg_npgs; i++) {
+ if (m->m_epg_pa[i - 1] + PAGE_SIZE != m->m_epg_pa[i])
+ break;
+ len += m_epg_pagelen(m, i, 0);
+ }
+ return (len);
+}
+
+static __inline void *
+m_epg_segbase(struct mbuf *m, size_t offset)
+{
+ u_int i, pglen, pgoff;
+
+ offset += mtod(m, vm_offset_t);
+ if (offset < m->m_epg_hdrlen)
+ return (m->m_epg_hdr + offset);
+ offset -= m->m_epg_hdrlen;
+ pgoff = m->m_epg_1st_off;
+ for (i = 0; i < m->m_epg_npgs; i++) {
+ pglen = m_epg_pagelen(m, i, pgoff);
+ if (offset < pglen)
+ return ((void *)PHYS_TO_DMAP(m->m_epg_pa[i] + pgoff +
+ offset));
+ offset -= pglen;
+ pgoff = 0;
+ }
+ KASSERT(offset <= m->m_epg_trllen, ("%s: offset beyond trailer",
+ __func__));
+ return (m->m_epg_trail + offset);
+}
+
+static __inline size_t
+m_epg_seglen(struct mbuf *m, size_t offset)
+{
+ u_int i, pglen, pgoff;
+
+ offset += mtod(m, vm_offset_t);
+ if (offset < m->m_epg_hdrlen)
+ return (m->m_epg_hdrlen - offset);
+ offset -= m->m_epg_hdrlen;
+ pgoff = m->m_epg_1st_off;
+ for (i = 0; i < m->m_epg_npgs; i++) {
+ pglen = m_epg_pagelen(m, i, pgoff);
+ if (offset < pglen)
+ return (m_epg_pages_extent(m, i, pglen) - offset);
+ offset -= pglen;
+ pgoff = 0;
+ }
+ KASSERT(offset <= m->m_epg_trllen, ("%s: offset beyond trailer",
+ __func__));
+ return (m->m_epg_trllen - offset);
+}
+
+static __inline void *
+m_epg_contiguous_subsegment(struct mbuf *m, size_t skip, size_t len)
+{
+ u_int i, pglen, pgoff;
+
+ skip += mtod(m, vm_offset_t);
+ if (skip < m->m_epg_hdrlen) {
+ if (len > m->m_epg_hdrlen - skip)
+ return (NULL);
+ return (m->m_epg_hdr + skip);
+ }
+ skip -= m->m_epg_hdrlen;
+ pgoff = m->m_epg_1st_off;
+ for (i = 0; i < m->m_epg_npgs; i++) {
+ pglen = m_epg_pagelen(m, i, pgoff);
+ if (skip < pglen) {
+ if (len > m_epg_pages_extent(m, i, pglen) - skip)
+ return (NULL);
+ return ((void *)PHYS_TO_DMAP(m->m_epg_pa[i] + pgoff +
+ skip));
+ }
+ skip -= pglen;
+ pgoff = 0;
+ }
+ KASSERT(skip <= m->m_epg_trllen && len <= m->m_epg_trllen - skip,
+ ("%s: segment beyond trailer", __func__));
+ return (m->m_epg_trail + skip);
+}
+
void
crypto_cursor_init(struct crypto_buffer_cursor *cc,
const struct crypto_buffer *cb)
@@ -345,8 +438,8 @@
case CRYPTO_BUF_MBUF:
if (cc->cc_mbuf == NULL)
return (NULL);
- KASSERT((cc->cc_mbuf->m_flags & M_EXTPG) == 0,
- ("%s: not supported for unmapped mbufs", __func__));
+ if (cc->cc_mbuf->m_flags & M_EXTPG)
+ return (m_epg_segbase(cc->cc_mbuf, cc->cc_offset));
return (mtod(cc->cc_mbuf, char *) + cc->cc_offset);
case CRYPTO_BUF_VMPAGE:
return ((char *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(
@@ -372,6 +465,8 @@
case CRYPTO_BUF_MBUF:
if (cc->cc_mbuf == NULL)
return (0);
+ if (cc->cc_mbuf->m_flags & M_EXTPG)
+ return (m_epg_seglen(cc->cc_mbuf, cc->cc_offset));
return (cc->cc_mbuf->m_len - cc->cc_offset);
case CRYPTO_BUF_UIO:
return (cc->cc_iov->iov_len - cc->cc_offset);
@@ -401,12 +496,14 @@
break;
case CRYPTO_BUF_MBUF:
for (;;) {
- KASSERT((cc->cc_mbuf->m_flags & M_EXTPG) == 0,
- ("%s: not supported for unmapped mbufs", __func__));
- dst = mtod(cc->cc_mbuf, char *) + cc->cc_offset;
+ /*
+ * This uses m_copyback() for individual
+ * mbufs so that cc_mbuf and cc_offset are
+ * updated.
+ */
remain = cc->cc_mbuf->m_len - cc->cc_offset;
todo = MIN(remain, size);
- memcpy(dst, src, todo);
+ m_copyback(cc->cc_mbuf, cc->cc_offset, todo, src);
src += todo;
if (todo < remain) {
cc->cc_offset += todo;
@@ -482,12 +579,14 @@
break;
case CRYPTO_BUF_MBUF:
for (;;) {
- KASSERT((cc->cc_mbuf->m_flags & M_EXTPG) == 0,
- ("%s: not supported for unmapped mbufs", __func__));
- src = mtod(cc->cc_mbuf, const char *) + cc->cc_offset;
+ /*
+ * This uses m_copydata() for individual
+ * mbufs so that cc_mbuf and cc_offset are
+ * updated.
+ */
remain = cc->cc_mbuf->m_len - cc->cc_offset;
todo = MIN(remain, size);
- memcpy(dst, src, todo);
+ m_copydata(cc->cc_mbuf, cc->cc_offset, todo, dst);
dst += todo;
if (todo < remain) {
cc->cc_offset += todo;
@@ -715,6 +814,8 @@
if (skip + len > m->m_len)
return (NULL);
+ if (m->m_flags & M_EXTPG)
+ return (m_epg_contiguous_subsegment(m, skip, len));
return (mtod(m, char*) + skip);
}

File Metadata

Mime Type
text/plain
Expires
Thu, May 1, 1:09 PM (8 h, 21 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17882009
Default Alt Text
D30134.diff (4 KB)

Event Timeline