diff options
author | Michael S. Tsirkin <mst@redhat.com> | 2010-06-24 09:59:59 -0400 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2010-06-27 04:52:25 -0400 |
commit | d5675bd204efd87a174eeea592de23c4c4e7f908 (patch) | |
tree | 11ec7e455d21285da68fa7db40af07ebf45f9d0e /drivers/vhost/vhost.c | |
parent | 38000a94a902e94ca8b5498f7871c6316de8957a (diff) |
vhost: break out of polling loop on error
When ring parsing fails, we currently handle this
as ring empty condition. This means that we enable
kicks and recheck ring empty: if this not empty,
we re-start polling which of course will fail again.
Instead, let's return a negative error code and stop polling.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'drivers/vhost/vhost.c')
-rw-r--r-- | drivers/vhost/vhost.c | 33 |
1 files changed, 17 insertions, 16 deletions
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 3b83382e06eb..5ccd384ec0be 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c | |||
@@ -873,12 +873,13 @@ static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq, | |||
873 | * number of output then some number of input descriptors, it's actually two | 873 | * number of output then some number of input descriptors, it's actually two |
874 | * iovecs, but we pack them into one and note how many of each there were. | 874 | * iovecs, but we pack them into one and note how many of each there were. |
875 | * | 875 | * |
876 | * This function returns the descriptor number found, or vq->num (which | 876 | * This function returns the descriptor number found, or vq->num (which is |
877 | * is never a valid descriptor number) if none was found. */ | 877 | * never a valid descriptor number) if none was found. A negative code is |
878 | unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq, | 878 | * returned on error. */ |
879 | struct iovec iov[], unsigned int iov_size, | 879 | int vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq, |
880 | unsigned int *out_num, unsigned int *in_num, | 880 | struct iovec iov[], unsigned int iov_size, |
881 | struct vhost_log *log, unsigned int *log_num) | 881 | unsigned int *out_num, unsigned int *in_num, |
882 | struct vhost_log *log, unsigned int *log_num) | ||
882 | { | 883 | { |
883 | struct vring_desc desc; | 884 | struct vring_desc desc; |
884 | unsigned int i, head, found = 0; | 885 | unsigned int i, head, found = 0; |
@@ -890,13 +891,13 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq, | |||
890 | if (get_user(vq->avail_idx, &vq->avail->idx)) { | 891 | if (get_user(vq->avail_idx, &vq->avail->idx)) { |
891 | vq_err(vq, "Failed to access avail idx at %p\n", | 892 | vq_err(vq, "Failed to access avail idx at %p\n", |
892 | &vq->avail->idx); | 893 | &vq->avail->idx); |
893 | return vq->num; | 894 | return -EFAULT; |
894 | } | 895 | } |
895 | 896 | ||
896 | if ((u16)(vq->avail_idx - last_avail_idx) > vq->num) { | 897 | if ((u16)(vq->avail_idx - last_avail_idx) > vq->num) { |
897 | vq_err(vq, "Guest moved used index from %u to %u", | 898 | vq_err(vq, "Guest moved used index from %u to %u", |
898 | last_avail_idx, vq->avail_idx); | 899 | last_avail_idx, vq->avail_idx); |
899 | return vq->num; | 900 | return -EFAULT; |
900 | } | 901 | } |
901 | 902 | ||
902 | /* If there's nothing new since last we looked, return invalid. */ | 903 | /* If there's nothing new since last we looked, return invalid. */ |
@@ -912,14 +913,14 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq, | |||
912 | vq_err(vq, "Failed to read head: idx %d address %p\n", | 913 | vq_err(vq, "Failed to read head: idx %d address %p\n", |
913 | last_avail_idx, | 914 | last_avail_idx, |
914 | &vq->avail->ring[last_avail_idx % vq->num]); | 915 | &vq->avail->ring[last_avail_idx % vq->num]); |
915 | return vq->num; | 916 | return -EFAULT; |
916 | } | 917 | } |
917 | 918 | ||
918 | /* If their number is silly, that's an error. */ | 919 | /* If their number is silly, that's an error. */ |
919 | if (head >= vq->num) { | 920 | if (head >= vq->num) { |
920 | vq_err(vq, "Guest says index %u > %u is available", | 921 | vq_err(vq, "Guest says index %u > %u is available", |
921 | head, vq->num); | 922 | head, vq->num); |
922 | return vq->num; | 923 | return -EINVAL; |
923 | } | 924 | } |
924 | 925 | ||
925 | /* When we start there are none of either input nor output. */ | 926 | /* When we start there are none of either input nor output. */ |
@@ -933,19 +934,19 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq, | |||
933 | if (i >= vq->num) { | 934 | if (i >= vq->num) { |
934 | vq_err(vq, "Desc index is %u > %u, head = %u", | 935 | vq_err(vq, "Desc index is %u > %u, head = %u", |
935 | i, vq->num, head); | 936 | i, vq->num, head); |
936 | return vq->num; | 937 | return -EINVAL; |
937 | } | 938 | } |
938 | if (++found > vq->num) { | 939 | if (++found > vq->num) { |
939 | vq_err(vq, "Loop detected: last one at %u " | 940 | vq_err(vq, "Loop detected: last one at %u " |
940 | "vq size %u head %u\n", | 941 | "vq size %u head %u\n", |
941 | i, vq->num, head); | 942 | i, vq->num, head); |
942 | return vq->num; | 943 | return -EINVAL; |
943 | } | 944 | } |
944 | ret = copy_from_user(&desc, vq->desc + i, sizeof desc); | 945 | ret = copy_from_user(&desc, vq->desc + i, sizeof desc); |
945 | if (ret) { | 946 | if (ret) { |
946 | vq_err(vq, "Failed to get descriptor: idx %d addr %p\n", | 947 | vq_err(vq, "Failed to get descriptor: idx %d addr %p\n", |
947 | i, vq->desc + i); | 948 | i, vq->desc + i); |
948 | return vq->num; | 949 | return -EFAULT; |
949 | } | 950 | } |
950 | if (desc.flags & VRING_DESC_F_INDIRECT) { | 951 | if (desc.flags & VRING_DESC_F_INDIRECT) { |
951 | ret = get_indirect(dev, vq, iov, iov_size, | 952 | ret = get_indirect(dev, vq, iov, iov_size, |
@@ -954,7 +955,7 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq, | |||
954 | if (ret < 0) { | 955 | if (ret < 0) { |
955 | vq_err(vq, "Failure detected " | 956 | vq_err(vq, "Failure detected " |
956 | "in indirect descriptor at idx %d\n", i); | 957 | "in indirect descriptor at idx %d\n", i); |
957 | return vq->num; | 958 | return ret; |
958 | } | 959 | } |
959 | continue; | 960 | continue; |
960 | } | 961 | } |
@@ -964,7 +965,7 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq, | |||
964 | if (ret < 0) { | 965 | if (ret < 0) { |
965 | vq_err(vq, "Translation failure %d descriptor idx %d\n", | 966 | vq_err(vq, "Translation failure %d descriptor idx %d\n", |
966 | ret, i); | 967 | ret, i); |
967 | return vq->num; | 968 | return ret; |
968 | } | 969 | } |
969 | if (desc.flags & VRING_DESC_F_WRITE) { | 970 | if (desc.flags & VRING_DESC_F_WRITE) { |
970 | /* If this is an input descriptor, | 971 | /* If this is an input descriptor, |
@@ -981,7 +982,7 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq, | |||
981 | if (*in_num) { | 982 | if (*in_num) { |
982 | vq_err(vq, "Descriptor has out after in: " | 983 | vq_err(vq, "Descriptor has out after in: " |
983 | "idx %d\n", i); | 984 | "idx %d\n", i); |
984 | return vq->num; | 985 | return -EINVAL; |
985 | } | 986 | } |
986 | *out_num += ret; | 987 | *out_num += ret; |
987 | } | 988 | } |