[转]qemu和vhost-user前后协商过程

转自 http://blog.chinaunix.net/uid-28541347-id-5786547.html

https://www.cnblogs.com/ck1020/p/8341914.html

https://www.cnblogs.com/ck1020/p/5939777.html virtio后端驱动

https://www.cnblogs.com/ck1020/p/6044134.html virtio前端驱动

 1 static Property vhost_user_blk_properties[] = {
 2     DEFINE_PROP_CHR("chardev", VHostUserBlk, chardev),
 3     DEFINE_PROP_UINT16("num-queues", VHostUserBlk, num_queues, 1),
 4     DEFINE_PROP_UINT32("queue-size", VHostUserBlk, queue_size, 128),
 5     DEFINE_PROP_BIT("config-wce", VHostUserBlk, config_wce, 0, true),
 6     DEFINE_PROP_END_OF_LIST(),
 7 };
 8 
 9 static void vhost_user_blk_class_init(ObjectClass *klass, void *data)
10 {
11     DeviceClass *dc = DEVICE_CLASS(klass);
12     VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
13 
14     device_class_set_props(dc, vhost_user_blk_properties);
15     dc->vmsd = &vmstate_vhost_user_blk;
16     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
17     vdc->realize = vhost_user_blk_device_realize;
18     vdc->unrealize = vhost_user_blk_device_unrealize;
19     vdc->get_config = vhost_user_blk_update_config;
20     vdc->set_config = vhost_user_blk_set_config;
21     vdc->get_features = vhost_user_blk_get_features;
22     vdc->set_status = vhost_user_blk_set_status;
23     vdc->reset = vhost_user_blk_reset;
24 }
25 
26 static const TypeInfo vhost_user_blk_info = {
27     .name = TYPE_VHOST_USER_BLK,
28     .parent = TYPE_VIRTIO_DEVICE,
29     .instance_size = sizeof(VHostUserBlk),
30     .instance_init = vhost_user_blk_instance_init,
31     .class_init = vhost_user_blk_class_init,
32 };
33 
34 static void virtio_register_types(void)
35 {
36     type_register_static(&vhost_user_blk_info);
37 }
38 
39 type_init(virtio_register_types)
 1 static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp)
 2 {
 3     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
 4     VHostUserBlk *s = VHOST_USER_BLK(vdev);
 5     Error *err = NULL;
 6     int i, ret;
 7 
 8     if (!s->chardev.chr) {
 9         error_setg(errp, "vhost-user-blk: chardev is mandatory");
10         return;
11     }
12 
13     if (!s->num_queues || s->num_queues > VIRTIO_QUEUE_MAX) {
14         error_setg(errp, "vhost-user-blk: invalid number of IO queues");
15         return;
16     }
17 
18     if (!s->queue_size) {
19         error_setg(errp, "vhost-user-blk: queue size must be non-zero");
20         return;
21     }
22 
23     if (!vhost_user_init(&s->vhost_user, &s->chardev, errp)) {
24         return;
25     }
26 
27     virtio_init(vdev, "virtio-blk", VIRTIO_ID_BLOCK,
28                 sizeof(struct virtio_blk_config));
29 
30     s->virtqs = g_new(VirtQueue *, s->num_queues);
31     for (i = 0; i < s->num_queues; i++) {
32         s->virtqs[i] = virtio_add_queue(vdev, s->queue_size,
33                                         vhost_user_blk_handle_output);
34     }
35 
36     s->inflight = g_new0(struct vhost_inflight, 1);
37     s->vhost_vqs = g_new0(struct vhost_virtqueue, s->num_queues);
38     s->watch = 0;
39     s->connected = false;
40 
41     qemu_chr_fe_set_handlers(&s->chardev,  NULL, NULL, vhost_user_blk_event,
42                              NULL, (void *)dev, NULL, true);
43 
44 reconnect:
45     if (qemu_chr_fe_wait_connected(&s->chardev, &err) < 0) {
46         error_report_err(err);
47         goto virtio_err;
48     }
49 
50     /* check whether vhost_user_blk_connect() failed or not */
51     if (!s->connected) {
52         goto reconnect;
53     }
54 
55     ret = vhost_dev_get_config(&s->dev, (uint8_t *)&s->blkcfg,
56                                sizeof(struct virtio_blk_config));
57     if (ret < 0) {
58         error_report("vhost-user-blk: get block config failed");
59         goto reconnect;
60     }
61 
62     if (s->blkcfg.num_queues != s->num_queues) {
63         s->blkcfg.num_queues = s->num_queues;
64     }
65 
66     return;
67 
68 virtio_err:
69     g_free(s->vhost_vqs);
70     g_free(s->inflight);
71     for (i = 0; i < s->num_queues; i++) {
72         virtio_delete_queue(s->virtqs[i]);
73     }
74     g_free(s->virtqs);
75     virtio_cleanup(vdev);
76     vhost_user_cleanup(&s->vhost_user);
77 }

ss

 1 static void vhost_user_blk_event(void *opaque, QEMUChrEvent event)
 2 {
 3     DeviceState *dev = opaque;
 4     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
 5     VHostUserBlk *s = VHOST_USER_BLK(vdev);
 6 
 7     switch (event) {
 8     case CHR_EVENT_OPENED://链接建立的逻辑
 9         if (vhost_user_blk_connect(dev) < 0) {
10             qemu_chr_fe_disconnect(&s->chardev);
11             return;
12         }
13         s->watch = qemu_chr_fe_add_watch(&s->chardev, G_IO_HUP,
14                                          vhost_user_blk_watch, dev);
15         break;
16     case CHR_EVENT_CLOSED:
17         vhost_user_blk_disconnect(dev);
18         if (s->watch) {
19             g_source_remove(s->watch);
20             s->watch = 0;
21         }
22         break;
23     case CHR_EVENT_BREAK:
24     case CHR_EVENT_MUX_IN:
25     case CHR_EVENT_MUX_OUT:
26         /* Ignore */
27         break;
28     }
29 }
 1 static int vhost_user_blk_connect(DeviceState *dev)
 2 {
 3     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
 4     VHostUserBlk *s = VHOST_USER_BLK(vdev);
 5     int ret = 0;
 6 
 7     if (s->connected) {
 8         return 0;
 9     }
10     s->connected = true;
11 
12     s->dev.nvqs = s->num_queues;
13     s->dev.vqs = s->vhost_vqs;
14     s->dev.vq_index = 0;
15     s->dev.backend_features = 0;
16 
17     vhost_dev_set_config_notifier(&s->dev, &blk_ops);
18 
19     ret = vhost_dev_init(&s->dev, &s->vhost_user, VHOST_BACKEND_TYPE_USER, 0);
20     if (ret < 0) {
21         error_report("vhost-user-blk: vhost initialization failed: %s",
22                      strerror(-ret));
23         return ret;
24     }
25 
26     /* restore vhost state */
27     if (virtio_device_started(vdev, vdev->status)) {
28         ret = vhost_user_blk_start(vdev);
29         if (ret < 0) {
30             error_report("vhost-user-blk: vhost start failed: %s",
31                          strerror(-ret));
32             return ret;
33         }
34     }
35 
36     return 0;
37 }

 vhost_dev_init

  1 int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
  2                    VhostBackendType backend_type, uint32_t busyloop_timeout)
  3 {
  4     uint64_t features;
  5     int i, r, n_initialized_vqs = 0;
  6     Error *local_err = NULL;
  7 
  8     hdev->vdev = NULL;
  9     hdev->migration_blocker = NULL;
 10 
 11     r = vhost_set_backend_type(hdev, backend_type);
 12     assert(r >= 0);
 13 
 14     r = hdev->vhost_ops->vhost_backend_init(hdev, opaque);
 15     if (r < 0) {
 16         goto fail;
 17     }
 18 
 19     r = hdev->vhost_ops->vhost_set_owner(hdev);
 20     if (r < 0) {
 21         VHOST_OPS_DEBUG("vhost_set_owner failed");
 22         goto fail;
 23     }
 24 
 25     r = hdev->vhost_ops->vhost_get_features(hdev, &features);
 26     if (r < 0) {
 27         VHOST_OPS_DEBUG("vhost_get_features failed");
 28         goto fail;
 29     }
 30 
 31     for (i = 0; i < hdev->nvqs; ++i, ++n_initialized_vqs) {
 32         r = vhost_virtqueue_init(hdev, hdev->vqs + i, hdev->vq_index + i);
 33         if (r < 0) {
 34             goto fail;
 35         }
 36     }
 37 
 38     if (busyloop_timeout) {
 39         for (i = 0; i < hdev->nvqs; ++i) {
 40             r = vhost_virtqueue_set_busyloop_timeout(hdev, hdev->vq_index + i,
 41                                                      busyloop_timeout);
 42             if (r < 0) {
 43                 goto fail_busyloop;
 44             }
 45         }
 46     }
 47 
 48     hdev->features = features;
 49 
 50     hdev->memory_listener = (MemoryListener) {
 51         .begin = vhost_begin,
 52         .commit = vhost_commit,
 53         .region_add = vhost_region_addnop,
 54         .region_nop = vhost_region_addnop,
 55         .log_start = vhost_log_start,
 56         .log_stop = vhost_log_stop,
 57         .log_sync = vhost_log_sync,
 58         .log_global_start = vhost_log_global_start,
 59         .log_global_stop = vhost_log_global_stop,
 60         .eventfd_add = vhost_eventfd_add,
 61         .eventfd_del = vhost_eventfd_del,
 62         .priority = 10
 63     };
 64 
 65     hdev->iommu_listener = (MemoryListener) {
 66         .region_add = vhost_iommu_region_add,
 67         .region_del = vhost_iommu_region_del,
 68     };
 69 
 70     if (hdev->migration_blocker == NULL) {
 71         if (!(hdev->features & (0x1ULL << VHOST_F_LOG_ALL))) {
 72             error_setg(&hdev->migration_blocker,
 73                        "Migration disabled: vhost lacks VHOST_F_LOG_ALL feature.");
 74         } else if (vhost_dev_log_is_shared(hdev) && !qemu_memfd_alloc_check()) {
 75             error_setg(&hdev->migration_blocker,
 76                        "Migration disabled: failed to allocate shared memory");
 77         }
 78     }
 79 
 80     if (hdev->migration_blocker != NULL) {
 81         r = migrate_add_blocker(hdev->migration_blocker, &local_err);
 82         if (local_err) {
 83             error_report_err(local_err);
 84             error_free(hdev->migration_blocker);
 85             goto fail_busyloop;
 86         }
 87     }
 88 
 89     hdev->mem = g_malloc0(offsetof(struct vhost_memory, regions));
 90     hdev->n_mem_sections = 0;
 91     hdev->mem_sections = NULL;
 92     hdev->log = NULL;
 93     hdev->log_size = 0;
 94     hdev->log_enabled = false;
 95     hdev->started = false;
 96     memory_listener_register(&hdev->memory_listener, &address_space_memory);
 97     QLIST_INSERT_HEAD(&vhost_devices, hdev, entry);
 98 
 99     if (used_memslots > hdev->vhost_ops->vhost_backend_memslots_limit(hdev)) {
100         error_report("vhost backend memory slots limit is less"
101                 " than current number of present memory slots");
102         r = -1;
103         if (busyloop_timeout) {
104             goto fail_busyloop;
105         } else {
106             goto fail;
107         }
108     }
109 
110     return 0;
111 
112 fail_busyloop:
113     while (--i >= 0) {
114         vhost_virtqueue_set_busyloop_timeout(hdev, hdev->vq_index + i, 0);
115     }
116 fail:
117     hdev->nvqs = n_initialized_vqs;
118     vhost_dev_cleanup(hdev);
119     return r;
120 }

vhost_user_blk_start

dd

原文地址:https://www.cnblogs.com/yi-mu-xi/p/12462884.html