diff options
author | K. Y. Srinivasan <kys@microsoft.com> | 2012-10-12 16:22:42 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-10-24 18:46:27 -0400 |
commit | 1392550240aaa72ce3a094a38bd23525cd67ce60 (patch) | |
tree | 10cb9a50ac0cf48f20a5068bd8499f317fb00226 /drivers/hv/channel.c | |
parent | 1b2077345c66f9e6c891e4b6bc5bb7a1bdd5f9a9 (diff) |
Drivers: hv: Cleanup error handling in vmbus_open()
Fix a memory leak in the error handling path in the function vmbus_open().
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Reported-by: Jason Wang <jasowang@redhat.com>
Cc: Stable <stable@vger.kernel.org>
Acked-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/hv/channel.c')
-rw-r--r-- | drivers/hv/channel.c | 24 |
1 files changed, 13 insertions, 11 deletions
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 406537420fff..f4c3d28cd1fc 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c | |||
@@ -146,14 +146,14 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, | |||
146 | 146 | ||
147 | if (ret != 0) { | 147 | if (ret != 0) { |
148 | err = ret; | 148 | err = ret; |
149 | goto errorout; | 149 | goto error0; |
150 | } | 150 | } |
151 | 151 | ||
152 | ret = hv_ringbuffer_init( | 152 | ret = hv_ringbuffer_init( |
153 | &newchannel->inbound, in, recv_ringbuffer_size); | 153 | &newchannel->inbound, in, recv_ringbuffer_size); |
154 | if (ret != 0) { | 154 | if (ret != 0) { |
155 | err = ret; | 155 | err = ret; |
156 | goto errorout; | 156 | goto error0; |
157 | } | 157 | } |
158 | 158 | ||
159 | 159 | ||
@@ -168,7 +168,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, | |||
168 | 168 | ||
169 | if (ret != 0) { | 169 | if (ret != 0) { |
170 | err = ret; | 170 | err = ret; |
171 | goto errorout; | 171 | goto error0; |
172 | } | 172 | } |
173 | 173 | ||
174 | /* Create and init the channel open message */ | 174 | /* Create and init the channel open message */ |
@@ -177,7 +177,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, | |||
177 | GFP_KERNEL); | 177 | GFP_KERNEL); |
178 | if (!open_info) { | 178 | if (!open_info) { |
179 | err = -ENOMEM; | 179 | err = -ENOMEM; |
180 | goto errorout; | 180 | goto error0; |
181 | } | 181 | } |
182 | 182 | ||
183 | init_completion(&open_info->waitevent); | 183 | init_completion(&open_info->waitevent); |
@@ -193,7 +193,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, | |||
193 | 193 | ||
194 | if (userdatalen > MAX_USER_DEFINED_BYTES) { | 194 | if (userdatalen > MAX_USER_DEFINED_BYTES) { |
195 | err = -EINVAL; | 195 | err = -EINVAL; |
196 | goto errorout; | 196 | goto error0; |
197 | } | 197 | } |
198 | 198 | ||
199 | if (userdatalen) | 199 | if (userdatalen) |
@@ -208,19 +208,18 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, | |||
208 | sizeof(struct vmbus_channel_open_channel)); | 208 | sizeof(struct vmbus_channel_open_channel)); |
209 | 209 | ||
210 | if (ret != 0) | 210 | if (ret != 0) |
211 | goto cleanup; | 211 | goto error1; |
212 | 212 | ||
213 | t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ); | 213 | t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ); |
214 | if (t == 0) { | 214 | if (t == 0) { |
215 | err = -ETIMEDOUT; | 215 | err = -ETIMEDOUT; |
216 | goto errorout; | 216 | goto error1; |
217 | } | 217 | } |
218 | 218 | ||
219 | 219 | ||
220 | if (open_info->response.open_result.status) | 220 | if (open_info->response.open_result.status) |
221 | err = open_info->response.open_result.status; | 221 | err = open_info->response.open_result.status; |
222 | 222 | ||
223 | cleanup: | ||
224 | spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); | 223 | spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); |
225 | list_del(&open_info->msglistentry); | 224 | list_del(&open_info->msglistentry); |
226 | spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); | 225 | spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); |
@@ -228,9 +227,12 @@ cleanup: | |||
228 | kfree(open_info); | 227 | kfree(open_info); |
229 | return err; | 228 | return err; |
230 | 229 | ||
231 | errorout: | 230 | error1: |
232 | hv_ringbuffer_cleanup(&newchannel->outbound); | 231 | spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); |
233 | hv_ringbuffer_cleanup(&newchannel->inbound); | 232 | list_del(&open_info->msglistentry); |
233 | spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); | ||
234 | |||
235 | error0: | ||
234 | free_pages((unsigned long)out, | 236 | free_pages((unsigned long)out, |
235 | get_order(send_ringbuffer_size + recv_ringbuffer_size)); | 237 | get_order(send_ringbuffer_size + recv_ringbuffer_size)); |
236 | kfree(open_info); | 238 | kfree(open_info); |