2 * Copyright (c) 2017, Mellanox Technologies inc. All rights reserved.
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33 #include <rdma/rdma_user_ioctl.h>
34 #include <rdma/uverbs_ioctl.h>
35 #include "rdma_core.h"
38 struct bundle_alloc_head
{
39 struct bundle_alloc_head
*next
;
45 struct bundle_alloc_head alloc_head
;
46 struct bundle_alloc_head
*allocated_mem
;
47 size_t internal_avail
;
50 struct radix_tree_root
*radix
;
51 const struct uverbs_api_ioctl_method
*method_elm
;
52 void __rcu
**radix_slots
;
53 unsigned long radix_slots_len
;
56 struct ib_uverbs_attr __user
*user_attrs
;
57 struct ib_uverbs_attr
*uattrs
;
59 DECLARE_BITMAP(uobj_finalize
, UVERBS_API_ATTR_BKEY_LEN
);
60 DECLARE_BITMAP(spec_finalize
, UVERBS_API_ATTR_BKEY_LEN
);
61 DECLARE_BITMAP(uobj_hw_obj_valid
, UVERBS_API_ATTR_BKEY_LEN
);
64 * Must be last. bundle ends in a flex array which overlaps
67 struct uverbs_attr_bundle bundle
;
68 u64 internal_buffer
[32];
72 * Each method has an absolute minimum amount of memory it needs to allocate,
73 * precompute that amount and determine if the onstack memory can be used or
74 * if allocation is need.
76 void uapi_compute_bundle_size(struct uverbs_api_ioctl_method
*method_elm
,
77 unsigned int num_attrs
)
79 struct bundle_priv
*pbundle
;
81 offsetof(struct bundle_priv
, internal_buffer
) +
82 sizeof(*pbundle
->bundle
.attrs
) * method_elm
->key_bitmap_len
+
83 sizeof(*pbundle
->uattrs
) * num_attrs
;
85 method_elm
->use_stack
= bundle_size
<= sizeof(*pbundle
);
86 method_elm
->bundle_size
=
87 ALIGN(bundle_size
+ 256, sizeof(*pbundle
->internal_buffer
));
89 /* Do not want order-2 allocations for this. */
90 WARN_ON_ONCE(method_elm
->bundle_size
> PAGE_SIZE
);
94 * uverbs_alloc() - Quickly allocate memory for use with a bundle
96 * @size: Number of bytes to allocate
97 * @flags: Allocator flags
99 * The bundle allocator is intended for allocations that are connected with
100 * processing the system call related to the bundle. The allocated memory is
101 * always freed once the system call completes, and cannot be freed any other
104 * This tries to use a small pool of pre-allocated memory for performance.
106 __malloc
void *_uverbs_alloc(struct uverbs_attr_bundle
*bundle
, size_t size
,
109 struct bundle_priv
*pbundle
=
110 container_of(bundle
, struct bundle_priv
, bundle
);
114 if (check_add_overflow(size
, pbundle
->internal_used
, &new_used
))
115 return ERR_PTR(-EOVERFLOW
);
117 if (new_used
> pbundle
->internal_avail
) {
118 struct bundle_alloc_head
*buf
;
120 buf
= kvmalloc(struct_size(buf
, data
, size
), flags
);
122 return ERR_PTR(-ENOMEM
);
123 buf
->next
= pbundle
->allocated_mem
;
124 pbundle
->allocated_mem
= buf
;
128 res
= (void *)pbundle
->internal_buffer
+ pbundle
->internal_used
;
129 pbundle
->internal_used
=
130 ALIGN(new_used
, sizeof(*pbundle
->internal_buffer
));
131 if (want_init_on_alloc(flags
))
132 memset(res
, 0, size
);
135 EXPORT_SYMBOL(_uverbs_alloc
);
137 static bool uverbs_is_attr_cleared(const struct ib_uverbs_attr
*uattr
,
140 if (uattr
->len
> sizeof_field(struct ib_uverbs_attr
, data
))
141 return ib_is_buffer_cleared(u64_to_user_ptr(uattr
->data
) + len
,
144 return !memchr_inv((const void *)&uattr
->data
+ len
,
145 0, uattr
->len
- len
);
148 static int uverbs_set_output(const struct uverbs_attr_bundle
*bundle
,
149 const struct uverbs_attr
*attr
)
151 struct bundle_priv
*pbundle
=
152 container_of(bundle
, struct bundle_priv
, bundle
);
155 flags
= pbundle
->uattrs
[attr
->ptr_attr
.uattr_idx
].flags
|
156 UVERBS_ATTR_F_VALID_OUTPUT
;
158 &pbundle
->user_attrs
[attr
->ptr_attr
.uattr_idx
].flags
))
163 static int uverbs_process_idrs_array(struct bundle_priv
*pbundle
,
164 const struct uverbs_api_attr
*attr_uapi
,
165 struct uverbs_objs_arr_attr
*attr
,
166 struct ib_uverbs_attr
*uattr
,
169 const struct uverbs_attr_spec
*spec
= &attr_uapi
->spec
;
175 if (uattr
->attr_data
.reserved
)
178 if (uattr
->len
% sizeof(u32
))
181 array_len
= uattr
->len
/ sizeof(u32
);
182 if (array_len
< spec
->u2
.objs_arr
.min_len
||
183 array_len
> spec
->u2
.objs_arr
.max_len
)
187 uverbs_alloc(&pbundle
->bundle
,
188 array_size(array_len
, sizeof(*attr
->uobjects
)));
189 if (IS_ERR(attr
->uobjects
))
190 return PTR_ERR(attr
->uobjects
);
193 * Since idr is 4B and *uobjects is >= 4B, we can use attr->uobjects
194 * to store idrs array and avoid additional memory allocation. The
195 * idrs array is offset to the end of the uobjects array so we will be
196 * able to read idr and replace with a pointer.
198 idr_vals
= (u32
*)(attr
->uobjects
+ array_len
) - array_len
;
200 if (uattr
->len
> sizeof(uattr
->data
)) {
201 ret
= copy_from_user(idr_vals
, u64_to_user_ptr(uattr
->data
),
206 memcpy(idr_vals
, &uattr
->data
, uattr
->len
);
209 for (i
= 0; i
!= array_len
; i
++) {
210 attr
->uobjects
[i
] = uverbs_get_uobject_from_file(
211 spec
->u2
.objs_arr
.obj_type
, spec
->u2
.objs_arr
.access
,
212 idr_vals
[i
], &pbundle
->bundle
);
213 if (IS_ERR(attr
->uobjects
[i
])) {
214 ret
= PTR_ERR(attr
->uobjects
[i
]);
220 __set_bit(attr_bkey
, pbundle
->spec_finalize
);
224 static void uverbs_free_idrs_array(const struct uverbs_api_attr
*attr_uapi
,
225 struct uverbs_objs_arr_attr
*attr
,
227 struct uverbs_attr_bundle
*attrs
)
229 const struct uverbs_attr_spec
*spec
= &attr_uapi
->spec
;
232 for (i
= 0; i
!= attr
->len
; i
++)
233 uverbs_finalize_object(attr
->uobjects
[i
],
234 spec
->u2
.objs_arr
.access
, false, commit
,
238 static int uverbs_process_attr(struct bundle_priv
*pbundle
,
239 const struct uverbs_api_attr
*attr_uapi
,
240 struct ib_uverbs_attr
*uattr
, u32 attr_bkey
)
242 const struct uverbs_attr_spec
*spec
= &attr_uapi
->spec
;
243 struct uverbs_attr
*e
= &pbundle
->bundle
.attrs
[attr_bkey
];
244 const struct uverbs_attr_spec
*val_spec
= spec
;
245 struct uverbs_obj_attr
*o_attr
;
247 switch (spec
->type
) {
248 case UVERBS_ATTR_TYPE_ENUM_IN
:
249 if (uattr
->attr_data
.enum_data
.elem_id
>= spec
->u
.enum_def
.num_elems
)
252 if (uattr
->attr_data
.enum_data
.reserved
)
255 val_spec
= &spec
->u2
.enum_def
.ids
[uattr
->attr_data
.enum_data
.elem_id
];
257 /* Currently we only support PTR_IN based enums */
258 if (val_spec
->type
!= UVERBS_ATTR_TYPE_PTR_IN
)
261 e
->ptr_attr
.enum_id
= uattr
->attr_data
.enum_data
.elem_id
;
263 case UVERBS_ATTR_TYPE_PTR_IN
:
264 /* Ensure that any data provided by userspace beyond the known
265 * struct is zero. Userspace that knows how to use some future
266 * longer struct will fail here if used with an old kernel and
267 * non-zero content, making ABI compat/discovery simpler.
269 if (uattr
->len
> val_spec
->u
.ptr
.len
&&
270 val_spec
->zero_trailing
&&
271 !uverbs_is_attr_cleared(uattr
, val_spec
->u
.ptr
.len
))
275 case UVERBS_ATTR_TYPE_PTR_OUT
:
276 if (uattr
->len
< val_spec
->u
.ptr
.min_len
||
277 (!val_spec
->zero_trailing
&&
278 uattr
->len
> val_spec
->u
.ptr
.len
))
281 if (spec
->type
!= UVERBS_ATTR_TYPE_ENUM_IN
&&
282 uattr
->attr_data
.reserved
)
285 e
->ptr_attr
.uattr_idx
= uattr
- pbundle
->uattrs
;
286 e
->ptr_attr
.len
= uattr
->len
;
288 if (val_spec
->alloc_and_copy
&& !uverbs_attr_ptr_is_inline(e
)) {
291 p
= uverbs_alloc(&pbundle
->bundle
, uattr
->len
);
297 if (copy_from_user(p
, u64_to_user_ptr(uattr
->data
),
301 e
->ptr_attr
.data
= uattr
->data
;
305 case UVERBS_ATTR_TYPE_IDR
:
306 case UVERBS_ATTR_TYPE_FD
:
307 if (uattr
->attr_data
.reserved
)
313 o_attr
= &e
->obj_attr
;
314 o_attr
->attr_elm
= attr_uapi
;
317 * The type of uattr->data is u64 for UVERBS_ATTR_TYPE_IDR and
318 * s64 for UVERBS_ATTR_TYPE_FD. We can cast the u64 to s64
319 * here without caring about truncation as we know that the
320 * IDR implementation today rejects negative IDs
322 o_attr
->uobject
= uverbs_get_uobject_from_file(
323 spec
->u
.obj
.obj_type
, spec
->u
.obj
.access
,
324 uattr
->data_s64
, &pbundle
->bundle
);
325 if (IS_ERR(o_attr
->uobject
))
326 return PTR_ERR(o_attr
->uobject
);
327 __set_bit(attr_bkey
, pbundle
->uobj_finalize
);
329 if (spec
->u
.obj
.access
== UVERBS_ACCESS_NEW
) {
330 unsigned int uattr_idx
= uattr
- pbundle
->uattrs
;
331 s64 id
= o_attr
->uobject
->id
;
333 /* Copy the allocated id to the user-space */
334 if (put_user(id
, &pbundle
->user_attrs
[uattr_idx
].data
))
340 case UVERBS_ATTR_TYPE_IDRS_ARRAY
:
341 return uverbs_process_idrs_array(pbundle
, attr_uapi
,
342 &e
->objs_arr_attr
, uattr
,
352 * We search the radix tree with the method prefix and now we want to fast
353 * search the suffix bits to get a particular attribute pointer. It is not
354 * totally clear to me if this breaks the radix tree encasulation or not, but
355 * it uses the iter data to determine if the method iter points at the same
356 * chunk that will store the attribute, if so it just derefs it directly. By
357 * construction in most kernel configs the method and attrs will all fit in a
358 * single radix chunk, so in most cases this will have no search. Other cases
359 * this falls back to a full search.
361 static void __rcu
**uapi_get_attr_for_method(struct bundle_priv
*pbundle
,
366 if (likely(attr_key
< pbundle
->radix_slots_len
)) {
369 slot
= pbundle
->radix_slots
+ attr_key
;
370 entry
= rcu_dereference_raw(*slot
);
371 if (likely(!radix_tree_is_internal_node(entry
) && entry
))
375 return radix_tree_lookup_slot(pbundle
->radix
,
376 pbundle
->method_key
| attr_key
);
379 static int uverbs_set_attr(struct bundle_priv
*pbundle
,
380 struct ib_uverbs_attr
*uattr
)
382 u32 attr_key
= uapi_key_attr(uattr
->attr_id
);
383 u32 attr_bkey
= uapi_bkey_attr(attr_key
);
384 const struct uverbs_api_attr
*attr
;
388 slot
= uapi_get_attr_for_method(pbundle
, attr_key
);
391 * Kernel does not support the attribute but user-space says it
394 if (uattr
->flags
& UVERBS_ATTR_F_MANDATORY
)
395 return -EPROTONOSUPPORT
;
398 attr
= rcu_dereference_protected(*slot
, true);
400 /* Reject duplicate attributes from user-space */
401 if (test_bit(attr_bkey
, pbundle
->bundle
.attr_present
))
404 ret
= uverbs_process_attr(pbundle
, attr
, uattr
, attr_bkey
);
408 __set_bit(attr_bkey
, pbundle
->bundle
.attr_present
);
413 static int ib_uverbs_run_method(struct bundle_priv
*pbundle
,
414 unsigned int num_attrs
)
416 int (*handler
)(struct uverbs_attr_bundle
*attrs
);
417 size_t uattrs_size
= array_size(sizeof(*pbundle
->uattrs
), num_attrs
);
418 unsigned int destroy_bkey
= pbundle
->method_elm
->destroy_bkey
;
422 /* See uverbs_disassociate_api() */
423 handler
= srcu_dereference(
424 pbundle
->method_elm
->handler
,
425 &pbundle
->bundle
.ufile
->device
->disassociate_srcu
);
429 pbundle
->uattrs
= uverbs_alloc(&pbundle
->bundle
, uattrs_size
);
430 if (IS_ERR(pbundle
->uattrs
))
431 return PTR_ERR(pbundle
->uattrs
);
432 if (copy_from_user(pbundle
->uattrs
, pbundle
->user_attrs
, uattrs_size
))
435 for (i
= 0; i
!= num_attrs
; i
++) {
436 ret
= uverbs_set_attr(pbundle
, &pbundle
->uattrs
[i
]);
441 /* User space did not provide all the mandatory attributes */
442 if (unlikely(!bitmap_subset(pbundle
->method_elm
->attr_mandatory
,
443 pbundle
->bundle
.attr_present
,
444 pbundle
->method_elm
->key_bitmap_len
)))
447 if (pbundle
->method_elm
->has_udata
)
448 uverbs_fill_udata(&pbundle
->bundle
,
449 &pbundle
->bundle
.driver_udata
,
450 UVERBS_ATTR_UHW_IN
, UVERBS_ATTR_UHW_OUT
);
452 pbundle
->bundle
.driver_udata
= (struct ib_udata
){};
454 if (destroy_bkey
!= UVERBS_API_ATTR_BKEY_LEN
) {
455 struct uverbs_obj_attr
*destroy_attr
=
456 &pbundle
->bundle
.attrs
[destroy_bkey
].obj_attr
;
458 ret
= uobj_destroy(destroy_attr
->uobject
, &pbundle
->bundle
);
461 __clear_bit(destroy_bkey
, pbundle
->uobj_finalize
);
463 ret
= handler(&pbundle
->bundle
);
464 uobj_put_destroy(destroy_attr
->uobject
);
466 ret
= handler(&pbundle
->bundle
);
470 * Until the drivers are revised to use the bundle directly we have to
471 * assume that the driver wrote to its UHW_OUT and flag userspace
474 if (!ret
&& pbundle
->method_elm
->has_udata
) {
475 const struct uverbs_attr
*attr
=
476 uverbs_attr_get(&pbundle
->bundle
, UVERBS_ATTR_UHW_OUT
);
479 ret
= uverbs_set_output(&pbundle
->bundle
, attr
);
483 * EPROTONOSUPPORT is ONLY to be returned if the ioctl framework can
484 * not invoke the method because the request is not supported. No
485 * other cases should return this code.
487 if (WARN_ON_ONCE(ret
== -EPROTONOSUPPORT
))
493 static void bundle_destroy(struct bundle_priv
*pbundle
, bool commit
)
495 unsigned int key_bitmap_len
= pbundle
->method_elm
->key_bitmap_len
;
496 struct bundle_alloc_head
*memblock
;
499 /* fast path for simple uobjects */
501 while ((i
= find_next_bit(pbundle
->uobj_finalize
, key_bitmap_len
,
502 i
+ 1)) < key_bitmap_len
) {
503 struct uverbs_attr
*attr
= &pbundle
->bundle
.attrs
[i
];
505 uverbs_finalize_object(
506 attr
->obj_attr
.uobject
,
507 attr
->obj_attr
.attr_elm
->spec
.u
.obj
.access
,
508 test_bit(i
, pbundle
->uobj_hw_obj_valid
),
514 while ((i
= find_next_bit(pbundle
->spec_finalize
, key_bitmap_len
,
515 i
+ 1)) < key_bitmap_len
) {
516 struct uverbs_attr
*attr
= &pbundle
->bundle
.attrs
[i
];
517 const struct uverbs_api_attr
*attr_uapi
;
520 slot
= uapi_get_attr_for_method(
522 pbundle
->method_key
| uapi_bkey_to_key_attr(i
));
526 attr_uapi
= rcu_dereference_protected(*slot
, true);
528 if (attr_uapi
->spec
.type
== UVERBS_ATTR_TYPE_IDRS_ARRAY
) {
529 uverbs_free_idrs_array(attr_uapi
, &attr
->objs_arr_attr
,
530 commit
, &pbundle
->bundle
);
534 for (memblock
= pbundle
->allocated_mem
; memblock
;) {
535 struct bundle_alloc_head
*tmp
= memblock
;
537 memblock
= memblock
->next
;
542 static int ib_uverbs_cmd_verbs(struct ib_uverbs_file
*ufile
,
543 struct ib_uverbs_ioctl_hdr
*hdr
,
544 struct ib_uverbs_attr __user
*user_attrs
)
546 const struct uverbs_api_ioctl_method
*method_elm
;
547 struct uverbs_api
*uapi
= ufile
->device
->uapi
;
548 struct radix_tree_iter attrs_iter
;
549 struct bundle_priv
*pbundle
;
550 struct bundle_priv onstack
;
554 if (unlikely(hdr
->driver_id
!= uapi
->driver_id
))
557 slot
= radix_tree_iter_lookup(
558 &uapi
->radix
, &attrs_iter
,
559 uapi_key_obj(hdr
->object_id
) |
560 uapi_key_ioctl_method(hdr
->method_id
));
562 return -EPROTONOSUPPORT
;
563 method_elm
= rcu_dereference_protected(*slot
, true);
565 if (!method_elm
->use_stack
) {
566 pbundle
= kmalloc(method_elm
->bundle_size
, GFP_KERNEL
);
569 pbundle
->internal_avail
=
570 method_elm
->bundle_size
-
571 offsetof(struct bundle_priv
, internal_buffer
);
572 pbundle
->alloc_head
.next
= NULL
;
573 pbundle
->allocated_mem
= &pbundle
->alloc_head
;
576 pbundle
->internal_avail
= sizeof(pbundle
->internal_buffer
);
577 pbundle
->allocated_mem
= NULL
;
580 /* Space for the pbundle->bundle.attrs flex array */
581 pbundle
->method_elm
= method_elm
;
582 pbundle
->method_key
= attrs_iter
.index
;
583 pbundle
->bundle
.ufile
= ufile
;
584 pbundle
->bundle
.context
= NULL
; /* only valid if bundle has uobject */
585 pbundle
->radix
= &uapi
->radix
;
586 pbundle
->radix_slots
= slot
;
587 pbundle
->radix_slots_len
= radix_tree_chunk_size(&attrs_iter
);
588 pbundle
->user_attrs
= user_attrs
;
590 pbundle
->internal_used
= ALIGN(pbundle
->method_elm
->key_bitmap_len
*
591 sizeof(*pbundle
->bundle
.attrs
),
592 sizeof(*pbundle
->internal_buffer
));
593 memset(pbundle
->bundle
.attr_present
, 0,
594 sizeof(pbundle
->bundle
.attr_present
));
595 memset(pbundle
->uobj_finalize
, 0, sizeof(pbundle
->uobj_finalize
));
596 memset(pbundle
->spec_finalize
, 0, sizeof(pbundle
->spec_finalize
));
597 memset(pbundle
->uobj_hw_obj_valid
, 0,
598 sizeof(pbundle
->uobj_hw_obj_valid
));
600 ret
= ib_uverbs_run_method(pbundle
, hdr
->num_attrs
);
601 bundle_destroy(pbundle
, ret
== 0);
605 long ib_uverbs_ioctl(struct file
*filp
, unsigned int cmd
, unsigned long arg
)
607 struct ib_uverbs_file
*file
= filp
->private_data
;
608 struct ib_uverbs_ioctl_hdr __user
*user_hdr
=
609 (struct ib_uverbs_ioctl_hdr __user
*)arg
;
610 struct ib_uverbs_ioctl_hdr hdr
;
614 if (unlikely(cmd
!= RDMA_VERBS_IOCTL
))
617 err
= copy_from_user(&hdr
, user_hdr
, sizeof(hdr
));
621 if (hdr
.length
> PAGE_SIZE
||
622 hdr
.length
!= struct_size(&hdr
, attrs
, hdr
.num_attrs
))
625 if (hdr
.reserved1
|| hdr
.reserved2
)
626 return -EPROTONOSUPPORT
;
628 srcu_key
= srcu_read_lock(&file
->device
->disassociate_srcu
);
629 err
= ib_uverbs_cmd_verbs(file
, &hdr
, user_hdr
->attrs
);
630 srcu_read_unlock(&file
->device
->disassociate_srcu
, srcu_key
);
634 int uverbs_get_flags64(u64
*to
, const struct uverbs_attr_bundle
*attrs_bundle
,
635 size_t idx
, u64 allowed_bits
)
637 const struct uverbs_attr
*attr
;
640 attr
= uverbs_attr_get(attrs_bundle
, idx
);
641 /* Missing attribute means 0 flags */
648 * New userspace code should use 8 bytes to pass flags, but we
649 * transparently support old userspaces that were using 4 bytes as
652 if (attr
->ptr_attr
.len
== 8)
653 flags
= attr
->ptr_attr
.data
;
654 else if (attr
->ptr_attr
.len
== 4)
655 flags
= *(u32
*)&attr
->ptr_attr
.data
;
659 if (flags
& ~allowed_bits
)
665 EXPORT_SYMBOL(uverbs_get_flags64
);
667 int uverbs_get_flags32(u32
*to
, const struct uverbs_attr_bundle
*attrs_bundle
,
668 size_t idx
, u64 allowed_bits
)
673 ret
= uverbs_get_flags64(&flags
, attrs_bundle
, idx
, allowed_bits
);
683 EXPORT_SYMBOL(uverbs_get_flags32
);
686 * Fill a ib_udata struct (core or uhw) using the given attribute IDs.
687 * This is primarily used to convert the UVERBS_ATTR_UHW() into the
688 * ib_udata format used by the drivers.
690 void uverbs_fill_udata(struct uverbs_attr_bundle
*bundle
,
691 struct ib_udata
*udata
, unsigned int attr_in
,
692 unsigned int attr_out
)
694 struct bundle_priv
*pbundle
=
695 container_of(bundle
, struct bundle_priv
, bundle
);
696 const struct uverbs_attr
*in
=
697 uverbs_attr_get(&pbundle
->bundle
, attr_in
);
698 const struct uverbs_attr
*out
=
699 uverbs_attr_get(&pbundle
->bundle
, attr_out
);
702 udata
->inlen
= in
->ptr_attr
.len
;
703 if (uverbs_attr_ptr_is_inline(in
))
705 &pbundle
->user_attrs
[in
->ptr_attr
.uattr_idx
]
708 udata
->inbuf
= u64_to_user_ptr(in
->ptr_attr
.data
);
715 udata
->outbuf
= u64_to_user_ptr(out
->ptr_attr
.data
);
716 udata
->outlen
= out
->ptr_attr
.len
;
718 udata
->outbuf
= NULL
;
723 int uverbs_copy_to(const struct uverbs_attr_bundle
*bundle
, size_t idx
,
724 const void *from
, size_t size
)
726 const struct uverbs_attr
*attr
= uverbs_attr_get(bundle
, idx
);
730 return PTR_ERR(attr
);
732 min_size
= min_t(size_t, attr
->ptr_attr
.len
, size
);
733 if (copy_to_user(u64_to_user_ptr(attr
->ptr_attr
.data
), from
, min_size
))
736 return uverbs_set_output(bundle
, attr
);
738 EXPORT_SYMBOL(uverbs_copy_to
);
742 * This is only used if the caller has directly used copy_to_use to write the
743 * data. It signals to user space that the buffer is filled in.
745 int uverbs_output_written(const struct uverbs_attr_bundle
*bundle
, size_t idx
)
747 const struct uverbs_attr
*attr
= uverbs_attr_get(bundle
, idx
);
750 return PTR_ERR(attr
);
752 return uverbs_set_output(bundle
, attr
);
755 int _uverbs_get_const(s64
*to
, const struct uverbs_attr_bundle
*attrs_bundle
,
756 size_t idx
, s64 lower_bound
, u64 upper_bound
,
759 const struct uverbs_attr
*attr
;
761 attr
= uverbs_attr_get(attrs_bundle
, idx
);
763 if ((PTR_ERR(attr
) != -ENOENT
) || !def_val
)
764 return PTR_ERR(attr
);
768 *to
= attr
->ptr_attr
.data
;
771 if (*to
< lower_bound
|| (*to
> 0 && (u64
)*to
> upper_bound
))
776 EXPORT_SYMBOL(_uverbs_get_const
);
778 int uverbs_copy_to_struct_or_zero(const struct uverbs_attr_bundle
*bundle
,
779 size_t idx
, const void *from
, size_t size
)
781 const struct uverbs_attr
*attr
= uverbs_attr_get(bundle
, idx
);
784 return PTR_ERR(attr
);
786 if (size
< attr
->ptr_attr
.len
) {
787 if (clear_user(u64_to_user_ptr(attr
->ptr_attr
.data
) + size
,
788 attr
->ptr_attr
.len
- size
))
791 return uverbs_copy_to(bundle
, idx
, from
, size
);
793 EXPORT_SYMBOL(uverbs_copy_to_struct_or_zero
);
795 /* Once called an abort will call through to the type's destroy_hw() */
796 void uverbs_finalize_uobj_create(const struct uverbs_attr_bundle
*bundle
,
799 struct bundle_priv
*pbundle
=
800 container_of(bundle
, struct bundle_priv
, bundle
);
802 __set_bit(uapi_bkey_attr(uapi_key_attr(idx
)),
803 pbundle
->uobj_hw_obj_valid
);
805 EXPORT_SYMBOL(uverbs_finalize_uobj_create
);