IB/uverbs: Add IDRs array attribute type to ioctl() interface

Methods sometimes need to get a flexible set of IDRs and not a strict set
as can be achieved today by the conventional IDR attribute. Add a new
IDRS_ARRAY attribute to the generic uverbs ioctl layer.

IDRS_ARRAY points to array of idrs of the same object type and same access
rights, only write and read are supported.

Signed-off-by: Guy Levi <guyle@mellanox.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>``
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
This commit is contained in:
Guy Levi
2018-09-06 17:27:01 +03:00
committed by Jason Gunthorpe
parent e806f9328b
commit 70cd20aed0
4 changed files with 201 additions and 3 deletions

View File

@@ -52,6 +52,7 @@ enum uverbs_attr_type {
UVERBS_ATTR_TYPE_IDR,
UVERBS_ATTR_TYPE_FD,
UVERBS_ATTR_TYPE_ENUM_IN,
UVERBS_ATTR_TYPE_IDRS_ARRAY,
};
enum uverbs_obj_access {
@@ -101,7 +102,7 @@ struct uverbs_attr_spec {
} enum_def;
} u;
/* This weird split of the enum lets us remove some padding */
/* This weird split lets us remove some padding */
union {
struct {
/*
@@ -111,6 +112,17 @@ struct uverbs_attr_spec {
*/
const struct uverbs_attr_spec *ids;
} enum_def;
struct {
/*
* higher bits mean the namespace and lower bits mean
* the type id within the namespace.
*/
u16 obj_type;
u16 min_len;
u16 max_len;
u8 access;
} objs_arr;
} u2;
};
@@ -251,6 +263,11 @@ static inline __attribute_const__ u32 uapi_bkey_attr(u32 attr_key)
return attr_key - 1;
}
static inline __attribute_const__ u32 uapi_bkey_to_key_attr(u32 attr_bkey)
{
return attr_bkey + 1;
}
/*
* =======================================
* Verbs definitions
@@ -323,6 +340,27 @@ struct uverbs_object_tree_def {
#define UA_MANDATORY .mandatory = 1
#define UA_OPTIONAL .mandatory = 0
/*
* min_len must be bigger than 0 and _max_len must be smaller than 4095. Only
* READ\WRITE accesses are supported.
*/
#define UVERBS_ATTR_IDRS_ARR(_attr_id, _idr_type, _access, _min_len, _max_len, \
...) \
(&(const struct uverbs_attr_def){ \
.id = (_attr_id) + \
BUILD_BUG_ON_ZERO((_min_len) == 0 || \
(_max_len) > \
PAGE_SIZE / sizeof(void *) || \
(_min_len) > (_max_len) || \
(_access) == UVERBS_ACCESS_NEW || \
(_access) == UVERBS_ACCESS_DESTROY), \
.attr = { .type = UVERBS_ATTR_TYPE_IDRS_ARRAY, \
.u2.objs_arr.obj_type = _idr_type, \
.u2.objs_arr.access = _access, \
.u2.objs_arr.min_len = _min_len, \
.u2.objs_arr.max_len = _max_len, \
__VA_ARGS__ } })
#define UVERBS_ATTR_IDR(_attr_id, _idr_type, _access, ...) \
(&(const struct uverbs_attr_def){ \
.id = _attr_id, \
@@ -440,10 +478,16 @@ struct uverbs_obj_attr {
const struct uverbs_api_attr *attr_elm;
};
struct uverbs_objs_arr_attr {
struct ib_uobject **uobjects;
u16 len;
};
struct uverbs_attr {
union {
struct uverbs_ptr_attr ptr_attr;
struct uverbs_obj_attr obj_attr;
struct uverbs_objs_arr_attr objs_arr_attr;
};
};
@@ -516,6 +560,31 @@ uverbs_attr_get_len(const struct uverbs_attr_bundle *attrs_bundle, u16 idx)
return attr->ptr_attr.len;
}
/**
* uverbs_attr_get_uobjs_arr() - Provides array's properties for attribute for
* UVERBS_ATTR_TYPE_IDRS_ARRAY.
* @arr: Returned pointer to array of pointers for uobjects or NULL if
* the attribute isn't provided.
*
* Return: The array length or 0 if no attribute was provided.
*/
static inline int uverbs_attr_get_uobjs_arr(
const struct uverbs_attr_bundle *attrs_bundle, u16 attr_idx,
struct ib_uobject ***arr)
{
const struct uverbs_attr *attr =
uverbs_attr_get(attrs_bundle, attr_idx);
if (IS_ERR(attr)) {
*arr = NULL;
return 0;
}
*arr = attr->objs_arr_attr.uobjects;
return attr->objs_arr_attr.len;
}
static inline bool uverbs_attr_ptr_is_inline(const struct uverbs_attr *attr)
{
return attr->ptr_attr.len <= sizeof(attr->ptr_attr.data);