diff --git a/lib/vhost/vhost.c b/lib/vhost/vhost.c index b5cac8875..03a0095f2 100644 --- a/lib/vhost/vhost.c +++ b/lib/vhost/vhost.c @@ -516,8 +516,8 @@ spdk_vhost_session_find_by_vid(int vid) struct spdk_vhost_dev *vdev; TAILQ_FOREACH(vdev, &g_spdk_vhost_devices, tailq) { - if (vdev->session.vid == vid) { - return &vdev->session; + if (vdev->session && vdev->session->vid == vid) { + return vdev->session; } } @@ -750,7 +750,6 @@ spdk_vhost_dev_register(struct spdk_vhost_dev *vdev, const char *name, const cha vdev->name = strdup(name); vdev->path = strdup(path); vdev->id = ctrlr_num++; - vdev->session.vid = -1; vdev->lcore = -1; vdev->cpumask = cpumask; vdev->registered = true; @@ -775,7 +774,7 @@ out: int spdk_vhost_dev_unregister(struct spdk_vhost_dev *vdev) { - if (vdev->session.vid != -1) { + if (vdev->session) { SPDK_ERRLOG("Controller %s has still valid connection.\n", vdev->name); return -EBUSY; } @@ -1267,16 +1266,23 @@ new_connection(int vid) return -1; } - /* since pollers are not running it safe not to use spdk_event here */ - vsession = &vdev->session; - if (vsession->vid != -1) { - SPDK_ERRLOG("Session with vid %d already exists.\n", vid); + if (vdev->session != NULL) { + SPDK_ERRLOG("Device %s is already connected.\n", vdev->name); + pthread_mutex_unlock(&g_spdk_vhost_mutex); + return -1; + } + + vsession = spdk_dma_zmalloc(sizeof(struct spdk_vhost_session), + SPDK_CACHE_LINE_SIZE, NULL); + if (vsession == NULL) { + SPDK_ERRLOG("spdk_dma_zmalloc failed\n"); pthread_mutex_unlock(&g_spdk_vhost_mutex); return -1; } vsession->vdev = vdev; vsession->vid = vid; + vdev->session = vsession; pthread_mutex_unlock(&g_spdk_vhost_mutex); return 0; } @@ -1294,8 +1300,8 @@ destroy_connection(int vid) return; } - /* since pollers are not running it safe not to use spdk_event here */ - vsession->vid = -1; + vsession->vdev->session = NULL; + spdk_dma_free(vsession); pthread_mutex_unlock(&g_spdk_vhost_mutex); } diff --git a/lib/vhost/vhost_blk.c b/lib/vhost/vhost_blk.c index 74aa5be95..90ee633e0 100644 --- a/lib/vhost/vhost_blk.c +++ b/lib/vhost/vhost_blk.c @@ -85,8 +85,8 @@ process_blk_request(struct spdk_vhost_blk_task *task, struct spdk_vhost_blk_dev static void blk_task_finish(struct spdk_vhost_blk_task *task) { - assert(task->bvdev->vdev.session.task_cnt > 0); - task->bvdev->vdev.session.task_cnt--; + assert(task->bvdev->vdev.session->task_cnt > 0); + task->bvdev->vdev.session->task_cnt--; task->used = false; } @@ -97,7 +97,7 @@ invalid_blk_request(struct spdk_vhost_blk_task *task, uint8_t status) *task->status = status; } - spdk_vhost_vq_used_ring_enqueue(&task->bvdev->vdev.session, task->vq, task->req_idx, + spdk_vhost_vq_used_ring_enqueue(task->bvdev->vdev.session, task->vq, task->req_idx, task->used_len); blk_task_finish(task); SPDK_DEBUGLOG(SPDK_LOG_VHOST_BLK_DATA, "Invalid request (status=%" PRIu8")\n", status); @@ -119,7 +119,7 @@ blk_iovs_setup(struct spdk_vhost_dev *vdev, struct spdk_vhost_virtqueue *vq, uin uint32_t desc_table_size, len = 0; int rc; - rc = spdk_vhost_vq_get_desc(&vdev->session, vq, req_idx, &desc, &desc_table, &desc_table_size); + rc = spdk_vhost_vq_get_desc(vdev->session, vq, req_idx, &desc, &desc_table, &desc_table_size); if (rc != 0) { SPDK_ERRLOG("%s: Invalid descriptor at index %"PRIu16".\n", vdev->name, req_idx); return -1; @@ -136,7 +136,7 @@ blk_iovs_setup(struct spdk_vhost_dev *vdev, struct spdk_vhost_virtqueue *vq, uin return -1; } - if (spdk_unlikely(spdk_vhost_vring_desc_to_iov(&vdev->session, iovs, &cnt, desc))) { + if (spdk_unlikely(spdk_vhost_vring_desc_to_iov(vdev->session, iovs, &cnt, desc))) { SPDK_DEBUGLOG(SPDK_LOG_VHOST_BLK, "Invalid descriptor %" PRIu16" (req_idx = %"PRIu16").\n", req_idx, cnt); return -1; @@ -174,7 +174,7 @@ static void blk_request_finish(bool success, struct spdk_vhost_blk_task *task) { *task->status = success ? VIRTIO_BLK_S_OK : VIRTIO_BLK_S_IOERR; - spdk_vhost_vq_used_ring_enqueue(&task->bvdev->vdev.session, task->vq, task->req_idx, + spdk_vhost_vq_used_ring_enqueue(task->bvdev->vdev.session, task->vq, task->req_idx, task->used_len); SPDK_DEBUGLOG(SPDK_LOG_VHOST_BLK, "Finished task (%p) req_idx=%d\n status: %s\n", task, task->req_idx, success ? "OK" : "FAIL"); @@ -377,7 +377,7 @@ static void process_vq(struct spdk_vhost_blk_dev *bvdev, struct spdk_vhost_virtqueue *vq) { struct spdk_vhost_blk_task *task; - struct spdk_vhost_session *vsession = &bvdev->vdev.session; + struct spdk_vhost_session *vsession = bvdev->vdev.session; int rc; uint16_t reqs[32]; uint16_t reqs_cnt, i; @@ -427,7 +427,7 @@ static int vdev_worker(void *arg) { struct spdk_vhost_blk_dev *bvdev = arg; - struct spdk_vhost_session *vsession = &bvdev->vdev.session; + struct spdk_vhost_session *vsession = bvdev->vdev.session; uint16_t q_idx; for (q_idx = 0; q_idx < vsession->max_queues; q_idx++) { @@ -442,7 +442,7 @@ vdev_worker(void *arg) static void no_bdev_process_vq(struct spdk_vhost_blk_dev *bvdev, struct spdk_vhost_virtqueue *vq) { - struct spdk_vhost_session *vsession = &bvdev->vdev.session; + struct spdk_vhost_session *vsession = bvdev->vdev.session; struct iovec iovs[SPDK_VHOST_IOVS_MAX]; uint32_t length; uint16_t iovcnt, req_idx; @@ -464,7 +464,7 @@ static int no_bdev_vdev_worker(void *arg) { struct spdk_vhost_blk_dev *bvdev = arg; - struct spdk_vhost_session *vsession = &bvdev->vdev.session; + struct spdk_vhost_session *vsession = bvdev->vdev.session; uint16_t q_idx; for (q_idx = 0; q_idx < vsession->max_queues; q_idx++) { @@ -534,7 +534,7 @@ bdev_remove_cb(void *remove_ctx) static void free_task_pool(struct spdk_vhost_blk_dev *bvdev) { - struct spdk_vhost_session *vsession = &bvdev->vdev.session; + struct spdk_vhost_session *vsession = bvdev->vdev.session; struct spdk_vhost_virtqueue *vq; uint16_t i; @@ -552,7 +552,7 @@ free_task_pool(struct spdk_vhost_blk_dev *bvdev) static int alloc_task_pool(struct spdk_vhost_blk_dev *bvdev) { - struct spdk_vhost_session *vsession = &bvdev->vdev.session; + struct spdk_vhost_session *vsession = bvdev->vdev.session; struct spdk_vhost_virtqueue *vq; struct spdk_vhost_blk_task *task; uint32_t task_cnt; @@ -602,7 +602,7 @@ static int spdk_vhost_blk_start(struct spdk_vhost_dev *vdev, void *event_ctx) { struct spdk_vhost_blk_dev *bvdev; - struct spdk_vhost_session *vsession = &vdev->session; + struct spdk_vhost_session *vsession = vdev->session; int i, rc = 0; bvdev = to_blk_dev(vdev); @@ -650,7 +650,7 @@ static int destroy_device_poller_cb(void *arg) { struct spdk_vhost_blk_dev *bvdev = arg; - struct spdk_vhost_session *vsession = &bvdev->vdev.session; + struct spdk_vhost_session *vsession = bvdev->vdev.session; int i; if (vsession->task_cnt > 0) { diff --git a/lib/vhost/vhost_internal.h b/lib/vhost/vhost_internal.h index f78e67e89..9ebedf00d 100644 --- a/lib/vhost/vhost_internal.h +++ b/lib/vhost/vhost_internal.h @@ -133,6 +133,23 @@ struct spdk_vhost_dev_backend { int (*remove_device)(struct spdk_vhost_dev *vdev); }; +struct spdk_vhost_session { + struct spdk_vhost_dev *vdev; + + /* rte_vhost connection ID. */ + int vid; + + struct rte_vhost_memory *mem; + + int task_cnt; + + uint16_t max_queues; + + uint64_t negotiated_features; + + struct spdk_vhost_virtqueue virtqueue[SPDK_VHOST_MAX_VQUEUES]; +}; + struct spdk_vhost_dev { char *name; char *path; @@ -164,22 +181,7 @@ struct spdk_vhost_dev { uint64_t stats_check_interval; /* Active connection to the device */ - struct spdk_vhost_session { - struct spdk_vhost_dev *vdev; - - /* rte_vhost connection ID. */ - int vid; - - struct rte_vhost_memory *mem; - - int task_cnt; - - uint16_t max_queues; - - uint64_t negotiated_features; - - struct spdk_vhost_virtqueue virtqueue[SPDK_VHOST_MAX_VQUEUES]; - } session; + struct spdk_vhost_session *session; TAILQ_ENTRY(spdk_vhost_dev) tailq; }; diff --git a/lib/vhost/vhost_nvme.c b/lib/vhost/vhost_nvme.c index 98ab48240..c26640c46 100644 --- a/lib/vhost/vhost_nvme.c +++ b/lib/vhost/vhost_nvme.c @@ -248,7 +248,7 @@ static int spdk_nvme_map_prps(struct spdk_vhost_nvme_dev *nvme, struct spdk_nvme_cmd *cmd, struct spdk_vhost_nvme_task *task, uint32_t len) { - struct spdk_vhost_session *vsession = &nvme->vdev.session; + struct spdk_vhost_session *vsession = nvme->vdev.session; uint64_t prp1, prp2; void *vva; uint32_t i; @@ -699,7 +699,7 @@ static int vhost_nvme_doorbell_buffer_config(struct spdk_vhost_nvme_dev *nvme, struct spdk_nvme_cmd *cmd, struct spdk_nvme_cpl *cpl) { - struct spdk_vhost_session *vsession = &nvme->vdev.session; + struct spdk_vhost_session *vsession = nvme->vdev.session; uint64_t dbs_dma_addr, eis_dma_addr; dbs_dma_addr = cmd->dptr.prp.prp1; @@ -765,7 +765,7 @@ vhost_nvme_create_io_sq(struct spdk_vhost_nvme_dev *nvme, sq->size = qsize + 1; sq->sq_head = sq->sq_tail = 0; requested_len = sizeof(struct spdk_nvme_cmd) * sq->size; - sq->sq_cmd = spdk_vhost_gpa_to_vva(&nvme->vdev.session, dma_addr, requested_len); + sq->sq_cmd = spdk_vhost_gpa_to_vva(nvme->vdev.session, dma_addr, requested_len); if (!sq->sq_cmd) { return -1; } @@ -848,7 +848,7 @@ vhost_nvme_create_io_cq(struct spdk_vhost_nvme_dev *nvme, cq->guest_signaled_cq_head = 0; cq->need_signaled_cnt = 0; requested_len = sizeof(struct spdk_nvme_cpl) * cq->size; - cq->cq_cqe = spdk_vhost_gpa_to_vva(&nvme->vdev.session, dma_addr, requested_len); + cq->cq_cqe = spdk_vhost_gpa_to_vva(nvme->vdev.session, dma_addr, requested_len); if (!cq->cq_cqe) { return -1; } @@ -893,7 +893,7 @@ spdk_vhost_nvme_get_by_name(int vid) struct spdk_vhost_nvme_dev *nvme; TAILQ_FOREACH(nvme, &g_nvme_ctrlrs, tailq) { - if (nvme->vdev.session.vid == vid) { + if (nvme->vdev.session != NULL && nvme->vdev.session->vid == vid) { return nvme; } } @@ -1084,7 +1084,7 @@ spdk_vhost_nvme_start_device(struct spdk_vhost_dev *vdev, void *event_ctx) return -1; } - SPDK_NOTICELOG("Start Device %u, Path %s, lcore %d\n", vdev->session.vid, + SPDK_NOTICELOG("Start Device %u, Path %s, lcore %d\n", vdev->session->vid, vdev->path, vdev->lcore); for (i = 0; i < nvme->num_ns; i++) { @@ -1171,7 +1171,7 @@ spdk_vhost_nvme_stop_device(struct spdk_vhost_dev *vdev, void *event_ctx) } free_task_pool(nvme); - SPDK_NOTICELOG("Stopping Device %u, Path %s\n", vdev->session.vid, vdev->path); + SPDK_NOTICELOG("Stopping Device %u, Path %s\n", vdev->session->vid, vdev->path); nvme->destroy_ctx.event_ctx = event_ctx; spdk_poller_unregister(&nvme->requestq_poller); diff --git a/lib/vhost/vhost_scsi.c b/lib/vhost/vhost_scsi.c index 2cd9f42dc..e421605ca 100644 --- a/lib/vhost/vhost_scsi.c +++ b/lib/vhost/vhost_scsi.c @@ -134,7 +134,7 @@ static void spdk_vhost_scsi_task_free_cb(struct spdk_scsi_task *scsi_task) { struct spdk_vhost_scsi_task *task = SPDK_CONTAINEROF(scsi_task, struct spdk_vhost_scsi_task, scsi); - struct spdk_vhost_session *vsession = &task->svdev->vdev.session; + struct spdk_vhost_session *vsession = task->svdev->vdev.session; assert(vsession->task_cnt > 0); vsession->task_cnt--; @@ -170,7 +170,7 @@ static void eventq_enqueue(struct spdk_vhost_scsi_dev *svdev, unsigned scsi_dev_num, uint32_t event, uint32_t reason) { - struct spdk_vhost_session *vsession = &svdev->vdev.session; + struct spdk_vhost_session *vsession = svdev->vdev.session; struct spdk_vhost_virtqueue *vq; struct vring_desc *desc, *desc_table; struct virtio_scsi_event *desc_ev; @@ -223,7 +223,7 @@ out: static void submit_completion(struct spdk_vhost_scsi_task *task) { - struct spdk_vhost_session *vsession = &task->svdev->vdev.session; + struct spdk_vhost_session *vsession = task->svdev->vdev.session; spdk_vhost_vq_used_ring_enqueue(vsession, task->vq, task->req_idx, task->used_len); @@ -280,7 +280,7 @@ mgmt_task_submit(struct spdk_vhost_scsi_task *task, enum spdk_scsi_task_func fun static void invalid_request(struct spdk_vhost_scsi_task *task) { - struct spdk_vhost_session *vsession = &task->svdev->vdev.session; + struct spdk_vhost_session *vsession = task->svdev->vdev.session; spdk_vhost_vq_used_ring_enqueue(vsession, task->vq, task->req_idx, task->used_len); @@ -321,7 +321,7 @@ static void process_ctrl_request(struct spdk_vhost_scsi_task *task) { struct spdk_vhost_dev *vdev = &task->svdev->vdev; - struct spdk_vhost_session *vsession = &vdev->session; + struct spdk_vhost_session *vsession = vdev->session; struct vring_desc *desc, *desc_table; struct virtio_scsi_ctrl_tmf_req *ctrl_req; struct virtio_scsi_ctrl_an_resp *an_resp; @@ -423,7 +423,7 @@ task_data_setup(struct spdk_vhost_scsi_task *task, struct virtio_scsi_cmd_req **req) { struct spdk_vhost_dev *vdev = &task->svdev->vdev; - struct spdk_vhost_session *vsession = &vdev->session; + struct spdk_vhost_session *vsession = vdev->session; struct vring_desc *desc, *desc_table; struct iovec *iovs = task->iovs; uint16_t iovcnt = 0; @@ -586,7 +586,7 @@ process_request(struct spdk_vhost_scsi_task *task) static void process_controlq(struct spdk_vhost_scsi_dev *svdev, struct spdk_vhost_virtqueue *vq) { - struct spdk_vhost_session *vsession = &svdev->vdev.session; + struct spdk_vhost_session *vsession = svdev->vdev.session; struct spdk_vhost_scsi_task *task; uint16_t reqs[32]; uint16_t reqs_cnt, i; @@ -619,7 +619,7 @@ process_controlq(struct spdk_vhost_scsi_dev *svdev, struct spdk_vhost_virtqueue static void process_requestq(struct spdk_vhost_scsi_dev *svdev, struct spdk_vhost_virtqueue *vq) { - struct spdk_vhost_session *vsession = &svdev->vdev.session; + struct spdk_vhost_session *vsession = svdev->vdev.session; struct spdk_vhost_scsi_task *task; uint16_t reqs[32]; uint16_t reqs_cnt, i; @@ -673,7 +673,7 @@ static int vdev_mgmt_worker(void *arg) { struct spdk_vhost_scsi_dev *svdev = arg; - struct spdk_vhost_session *vsession = &svdev->vdev.session; + struct spdk_vhost_session *vsession = svdev->vdev.session; process_removed_devs(svdev); spdk_vhost_vq_used_signal(vsession, &vsession->virtqueue[VIRTIO_SCSI_EVENTQ]); @@ -688,7 +688,7 @@ static int vdev_worker(void *arg) { struct spdk_vhost_scsi_dev *svdev = arg; - struct spdk_vhost_session *vsession = &svdev->vdev.session; + struct spdk_vhost_session *vsession = svdev->vdev.session; uint32_t q_idx; for (q_idx = VIRTIO_SCSI_REQUESTQ; q_idx < vsession->max_queues; q_idx++) { @@ -793,7 +793,7 @@ spdk_vhost_scsi_lun_hotremove(const struct spdk_scsi_lun *lun, void *arg) assert(lun != NULL); assert(svdev != NULL); if (svdev->vdev.lcore != -1 && - !spdk_vhost_dev_has_feature(&svdev->vdev.session, VIRTIO_SCSI_F_HOTPLUG)) { + !spdk_vhost_dev_has_feature(svdev->vdev.session, VIRTIO_SCSI_F_HOTPLUG)) { SPDK_WARNLOG("%s: hotremove is not enabled for this controller.\n", svdev->vdev.name); return; } @@ -873,7 +873,7 @@ spdk_vhost_scsi_dev_add_tgt(struct spdk_vhost_dev *vdev, unsigned scsi_tgt_num, spdk_scsi_dev_allocate_io_channels(svdev->scsi_dev[scsi_tgt_num]); - if (spdk_vhost_dev_has_feature(&vdev->session, VIRTIO_SCSI_F_HOTPLUG)) { + if (spdk_vhost_dev_has_feature(vdev->session, VIRTIO_SCSI_F_HOTPLUG)) { eventq_enqueue(svdev, scsi_tgt_num, VIRTIO_SCSI_T_TRANSPORT_RESET, VIRTIO_SCSI_EVT_RESET_RESCAN); } else { @@ -922,7 +922,7 @@ spdk_vhost_scsi_dev_remove_tgt(struct spdk_vhost_dev *vdev, unsigned scsi_tgt_nu return rc; } - if (!spdk_vhost_dev_has_feature(&vdev->session, VIRTIO_SCSI_F_HOTPLUG)) { + if (!spdk_vhost_dev_has_feature(vdev->session, VIRTIO_SCSI_F_HOTPLUG)) { SPDK_WARNLOG("%s: 'Target %u' is in use and hot-detach is not enabled for this controller.\n", svdev->vdev.name, scsi_tgt_num); return -ENOTSUP; @@ -1015,7 +1015,7 @@ spdk_vhost_scsi_controller_construct(void) static void free_task_pool(struct spdk_vhost_scsi_dev *svdev) { - struct spdk_vhost_session *vsession = &svdev->vdev.session; + struct spdk_vhost_session *vsession = svdev->vdev.session; struct spdk_vhost_virtqueue *vq; uint16_t i; @@ -1033,7 +1033,7 @@ free_task_pool(struct spdk_vhost_scsi_dev *svdev) static int alloc_task_pool(struct spdk_vhost_scsi_dev *svdev) { - struct spdk_vhost_session *vsession = &svdev->vdev.session; + struct spdk_vhost_session *vsession = svdev->vdev.session; struct spdk_vhost_virtqueue *vq; struct spdk_vhost_scsi_task *task; uint32_t task_cnt; @@ -1082,7 +1082,7 @@ static int spdk_vhost_scsi_start(struct spdk_vhost_dev *vdev, void *event_ctx) { struct spdk_vhost_scsi_dev *svdev; - struct spdk_vhost_session *vsession = &vdev->session; + struct spdk_vhost_session *vsession = vdev->session; uint32_t i; int rc; @@ -1132,7 +1132,7 @@ static int destroy_device_poller_cb(void *arg) { struct spdk_vhost_scsi_dev *svdev = arg; - struct spdk_vhost_session *vsession = &svdev->vdev.session; + struct spdk_vhost_session *vsession = svdev->vdev.session; uint32_t i; if (vsession->task_cnt > 0) { diff --git a/test/unit/lib/vhost/vhost.c/vhost_ut.c b/test/unit/lib/vhost/vhost.c/vhost_ut.c index f7888865d..12f622e9f 100644 --- a/test/unit/lib/vhost/vhost.c/vhost_ut.c +++ b/test/unit/lib/vhost/vhost.c/vhost_ut.c @@ -152,6 +152,7 @@ static void start_vdev(struct spdk_vhost_dev *vdev) { struct rte_vhost_memory *mem; + int rc; mem = calloc(1, sizeof(*mem) + 2 * sizeof(struct rte_vhost_mem_region)); SPDK_CU_ASSERT_FATAL(mem != NULL); @@ -164,22 +165,29 @@ start_vdev(struct spdk_vhost_dev *vdev) mem->regions[1].host_user_addr = 0x2000000; vdev->lcore = 0; - vdev->session.vid = 0; - vdev->session.mem = mem; + assert(vdev->session == NULL); + /* spdk_vhost_dev must be allocated on a cache line boundary. */ + rc = posix_memalign((void **)&vdev->session, 64, sizeof(*vdev->session)); + CU_ASSERT(rc == 0); + SPDK_CU_ASSERT_FATAL(vdev->session != NULL); + vdev->session->vid = 0; + vdev->session->mem = mem; } static void stop_vdev(struct spdk_vhost_dev *vdev) { - free(vdev->session.mem); - vdev->session.mem = NULL; - vdev->session.vid = -1; + free(vdev->session->mem); + free(vdev->session); + vdev->session = NULL; } static void cleanup_vdev(struct spdk_vhost_dev *vdev) { - stop_vdev(vdev); + if (vdev->session) { + stop_vdev(vdev); + } spdk_vhost_dev_unregister(vdev); free(vdev); } @@ -198,7 +206,7 @@ desc_to_iov_test(void) SPDK_CU_ASSERT_FATAL(rc == 0 && vdev); start_vdev(vdev); - vsession = &vdev->session; + vsession = vdev->session; /* Test simple case where iov falls fully within a 2MB page. */ desc.addr = 0x110000; @@ -310,12 +318,13 @@ session_find_by_vid_test(void) rc = alloc_vdev(&vdev, "vdev_name_0", "0x1"); SPDK_CU_ASSERT_FATAL(rc == 0 && vdev); + start_vdev(vdev); - tmp = spdk_vhost_session_find_by_vid(vdev->session.vid); - CU_ASSERT(tmp == &vdev->session); + tmp = spdk_vhost_session_find_by_vid(vdev->session->vid); + CU_ASSERT(tmp == vdev->session); /* Search for a device with incorrect vid */ - tmp = spdk_vhost_session_find_by_vid(vdev->session.vid + 0xFF); + tmp = spdk_vhost_session_find_by_vid(vdev->session->vid + 0xFF); CU_ASSERT(tmp == NULL); cleanup_vdev(vdev);