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,19 +1044,21 @@ typedef struct TAPState {
1044 char down_script_arg[128]; 1044 char down_script_arg[128];
1045 uint8_t buf[4096]; 1045 uint8_t buf[4096];
1046 unsigned int read_poll : 1; 1046 unsigned int read_poll : 1;
  1047 + unsigned int write_poll : 1;
1047 } TAPState; 1048 } TAPState;
1048 1049
1049 static int launch_script(const char *setup_script, const char *ifname, int fd); 1050 static int launch_script(const char *setup_script, const char *ifname, int fd);
1050 1051
1051 static int tap_can_send(void *opaque); 1052 static int tap_can_send(void *opaque);
1052 static void tap_send(void *opaque); 1053 static void tap_send(void *opaque);
  1054 +static void tap_writable(void *opaque);
1053 1055
1054 static void tap_update_fd_handler(TAPState *s) 1056 static void tap_update_fd_handler(TAPState *s)
1055 { 1057 {
1056 qemu_set_fd_handler2(s->fd, 1058 qemu_set_fd_handler2(s->fd,
1057 s->read_poll ? tap_can_send : NULL, 1059 s->read_poll ? tap_can_send : NULL,
1058 s->read_poll ? tap_send : NULL, 1060 s->read_poll ? tap_send : NULL,
1059 - NULL, 1061 + s->write_poll ? tap_writable : NULL,
1060 s); 1062 s);
1061 } 1063 }
1062 1064
@@ -1066,6 +1068,21 @@ static void tap_read_poll(TAPState *s, int enable) @@ -1066,6 +1068,21 @@ static void tap_read_poll(TAPState *s, int enable)
1066 tap_update_fd_handler(s); 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 static ssize_t tap_receive_iov(VLANClientState *vc, const struct iovec *iov, 1086 static ssize_t tap_receive_iov(VLANClientState *vc, const struct iovec *iov,
1070 int iovcnt) 1087 int iovcnt)
1071 { 1088 {
@@ -1074,7 +1091,12 @@ static ssize_t tap_receive_iov(VLANClientState *vc, const struct iovec *iov, @@ -1074,7 +1091,12 @@ static ssize_t tap_receive_iov(VLANClientState *vc, const struct iovec *iov,
1074 1091
1075 do { 1092 do {
1076 len = writev(s->fd, iov, iovcnt); 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 return len; 1101 return len;
1080 } 1102 }
@@ -1150,6 +1172,7 @@ static void tap_cleanup(VLANClientState *vc) @@ -1150,6 +1172,7 @@ static void tap_cleanup(VLANClientState *vc)
1150 launch_script(s->down_script, s->down_script_arg, s->fd); 1172 launch_script(s->down_script, s->down_script_arg, s->fd);
1151 1173
1152 tap_read_poll(s, 0); 1174 tap_read_poll(s, 0);
  1175 + tap_write_poll(s, 0);
1153 close(s->fd); 1176 close(s->fd);
1154 qemu_free(s); 1177 qemu_free(s);
1155 } 1178 }