Re: [PATCH RFC 03/10] IB/core: Add new ioctl interface

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Apr 19, 2017 at 06:20:18PM +0300, Matan Barak wrote:
> In this ioctl interface, processing the command starts from
> properties of the command and fetching the appropriate user objects
> before calling the handler.
>
> Parsing and validation is done according to a specifier declared by
> the driver's code. In the driver, all supported types are declared.
> These types are separated to different type groups, each could be
> declared in a different place (for example, common types and driver
> specific types).
>
> For each type we list all supported actions. Similarly to types,
> actions are separated to actions groups too. Each group is declared
> separately. This could be used in order to add actions to an existing
> type.
>
> Each action has a specifies a handler, which could be either a
> standard command or a driver specific command.
> Along with the handler, a group of attributes is specified as well.
> This group lists all supported attributes and is used for automatic
> fetching and validation of the command, response and its related
> objects.
>
> When a group of elements is used, the high bits of the elements ids
> are used in order to calculate the group index. Then, these high bits
> are masked out in order to have a zero based namespace for every
> group. This is mandatory for compact representation and O(1) array
> access.
>
> A group of attributes is actually an array of attributes. Each
> attribute has a type (PTR_IN, PTR_OUT, IDR and FD) and a length.
> Attributes could be validated through some attributes, like:
> (*) Minimum size / Exact size
> (*) Fops for FD
> (*) Object type for IDR
>
> If an IDR/fd attribute is specified, the kernel also states the object
> type and the required access (NEW, WRITE, READ or DESTROY).
> All uobject/fd management is done automatically by the infrastructure,
> meaning - the infrastructure will fail concurrent commands that at
> least one of them requires concurrent access (WRITE/DESTROY),
> synchronize actions with device removals (dissociate context events)
> and take care of reference counting (increase/decrease) for concurrent
> actions invocation. The reference counts on the actual kernel objects
> shall be handled by the handlers.
>
>  types
> +--------+
> |        |
> |        |   actions                                                                +--------+
> |        |   group      action      action_spec                           +-----+   |len     |
> +--------+  +------+[d]+-------+   +----------------+[d]+------------+    |attr1+-> |type    |
> | type   +> |action+-> | spec  +-> +  attr_groups   +-> |common sec  +--> +-----+   |idr_type|
> +--------+  +------+   |handler|   |                |   +------------+    |attr2|   |access  |
> |        |  |      |   +-------+   +----------------+   |device sec  |    +-----+   +--------+
> |        |  |      |                                    +------------+
> |        |  +------+
> |        |
> |        |
> |        |
> |        |
> |        |
> |        |
> |        |
> |        |
> |        |
> |        |
> +--------+
>
> [d] = distribute ids to groups using the high order bits
>
> The right types table is also chosen by using the high bits from
> uverbs_types_groups.
>
> Once validation and object fetching (or creation) completed, we call
> the handler:
> int (*handler)(struct ib_device *ib_dev, struct ib_ucontext *ucontext,
>                struct uverbs_attr_array *ctx, size_t num);
>
> Where ctx is an array of uverbs_attr_array. Each element in this array
> is an array of attributes which corresponds to one group of attributes.
> For example, in the usually used case:
>
>  ctx                               core
> +----------------------------+     +------------+
> | core: uverbs_attr_array    +---> | valid      |
> +----------------------------+     | cmd_attr   |
> | driver: uverbs_attr_array  |     +------------+
> |----------------------------+--+  | valid      |
>                                 |  | cmd_attr   |
>                                 |  +------------+
>                                 |  | valid      |
>                                 |  | obj_attr   |
>                                 |  +------------+
>                                 |
>                                 |  vendor
>                                 |  +------------+
>                                 +> | valid      |
>                                    | cmd_attr   |
>                                    +------------+
>                                    | valid      |
>                                    | cmd_attr   |
>                                    +------------+
>                                    | valid      |
>                                    | obj_attr   |
>                                    +------------+
>
> Ctx array's indices corresponds to the attributes groups order. The indices
> of core and driver corresponds to the attributes name spaces of each
> group. Thus, we could think of the following as one object:
> 1. Set of attribute specification (with their attribute IDs)
> 2. Attribute group which owns (1) specifications
> 3. A function which could handle this attributes which the handler
>    could call
> 4. The allocation descriptor of this type uverbs_obj_type.
>
> Upon success of a handler invocation, reference count of uobjects and
> use count will be a updated automatically according to the
> specification.
>
> Signed-off-by: Matan Barak <matanb@xxxxxxxxxxxx>
> ---
>  drivers/infiniband/core/Makefile       |   2 +-
>  drivers/infiniband/core/rdma_core.c    |  45 +++++
>  drivers/infiniband/core/rdma_core.h    |   5 +
>  drivers/infiniband/core/uverbs_ioctl.c | 351 +++++++++++++++++++++++++++++++++
>  include/rdma/ib_verbs.h                |   2 +
>  include/rdma/uverbs_ioctl.h            |  65 ++++--
>  include/uapi/rdma/rdma_user_ioctl.h    |  25 +++
>  7 files changed, 481 insertions(+), 14 deletions(-)
>  create mode 100644 drivers/infiniband/core/uverbs_ioctl.c
>
> diff --git a/drivers/infiniband/core/Makefile b/drivers/infiniband/core/Makefile
> index 6ebd9ad..e18f2f8 100644
> --- a/drivers/infiniband/core/Makefile
> +++ b/drivers/infiniband/core/Makefile
> @@ -30,4 +30,4 @@ ib_umad-y :=			user_mad.o
>  ib_ucm-y :=			ucm.o
>
>  ib_uverbs-y :=			uverbs_main.o uverbs_cmd.o uverbs_marshall.o \
> -				rdma_core.o uverbs_std_types.o
> +				rdma_core.o uverbs_std_types.o uverbs_ioctl.o
> diff --git a/drivers/infiniband/core/rdma_core.c b/drivers/infiniband/core/rdma_core.c
> index 78ffd8c..a6e35b3 100644
> --- a/drivers/infiniband/core/rdma_core.c
> +++ b/drivers/infiniband/core/rdma_core.c
> @@ -40,6 +40,51 @@
>  #include "core_priv.h"
>  #include "rdma_core.h"
>
> +int uverbs_group_idx(u16 *id, unsigned int ngroups)
> +{
> +	int ret = (*id & UVERBS_ID_RESERVED_MASK) >> UVERBS_ID_RESERVED_SHIFT;
> +
> +	if (ret >= ngroups)
> +		return -EINVAL;
> +
> +	*id &= ~UVERBS_ID_RESERVED_MASK;
> +	return ret;
> +}
> +
> +const struct uverbs_type *uverbs_get_type(const struct ib_device *ibdev,
> +					  uint16_t type)
> +{
> +	const struct uverbs_root *groups = ibdev->specs_root;
> +	const struct uverbs_type_group *types;
> +	int ret = uverbs_group_idx(&type, groups->num_groups);
> +
> +	if (ret < 0)
> +		return NULL;
> +
> +	types = groups->type_groups[ret];
> +
> +	if (type >= types->num_types)
> +		return NULL;
> +
> +	return types->types[type];
> +}
> +
> +const struct uverbs_action *uverbs_get_action(const struct uverbs_type *type,
> +					      uint16_t action)
> +{
> +	const struct uverbs_action_group *action_group;
> +	int ret = uverbs_group_idx(&action, type->num_groups);
> +
> +	if (ret < 0)
> +		return NULL;
> +
> +	action_group = type->action_groups[ret];
> +	if (action >= action_group->num_actions)
> +		return NULL;
> +
> +	return action_group->actions[action];
> +}
> +
>  void uverbs_uobject_get(struct ib_uobject *uobject)
>  {
>  	kref_get(&uobject->ref);
> diff --git a/drivers/infiniband/core/rdma_core.h b/drivers/infiniband/core/rdma_core.h
> index 0aebc47..82db2bc 100644
> --- a/drivers/infiniband/core/rdma_core.h
> +++ b/drivers/infiniband/core/rdma_core.h
> @@ -43,6 +43,11 @@
>  #include <rdma/ib_verbs.h>
>  #include <linux/mutex.h>
>
> +int uverbs_group_idx(u16 *id, unsigned int ngroups);
> +const struct uverbs_type *uverbs_get_type(const struct ib_device *ibdev,
> +					  uint16_t type);
> +const struct uverbs_action *uverbs_get_action(const struct uverbs_type *type,
> +					      uint16_t action);
>  /*
>   * These functions initialize the context and cleanups its uobjects.
>   * The context has a list of objects which is protected by a mutex
> diff --git a/drivers/infiniband/core/uverbs_ioctl.c b/drivers/infiniband/core/uverbs_ioctl.c
> new file mode 100644
> index 0000000..3465a18
> --- /dev/null
> +++ b/drivers/infiniband/core/uverbs_ioctl.c
> @@ -0,0 +1,351 @@
> +/*
> + * Copyright (c) 2017, Mellanox Technologies inc.  All rights reserved.
> + *
> + * This software is available to you under a choice of one of two
> + * licenses.  You may choose to be licensed under the terms of the GNU
> + * General Public License (GPL) Version 2, available from the file
> + * COPYING in the main directory of this source tree, or the
> + * OpenIB.org BSD license below:
> + *
> + *     Redistribution and use in source and binary forms, with or
> + *     without modification, are permitted provided that the following
> + *     conditions are met:
> + *
> + *      - Redistributions of source code must retain the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer.
> + *
> + *      - Redistributions in binary form must reproduce the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer in the documentation and/or other materials
> + *        provided with the distribution.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> + * SOFTWARE.
> + */
> +
> +#include <rdma/rdma_user_ioctl.h>
> +#include <rdma/uverbs_ioctl.h>
> +#include "rdma_core.h"
> +#include "uverbs.h"
> +
> +static int uverbs_process_attr(struct ib_device *ibdev,
> +			       struct ib_ucontext *ucontext,
> +			       const struct ib_uverbs_attr *uattr,
> +			       u16 attr_id,
> +			       const struct uverbs_attr_spec_group *attr_spec_group,
> +			       struct uverbs_attr_array *attr_array,
> +			       struct ib_uverbs_attr __user *uattr_ptr)
> +{
> +	const struct uverbs_attr_spec *spec;
> +	struct uverbs_attr *e;
> +	const struct uverbs_type *type;
> +	struct uverbs_obj_attr *o_attr;
> +	struct uverbs_attr *elements = attr_array->attrs;
> +
> +	if (uattr->reserved)
> +		return -EINVAL;
> +
> +	if (attr_id >= attr_spec_group->num_attrs) {
> +		if (uattr->flags & UVERBS_ATTR_F_MANDATORY)
> +			return -EINVAL;
> +		else
> +			return 0;
> +	}
> +
> +	spec = &attr_spec_group->attrs[attr_id];
> +	e = &elements[attr_id];
> +
> +	switch (spec->type) {
> +	case UVERBS_ATTR_TYPE_PTR_IN:
> +	case UVERBS_ATTR_TYPE_PTR_OUT:
> +		if (uattr->len < spec->len ||
> +		    (!(spec->flags & UVERBS_ATTR_SPEC_F_MIN_SZ) &&
> +		     uattr->len > spec->len))
> +			return -EINVAL;
> +
> +		e->ptr_attr.ptr = (void * __user)uattr->data;
> +		e->ptr_attr.len = uattr->len;
> +		break;
> +
> +	case UVERBS_ATTR_TYPE_IDR:
> +		if (uattr->data >> 32)
> +			return -EINVAL;
> +	/* fall through */
> +	case UVERBS_ATTR_TYPE_FD:
> +		if (uattr->len != 0 || !ucontext || uattr->data > INT_MAX)
> +			return -EINVAL;
> +
> +		o_attr = &e->obj_attr;
> +		type = uverbs_get_type(ibdev, spec->obj.obj_type);
> +		if (!type)
> +			return -EINVAL;
> +		o_attr->type = type->type_attrs;
> +		o_attr->uattr = uattr_ptr;
> +
> +		o_attr->id = (int)uattr->data;
> +		o_attr->uobject = uverbs_get_uobject_from_context(
> +					o_attr->type,
> +					ucontext,
> +					spec->obj.access,
> +					o_attr->id);
> +
> +		if (IS_ERR(o_attr->uobject))
> +			return -EINVAL;
> +
> +		if (spec->obj.access == UVERBS_ACCESS_NEW) {
> +			u64 id = o_attr->uobject->id;
> +
> +			if (put_user(id, &o_attr->uattr->data)) {
> +				uverbs_finalize_object(o_attr->uobject,
> +						       UVERBS_ACCESS_NEW,
> +						       false);
> +				return -EFAULT;
> +			}
> +		}
> +
> +		break;
> +	default:
> +		return -EOPNOTSUPP;
> +	};
> +
> +	set_bit(attr_id, attr_array->valid_bitmap);
> +	return 0;
> +}
> +
> +static int uverbs_uattrs_process(struct ib_device *ibdev,
> +				 struct ib_ucontext *ucontext,
> +				 const struct ib_uverbs_attr *uattrs,
> +				 size_t num_uattrs,
> +				 const struct uverbs_action *action,
> +				 struct uverbs_attr_array *attr_array,
> +				 struct ib_uverbs_attr __user *uattr_ptr)
> +{
> +	size_t i;
> +	int ret = 0;
> +	int num_given_groups = 0;
> +
> +	for (i = 0; i < num_uattrs; i++) {
> +		const struct ib_uverbs_attr *uattr = &uattrs[i];
> +		u16 attr_id = uattr->attr_id;
> +		const struct uverbs_attr_spec_group *attr_spec_group;
> +
> +		ret = uverbs_group_idx(&attr_id, action->num_groups);
> +		if (ret < 0) {
> +			if (uattr->flags & UVERBS_ATTR_F_MANDATORY)
> +				return ret;
> +
> +			continue;
> +		}
> +
> +		if (ret >= num_given_groups)
> +			num_given_groups = ret + 1;
> +
> +		attr_spec_group = action->attr_groups[ret];
> +		ret = uverbs_process_attr(ibdev, ucontext, uattr, attr_id,
> +					  attr_spec_group, &attr_array[ret],
> +					  uattr_ptr++);
> +		if (ret) {
> +			uverbs_finalize_objects(attr_array,
> +						num_given_groups,
> +						action, false);
> +			return ret;
> +		}
> +	}
> +
> +	return ret ?: num_given_groups;
> +}
> +
> +static int uverbs_validate_kernel_mandatory(const struct uverbs_action *action,
> +					    struct uverbs_attr_array *attr_array,
> +					    unsigned int num_given_groups)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < num_given_groups; i++) {
> +		const struct uverbs_attr_spec_group *attr_spec_group =
> +			action->attr_groups[i];
> +
> +		if (!bitmap_subset(attr_spec_group->mandatory_attrs_bitmask,
> +				   attr_array[i].valid_bitmap,
> +				   attr_spec_group->num_attrs))
> +			return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int uverbs_handle_action(struct ib_uverbs_attr __user *uattr_ptr,
> +				const struct ib_uverbs_attr *uattrs,
> +				size_t num_uattrs,
> +				struct ib_device *ibdev,
> +				struct ib_uverbs_file *ufile,
> +				const struct uverbs_action *action,
> +				struct uverbs_attr_array *attr_array)
> +{
> +	int ret;
> +	int finalize_ret;
> +	int num_given_groups;
> +
> +	num_given_groups = uverbs_uattrs_process(ibdev, ufile->ucontext, uattrs,
> +						 num_uattrs, action, attr_array,
> +						 uattr_ptr);
> +	if (num_given_groups <= 0)
> +		return -EINVAL;
> +
> +	ret = uverbs_validate_kernel_mandatory(action, attr_array,
> +					       num_given_groups);
> +	if (ret)
> +		goto cleanup;
> +
> +	ret = action->handler(ibdev, ufile, attr_array, num_given_groups);
> +cleanup:
> +	finalize_ret = uverbs_finalize_objects(attr_array, num_given_groups,
> +					       action, !ret);
> +
> +	return ret ? ret : finalize_ret;
> +}
> +
> +#define UVERBS_OPTIMIZE_USING_STACK_SZ  256
> +long ib_uverbs_cmd_verbs(struct ib_device *ib_dev,
> +			 struct ib_uverbs_file *file,
> +			 struct ib_uverbs_ioctl_hdr *hdr,
> +			 void __user *buf)
> +{
> +	const struct uverbs_type *type;
> +	const struct uverbs_action *action;
> +	long err = 0;
> +	unsigned int i;
> +	struct {
> +		struct ib_uverbs_attr		*uattrs;
> +		struct uverbs_attr_array	*uverbs_attr_array;
> +	} *ctx = NULL;
> +	struct uverbs_attr *curr_attr;
> +	unsigned long *curr_bitmap;
> +	size_t ctx_size;
> +#ifdef UVERBS_OPTIMIZE_USING_STACK_SZ
> +	uintptr_t data[UVERBS_OPTIMIZE_USING_STACK_SZ / sizeof(uintptr_t)];
> +#endif
> +
> +	if (hdr->reserved)
> +		return -EINVAL;
> +
> +	type = uverbs_get_type(ib_dev, hdr->object_type);
> +	if (!type)
> +		return -EOPNOTSUPP;
> +
> +	action = uverbs_get_action(type, hdr->action);
> +	if (!action)
> +		return -EOPNOTSUPP;
> +
> +	if ((action->flags & UVERBS_ACTION_FLAG_CREATE_ROOT) ^ !file->ucontext)
> +		return -EINVAL;
> +
> +	ctx_size = sizeof(*ctx) +
> +		   sizeof(struct uverbs_attr_array) * action->num_groups +
> +		   sizeof(*ctx->uattrs) * hdr->num_attrs +
> +		   sizeof(*ctx->uverbs_attr_array->attrs) *
> +		   action->num_child_attrs +
> +		   sizeof(*ctx->uverbs_attr_array->valid_bitmap) *
> +			(action->num_child_attrs / BITS_PER_LONG +
> +			 action->num_groups);
> +
> +#ifdef UVERBS_OPTIMIZE_USING_STACK_SZ
> +	if (ctx_size <= UVERBS_OPTIMIZE_USING_STACK_SZ)
> +		ctx = (void *)data;
> +
> +	if (!ctx)
> +#endif
> +	ctx = kmalloc(ctx_size, GFP_KERNEL);
> +	if (!ctx)
> +		return -ENOMEM;
> +
> +	ctx->uverbs_attr_array = (void *)ctx + sizeof(*ctx);
> +	ctx->uattrs = (void *)(ctx->uverbs_attr_array +
> +			       action->num_groups);
> +	curr_attr = (void *)(ctx->uattrs + hdr->num_attrs);
> +	curr_bitmap = (void *)(curr_attr + action->num_child_attrs);
> +
> +	/*
> +	 * We just fill the pointers and num_attrs here. The data itself will be
> +	 * filled at a later stage (uverbs_process_attr)
> +	 */
> +	for (i = 0; i < action->num_groups; i++) {
> +		unsigned int curr_num_attrs = action->attr_groups[i]->num_attrs;
> +
> +		ctx->uverbs_attr_array[i].attrs = curr_attr;
> +		curr_attr += curr_num_attrs;
> +		ctx->uverbs_attr_array[i].num_attrs = curr_num_attrs;
> +		ctx->uverbs_attr_array[i].valid_bitmap = curr_bitmap;
> +		bitmap_zero(curr_bitmap, curr_num_attrs);
> +		curr_bitmap += BITS_TO_LONGS(curr_num_attrs);
> +	}
> +
> +	err = copy_from_user(ctx->uattrs, buf,
> +			     sizeof(*ctx->uattrs) * hdr->num_attrs);
> +	if (err) {
> +		err = -EFAULT;
> +		goto out;
> +	}
> +
> +	err = uverbs_handle_action(buf, ctx->uattrs, hdr->num_attrs, ib_dev,
> +				   file, action, ctx->uverbs_attr_array);
> +out:
> +#ifdef UVERBS_OPTIMIZE_USING_STACK_SZ
> +	if (ctx_size > UVERBS_OPTIMIZE_USING_STACK_SZ)
> +#endif
> +	kfree(ctx);

What is the purpose of UVERBS_OPTIMIZE_USING_STACK_SZ?
And something wrong with this "if" and kfree after that.


> +	return err;
> +}
> +
> +#define IB_UVERBS_MAX_CMD_SZ 4096
> +
> +long ib_uverbs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> +{
> +	struct ib_uverbs_file *file = filp->private_data;
> +	struct ib_uverbs_ioctl_hdr __user *user_hdr =
> +		(struct ib_uverbs_ioctl_hdr __user *)arg;
> +	struct ib_uverbs_ioctl_hdr hdr;
> +	struct ib_device *ib_dev;
> +	int srcu_key;
> +	long err;
> +
> +	srcu_key = srcu_read_lock(&file->device->disassociate_srcu);
> +	ib_dev = srcu_dereference(file->device->ib_dev,
> +				  &file->device->disassociate_srcu);
> +	if (!ib_dev) {
> +		err = -EIO;
> +		goto out;
> +	}
> +
> +	if (cmd == RDMA_VERBS_IOCTL) {
> +		err = copy_from_user(&hdr, user_hdr, sizeof(hdr));
> +
> +		if (err || hdr.length > IB_UVERBS_MAX_CMD_SZ ||
> +		    hdr.length != sizeof(hdr) + hdr.num_attrs * sizeof(struct ib_uverbs_attr)) {
> +			err = -EINVAL;
> +			goto out;
> +		}
> +
> +		/* currently there are no flags supported */
> +		if (hdr.flags) {
> +			err = -EOPNOTSUPP;
> +			goto out;
> +		}
> +
> +		err = ib_uverbs_cmd_verbs(ib_dev, file, &hdr,
> +					  (__user void *)arg + sizeof(hdr));
> +	} else {
> +		err = -ENOIOCTLCMD;
> +	}
> +out:
> +	srcu_read_unlock(&file->device->disassociate_srcu, srcu_key);
> +
> +	return err;
> +}
> diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
> index 3a8e058..44cd98b 100644
> --- a/include/rdma/ib_verbs.h
> +++ b/include/rdma/ib_verbs.h
> @@ -2165,6 +2165,8 @@ struct ib_device {
>  	 */
>  	int (*get_port_immutable)(struct ib_device *, u8, struct ib_port_immutable *);
>  	void (*get_dev_fw_str)(struct ib_device *, char *str, size_t str_len);
> +
> +	struct uverbs_root                      *specs_root;
>  };
>
>  struct ib_client {
> diff --git a/include/rdma/uverbs_ioctl.h b/include/rdma/uverbs_ioctl.h
> index 1f84f30..71a6b84 100644
> --- a/include/rdma/uverbs_ioctl.h
> +++ b/include/rdma/uverbs_ioctl.h
> @@ -41,8 +41,13 @@
>   * =======================================
>   */
>
> +#define UVERBS_ID_RESERVED_MASK 0xF000
> +#define UVERBS_ID_RESERVED_SHIFT 12
> +
>  enum uverbs_attr_type {
>  	UVERBS_ATTR_TYPE_NA,
> +	UVERBS_ATTR_TYPE_PTR_IN,
> +	UVERBS_ATTR_TYPE_PTR_OUT,
>  	UVERBS_ATTR_TYPE_IDR,
>  	UVERBS_ATTR_TYPE_FD,
>  };
> @@ -54,8 +59,14 @@ enum uverbs_idr_access {
>  	UVERBS_ACCESS_DESTROY
>  };
>
> +enum uverbs_attr_spec_flags {
> +	UVERBS_ATTR_SPEC_F_MANDATORY	= 1U << 0,
> +	UVERBS_ATTR_SPEC_F_MIN_SZ	= 1U << 1,
> +};
> +
>  struct uverbs_attr_spec {
>  	enum uverbs_attr_type		type;
> +	u8				flags;
>  	union {
>  		u16				len;
>  		struct {
> @@ -68,11 +79,45 @@ struct uverbs_attr_spec {
>  struct uverbs_attr_spec_group {
>  	struct uverbs_attr_spec		*attrs;
>  	size_t				num_attrs;
> +	/* populate at runtime */
> +	unsigned long			*mandatory_attrs_bitmask;
> +};
> +
> +struct uverbs_attr_array;
> +struct ib_uverbs_file;
> +
> +enum uverbs_action_flags {
> +	UVERBS_ACTION_FLAG_CREATE_ROOT = 1 << 0,
>  };
>
>  struct uverbs_action {
> -	const struct uverbs_attr_spec_group		**attr_groups;
> +	struct uverbs_attr_spec_group			**attr_groups;
>  	size_t						num_groups;
> +	size_t						num_child_attrs;
> +	u32 flags;
> +	int (*handler)(struct ib_device *ib_dev, struct ib_uverbs_file *ufile,
> +		       struct uverbs_attr_array *ctx, size_t num);
> +};
> +
> +struct uverbs_action_group {
> +	size_t					num_actions;
> +	struct uverbs_action			**actions;
> +};
> +
> +struct uverbs_type {
> +	size_t					num_groups;
> +	const struct uverbs_action_group	**action_groups;
> +	const struct uverbs_obj_type		*type_attrs;
> +};
> +
> +struct uverbs_type_group {
> +	size_t					num_types;
> +	const struct uverbs_type		**types;
> +};
> +
> +struct uverbs_root {
> +	const struct uverbs_type_group		**type_groups;
> +	size_t					num_groups;
>  };
>
>  /* =================================================
> @@ -80,28 +125,22 @@ struct uverbs_action {
>   * =================================================
>   */
>
> -struct uverbs_fd_attr {
> -	int		fd;
> -};
> -
> -struct uverbs_uobj_attr {
> -	/*  idr handle */
> -	u32	idr;
> +struct uverbs_ptr_attr {
> +	void	* __user ptr;
> +	u16		len;
>  };
>
>  struct uverbs_obj_attr {
>  	/* pointer to the kernel descriptor -> type, access, etc */
>  	struct ib_uverbs_attr __user	*uattr;
> -	const struct uverbs_type_alloc_action	*type;
> +	const struct uverbs_obj_type	*type;
>  	struct ib_uobject		*uobject;
> -	union {
> -		struct uverbs_fd_attr		fd;
> -		struct uverbs_uobj_attr		uobj;
> -	};
> +	int				id;
>  };
>
>  struct uverbs_attr {
>  	union {
> +		struct uverbs_ptr_attr	ptr_attr;
>  		struct uverbs_obj_attr	obj_attr;
>  	};
>  };
> diff --git a/include/uapi/rdma/rdma_user_ioctl.h b/include/uapi/rdma/rdma_user_ioctl.h
> index 9388125..12663f6 100644
> --- a/include/uapi/rdma/rdma_user_ioctl.h
> +++ b/include/uapi/rdma/rdma_user_ioctl.h
> @@ -43,6 +43,31 @@
>  /* Legacy name, for user space application which already use it */
>  #define IB_IOCTL_MAGIC		RDMA_IOCTL_MAGIC
>
> +#define RDMA_VERBS_IOCTL \
> +	_IOWR(RDMA_IOCTL_MAGIC, 1, struct ib_uverbs_ioctl_hdr)
> +
> +enum ib_uverbs_attr_flags {
> +	UVERBS_ATTR_F_MANDATORY = 1U << 0,
> +};
> +
> +struct ib_uverbs_attr {
> +	__u16 attr_id;		/* command specific type attribute */
> +	__u16 len;		/* NA for idr */
> +	__u16 flags;		/* combination of uverbs_attr_flags */
> +	__u16 reserved;
> +	__u64 data;		/* ptr to command, inline data or idr/fd */
> +};
> +
> +struct ib_uverbs_ioctl_hdr {
> +	__u16 length;
> +	__u16 flags;
> +	__u16 object_type;
> +	__u16 reserved;		/* future use for driver_id */
> +	__u16 action;
> +	__u16 num_attrs;
> +	struct ib_uverbs_attr  attrs[0];
> +};
> +
>  /*
>   * General blocks assignments
>   * It is closed on purpose do not expose it it user space
> --
> 1.8.3.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux