diff options
author | Jason Wang <jasowang@redhat.com> | 2013-01-27 20:05:17 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-01-29 15:43:03 -0500 |
commit | 692a998b908ae4c612d95d1f5f5adae03eca2b79 (patch) | |
tree | c25929f71faec4963eafa1cfbeb992bee6cd4720 /drivers/vhost/net.c | |
parent | af668b3c276d0f958a3aa46ef8ec47e2d5d333b3 (diff) |
vhost_net: correct error handling in vhost_net_set_backend()
Currently, when vhost_init_used() fails the sock refcnt and ubufs were
leaked. Correct this by calling vhost_init_used() before assign ubufs and
restore the oldsock when it fails.
Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/vhost/net.c')
-rw-r--r-- | drivers/vhost/net.c | 16 |
1 files changed, 11 insertions, 5 deletions
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index ebd08b21b234..d10ad6f8df7e 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c | |||
@@ -827,15 +827,16 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd) | |||
827 | r = PTR_ERR(ubufs); | 827 | r = PTR_ERR(ubufs); |
828 | goto err_ubufs; | 828 | goto err_ubufs; |
829 | } | 829 | } |
830 | oldubufs = vq->ubufs; | 830 | |
831 | vq->ubufs = ubufs; | ||
832 | vhost_net_disable_vq(n, vq); | 831 | vhost_net_disable_vq(n, vq); |
833 | rcu_assign_pointer(vq->private_data, sock); | 832 | rcu_assign_pointer(vq->private_data, sock); |
834 | vhost_net_enable_vq(n, vq); | ||
835 | |||
836 | r = vhost_init_used(vq); | 833 | r = vhost_init_used(vq); |
837 | if (r) | 834 | if (r) |
838 | goto err_vq; | 835 | goto err_used; |
836 | vhost_net_enable_vq(n, vq); | ||
837 | |||
838 | oldubufs = vq->ubufs; | ||
839 | vq->ubufs = ubufs; | ||
839 | 840 | ||
840 | n->tx_packets = 0; | 841 | n->tx_packets = 0; |
841 | n->tx_zcopy_err = 0; | 842 | n->tx_zcopy_err = 0; |
@@ -859,6 +860,11 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd) | |||
859 | mutex_unlock(&n->dev.mutex); | 860 | mutex_unlock(&n->dev.mutex); |
860 | return 0; | 861 | return 0; |
861 | 862 | ||
863 | err_used: | ||
864 | rcu_assign_pointer(vq->private_data, oldsock); | ||
865 | vhost_net_enable_vq(n, vq); | ||
866 | if (ubufs) | ||
867 | vhost_ubuf_put_and_wait(ubufs); | ||
862 | err_ubufs: | 868 | err_ubufs: |
863 | fput(sock->file); | 869 | fput(sock->file); |
864 | err_vq: | 870 | err_vq: |