From: Jason Gunthorpe <jgg@xxxxxxxxxxxx> To be able to add new fields to the end of the struct without breaking the ABI introduce a new query function that takes the length of the struct as an argument and have the inline wrapper preserve the user API. Signed-off-by: Jason Gunthorpe <jgg@xxxxxxxxxxxx> Signed-off-by: Yishai Hadas <yishaih@xxxxxxxxxxxx> --- libibverbs/device.c | 8 +++++++ libibverbs/dummy_ops.c | 2 +- libibverbs/ibverbs.h | 2 ++ libibverbs/verbs.c | 53 +++++++++++++++++++++++++++++++++++++++++++++-- libibverbs/verbs.h | 27 ++++++++++++++++++------ providers/bnxt_re/verbs.c | 1 - 6 files changed, 83 insertions(+), 10 deletions(-) diff --git a/libibverbs/device.c b/libibverbs/device.c index 1fed29b..d710513 100644 --- a/libibverbs/device.c +++ b/libibverbs/device.c @@ -306,6 +306,14 @@ err_free: static void set_lib_ops(struct verbs_context *vctx) { vctx->create_cq_ex = __lib_ibv_create_cq_ex; + + /* + * The compat symver entry point behaves identically to what used to + * be pointed to by _compat_query_port. + */ +#undef ibv_query_port + vctx->context.ops._compat_query_port = ibv_query_port; + vctx->query_port = __lib_query_port; } struct ibv_context *verbs_open_device(struct ibv_device *device, void *private_data) diff --git a/libibverbs/dummy_ops.c b/libibverbs/dummy_ops.c index a5e9380..c861c3a 100644 --- a/libibverbs/dummy_ops.c +++ b/libibverbs/dummy_ops.c @@ -616,7 +616,7 @@ void verbs_set_ops(struct verbs_context *vctx, SET_OP(ctx, post_srq_recv); SET_PRIV_OP(ctx, query_device); SET_OP(vctx, query_device_ex); - SET_PRIV_OP(ctx, query_port); + SET_PRIV_OP_IC(ctx, query_port); SET_PRIV_OP(ctx, query_qp); SET_OP(vctx, query_rt_values); SET_OP(vctx, read_counters); diff --git a/libibverbs/ibverbs.h b/libibverbs/ibverbs.h index 36e29a6..6e4cff4 100644 --- a/libibverbs/ibverbs.h +++ b/libibverbs/ibverbs.h @@ -58,6 +58,8 @@ int ibverbs_get_device_list(struct list_head *list); int ibverbs_init(void); void ibverbs_device_put(struct ibv_device *dev); void ibverbs_device_hold(struct ibv_device *dev); +int __lib_query_port(struct ibv_context *context, uint8_t port_num, + struct ibv_port_attr *port_attr, size_t port_attr_len); #ifdef _STATIC_LIBRARY_BUILD_ static inline void load_drivers(void) diff --git a/libibverbs/verbs.c b/libibverbs/verbs.c index 5edd1bb..3540ef2 100644 --- a/libibverbs/verbs.c +++ b/libibverbs/verbs.c @@ -145,12 +145,61 @@ LATEST_SYMVER_FUNC(ibv_query_device, 1_1, "IBVERBS_1.1", return get_ops(context)->query_device(context, device_attr); } +int __lib_query_port(struct ibv_context *context, uint8_t port_num, + struct ibv_port_attr *port_attr, size_t port_attr_len) +{ + /* Don't expose this mess to the provider, provide a large enough + * temporary buffer if the user buffer is too small. + */ + if (port_attr_len < sizeof(struct ibv_port_attr)) { + struct ibv_port_attr tmp_attr = {}; + int rc; + + rc = get_ops(context)->query_port(context, port_num, + &tmp_attr); + if (rc) + return rc; + + memcpy(port_attr, &tmp_attr, port_attr_len); + return 0; + } + + memset(port_attr, 0, port_attr_len); + return get_ops(context)->query_port(context, port_num, port_attr); +} + +struct _compat_ibv_port_attr { + enum ibv_port_state state; + enum ibv_mtu max_mtu; + enum ibv_mtu active_mtu; + int gid_tbl_len; + uint32_t port_cap_flags; + uint32_t max_msg_sz; + uint32_t bad_pkey_cntr; + uint32_t qkey_viol_cntr; + uint16_t pkey_tbl_len; + uint16_t lid; + uint16_t sm_lid; + uint8_t lmc; + uint8_t max_vl_num; + uint8_t sm_sl; + uint8_t subnet_timeout; + uint8_t init_type_reply; + uint8_t active_width; + uint8_t active_speed; + uint8_t phys_state; + uint8_t link_layer; + uint8_t flags; +}; + LATEST_SYMVER_FUNC(ibv_query_port, 1_1, "IBVERBS_1.1", int, struct ibv_context *context, uint8_t port_num, - struct ibv_port_attr *port_attr) + struct _compat_ibv_port_attr *port_attr) { - return get_ops(context)->query_port(context, port_num, port_attr); + return __lib_query_port(context, port_num, + (struct ibv_port_attr *)port_attr, + sizeof(*port_attr)); } LATEST_SYMVER_FUNC(ibv_query_gid, 1_1, "IBVERBS_1.1", diff --git a/libibverbs/verbs.h b/libibverbs/verbs.h index caf78f4..4851c72 100644 --- a/libibverbs/verbs.h +++ b/libibverbs/verbs.h @@ -1661,9 +1661,12 @@ struct ibv_device { char ibdev_path[IBV_SYSFS_PATH_MAX]; }; +struct _compat_ibv_port_attr; struct ibv_context_ops { void *(*_compat_query_device)(void); - void *(*_compat_query_port)(void); + int (*_compat_query_port)(struct ibv_context *context, + uint8_t port_num, + struct _compat_ibv_port_attr *port_attr); void *(*_compat_alloc_pd)(void); void *(*_compat_dealloc_pd)(void); void *(*_compat_reg_mr)(void); @@ -1786,6 +1789,9 @@ struct ibv_values_ex { struct verbs_context { /* "grows up" - new fields go here */ + int (*query_port)(struct ibv_context *context, uint8_t port_num, + struct ibv_port_attr *port_attr, + size_t port_attr_len); int (*advise_mr)(struct ibv_pd *pd, enum ibv_advise_mr_advice advice, uint32_t flags, @@ -1997,17 +2003,26 @@ int ibv_query_device(struct ibv_context *context, * ibv_query_port - Get port properties */ int ibv_query_port(struct ibv_context *context, uint8_t port_num, - struct ibv_port_attr *port_attr); + struct _compat_ibv_port_attr *port_attr); static inline int ___ibv_query_port(struct ibv_context *context, uint8_t port_num, struct ibv_port_attr *port_attr) { - /* For compatibility when running with old libibverbs */ - port_attr->link_layer = IBV_LINK_LAYER_UNSPECIFIED; - port_attr->flags = 0; + struct verbs_context *vctx = verbs_get_ctx_op(context, query_port); - return ibv_query_port(context, port_num, port_attr); + if (!vctx) { + int rc; + + memset(port_attr, 0, sizeof(*port_attr)); + + rc = ibv_query_port(context, port_num, + (struct _compat_ibv_port_attr *)port_attr); + return rc; + } + + return vctx->query_port(context, port_num, port_attr, + sizeof(*port_attr)); } #define ibv_query_port(context, port_num, port_attr) \ diff --git a/providers/bnxt_re/verbs.c b/providers/bnxt_re/verbs.c index 39b29b0..7786d24 100644 --- a/providers/bnxt_re/verbs.c +++ b/providers/bnxt_re/verbs.c @@ -74,7 +74,6 @@ int bnxt_re_query_port(struct ibv_context *ibvctx, uint8_t port, { struct ibv_query_port cmd; - memset(port_attr, 0, sizeof(struct ibv_port_attr)); return ibv_cmd_query_port(ibvctx, port, port_attr, &cmd, sizeof(cmd)); } -- 1.8.3.1