# HG changeset patch # User Matt Johnston # Date 1426863212 -28800 # Node ID 686cd3e8e13edef07eae7e4b7b17691f4fc65913 # Parent ce21d0bfaf9842deeb0b9cabbdebaa5c43d4e14c avoid malloc for iovec diff -r ce21d0bfaf98 -r 686cd3e8e13e common-channel.c --- a/common-channel.c Mon Mar 16 21:33:01 2015 +0800 +++ b/common-channel.c Fri Mar 20 22:53:32 2015 +0800 @@ -482,7 +482,7 @@ if (written < 0) { if (errno != EINTR && errno != EAGAIN) { - TRACE(("errno %d len %d", errno, len)) + TRACE(("errno %d", errno)) close_chan_fd(channel, fd, SHUT_WR); } } else { diff -r ce21d0bfaf98 -r 686cd3e8e13e netio.c --- a/netio.c Mon Mar 16 21:33:01 2015 +0800 +++ b/netio.c Fri Mar 20 22:53:32 2015 +0800 @@ -72,6 +72,7 @@ int fastopen = 0; #ifdef DROPBEAR_TCP_FAST_OPEN struct msghdr message; + struct iovec message; #endif for (r = c->res_iter; r; r = r->ai_next) @@ -99,8 +100,11 @@ message.msg_namelen = r->ai_addrlen; if (c->writequeue) { - int iovlen; /* Linux msg_iovlen is a size_t */ - message.msg_iov = packet_queue_to_iovec(c->writequeue, &iovlen); + /* 6 is arbitrary, enough to hold initial packets */ + int iovlen = 6; /* Linux msg_iovlen is a size_t */ + struct iov[6]; + packet_queue_to_iovec(c->writequeue, iov, &iovlen); + message.msg_iov = &iov; message.msg_iovlen = iovlen; res = sendmsg(c->sock, &message, MSG_FASTOPEN); if (res < 0 && errno != EINPROGRESS) { @@ -114,7 +118,6 @@ /* Set to NULL to avoid trying again */ c->writequeue = NULL; } - m_free(message.msg_iov); packet_queue_consume(c->writequeue, res); } #endif @@ -258,8 +261,7 @@ c->writequeue = writequeue; } -struct iovec * packet_queue_to_iovec(struct Queue *queue, int *ret_iov_count) { - struct iovec *iov = NULL; +void packet_queue_to_iovec(struct Queue *queue, struct iovec *iov, unsigned int *iov_count) { struct Link *l; unsigned int i; int len; @@ -269,9 +271,8 @@ #define IOV_MAX UIO_MAXIOV #endif - *ret_iov_count = MIN(queue->count, IOV_MAX); + *iov_count = MIN(MIN(queue->count, IOV_MAX), *iov_count); - iov = m_malloc(sizeof(*iov) * *ret_iov_count); for (l = queue->head, i = 0; l; l = l->link, i++) { writebuf = (buffer*)l->item; @@ -282,8 +283,6 @@ iov[i].iov_base = buf_getptr(writebuf, len); iov[i].iov_len = len; } - - return iov; } void packet_queue_consume(struct Queue *queue, ssize_t written) { diff -r ce21d0bfaf98 -r 686cd3e8e13e netio.h --- a/netio.h Mon Mar 16 21:33:01 2015 +0800 +++ b/netio.h Fri Mar 20 22:53:32 2015 +0800 @@ -44,7 +44,8 @@ void connect_set_writequeue(struct dropbear_progress_connection *c, struct Queue *writequeue); /* TODO: writev #ifdef guard */ -struct iovec * packet_queue_to_iovec(struct Queue *queue, int *ret_iov_count); +/* Fills out iov which contains iov_count slots, returning the number filled in iov_count */ +void packet_queue_to_iovec(struct Queue *queue, struct iovec *iov, unsigned int *iov_count); void packet_queue_consume(struct Queue *queue, ssize_t written); #ifdef DROPBEAR_TCP_FAST_OPEN diff -r ce21d0bfaf98 -r 686cd3e8e13e packet.c --- a/packet.c Mon Mar 16 21:33:01 2015 +0800 +++ b/packet.c Fri Mar 20 22:53:32 2015 +0800 @@ -58,8 +58,9 @@ ssize_t written; #ifdef HAVE_WRITEV - struct iovec *iov = NULL; - int iov_count; + /* 50 is somewhat arbitrary */ + int iov_count = 50; + struct iovec iov[50]; #endif TRACE2(("enter write_packet")) @@ -67,7 +68,7 @@ #if defined(HAVE_WRITEV) && (defined(IOV_MAX) || defined(UIO_MAXIOV)) - iov = packet_queue_to_iovec(&ses.writequeue, &iov_count); + packet_queue_to_iovec(&ses.writequeue, iov, &iov_count); /* This may return EAGAIN. The main loop sometimes calls write_packet() without bothering to test with select() since it's likely to be necessary */ @@ -75,13 +76,11 @@ if (written < 0) { if (errno == EINTR || errno == EAGAIN) { TRACE2(("leave write_packet: EINTR")) - m_free(iov); return; } else { dropbear_exit("Error writing: %s", strerror(errno)); } } - m_free(iov); packet_queue_consume(&ses.writequeue, written);