Index: sys/crypto/aesni/aesni.c =================================================================== --- sys/crypto/aesni/aesni.c +++ sys/crypto/aesni/aesni.c @@ -399,13 +399,44 @@ return (error); } +/* + * Find an iovec in the given uio that contains a + * vector. To qualify, the vector + * must be entirely contained with a single iovec. + * If it is found, return the address; otherwise, + * return NULL. + */ +static void * +find_vector(struct uio *uio, size_t start, size_t length) +{ + int indx; + size_t curr_offset = 0, end = start + length; + + for (indx = 0; + indx < uio->uio_iovcnt && curr_offset <= start; + indx++) { + /* + * See if is in the range + * of iov[indx].iov_len> + */ + struct iovec *iov = &uio->uio_iov[indx]; + if (curr_offset <= start && + ((curr_offset + iov->iov_len) >= end)) { + size_t offset = start - curr_offset; + uint8_t *retval = iov->iov_base; + return (void*)(retval + offset); + } + curr_offset += iov->iov_len; + } + return NULL; +} + static uint8_t * aesni_cipher_alloc(struct cryptodesc *enccrd, struct cryptop *crp, bool *allocated) { struct mbuf *m; struct uio *uio; - struct iovec *iov; uint8_t *addr; if (crp->crp_flags & CRYPTO_F_IMBUF) { @@ -415,10 +446,18 @@ addr = mtod(m, uint8_t *); } else if (crp->crp_flags & CRYPTO_F_IOV) { uio = (struct uio *)crp->crp_buf; - if (uio->uio_iovcnt != 1) - goto alloc; - iov = uio->uio_iov; - addr = (uint8_t *)iov->iov_base; + /* + * If the data range we need is entirely + * contained within one iovec, we should + * use that, instead of trying to allocate + * memory. + */ + addr = find_vector(uio, enccrd->crd_skip, enccrd->crd_len); + if (addr != NULL) { + *allocated = 0; + return (addr); + } + goto alloc; } else addr = (uint8_t *)crp->crp_buf; *allocated = false;