• [转]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工具类
    AES加密算法
    DES加密算法
    Http工具类,Lz提供
    接口调用工具类
    autofac生命周期入门(如何避免内存泄漏)
    ASP.NET异步
    Global Error Handling in ASP.NET Web API 2(webapi2 中的全局异常处理)
    ado.net EF学习系列----深入理解查询延迟加载技术(转载)
  • 原文地址:https://www.cnblogs.com/yi-mu-xi/p/12462884.html
Copyright © 2020-2023  润新知