diff --git a/debian/libibverbs1.symbols b/debian/libibverbs1.symbols index bb7eac952..1ba5453f1 100644 --- a/debian/libibverbs1.symbols +++ b/debian/libibverbs1.symbols @@ -67,6 +67,7 @@ libibverbs.so.1 libibverbs1 #MINVER# ibv_get_device_name@IBVERBS_1.1 1.1.6 ibv_get_pkey_index@IBVERBS_1.5 20 ibv_get_sysfs_path@IBVERBS_1.0 1.1.6 + ibv_import_device@IBVERBS_1.10 31 ibv_init_ah_from_wc@IBVERBS_1.1 1.1.6 ibv_modify_qp@IBVERBS_1.0 1.1.6 ibv_modify_qp@IBVERBS_1.1 1.1.6 diff --git a/libibverbs/device.c b/libibverbs/device.c index 4ef2a6a06..e9c429a51 100644 --- a/libibverbs/device.c +++ b/libibverbs/device.c @@ -382,6 +382,68 @@ LATEST_SYMVER_FUNC(ibv_open_device, 1_1, "IBVERBS_1.1", return verbs_open_device(device, NULL); } +struct ibv_context *ibv_import_device(int cmd_fd) +{ + struct verbs_device *verbs_device = NULL; + struct verbs_context *context_ex; + struct ibv_device **dev_list; + struct ibv_context *ctx = NULL; + struct stat st; + int ret; + int i; + + if (fstat(cmd_fd, &st) || !S_ISCHR(st.st_mode)) { + errno = EINVAL; + return NULL; + } + + dev_list = ibv_get_device_list(NULL); + if (!dev_list) { + errno = ENODEV; + return NULL; + } + + for (i = 0; dev_list[i]; ++i) { + if (verbs_get_device(dev_list[i])->sysfs->sysfs_cdev == + st.st_rdev) { + verbs_device = verbs_get_device(dev_list[i]); + break; + } + } + + if (!verbs_device) { + errno = ENODEV; + goto out; + } + + if (!verbs_device->ops->import_context) { + errno = EOPNOTSUPP; + goto out; + } + + /* In case the underlay cdev number was assigned in the meantime to + * other device as of some disassociate flow, the next call on the + * FD will end up with EIO (i.e. query_context command) and we should + * be safe from using the wrong device. + */ + context_ex = verbs_device->ops->import_context(&verbs_device->device, cmd_fd); + if (!context_ex) + goto out; + + set_lib_ops(context_ex); + + context_ex->priv->imported = true; + ctx = &context_ex->context; + ret = ibv_cmd_alloc_async_fd(ctx); + if (ret) { + ibv_close_device(ctx); + ctx = NULL; + } +out: + ibv_free_device_list(dev_list); + return ctx; +} + void verbs_uninit_context(struct verbs_context *context_ex) { free(context_ex->priv); diff --git a/libibverbs/driver.h b/libibverbs/driver.h index a1b241b7f..48eace43c 100644 --- a/libibverbs/driver.h +++ b/libibverbs/driver.h @@ -216,6 +216,8 @@ struct verbs_device_ops { struct verbs_context *(*alloc_context)(struct ibv_device *device, int cmd_fd, void *private_data); + struct verbs_context *(*import_context)(struct ibv_device *device, + int cmd_fd); struct verbs_device *(*alloc_device)(struct verbs_sysfs_dev *sysfs_dev); void (*uninit_device)(struct verbs_device *device); diff --git a/libibverbs/libibverbs.map.in b/libibverbs/libibverbs.map.in index 61b6a8038..be75717b5 100644 --- a/libibverbs/libibverbs.map.in +++ b/libibverbs/libibverbs.map.in @@ -133,6 +133,7 @@ IBVERBS_1.9 { IBVERBS_1.10 { global: + ibv_import_device; ibv_query_ece; ibv_set_ece; } IBVERBS_1.9; diff --git a/libibverbs/man/CMakeLists.txt b/libibverbs/man/CMakeLists.txt index a9cf61e31..06b5b49f1 100644 --- a/libibverbs/man/CMakeLists.txt +++ b/libibverbs/man/CMakeLists.txt @@ -37,6 +37,7 @@ rdma_man_pages( ibv_get_device_name.3.md ibv_get_pkey_index.3.md ibv_get_srq_num.3.md + ibv_import_device.3.md ibv_inc_rkey.3.md ibv_modify_qp.3 ibv_modify_qp_rate_limit.3 diff --git a/libibverbs/man/ibv_import_device.3.md b/libibverbs/man/ibv_import_device.3.md new file mode 100644 index 000000000..601b50a8f --- /dev/null +++ b/libibverbs/man/ibv_import_device.3.md @@ -0,0 +1,48 @@ +--- +date: 2020-5-3 +footer: libibverbs +header: "Libibverbs Programmer's Manual" +layout: page +license: 'Licensed under the OpenIB.org BSD license (FreeBSD Variant) - See COPYING.md' +section: 3 +title: ibv_import_device +--- + +# NAME + +ibv_import_device - import a device from a given comamnd FD + +# SYNOPSIS + +```c +#include + +struct ibv_context *ibv_import_device(int cmd_fd); + +``` + + +# DESCRIPTION + +**ibv_import_device()** returns an *ibv_context* pointer that is associated with the given +*cmd_fd*. + +The *cmd_fd* is obtained from the ibv_context cmd_fd member, which must be dup'd (eg by dup(), SCM_RIGHTS, etc) +before being passed to ibv_import_device(). + +Once the *ibv_context* usage has been ended *ibv_close_device()* should be called. +This call may cleanup whatever is needed/opposite of the import including closing the command FD. + +# RETURN VALUE + +**ibv_import_device()** returns a pointer to the allocated RDMA context, or NULL if the request fails. + +# SEE ALSO + +**ibv_open_device**(3), +**ibv_close_device**(3), + +# AUTHOR + +Yishai Hadas + diff --git a/libibverbs/verbs.h b/libibverbs/verbs.h index f72c1ab30..e1247b8e8 100644 --- a/libibverbs/verbs.h +++ b/libibverbs/verbs.h @@ -2241,6 +2241,11 @@ struct ibv_context *ibv_open_device(struct ibv_device *device); */ int ibv_close_device(struct ibv_context *context); +/** + * ibv_import_device - Import device + */ +struct ibv_context *ibv_import_device(int cmd_fd); + /** * ibv_get_async_event - Get next async event * @event: Pointer to use to return async event