# HG changeset patch # User anthony@localhost.localdomain # Node ID 32d5f77cf5e8c5a15b38b1fa86f588f374ebd3ad # Parent 0e52f303222037247747558d43d72b5b89817828 Sometimes partial reads occur even though there's still data to be read. This patch makes sure that we read all the data that's available to read. This has a huge performance impact for the shmem character device since. diff -r 0e52f3032220 -r 32d5f77cf5e8 vl.c --- a/vl.c Sun Jul 16 17:04:01 2006 +++ b/vl.c Sun Jul 16 17:23:21 2006 @@ -1205,6 +1205,29 @@ return s->max_size; } +static int fd_read_blocks(int fd) +{ + fd_set rfds; + struct timeval tv; + int ret; + + again: + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + + tv.tv_sec = 0; + tv.tv_usec = 0; + + ret = select(fd + 1, &rfds, NULL, NULL, &tv); + if (ret == -1) { + if (errno == EINTR) + goto again; + return -1; + } + + return !FD_ISSET(fd, &rfds); +} + static void fd_chr_read(void *opaque) { CharDriverState *chr = opaque; @@ -1217,7 +1240,25 @@ len = s->max_size; if (len == 0) return; - size = read(s->fd_in, buf, len); + + for (size = 0; size < len;) { + int l; + l = read(s->fd_in, buf + size, len - size); + if (l == -1) { + if (errno == EINTR) + continue; + break; + } else if (l == 0) { + break; + } + + size += l; + + if (size < len && fd_read_blocks(s->fd_in)) + break; + } + + if (size > 0) { s->fd_read(s->fd_opaque, buf, size); }