diff options
Diffstat (limited to 'drivers/vhost/net.c')
-rw-r--r-- | drivers/vhost/net.c | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index df5b6b971f26..d219070fed3d 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c | |||
@@ -98,7 +98,8 @@ static void tx_poll_start(struct vhost_net *net, struct socket *sock) | |||
98 | static void handle_tx(struct vhost_net *net) | 98 | static void handle_tx(struct vhost_net *net) |
99 | { | 99 | { |
100 | struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_TX]; | 100 | struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_TX]; |
101 | unsigned head, out, in, s; | 101 | unsigned out, in, s; |
102 | int head; | ||
102 | struct msghdr msg = { | 103 | struct msghdr msg = { |
103 | .msg_name = NULL, | 104 | .msg_name = NULL, |
104 | .msg_namelen = 0, | 105 | .msg_namelen = 0, |
@@ -135,6 +136,9 @@ static void handle_tx(struct vhost_net *net) | |||
135 | ARRAY_SIZE(vq->iov), | 136 | ARRAY_SIZE(vq->iov), |
136 | &out, &in, | 137 | &out, &in, |
137 | NULL, NULL); | 138 | NULL, NULL); |
139 | /* On error, stop handling until the next kick. */ | ||
140 | if (unlikely(head < 0)) | ||
141 | break; | ||
138 | /* Nothing new? Wait for eventfd to tell us they refilled. */ | 142 | /* Nothing new? Wait for eventfd to tell us they refilled. */ |
139 | if (head == vq->num) { | 143 | if (head == vq->num) { |
140 | wmem = atomic_read(&sock->sk->sk_wmem_alloc); | 144 | wmem = atomic_read(&sock->sk->sk_wmem_alloc); |
@@ -173,8 +177,8 @@ static void handle_tx(struct vhost_net *net) | |||
173 | break; | 177 | break; |
174 | } | 178 | } |
175 | if (err != len) | 179 | if (err != len) |
176 | pr_err("Truncated TX packet: " | 180 | pr_debug("Truncated TX packet: " |
177 | " len %d != %zd\n", err, len); | 181 | " len %d != %zd\n", err, len); |
178 | vhost_add_used_and_signal(&net->dev, vq, head, 0); | 182 | vhost_add_used_and_signal(&net->dev, vq, head, 0); |
179 | total_len += len; | 183 | total_len += len; |
180 | if (unlikely(total_len >= VHOST_NET_WEIGHT)) { | 184 | if (unlikely(total_len >= VHOST_NET_WEIGHT)) { |
@@ -192,7 +196,8 @@ static void handle_tx(struct vhost_net *net) | |||
192 | static void handle_rx(struct vhost_net *net) | 196 | static void handle_rx(struct vhost_net *net) |
193 | { | 197 | { |
194 | struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_RX]; | 198 | struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_RX]; |
195 | unsigned head, out, in, log, s; | 199 | unsigned out, in, log, s; |
200 | int head; | ||
196 | struct vhost_log *vq_log; | 201 | struct vhost_log *vq_log; |
197 | struct msghdr msg = { | 202 | struct msghdr msg = { |
198 | .msg_name = NULL, | 203 | .msg_name = NULL, |
@@ -228,6 +233,9 @@ static void handle_rx(struct vhost_net *net) | |||
228 | ARRAY_SIZE(vq->iov), | 233 | ARRAY_SIZE(vq->iov), |
229 | &out, &in, | 234 | &out, &in, |
230 | vq_log, &log); | 235 | vq_log, &log); |
236 | /* On error, stop handling until the next kick. */ | ||
237 | if (unlikely(head < 0)) | ||
238 | break; | ||
231 | /* OK, now we need to know about added descriptors. */ | 239 | /* OK, now we need to know about added descriptors. */ |
232 | if (head == vq->num) { | 240 | if (head == vq->num) { |
233 | if (unlikely(vhost_enable_notify(vq))) { | 241 | if (unlikely(vhost_enable_notify(vq))) { |
@@ -267,8 +275,8 @@ static void handle_rx(struct vhost_net *net) | |||
267 | } | 275 | } |
268 | /* TODO: Should check and handle checksum. */ | 276 | /* TODO: Should check and handle checksum. */ |
269 | if (err > len) { | 277 | if (err > len) { |
270 | pr_err("Discarded truncated rx packet: " | 278 | pr_debug("Discarded truncated rx packet: " |
271 | " len %d > %zd\n", err, len); | 279 | " len %d > %zd\n", err, len); |
272 | vhost_discard_vq_desc(vq); | 280 | vhost_discard_vq_desc(vq); |
273 | continue; | 281 | continue; |
274 | } | 282 | } |
@@ -526,11 +534,16 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd) | |||
526 | rcu_assign_pointer(vq->private_data, sock); | 534 | rcu_assign_pointer(vq->private_data, sock); |
527 | vhost_net_enable_vq(n, vq); | 535 | vhost_net_enable_vq(n, vq); |
528 | done: | 536 | done: |
537 | mutex_unlock(&vq->mutex); | ||
538 | |||
529 | if (oldsock) { | 539 | if (oldsock) { |
530 | vhost_net_flush_vq(n, index); | 540 | vhost_net_flush_vq(n, index); |
531 | fput(oldsock->file); | 541 | fput(oldsock->file); |
532 | } | 542 | } |
533 | 543 | ||
544 | mutex_unlock(&n->dev.mutex); | ||
545 | return 0; | ||
546 | |||
534 | err_vq: | 547 | err_vq: |
535 | mutex_unlock(&vq->mutex); | 548 | mutex_unlock(&vq->mutex); |
536 | err: | 549 | err: |