diff options
author | Jason Wang <jasowang@redhat.com> | 2013-09-02 04:40:58 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-09-03 22:46:57 -0400 |
commit | c49e4e573be86acd36c747511ea5dc76be122206 (patch) | |
tree | 682e11f8da283fb6ddc3ab5bd8bbae3486726afd /drivers/vhost | |
parent | c92112aed3f0b14fdd2dbd9f192cce1af22c0e1c (diff) |
vhost: switch to use vhost_add_used_n()
Let vhost_add_used() to use vhost_add_used_n() to reduce the code
duplication. To avoid the overhead brought by __copy_to_user(). We will use
put_user() when one used need to be added.
Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/vhost')
-rw-r--r-- | drivers/vhost/vhost.c | 54 |
1 files changed, 12 insertions, 42 deletions
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 448efe01f18a..9a9502a4aa50 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c | |||
@@ -1332,48 +1332,9 @@ EXPORT_SYMBOL_GPL(vhost_discard_vq_desc); | |||
1332 | * want to notify the guest, using eventfd. */ | 1332 | * want to notify the guest, using eventfd. */ |
1333 | int vhost_add_used(struct vhost_virtqueue *vq, unsigned int head, int len) | 1333 | int vhost_add_used(struct vhost_virtqueue *vq, unsigned int head, int len) |
1334 | { | 1334 | { |
1335 | struct vring_used_elem __user *used; | 1335 | struct vring_used_elem heads = { head, len }; |
1336 | 1336 | ||
1337 | /* The virtqueue contains a ring of used buffers. Get a pointer to the | 1337 | return vhost_add_used_n(vq, &heads, 1); |
1338 | * next entry in that used ring. */ | ||
1339 | used = &vq->used->ring[vq->last_used_idx % vq->num]; | ||
1340 | if (__put_user(head, &used->id)) { | ||
1341 | vq_err(vq, "Failed to write used id"); | ||
1342 | return -EFAULT; | ||
1343 | } | ||
1344 | if (__put_user(len, &used->len)) { | ||
1345 | vq_err(vq, "Failed to write used len"); | ||
1346 | return -EFAULT; | ||
1347 | } | ||
1348 | /* Make sure buffer is written before we update index. */ | ||
1349 | smp_wmb(); | ||
1350 | if (__put_user(vq->last_used_idx + 1, &vq->used->idx)) { | ||
1351 | vq_err(vq, "Failed to increment used idx"); | ||
1352 | return -EFAULT; | ||
1353 | } | ||
1354 | if (unlikely(vq->log_used)) { | ||
1355 | /* Make sure data is seen before log. */ | ||
1356 | smp_wmb(); | ||
1357 | /* Log used ring entry write. */ | ||
1358 | log_write(vq->log_base, | ||
1359 | vq->log_addr + | ||
1360 | ((void __user *)used - (void __user *)vq->used), | ||
1361 | sizeof *used); | ||
1362 | /* Log used index update. */ | ||
1363 | log_write(vq->log_base, | ||
1364 | vq->log_addr + offsetof(struct vring_used, idx), | ||
1365 | sizeof vq->used->idx); | ||
1366 | if (vq->log_ctx) | ||
1367 | eventfd_signal(vq->log_ctx, 1); | ||
1368 | } | ||
1369 | vq->last_used_idx++; | ||
1370 | /* If the driver never bothers to signal in a very long while, | ||
1371 | * used index might wrap around. If that happens, invalidate | ||
1372 | * signalled_used index we stored. TODO: make sure driver | ||
1373 | * signals at least once in 2^16 and remove this. */ | ||
1374 | if (unlikely(vq->last_used_idx == vq->signalled_used)) | ||
1375 | vq->signalled_used_valid = false; | ||
1376 | return 0; | ||
1377 | } | 1338 | } |
1378 | EXPORT_SYMBOL_GPL(vhost_add_used); | 1339 | EXPORT_SYMBOL_GPL(vhost_add_used); |
1379 | 1340 | ||
@@ -1387,7 +1348,16 @@ static int __vhost_add_used_n(struct vhost_virtqueue *vq, | |||
1387 | 1348 | ||
1388 | start = vq->last_used_idx % vq->num; | 1349 | start = vq->last_used_idx % vq->num; |
1389 | used = vq->used->ring + start; | 1350 | used = vq->used->ring + start; |
1390 | if (__copy_to_user(used, heads, count * sizeof *used)) { | 1351 | if (count == 1) { |
1352 | if (__put_user(heads[0].id, &used->id)) { | ||
1353 | vq_err(vq, "Failed to write used id"); | ||
1354 | return -EFAULT; | ||
1355 | } | ||
1356 | if (__put_user(heads[0].len, &used->len)) { | ||
1357 | vq_err(vq, "Failed to write used len"); | ||
1358 | return -EFAULT; | ||
1359 | } | ||
1360 | } else if (__copy_to_user(used, heads, count * sizeof *used)) { | ||
1391 | vq_err(vq, "Failed to write used"); | 1361 | vq_err(vq, "Failed to write used"); |
1392 | return -EFAULT; | 1362 | return -EFAULT; |
1393 | } | 1363 | } |