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, ...@@ -60,8 +60,11 @@ static void *uapi_add_get_elm(struct uverbs_api *uapi, u32 key,
return elm; return elm;
} }
static int uapi_create_write(struct uverbs_api *uapi, struct ib_device *ibdev, static int uapi_create_write(struct uverbs_api *uapi,
const struct uapi_definition *def, u32 obj_key) struct ib_device *ibdev,
const struct uapi_definition *def,
u32 obj_key,
u32 *cur_method_key)
{ {
struct uverbs_api_write_method *method_elm; struct uverbs_api_write_method *method_elm;
u32 method_key = obj_key; u32 method_key = obj_key;
...@@ -93,6 +96,8 @@ static int uapi_create_write(struct uverbs_api *uapi, struct ib_device *ibdev, ...@@ -93,6 +96,8 @@ static int uapi_create_write(struct uverbs_api *uapi, struct ib_device *ibdev,
method_elm->disabled = !(ibdev->uverbs_cmd_mask & method_elm->disabled = !(ibdev->uverbs_cmd_mask &
BIT_ULL(def->write.command_num)); BIT_ULL(def->write.command_num));
} }
*cur_method_key = method_key;
return 0; return 0;
} }
...@@ -218,7 +223,8 @@ static int uapi_merge_obj_tree(struct uverbs_api *uapi, ...@@ -218,7 +223,8 @@ static int uapi_merge_obj_tree(struct uverbs_api *uapi,
static int uapi_disable_elm(struct uverbs_api *uapi, static int uapi_disable_elm(struct uverbs_api *uapi,
const struct uapi_definition *def, const struct uapi_definition *def,
u32 obj_key) u32 obj_key,
u32 method_key)
{ {
bool exists; bool exists;
...@@ -233,6 +239,31 @@ static int uapi_disable_elm(struct uverbs_api *uapi, ...@@ -233,6 +239,31 @@ static int uapi_disable_elm(struct uverbs_api *uapi,
return 0; 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); WARN_ON(true);
return -EINVAL; return -EINVAL;
} }
...@@ -243,6 +274,7 @@ static int uapi_merge_def(struct uverbs_api *uapi, struct ib_device *ibdev, ...@@ -243,6 +274,7 @@ static int uapi_merge_def(struct uverbs_api *uapi, struct ib_device *ibdev,
{ {
const struct uapi_definition *def = def_list; const struct uapi_definition *def = def_list;
u32 cur_obj_key = UVERBS_API_KEY_ERR; u32 cur_obj_key = UVERBS_API_KEY_ERR;
u32 cur_method_key = UVERBS_API_KEY_ERR;
bool exists; bool exists;
int rc; int rc;
...@@ -277,7 +309,8 @@ static int uapi_merge_def(struct uverbs_api *uapi, struct ib_device *ibdev, ...@@ -277,7 +309,8 @@ static int uapi_merge_def(struct uverbs_api *uapi, struct ib_device *ibdev,
if (*ibdev_fn) if (*ibdev_fn)
continue; continue;
rc = uapi_disable_elm(uapi, def, cur_obj_key); rc = uapi_disable_elm(
uapi, def, cur_obj_key, cur_method_key);
if (rc) if (rc)
return rc; return rc;
continue; continue;
...@@ -286,7 +319,8 @@ static int uapi_merge_def(struct uverbs_api *uapi, struct ib_device *ibdev, ...@@ -286,7 +319,8 @@ static int uapi_merge_def(struct uverbs_api *uapi, struct ib_device *ibdev,
case UAPI_DEF_IS_SUPPORTED_FUNC: case UAPI_DEF_IS_SUPPORTED_FUNC:
if (def->func_is_supported(ibdev)) if (def->func_is_supported(ibdev))
continue; continue;
rc = uapi_disable_elm(uapi, def, cur_obj_key); rc = uapi_disable_elm(
uapi, def, cur_obj_key, cur_method_key);
if (rc) if (rc)
return rc; return rc;
continue; continue;
...@@ -303,7 +337,8 @@ static int uapi_merge_def(struct uverbs_api *uapi, struct ib_device *ibdev, ...@@ -303,7 +337,8 @@ static int uapi_merge_def(struct uverbs_api *uapi, struct ib_device *ibdev,
} }
case UAPI_DEF_WRITE: 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) if (rc)
return rc; return rc;
continue; continue;
......
...@@ -350,6 +350,7 @@ enum uapi_definition_kind { ...@@ -350,6 +350,7 @@ enum uapi_definition_kind {
enum uapi_definition_scope { enum uapi_definition_scope {
UAPI_SCOPE_OBJECT = 1, UAPI_SCOPE_OBJECT = 1,
UAPI_SCOPE_METHOD = 2,
}; };
struct uapi_definition { struct uapi_definition {
...@@ -422,6 +423,21 @@ struct uapi_definition { ...@@ -422,6 +423,21 @@ struct uapi_definition {
sizeof(void *)), \ 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 */ /* Call a function to determine if the entire object is supported or not */
#define UAPI_DEF_IS_OBJ_SUPPORTED(_func) \ #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