aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libvfio-user.h31
-rw-r--r--lib/libvfio-user.c44
-rw-r--r--lib/private.h2
-rw-r--r--samples/gpio-pci-idio-16.c10
-rw-r--r--samples/null.c10
-rw-r--r--samples/server.c10
-rw-r--r--test/unit-tests.c33
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);