Commit 1f7babf6d5ca24460694556d617cd17ae8be2ed4

Authored by Mark McLoughlin
Committed by Anthony Liguori
1 parent b664e367

net: handle EAGAIN from tapfd write()

If a write() on tapfd returns EAGAIN, return zero so that the packet
gets queued (in the case of async send) and enable polling tapfd for
writing.

When tapfd becomes writable, disable write polling and flush any queued
packets.

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Showing 1 changed file with 25 additions and 2 deletions
... ... @@ -1044,19 +1044,21 @@ typedef struct TAPState {
1044 1044 char down_script_arg[128];
1045 1045 uint8_t buf[4096];
1046 1046 unsigned int read_poll : 1;
  1047 + unsigned int write_poll : 1;
1047 1048 } TAPState;
1048 1049  
1049 1050 static int launch_script(const char *setup_script, const char *ifname, int fd);
1050 1051  
1051 1052 static int tap_can_send(void *opaque);
1052 1053 static void tap_send(void *opaque);
  1054 +static void tap_writable(void *opaque);
1053 1055  
1054 1056 static void tap_update_fd_handler(TAPState *s)
1055 1057 {
1056 1058 qemu_set_fd_handler2(s->fd,
1057 1059 s->read_poll ? tap_can_send : NULL,
1058 1060 s->read_poll ? tap_send : NULL,
1059   - NULL,
  1061 + s->write_poll ? tap_writable : NULL,
1060 1062 s);
1061 1063 }
1062 1064  
... ... @@ -1066,6 +1068,21 @@ static void tap_read_poll(TAPState *s, int enable)
1066 1068 tap_update_fd_handler(s);
1067 1069 }
1068 1070  
  1071 +static void tap_write_poll(TAPState *s, int enable)
  1072 +{
  1073 + s->write_poll = !!enable;
  1074 + tap_update_fd_handler(s);
  1075 +}
  1076 +
  1077 +static void tap_writable(void *opaque)
  1078 +{
  1079 + TAPState *s = opaque;
  1080 +
  1081 + tap_write_poll(s, 0);
  1082 +
  1083 + qemu_flush_queued_packets(s->vc);
  1084 +}
  1085 +
1069 1086 static ssize_t tap_receive_iov(VLANClientState *vc, const struct iovec *iov,
1070 1087 int iovcnt)
1071 1088 {
... ... @@ -1074,7 +1091,12 @@ static ssize_t tap_receive_iov(VLANClientState *vc, const struct iovec *iov,
1074 1091  
1075 1092 do {
1076 1093 len = writev(s->fd, iov, iovcnt);
1077   - } while (len == -1 && (errno == EINTR || errno == EAGAIN));
  1094 + } while (len == -1 && errno == EINTR);
  1095 +
  1096 + if (len == -1 && errno == EAGAIN) {
  1097 + tap_write_poll(s, 1);
  1098 + return 0;
  1099 + }
1078 1100  
1079 1101 return len;
1080 1102 }
... ... @@ -1150,6 +1172,7 @@ static void tap_cleanup(VLANClientState *vc)
1150 1172 launch_script(s->down_script, s->down_script_arg, s->fd);
1151 1173  
1152 1174 tap_read_poll(s, 0);
  1175 + tap_write_poll(s, 0);
1153 1176 close(s->fd);
1154 1177 qemu_free(s);
1155 1178 }
... ...