IB/uverbs: Remove the ib_uverbs_attr pointer from each attr
Memory in the bundle is valuable, do not waste it holding an 8 byte pointer for the rare case of writing to a PTR_OUT. We can compute the pointer by storing a small 1 byte array offset and the base address of the uattr memory in the bundle private memory. This also means we can access the kernel's copy of the ib_uverbs_attr, so drop the copy of flags as well. Since the uattr base should be private bundle information this also de-inlines the already too big uverbs_copy_to inline and moves create_udata into uverbs_ioctl.c so they can see the private struct definition. Signed-off-by: Jason Gunthorpe <jgg@mellanox.com> Reviewed-by: Leon Romanovsky <leonro@mellanox.com>
This commit is contained in:
@@ -461,8 +461,7 @@ struct uverbs_ptr_attr {
|
||||
u64 data;
|
||||
};
|
||||
u16 len;
|
||||
/* Combination of bits from enum UVERBS_ATTR_F_XXXX */
|
||||
u16 flags;
|
||||
u16 uattr_idx;
|
||||
u8 enum_id;
|
||||
};
|
||||
|
||||
@@ -471,11 +470,6 @@ struct uverbs_obj_attr {
|
||||
};
|
||||
|
||||
struct uverbs_attr {
|
||||
/*
|
||||
* pointer to the user-space given attribute, in order to write the
|
||||
* new uobject's id or update flags.
|
||||
*/
|
||||
struct ib_uverbs_attr __user *uattr;
|
||||
union {
|
||||
struct uverbs_ptr_attr ptr_attr;
|
||||
struct uverbs_obj_attr obj_attr;
|
||||
@@ -575,27 +569,6 @@ uverbs_attr_get_len(const struct uverbs_attr_bundle *attrs_bundle, u16 idx)
|
||||
return attr->ptr_attr.len;
|
||||
}
|
||||
|
||||
static inline int uverbs_copy_to(const struct uverbs_attr_bundle *attrs_bundle,
|
||||
size_t idx, const void *from, size_t size)
|
||||
{
|
||||
const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
|
||||
u16 flags;
|
||||
size_t min_size;
|
||||
|
||||
if (IS_ERR(attr))
|
||||
return PTR_ERR(attr);
|
||||
|
||||
min_size = min_t(size_t, attr->ptr_attr.len, size);
|
||||
if (copy_to_user(u64_to_user_ptr(attr->ptr_attr.data), from, min_size))
|
||||
return -EFAULT;
|
||||
|
||||
flags = attr->ptr_attr.flags | UVERBS_ATTR_F_VALID_OUTPUT;
|
||||
if (put_user(flags, &attr->uattr->flags))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool uverbs_attr_ptr_is_inline(const struct uverbs_attr *attr)
|
||||
{
|
||||
return attr->ptr_attr.len <= sizeof(attr->ptr_attr.data);
|
||||
@@ -676,6 +649,8 @@ int uverbs_get_flags64(u64 *to, const struct uverbs_attr_bundle *attrs_bundle,
|
||||
size_t idx, u64 allowed_bits);
|
||||
int uverbs_get_flags32(u32 *to, const struct uverbs_attr_bundle *attrs_bundle,
|
||||
size_t idx, u64 allowed_bits);
|
||||
int uverbs_copy_to(const struct uverbs_attr_bundle *attrs_bundle, size_t idx,
|
||||
const void *from, size_t size);
|
||||
#else
|
||||
static inline int
|
||||
uverbs_get_flags64(u64 *to, const struct uverbs_attr_bundle *attrs_bundle,
|
||||
@@ -689,6 +664,11 @@ uverbs_get_flags32(u32 *to, const struct uverbs_attr_bundle *attrs_bundle,
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
static inline int uverbs_copy_to(const struct uverbs_attr_bundle *attrs_bundle,
|
||||
size_t idx, const void *from, size_t size)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* =================================================
|
||||
|
Reference in New Issue
Block a user