diff options
-rw-r--r-- | include/libvfio-user.h | 31 | ||||
-rw-r--r-- | lib/libvfio-user.c | 44 | ||||
-rw-r--r-- | lib/private.h | 2 | ||||
-rw-r--r-- | samples/gpio-pci-idio-16.c | 10 | ||||
-rw-r--r-- | samples/null.c | 10 | ||||
-rw-r--r-- | samples/server.c | 10 | ||||
-rw-r--r-- | test/unit-tests.c | 33 |
7 files changed, 86 insertions, 54 deletions
diff --git a/include/libvfio-user.h b/include/libvfio-user.h index 9be5846..c0636ae 100644 --- a/include/libvfio-user.h +++ b/include/libvfio-user.h @@ -214,10 +214,9 @@ typedef struct { } vfu_migration_t; /* - * Attaching to the transport is non-blocking. The library will not attempt - * to attach during context creation time. The caller must then manually - * call vfu_ctx_try_attach(), which is non-blocking, as many times as - * necessary. + * Attaching to the transport is non-blocking. + * The caller must then manually call vfu_attach_ctx(), + * which is non-blocking, as many times as necessary. */ #define LIBVFIO_USER_FLAG_ATTACH_NB (1 << 0) @@ -607,27 +606,27 @@ uint8_t * vfu_get_pci_non_std_config_space(vfu_ctx_t *vfu_ctx); /* - * Attempts to attach to the transport. LIBVFIO_USER_FLAG_ATTACH_NB must be set - * when creating the context. Returns 0 on success and -1 on error. If errno is - * set to EAGAIN or EWOULDBLOCK then the transport is not ready to attach to and - * the operation must be retried. - * + * Finalizes the device making it ready for vfu_attach_ctx(). This function is + * mandatory to be called before vfu_attach_ctx(). * @vfu_ctx: the libvfio-user context + * + * @returns: 0 on success, -1 on error. Sets errno. */ int -vfu_ctx_try_attach(vfu_ctx_t *vfu_ctx); +vfu_realize_ctx(vfu_ctx_t *vfu_ctx); /* - * Finalizes the device making it ready for vfu_ctx_drive or vfu_ctx_try_attach. - * This function is optional as it is automatically called by vfu_ctx_drive or - * vfu_ctx_try_attach. Calling it multiple times is idempotent. + * Attempts to attach to the transport. Attach is mandatory before + * vfu_ctx_drive() or vfu_ctx_poll() and is non blocking if context is created + * with LIBVFIO_USER_FLAG_ATTACH_NB flag. + * Returns client's file descriptor on success and -1 on error. If errno is + * set to EAGAIN or EWOULDBLOCK then the transport is not ready to attach to and + * the operation must be retried. * * @vfu_ctx: the libvfio-user context - * - * @returns: 0 on success, -1 on error. Sets errno. */ int -vfu_realize_ctx(vfu_ctx_t *vfu_ctx); +vfu_attach_ctx(vfu_ctx_t *vfu_ctx); /* * FIXME need to make sure that there can be at most one capability with a given diff --git a/lib/libvfio-user.c b/lib/libvfio-user.c index 007169f..5e04794 100644 --- a/lib/libvfio-user.c +++ b/lib/libvfio-user.c @@ -1085,30 +1085,13 @@ vfu_realize_ctx(vfu_ctx_t *vfu_ctx) { vfu_reg_info_t *cfg_reg; const vfu_reg_info_t zero_reg = { 0 }; - int err; uint32_t max_ivs = 0, i; size_t size; - if (vfu_ctx->ready) { + if (vfu_ctx->realized) { return 0; } - /* - * With LIBVFIO_USER_FLAG_ATTACH_NB caller is always expected to call - * vfu_ctx_try_attach(). - */ - if ((vfu_ctx->flags & LIBVFIO_USER_FLAG_ATTACH_NB) == 0) { - vfu_ctx->conn_fd = vfu_ctx->trans->attach(vfu_ctx); - if (vfu_ctx->conn_fd < 0) { - err = vfu_ctx->conn_fd; - if (err != EINTR) { - vfu_log(vfu_ctx, LOG_ERR, "failed to attach: %s", - strerror(-err)); - } - return ERROR(err); - } - } - cfg_reg = &vfu_ctx->reg_info[VFU_PCI_DEV_CFG_REGION_IDX]; // Set a default config region if none provided. @@ -1173,7 +1156,7 @@ vfu_realize_ctx(vfu_ctx_t *vfu_ctx) vfu_ctx->pci.config_space->hdr.sts.cl = 0x1; vfu_ctx->pci.config_space->hdr.cap = PCI_STD_HEADER_SIZEOF; } - vfu_ctx->ready = true; + vfu_ctx->realized = true; return 0; } @@ -1183,15 +1166,10 @@ vfu_ctx_drive(vfu_ctx_t *vfu_ctx) { int err; - if (vfu_ctx == NULL) { + if (vfu_ctx == NULL || !vfu_ctx->realized) { return ERROR(EINVAL); } - err = vfu_realize_ctx(vfu_ctx); - if (err == -1) { - return -1; - } - do { err = process_request(vfu_ctx); } while (err >= 0); @@ -1208,7 +1186,9 @@ vfu_ctx_poll(vfu_ctx_t *vfu_ctx) return -ENOTSUP; } - assert(vfu_ctx->ready); + if (!vfu_ctx->realized) { + return ERROR(EINVAL); + } err = process_request(vfu_ctx); return err >= 0 ? 0 : err; @@ -1269,21 +1249,11 @@ vfu_destroy_ctx(vfu_ctx_t *vfu_ctx) } int -vfu_ctx_try_attach(vfu_ctx_t *vfu_ctx) +vfu_attach_ctx(vfu_ctx_t *vfu_ctx) { - int err; assert(vfu_ctx != NULL); - if ((vfu_ctx->flags & LIBVFIO_USER_FLAG_ATTACH_NB) == 0) { - return ERROR(EINVAL); - } - - err = vfu_realize_ctx(vfu_ctx); - if (err == -1) { - return err; - } - return vfu_ctx->trans->attach(vfu_ctx); } diff --git a/lib/private.h b/lib/private.h index 1321b8f..e8afd79 100644 --- a/lib/private.h +++ b/lib/private.h @@ -129,7 +129,7 @@ struct vfu_ctx { uint32_t irq_count[VFU_DEV_NUM_IRQS]; vfu_irqs_t *irqs; - bool ready; + bool realized; vfu_dev_type_t dev_type; }; diff --git a/samples/gpio-pci-idio-16.c b/samples/gpio-pci-idio-16.c index e786d43..a957117 100644 --- a/samples/gpio-pci-idio-16.c +++ b/samples/gpio-pci-idio-16.c @@ -133,6 +133,16 @@ main(int argc, char *argv[]) err(EXIT_FAILURE, "failed to setup irq counts"); } + ret = vfu_realize_ctx(vfu_ctx); + if (ret < 0) { + err(EXIT_FAILURE, "failed to realize device"); + } + + ret = vfu_attach_ctx(vfu_ctx); + if (ret < 0) { + err(EXIT_FAILURE, "failed to attach device"); + } + ret = vfu_ctx_drive(vfu_ctx); if (ret != 0) { if (ret != -ENOTCONN && ret != -EINTR) { diff --git a/samples/null.c b/samples/null.c index fda260e..7944e30 100644 --- a/samples/null.c +++ b/samples/null.c @@ -62,6 +62,16 @@ static void* null_drive(void *arg) fprintf(stderr, "failed to enable cancel type: %s\n", strerror(ret)); return NULL; } + ret = vfu_realize_ctx(vfu_ctx); + if (ret < 0) { + fprintf(stderr, "failed to realize device\n"); + return NULL; + } + ret = vfu_attach_ctx(vfu_ctx); + if (ret < 0) { + fprintf(stderr, "failed to attach device\n"); + return NULL; + } printf("starting device emulation\n"); vfu_ctx_drive(vfu_ctx); return NULL; diff --git a/samples/server.c b/samples/server.c index 25bf101..be3c4d9 100644 --- a/samples/server.c +++ b/samples/server.c @@ -485,6 +485,16 @@ int main(int argc, char *argv[]) err(EXIT_FAILURE, "failed to allocate migration data"); } + ret = vfu_realize_ctx(vfu_ctx); + if (ret < 0) { + err(EXIT_FAILURE, "failed to realize device"); + } + + ret = vfu_attach_ctx(vfu_ctx); + if (ret < 0) { + err(EXIT_FAILURE, "failed to attach device"); + } + do { ret = vfu_ctx_drive(vfu_ctx); if (ret == -EINTR) { diff --git a/test/unit-tests.c b/test/unit-tests.c index a20f4fe..5d3703a 100644 --- a/test/unit-tests.c +++ b/test/unit-tests.c @@ -325,6 +325,37 @@ test_process_command_free_passed_fds(void **state __attribute__((unused))) assert_int_equal(0, process_request(&vfu_ctx)); } +static void +test_realize_ctx(void **state __attribute__((unused))) +{ + vfu_reg_info_t *cfg_reg; + vfu_reg_info_t reg_info[VFU_PCI_DEV_NUM_REGIONS + 1] = { 0 }; + vfu_ctx_t vfu_ctx = { + .reg_info = reg_info, + .nr_regions = VFU_PCI_DEV_NUM_REGIONS + 1 + }; + + assert_int_equal(0, vfu_realize_ctx(&vfu_ctx)); + assert_true(vfu_ctx.realized); + cfg_reg = &vfu_ctx.reg_info[VFU_PCI_DEV_CFG_REGION_IDX]; + assert_int_equal(VFU_REGION_FLAG_RW, cfg_reg->flags); + assert_int_equal(PCI_CFG_SPACE_SIZE, cfg_reg->size); + assert_non_null(vfu_ctx.pci.config_space); + assert_non_null(vfu_ctx.irqs); + assert_null(vfu_ctx.pci.caps); +} + +static void +test_attach_ctx(void **state __attribute__((unused))) +{ + vfu_ctx_t vfu_ctx = { + .trans = &sock_transport_ops, + .fd = 111 + }; + + assert_int_equal(-1, vfu_attach_ctx(&vfu_ctx)); +} + /* * FIXME we shouldn't have to specify a setup function explicitly for each unit * test, cmocka should provide that. E.g. cmocka_run_group_tests enables us to @@ -348,6 +379,8 @@ int main(void) cmocka_unit_test_setup(test_dma_controller_add_region_no_fd, setup), cmocka_unit_test_setup(test_dma_controller_remove_region_no_fd, setup), cmocka_unit_test_setup(test_process_command_free_passed_fds, setup), + cmocka_unit_test_setup(test_realize_ctx, setup), + cmocka_unit_test_setup(test_attach_ctx, setup), }; return cmocka_run_group_tests(tests, NULL, NULL); |