Skip to content

Commit bccd062

Browse files
committed
IB/uverbs: Add UVERBS_ATTR_FLAGS_IN to the specs language
This clearly indicates that the input is a bitwise combination of values in an enum, and identifies which enum contains the definition of the bits. Special accessors are provided that handle the mandatory validation of the allowed bits and enforce the correct type for bitwise flags. If we had introduced this at the start then the kabi would have uniformly used u64 data to pass flags, however today there is a mixture of u64 and u32 flags. All places are converted to accept both sizes and the accessor fixes it. This allows all existing flags to grow to u64 in future without any hassle. Finally all flags are, by definition, optional. If flags are not passed the accessor does not fail, but provides a value of zero. Signed-off-by: Jason Gunthorpe <[email protected]> Reviewed-by: Leon Romanovsky <[email protected]>
1 parent d34ac5c commit bccd062

File tree

7 files changed

+119
-30
lines changed

7 files changed

+119
-30
lines changed

drivers/infiniband/core/uverbs_ioctl.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,3 +486,54 @@ long ib_uverbs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
486486

487487
return err;
488488
}
489+
490+
int uverbs_get_flags64(u64 *to, const struct uverbs_attr_bundle *attrs_bundle,
491+
size_t idx, u64 allowed_bits)
492+
{
493+
const struct uverbs_attr *attr;
494+
u64 flags;
495+
496+
attr = uverbs_attr_get(attrs_bundle, idx);
497+
/* Missing attribute means 0 flags */
498+
if (IS_ERR(attr)) {
499+
*to = 0;
500+
return 0;
501+
}
502+
503+
/*
504+
* New userspace code should use 8 bytes to pass flags, but we
505+
* transparently support old userspaces that were using 4 bytes as
506+
* well.
507+
*/
508+
if (attr->ptr_attr.len == 8)
509+
flags = attr->ptr_attr.data;
510+
else if (attr->ptr_attr.len == 4)
511+
memcpy(&flags, &attr->ptr_attr.data, 4);
512+
else
513+
return -EINVAL;
514+
515+
if (flags & ~allowed_bits)
516+
return -EINVAL;
517+
518+
*to = flags;
519+
return 0;
520+
}
521+
EXPORT_SYMBOL(uverbs_get_flags64);
522+
523+
int uverbs_get_flags32(u32 *to, const struct uverbs_attr_bundle *attrs_bundle,
524+
size_t idx, u64 allowed_bits)
525+
{
526+
u64 flags;
527+
int ret;
528+
529+
ret = uverbs_get_flags64(&flags, attrs_bundle, idx, allowed_bits);
530+
if (ret)
531+
return ret;
532+
533+
if (flags > U32_MAX)
534+
return -EINVAL;
535+
*to = flags;
536+
537+
return 0;
538+
}
539+
EXPORT_SYMBOL(uverbs_get_flags32);

drivers/infiniband/core/uverbs_std_types_counters.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,9 @@ static int UVERBS_HANDLER(UVERBS_METHOD_COUNTERS_READ)(struct ib_device *ib_dev,
9797
if (!atomic_read(&counters->usecnt))
9898
return -EINVAL;
9999

100-
ret = uverbs_copy_from(&read_attr.flags, attrs,
101-
UVERBS_ATTR_READ_COUNTERS_FLAGS);
100+
ret = uverbs_get_flags32(&read_attr.flags, attrs,
101+
UVERBS_ATTR_READ_COUNTERS_FLAGS,
102+
IB_UVERBS_READ_COUNTERS_PREFER_CACHED);
102103
if (ret)
103104
return ret;
104105

@@ -147,9 +148,8 @@ DECLARE_UVERBS_NAMED_METHOD(
147148
UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_READ_COUNTERS_BUFF,
148149
UVERBS_ATTR_MIN_SIZE(0),
149150
UA_MANDATORY),
150-
UVERBS_ATTR_PTR_IN(UVERBS_ATTR_READ_COUNTERS_FLAGS,
151-
UVERBS_ATTR_TYPE(__u32),
152-
UA_MANDATORY));
151+
UVERBS_ATTR_FLAGS_IN(UVERBS_ATTR_READ_COUNTERS_FLAGS,
152+
enum ib_uverbs_read_counters_flags));
153153

154154
DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_COUNTERS,
155155
UVERBS_TYPE_ALLOC_IDR(uverbs_free_counters),

drivers/infiniband/core/uverbs_std_types_cq.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,12 @@ static int UVERBS_HANDLER(UVERBS_METHOD_CQ_CREATE)(struct ib_device *ib_dev,
8484
if (ret)
8585
return ret;
8686

87-
/* Optional param, if it doesn't exist, we get -ENOENT and skip it */
88-
if (IS_UVERBS_COPY_ERR(uverbs_copy_from(&attr.flags, attrs,
89-
UVERBS_ATTR_CREATE_CQ_FLAGS)))
90-
return -EFAULT;
87+
ret = uverbs_get_flags32(&attr.flags, attrs,
88+
UVERBS_ATTR_CREATE_CQ_FLAGS,
89+
IB_UVERBS_CQ_FLAGS_TIMESTAMP_COMPLETION |
90+
IB_UVERBS_CQ_FLAGS_IGNORE_OVERRUN);
91+
if (ret)
92+
return ret;
9193

9294
ev_file_uobj = uverbs_attr_get_uobject(attrs, UVERBS_ATTR_CREATE_CQ_COMP_CHANNEL);
9395
if (!IS_ERR(ev_file_uobj)) {
@@ -164,7 +166,8 @@ DECLARE_UVERBS_NAMED_METHOD(
164166
UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_CQ_COMP_VECTOR,
165167
UVERBS_ATTR_TYPE(u32),
166168
UA_MANDATORY),
167-
UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_CQ_FLAGS, UVERBS_ATTR_TYPE(u32)),
169+
UVERBS_ATTR_FLAGS_IN(UVERBS_ATTR_CREATE_CQ_FLAGS,
170+
enum ib_uverbs_ex_create_cq_flags),
168171
UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_CREATE_CQ_RESP_CQE,
169172
UVERBS_ATTR_TYPE(u32),
170173
UA_MANDATORY),

drivers/infiniband/core/uverbs_std_types_mr.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,9 @@ static int UVERBS_HANDLER(UVERBS_METHOD_DM_MR_REG)(struct ib_device *ib_dev,
6262
if (ret)
6363
return ret;
6464

65-
ret = uverbs_copy_from(&attr.access_flags, attrs,
66-
UVERBS_ATTR_REG_DM_MR_ACCESS_FLAGS);
65+
ret = uverbs_get_flags32(&attr.access_flags, attrs,
66+
UVERBS_ATTR_REG_DM_MR_ACCESS_FLAGS,
67+
IB_ACCESS_SUPPORTED);
6768
if (ret)
6869
return ret;
6970

@@ -131,9 +132,8 @@ DECLARE_UVERBS_NAMED_METHOD(
131132
UVERBS_OBJECT_PD,
132133
UVERBS_ACCESS_READ,
133134
UA_MANDATORY),
134-
UVERBS_ATTR_PTR_IN(UVERBS_ATTR_REG_DM_MR_ACCESS_FLAGS,
135-
UVERBS_ATTR_TYPE(u32),
136-
UA_MANDATORY),
135+
UVERBS_ATTR_FLAGS_IN(UVERBS_ATTR_REG_DM_MR_ACCESS_FLAGS,
136+
enum ib_access_flags),
137137
UVERBS_ATTR_IDR(UVERBS_ATTR_REG_DM_MR_DM_HANDLE,
138138
UVERBS_OBJECT_DM,
139139
UVERBS_ACCESS_READ,

drivers/infiniband/hw/mlx5/devx.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -858,16 +858,21 @@ static int devx_umem_get(struct mlx5_ib_dev *dev, struct ib_ucontext *ucontext,
858858
{
859859
u64 addr;
860860
size_t size;
861-
int access;
861+
u32 access;
862862
int npages;
863863
int err;
864864
u32 page_mask;
865865

866866
if (uverbs_copy_from(&addr, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR) ||
867-
uverbs_copy_from(&size, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_LEN) ||
868-
uverbs_copy_from(&access, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS))
867+
uverbs_copy_from(&size, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_LEN))
869868
return -EFAULT;
870869

870+
err = uverbs_get_flags32(&access, attrs,
871+
MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS,
872+
IB_ACCESS_SUPPORTED);
873+
if (err)
874+
return err;
875+
871876
err = ib_check_mr_access(access);
872877
if (err)
873878
return err;
@@ -1012,9 +1017,8 @@ DECLARE_UVERBS_NAMED_METHOD(
10121017
UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_LEN,
10131018
UVERBS_ATTR_TYPE(u64),
10141019
UA_MANDATORY),
1015-
UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS,
1016-
UVERBS_ATTR_TYPE(u32),
1017-
UA_MANDATORY),
1020+
UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS,
1021+
enum ib_access_flags),
10181022
UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID,
10191023
UVERBS_ATTR_TYPE(u32),
10201024
UA_MANDATORY));

drivers/infiniband/hw/mlx5/main.c

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3859,12 +3859,11 @@ mlx5_ib_create_flow_action_esp(struct ib_device *device,
38593859
u64 flags;
38603860
int err = 0;
38613861

3862-
if (IS_UVERBS_COPY_ERR(uverbs_copy_from(&action_flags, attrs,
3863-
MLX5_IB_ATTR_CREATE_FLOW_ACTION_FLAGS)))
3864-
return ERR_PTR(-EFAULT);
3865-
3866-
if (action_flags >= (MLX5_FLOW_ACTION_ESP_CREATE_LAST_SUPPORTED << 1))
3867-
return ERR_PTR(-EOPNOTSUPP);
3862+
err = uverbs_get_flags64(
3863+
&action_flags, attrs, MLX5_IB_ATTR_CREATE_FLOW_ACTION_FLAGS,
3864+
((MLX5_FLOW_ACTION_ESP_CREATE_LAST_SUPPORTED << 1) - 1));
3865+
if (err)
3866+
return ERR_PTR(err);
38683867

38693868
flags = mlx5_ib_flow_action_flags_to_accel_xfrm_flags(action_flags);
38703869

@@ -5531,9 +5530,8 @@ ADD_UVERBS_ATTRIBUTES_SIMPLE(
55315530
mlx5_ib_flow_action,
55325531
UVERBS_OBJECT_FLOW_ACTION,
55335532
UVERBS_METHOD_FLOW_ACTION_ESP_CREATE,
5534-
UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_CREATE_FLOW_ACTION_FLAGS,
5535-
UVERBS_ATTR_TYPE(u64),
5536-
UA_MANDATORY));
5533+
UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_CREATE_FLOW_ACTION_FLAGS,
5534+
enum mlx5_ib_uapi_flow_action_flags));
55375535

55385536
#define NUM_TREES 5
55395537
static int populate_specs_root(struct mlx5_ib_dev *dev)

include/rdma/uverbs_ioctl.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,19 @@ struct uverbs_object_tree_def {
268268
__VA_ARGS__ }, \
269269
})
270270

271+
/*
272+
* An input value that is a bitwise combination of values of _enum_type.
273+
* This permits the flag value to be passed as either a u32 or u64, it must
274+
* be retrieved via uverbs_get_flag().
275+
*/
276+
#define UVERBS_ATTR_FLAGS_IN(_attr_id, _enum_type, ...) \
277+
UVERBS_ATTR_PTR_IN( \
278+
_attr_id, \
279+
UVERBS_ATTR_SIZE(sizeof(u32) + BUILD_BUG_ON_ZERO( \
280+
!sizeof(_enum_type *)), \
281+
sizeof(u64)), \
282+
__VA_ARGS__)
283+
271284
/*
272285
* This spec is used in order to pass information to the hardware driver in a
273286
* legacy way. Every verb that could get driver specific data should get this
@@ -520,6 +533,26 @@ static inline int _uverbs_copy_from_or_zero(void *to,
520533
#define uverbs_copy_from_or_zero(to, attrs_bundle, idx) \
521534
_uverbs_copy_from_or_zero(to, attrs_bundle, idx, sizeof(*to))
522535

536+
#if IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS)
537+
int uverbs_get_flags64(u64 *to, const struct uverbs_attr_bundle *attrs_bundle,
538+
size_t idx, u64 allowed_bits);
539+
int uverbs_get_flags32(u32 *to, const struct uverbs_attr_bundle *attrs_bundle,
540+
size_t idx, u64 allowed_bits);
541+
#else
542+
static inline int
543+
uverbs_get_flags64(u64 *to, const struct uverbs_attr_bundle *attrs_bundle,
544+
size_t idx, u64 allowed_bits)
545+
{
546+
return -EINVAL;
547+
}
548+
static inline int
549+
uverbs_get_flags32(u32 *to, const struct uverbs_attr_bundle *attrs_bundle,
550+
size_t idx, u64 allowed_bits)
551+
{
552+
return -EINVAL;
553+
}
554+
#endif
555+
523556
/* =================================================
524557
* Definitions -> Specs infrastructure
525558
* =================================================

0 commit comments

Comments
 (0)