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 | } |