diff options
| author | Asias He <asias@redhat.com> | 2013-05-05 23:16:00 -0400 |
|---|---|---|
| committer | Michael S. Tsirkin <mst@redhat.com> | 2013-05-06 05:57:54 -0400 |
| commit | b1ad8496c9f47d8b545ed4e948ab4271627c8bcf (patch) | |
| tree | 6848310c33e199c7a6888f51e82e4663cfb5e4c3 /drivers/vhost | |
| parent | 54db63c2ca153ebf0c868cdf79f52ec9e701d38c (diff) | |
vhost-net: Free ubuf when vhost_dev_set_owner fails
Signed-off-by: Asias He <asias@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'drivers/vhost')
| -rw-r--r-- | drivers/vhost/net.c | 38 |
1 files changed, 32 insertions, 6 deletions
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index a3645bd163d8..354665a3ecd8 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c | |||
| @@ -146,6 +146,19 @@ void vhost_ubuf_put_and_wait(struct vhost_ubuf_ref *ubufs) | |||
| 146 | kfree(ubufs); | 146 | kfree(ubufs); |
| 147 | } | 147 | } |
| 148 | 148 | ||
| 149 | static void vhost_net_clear_ubuf_info(struct vhost_net *n) | ||
| 150 | { | ||
| 151 | |||
| 152 | bool zcopy; | ||
| 153 | int i; | ||
| 154 | |||
| 155 | for (i = 0; i < n->dev.nvqs; ++i) { | ||
| 156 | zcopy = vhost_zcopy_mask & (0x1 << i); | ||
| 157 | if (zcopy) | ||
| 158 | kfree(n->vqs[i].ubuf_info); | ||
| 159 | } | ||
| 160 | } | ||
| 161 | |||
| 149 | int vhost_net_set_ubuf_info(struct vhost_net *n) | 162 | int vhost_net_set_ubuf_info(struct vhost_net *n) |
| 150 | { | 163 | { |
| 151 | bool zcopy; | 164 | bool zcopy; |
| @@ -1027,6 +1040,23 @@ static int vhost_net_set_features(struct vhost_net *n, u64 features) | |||
| 1027 | return 0; | 1040 | return 0; |
| 1028 | } | 1041 | } |
| 1029 | 1042 | ||
| 1043 | static long vhost_net_set_owner(struct vhost_net *n) | ||
| 1044 | { | ||
| 1045 | int r; | ||
| 1046 | |||
| 1047 | mutex_lock(&n->dev.mutex); | ||
| 1048 | r = vhost_net_set_ubuf_info(n); | ||
| 1049 | if (r) | ||
| 1050 | goto out; | ||
| 1051 | r = vhost_dev_set_owner(&n->dev); | ||
| 1052 | if (r) | ||
| 1053 | vhost_net_clear_ubuf_info(n); | ||
| 1054 | vhost_net_flush(n); | ||
| 1055 | out: | ||
| 1056 | mutex_unlock(&n->dev.mutex); | ||
| 1057 | return r; | ||
| 1058 | } | ||
| 1059 | |||
| 1030 | static long vhost_net_ioctl(struct file *f, unsigned int ioctl, | 1060 | static long vhost_net_ioctl(struct file *f, unsigned int ioctl, |
| 1031 | unsigned long arg) | 1061 | unsigned long arg) |
| 1032 | { | 1062 | { |
| @@ -1055,19 +1085,15 @@ static long vhost_net_ioctl(struct file *f, unsigned int ioctl, | |||
| 1055 | return vhost_net_set_features(n, features); | 1085 | return vhost_net_set_features(n, features); |
| 1056 | case VHOST_RESET_OWNER: | 1086 | case VHOST_RESET_OWNER: |
| 1057 | return vhost_net_reset_owner(n); | 1087 | return vhost_net_reset_owner(n); |
| 1088 | case VHOST_SET_OWNER: | ||
| 1089 | return vhost_net_set_owner(n); | ||
| 1058 | default: | 1090 | default: |
| 1059 | mutex_lock(&n->dev.mutex); | 1091 | mutex_lock(&n->dev.mutex); |
| 1060 | if (ioctl == VHOST_SET_OWNER) { | ||
| 1061 | r = vhost_net_set_ubuf_info(n); | ||
| 1062 | if (r) | ||
| 1063 | goto out; | ||
| 1064 | } | ||
| 1065 | r = vhost_dev_ioctl(&n->dev, ioctl, argp); | 1092 | r = vhost_dev_ioctl(&n->dev, ioctl, argp); |
| 1066 | if (r == -ENOIOCTLCMD) | 1093 | if (r == -ENOIOCTLCMD) |
| 1067 | r = vhost_vring_ioctl(&n->dev, ioctl, argp); | 1094 | r = vhost_vring_ioctl(&n->dev, ioctl, argp); |
| 1068 | else | 1095 | else |
| 1069 | vhost_net_flush(n); | 1096 | vhost_net_flush(n); |
| 1070 | out: | ||
| 1071 | mutex_unlock(&n->dev.mutex); | 1097 | mutex_unlock(&n->dev.mutex); |
| 1072 | return r; | 1098 | return r; |
| 1073 | } | 1099 | } |
