Commit e6bcb1b6 authored by Marc-André Lureau's avatar Marc-André Lureau Committed by Michael S. Tsirkin
Browse files

vhost-user: keep vhost_net after a disconnection



Many code paths assume get_vhost_net() returns non-null.

Keep VhostUserState.vhost_net after a successful vhost_net_init(),
instead of freeing it in vhost_net_cleanup().

VhostUserState.vhost_net is thus freed before after being recreated or
on final vhost_user_cleanup() and there is no need to save the acked
features.

Signed-off-by: default avatarMarc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
parent c4843a45
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -378,7 +378,6 @@ void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs,
void vhost_net_cleanup(struct vhost_net *net)
{
    vhost_dev_cleanup(&net->dev);
    g_free(net);
}

int vhost_net_notify_migration_done(struct vhost_net *net, char* mac_addr)
+1 −0
Original line number Diff line number Diff line
@@ -312,6 +312,7 @@ static void tap_cleanup(NetClientState *nc)

    if (s->vhost_net) {
        vhost_net_cleanup(s->vhost_net);
        g_free(s->vhost_net);
        s->vhost_net = NULL;
    }

+19 −17
Original line number Diff line number Diff line
@@ -45,11 +45,6 @@ uint64_t vhost_user_get_acked_features(NetClientState *nc)
    return s->acked_features;
}

static int vhost_user_running(VhostUserState *s)
{
    return (s->vhost_net) ? 1 : 0;
}

static void vhost_user_stop(int queues, NetClientState *ncs[])
{
    VhostUserState *s;
@@ -59,15 +54,14 @@ static void vhost_user_stop(int queues, NetClientState *ncs[])
        assert(ncs[i]->info->type == NET_CLIENT_DRIVER_VHOST_USER);

        s = DO_UPCAST(VhostUserState, nc, ncs[i]);
        if (!vhost_user_running(s)) {
            continue;
        }

        if (s->vhost_net) {
            /* save acked features */
            s->acked_features = vhost_net_get_acked_features(s->vhost_net);
            uint64_t features = vhost_net_get_acked_features(s->vhost_net);
            if (features) {
                s->acked_features = features;
            }
            vhost_net_cleanup(s->vhost_net);
            s->vhost_net = NULL;
        }
    }
}
@@ -75,6 +69,7 @@ static void vhost_user_stop(int queues, NetClientState *ncs[])
static int vhost_user_start(int queues, NetClientState *ncs[])
{
    VhostNetOptions options;
    struct vhost_net *net = NULL;
    VhostUserState *s;
    int max_queues;
    int i;
@@ -85,33 +80,39 @@ static int vhost_user_start(int queues, NetClientState *ncs[])
        assert(ncs[i]->info->type == NET_CLIENT_DRIVER_VHOST_USER);

        s = DO_UPCAST(VhostUserState, nc, ncs[i]);
        if (vhost_user_running(s)) {
            continue;
        }

        options.net_backend = ncs[i];
        options.opaque      = s->chr;
        options.busyloop_timeout = 0;
        s->vhost_net = vhost_net_init(&options);
        if (!s->vhost_net) {
        net = vhost_net_init(&options);
        if (!net) {
            error_report("failed to init vhost_net for queue %d", i);
            goto err;
        }

        if (i == 0) {
            max_queues = vhost_net_get_max_queues(s->vhost_net);
            max_queues = vhost_net_get_max_queues(net);
            if (queues > max_queues) {
                error_report("you are asking more queues than supported: %d",
                             max_queues);
                goto err;
            }
        }

        if (s->vhost_net) {
            vhost_net_cleanup(s->vhost_net);
            g_free(s->vhost_net);
        }
        s->vhost_net = net;
    }

    return 0;

err:
    vhost_user_stop(i + 1, ncs);
    if (net) {
        vhost_net_cleanup(net);
    }
    vhost_user_stop(i, ncs);
    return -1;
}

@@ -150,6 +151,7 @@ static void vhost_user_cleanup(NetClientState *nc)

    if (s->vhost_net) {
        vhost_net_cleanup(s->vhost_net);
        g_free(s->vhost_net);
        s->vhost_net = NULL;
    }
    if (s->chr) {