Commit a140692a authored by Jason Gunthorpe's avatar Jason Gunthorpe

RDMA/uverbs: Check for NULL driver methods for every write call

Add annotations to the uverbs_api structure indicating which driver
methods are called by the implementation. If the required method
is NULL the write API will be not be callable.

This effectively duplicates the cmd_mask system, however it does it by
expressing invariants required by the core code, not by delegating
decision making to the driver. This is another step toward eliminating
cmd_mask.
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
parent 1de751ca
This diff is collapsed.
......@@ -60,8 +60,11 @@ static void *uapi_add_get_elm(struct uverbs_api *uapi, u32 key,
return elm;
}
static int uapi_create_write(struct uverbs_api *uapi, struct ib_device *ibdev,
const struct uapi_definition *def, u32 obj_key)
static int uapi_create_write(struct uverbs_api *uapi,
struct ib_device *ibdev,
const struct uapi_definition *def,
u32 obj_key,
u32 *cur_method_key)
{
struct uverbs_api_write_method *method_elm;
u32 method_key = obj_key;
......@@ -93,6 +96,8 @@ static int uapi_create_write(struct uverbs_api *uapi, struct ib_device *ibdev,
method_elm->disabled = !(ibdev->uverbs_cmd_mask &
BIT_ULL(def->write.command_num));
}
*cur_method_key = method_key;
return 0;
}
......@@ -218,7 +223,8 @@ static int uapi_merge_obj_tree(struct uverbs_api *uapi,
static int uapi_disable_elm(struct uverbs_api *uapi,
const struct uapi_definition *def,
u32 obj_key)
u32 obj_key,
u32 method_key)
{
bool exists;
......@@ -233,6 +239,31 @@ static int uapi_disable_elm(struct uverbs_api *uapi,
return 0;
}
if (def->scope == UAPI_SCOPE_METHOD &&
uapi_key_is_ioctl_method(method_key)) {
struct uverbs_api_ioctl_method *method_elm;
method_elm = uapi_add_get_elm(uapi, method_key,
sizeof(*method_elm), &exists);
if (IS_ERR(method_elm))
return PTR_ERR(method_elm);
method_elm->disabled = 1;
return 0;
}
if (def->scope == UAPI_SCOPE_METHOD &&
(uapi_key_is_write_method(method_key) ||
uapi_key_is_write_ex_method(method_key))) {
struct uverbs_api_write_method *write_elm;
write_elm = uapi_add_get_elm(uapi, method_key,
sizeof(*write_elm), &exists);
if (IS_ERR(write_elm))
return PTR_ERR(write_elm);
write_elm->disabled = 1;
return 0;
}
WARN_ON(true);
return -EINVAL;
}
......@@ -243,6 +274,7 @@ static int uapi_merge_def(struct uverbs_api *uapi, struct ib_device *ibdev,
{
const struct uapi_definition *def = def_list;
u32 cur_obj_key = UVERBS_API_KEY_ERR;
u32 cur_method_key = UVERBS_API_KEY_ERR;
bool exists;
int rc;
......@@ -277,7 +309,8 @@ static int uapi_merge_def(struct uverbs_api *uapi, struct ib_device *ibdev,
if (*ibdev_fn)
continue;
rc = uapi_disable_elm(uapi, def, cur_obj_key);
rc = uapi_disable_elm(
uapi, def, cur_obj_key, cur_method_key);
if (rc)
return rc;
continue;
......@@ -286,7 +319,8 @@ static int uapi_merge_def(struct uverbs_api *uapi, struct ib_device *ibdev,
case UAPI_DEF_IS_SUPPORTED_FUNC:
if (def->func_is_supported(ibdev))
continue;
rc = uapi_disable_elm(uapi, def, cur_obj_key);
rc = uapi_disable_elm(
uapi, def, cur_obj_key, cur_method_key);
if (rc)
return rc;
continue;
......@@ -303,7 +337,8 @@ static int uapi_merge_def(struct uverbs_api *uapi, struct ib_device *ibdev,
}
case UAPI_DEF_WRITE:
rc = uapi_create_write(uapi, ibdev, def, cur_obj_key);
rc = uapi_create_write(
uapi, ibdev, def, cur_obj_key, &cur_method_key);
if (rc)
return rc;
continue;
......
......@@ -350,6 +350,7 @@ enum uapi_definition_kind {
enum uapi_definition_scope {
UAPI_SCOPE_OBJECT = 1,
UAPI_SCOPE_METHOD = 2,
};
struct uapi_definition {
......@@ -422,6 +423,21 @@ struct uapi_definition {
sizeof(void *)), \
}
/*
* Method is only supported if the function pointer named ibdev_fn in struct
* ib_device is not NULL.
*/
#define UAPI_DEF_METHOD_NEEDS_FN(ibdev_fn) \
{ \
.kind = UAPI_DEF_IS_SUPPORTED_DEV_FN, \
.scope = UAPI_SCOPE_METHOD, \
.needs_fn_offset = \
offsetof(struct ib_device, ibdev_fn) + \
BUILD_BUG_ON_ZERO( \
sizeof(((struct ib_device *)0)->ibdev_fn) != \
sizeof(void *)), \
}
/* Call a function to determine if the entire object is supported or not */
#define UAPI_DEF_IS_OBJ_SUPPORTED(_func) \
{ \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment