]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - include/rdma/uverbs_ioctl.h
RDMA/uverbs: Split UVERBS_ATTR_FLOW_ACTION_ESP_HANDLE
[mirror_ubuntu-jammy-kernel.git] / include / rdma / uverbs_ioctl.h
CommitLineData
a0aa309c
MB
1/*
2 * Copyright (c) 2017, Mellanox Technologies inc. All rights reserved.
3 *
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:
9 *
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
12 * conditions are met:
13 *
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer.
17 *
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.
22 *
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
30 * SOFTWARE.
31 */
32
33#ifndef _UVERBS_IOCTL_
34#define _UVERBS_IOCTL_
35
36#include <rdma/uverbs_types.h>
35410306
MB
37#include <linux/uaccess.h>
38#include <rdma/rdma_user_ioctl.h>
d70724f1 39#include <rdma/ib_user_ioctl_verbs.h>
1f7ff9d5 40#include <rdma/ib_user_ioctl_cmds.h>
a0aa309c
MB
41
42/*
43 * =======================================
44 * Verbs action specifications
45 * =======================================
46 */
47
f43dbebf
MB
48enum uverbs_attr_type {
49 UVERBS_ATTR_TYPE_NA,
fac9658c
MB
50 UVERBS_ATTR_TYPE_PTR_IN,
51 UVERBS_ATTR_TYPE_PTR_OUT,
f43dbebf
MB
52 UVERBS_ATTR_TYPE_IDR,
53 UVERBS_ATTR_TYPE_FD,
494c5580 54 UVERBS_ATTR_TYPE_ENUM_IN,
f43dbebf
MB
55};
56
a0aa309c
MB
57enum uverbs_obj_access {
58 UVERBS_ACCESS_READ,
59 UVERBS_ACCESS_WRITE,
60 UVERBS_ACCESS_NEW,
61 UVERBS_ACCESS_DESTROY
62};
63
fac9658c
MB
64enum {
65 UVERBS_ATTR_SPEC_F_MANDATORY = 1U << 0,
c66db311
MB
66 /* Support extending attributes by length, validate all unknown size == zero */
67 UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO = 1U << 1,
8762d149
MB
68 /*
69 * Valid only for PTR_IN. Allocate and copy the data inside the parser
70 */
71 UVERBS_ATTR_SPEC_F_ALLOC_AND_COPY = 1U << 2,
fac9658c
MB
72};
73
1f07e08f 74/* Specification of a single attribute inside the ioctl message */
f43dbebf 75struct uverbs_attr_spec {
fac9658c 76 union {
1f07e08f 77 /* Header shared by all following union members - to reduce space. */
fac9658c 78 struct {
1f07e08f
MB
79 enum uverbs_attr_type type;
80 /* Combination of bits from enum UVERBS_ATTR_SPEC_F_XXXX */
81 u8 flags;
82 };
83 struct {
84 enum uverbs_attr_type type;
85 /* Combination of bits from enum UVERBS_ATTR_SPEC_F_XXXX */
86 u8 flags;
c66db311 87 /* Current known size to kernel */
1f07e08f 88 u16 len;
c66db311
MB
89 /* User isn't allowed to provide something < min_len */
90 u16 min_len;
1f07e08f
MB
91 } ptr;
92 struct {
93 enum uverbs_attr_type type;
94 /* Combination of bits from enum UVERBS_ATTR_SPEC_F_XXXX */
95 u8 flags;
fac9658c
MB
96 /*
97 * higher bits mean the namespace and lower bits mean
98 * the type id within the namespace.
99 */
100 u16 obj_type;
101 u8 access;
102 } obj;
494c5580
MB
103 struct {
104 enum uverbs_attr_type type;
105 /* Combination of bits from enum UVERBS_ATTR_SPEC_F_XXXX */
106 u8 flags;
107 u8 num_elems;
108 /*
109 * The enum attribute can select one of the attributes
110 * contained in the ids array. Currently only PTR_IN
111 * attributes are supported in the ids array.
112 */
113 const struct uverbs_attr_spec *ids;
114 } enum_def;
fac9658c 115 };
f43dbebf
MB
116};
117
118struct uverbs_attr_spec_hash {
119 size_t num_attrs;
fac9658c 120 unsigned long *mandatory_attrs_bitmask;
f43dbebf
MB
121 struct uverbs_attr_spec attrs[0];
122};
123
fac9658c
MB
124struct uverbs_attr_bundle;
125struct ib_uverbs_file;
126
127enum {
128 /*
129 * Action marked with this flag creates a context (or root for all
130 * objects).
131 */
132 UVERBS_ACTION_FLAG_CREATE_ROOT = 1U << 0,
133};
134
135struct uverbs_method_spec {
136 /* Combination of bits from enum UVERBS_ACTION_FLAG_XXXX */
137 u32 flags;
138 size_t num_buckets;
139 size_t num_child_attrs;
140 int (*handler)(struct ib_device *ib_dev, struct ib_uverbs_file *ufile,
141 struct uverbs_attr_bundle *ctx);
142 struct uverbs_attr_spec_hash *attr_buckets[0];
143};
144
145struct uverbs_method_spec_hash {
146 size_t num_methods;
147 struct uverbs_method_spec *methods[0];
148};
149
150struct uverbs_object_spec {
151 const struct uverbs_obj_type *type_attrs;
152 size_t num_buckets;
153 struct uverbs_method_spec_hash *method_buckets[0];
154};
155
156struct uverbs_object_spec_hash {
157 size_t num_objects;
158 struct uverbs_object_spec *objects[0];
159};
160
161struct uverbs_root_spec {
162 size_t num_buckets;
163 struct uverbs_object_spec_hash *object_buckets[0];
164};
165
5009010f
MB
166/*
167 * =======================================
168 * Verbs definitions
169 * =======================================
170 */
171
09e3ebf8
MB
172struct uverbs_attr_def {
173 u16 id;
174 struct uverbs_attr_spec attr;
175};
176
177struct uverbs_method_def {
178 u16 id;
179 /* Combination of bits from enum UVERBS_ACTION_FLAG_XXXX */
180 u32 flags;
181 size_t num_attrs;
182 const struct uverbs_attr_def * const (*attrs)[];
183 int (*handler)(struct ib_device *ib_dev, struct ib_uverbs_file *ufile,
184 struct uverbs_attr_bundle *ctx);
185};
186
5009010f 187struct uverbs_object_def {
09e3ebf8 188 u16 id;
5009010f 189 const struct uverbs_obj_type *type_attrs;
09e3ebf8
MB
190 size_t num_methods;
191 const struct uverbs_method_def * const (*methods)[];
192};
193
194struct uverbs_object_tree_def {
195 size_t num_objects;
196 const struct uverbs_object_def * const (*objects)[];
5009010f
MB
197};
198
35410306 199#define UA_FLAGS(_flags) .flags = _flags
c66db311 200#define __UVERBS_ATTR0(_id, _type, _fld, _attr, ...) \
35410306 201 ((const struct uverbs_attr_def) \
c66db311
MB
202 {.id = _id, .attr = {{._fld = {.type = _type, _attr, .flags = 0, } }, } })
203#define __UVERBS_ATTR1(_id, _type, _fld, _attr, _extra1, ...) \
35410306 204 ((const struct uverbs_attr_def) \
c66db311
MB
205 {.id = _id, .attr = {{._fld = {.type = _type, _attr, _extra1 } },} })
206#define __UVERBS_ATTR2(_id, _type, _fld, _attr, _extra1, _extra2) \
207 ((const struct uverbs_attr_def) \
208 {.id = _id, .attr = {{._fld = {.type = _type, _attr, _extra1, _extra2 } },} })
209#define __UVERBS_ATTR(_id, _type, _fld, _attr, _extra1, _extra2, _n, ...) \
210 __UVERBS_ATTR##_n(_id, _type, _fld, _attr, _extra1, _extra2)
211
212#define UVERBS_ATTR_TYPE(_type) \
213 .min_len = sizeof(_type), .len = sizeof(_type)
214#define UVERBS_ATTR_STRUCT(_type, _last) \
215 .min_len = ((uintptr_t)(&((_type *)0)->_last + 1)), .len = sizeof(_type)
216#define UVERBS_ATTR_SIZE(_min_len, _len) \
217 .min_len = _min_len, .len = _len
2d9c1bd7
MB
218#define UVERBS_ATTR_MIN_SIZE(_min_len) \
219 UVERBS_ATTR_SIZE(_min_len, USHRT_MAX)
c66db311 220
35410306
MB
221/*
222 * In new compiler, UVERBS_ATTR could be simplified by declaring it as
223 * [_id] = {.type = _type, .len = _len, ##__VA_ARGS__}
224 * But since we support older compilers too, we need the more complex code.
225 */
c66db311
MB
226#define UVERBS_ATTR(_id, _type, _fld, _attr, ...) \
227 __UVERBS_ATTR(_id, _type, _fld, _attr, ##__VA_ARGS__, 2, 1, 0)
35410306 228#define UVERBS_ATTR_PTR_IN_SZ(_id, _len, ...) \
c66db311 229 UVERBS_ATTR(_id, UVERBS_ATTR_TYPE_PTR_IN, ptr, _len, ##__VA_ARGS__)
35410306
MB
230/* If sizeof(_type) <= sizeof(u64), this will be inlined rather than a pointer */
231#define UVERBS_ATTR_PTR_IN(_id, _type, ...) \
c66db311 232 UVERBS_ATTR_PTR_IN_SZ(_id, _type, ##__VA_ARGS__)
35410306 233#define UVERBS_ATTR_PTR_OUT_SZ(_id, _len, ...) \
c66db311 234 UVERBS_ATTR(_id, UVERBS_ATTR_TYPE_PTR_OUT, ptr, _len, ##__VA_ARGS__)
35410306 235#define UVERBS_ATTR_PTR_OUT(_id, _type, ...) \
c66db311 236 UVERBS_ATTR_PTR_OUT_SZ(_id, _type, ##__VA_ARGS__)
494c5580
MB
237#define UVERBS_ATTR_ENUM_IN(_id, _enum_arr, ...) \
238 UVERBS_ATTR(_id, UVERBS_ATTR_TYPE_ENUM_IN, enum_def, \
239 .ids = (_enum_arr), \
240 .num_elems = ARRAY_SIZE(_enum_arr), ##__VA_ARGS__)
35410306
MB
241
242/*
243 * In new compiler, UVERBS_ATTR_IDR (and FD) could be simplified by declaring
244 * it as
245 * {.id = _id, \
246 * .attr {.type = __obj_class, \
247 * .obj = {.obj_type = _idr_type, \
248 * .access = _access \
249 * }, ##__VA_ARGS__ } }
250 * But since we support older compilers too, we need the more complex code.
251 */
252#define ___UVERBS_ATTR_OBJ0(_id, _obj_class, _obj_type, _access, ...)\
253 ((const struct uverbs_attr_def) \
254 {.id = _id, \
1f07e08f
MB
255 .attr = { {.obj = {.type = _obj_class, .obj_type = _obj_type, \
256 .access = _access, .flags = 0 } }, } })
35410306
MB
257#define ___UVERBS_ATTR_OBJ1(_id, _obj_class, _obj_type, _access, _flags)\
258 ((const struct uverbs_attr_def) \
259 {.id = _id, \
1f07e08f
MB
260 .attr = { {.obj = {.type = _obj_class, .obj_type = _obj_type, \
261 .access = _access, _flags} }, } })
35410306
MB
262#define ___UVERBS_ATTR_OBJ(_id, _obj_class, _obj_type, _access, _flags, \
263 _n, ...) \
264 ___UVERBS_ATTR_OBJ##_n(_id, _obj_class, _obj_type, _access, _flags)
265#define __UVERBS_ATTR_OBJ(_id, _obj_class, _obj_type, _access, ...) \
266 ___UVERBS_ATTR_OBJ(_id, _obj_class, _obj_type, _access, \
267 ##__VA_ARGS__, 1, 0)
268#define UVERBS_ATTR_IDR(_id, _idr_type, _access, ...) \
269 __UVERBS_ATTR_OBJ(_id, UVERBS_ATTR_TYPE_IDR, _idr_type, _access,\
270 ##__VA_ARGS__)
271#define UVERBS_ATTR_FD(_id, _fd_type, _access, ...) \
272 __UVERBS_ATTR_OBJ(_id, UVERBS_ATTR_TYPE_FD, _fd_type, \
273 (_access) + BUILD_BUG_ON_ZERO( \
274 (_access) != UVERBS_ACCESS_NEW && \
275 (_access) != UVERBS_ACCESS_READ), \
276 ##__VA_ARGS__)
277#define DECLARE_UVERBS_ATTR_SPEC(_name, ...) \
278 const struct uverbs_attr_def _name = __VA_ARGS__
279
494c5580
MB
280#define DECLARE_UVERBS_ENUM(_name, ...) \
281 const struct uverbs_enum_spec _name = { \
282 .len = ARRAY_SIZE(((struct uverbs_attr_spec[]){__VA_ARGS__})),\
283 .ids = {__VA_ARGS__}, \
284 }
35410306
MB
285#define _UVERBS_METHOD_ATTRS_SZ(...) \
286 (sizeof((const struct uverbs_attr_def * const []){__VA_ARGS__}) /\
287 sizeof(const struct uverbs_attr_def *))
288#define _UVERBS_METHOD(_id, _handler, _flags, ...) \
289 ((const struct uverbs_method_def) { \
290 .id = _id, \
291 .flags = _flags, \
292 .handler = _handler, \
293 .num_attrs = _UVERBS_METHOD_ATTRS_SZ(__VA_ARGS__), \
294 .attrs = &(const struct uverbs_attr_def * const []){__VA_ARGS__} })
295#define DECLARE_UVERBS_METHOD(_name, _id, _handler, ...) \
296 const struct uverbs_method_def _name = \
297 _UVERBS_METHOD(_id, _handler, 0, ##__VA_ARGS__)
298#define DECLARE_UVERBS_CTX_METHOD(_name, _id, _handler, _flags, ...) \
299 const struct uverbs_method_def _name = \
300 _UVERBS_METHOD(_id, _handler, \
301 UVERBS_ACTION_FLAG_CREATE_ROOT, \
302 ##__VA_ARGS__)
303#define _UVERBS_OBJECT_METHODS_SZ(...) \
304 (sizeof((const struct uverbs_method_def * const []){__VA_ARGS__}) / \
305 sizeof(const struct uverbs_method_def *))
5009010f
MB
306#define _UVERBS_OBJECT(_id, _type_attrs, ...) \
307 ((const struct uverbs_object_def) { \
09e3ebf8 308 .id = _id, \
35410306
MB
309 .type_attrs = _type_attrs, \
310 .num_methods = _UVERBS_OBJECT_METHODS_SZ(__VA_ARGS__), \
311 .methods = &(const struct uverbs_method_def * const []){__VA_ARGS__} })
5009010f
MB
312#define DECLARE_UVERBS_OBJECT(_name, _id, _type_attrs, ...) \
313 const struct uverbs_object_def _name = \
314 _UVERBS_OBJECT(_id, _type_attrs, ##__VA_ARGS__)
09e3ebf8
MB
315#define _UVERBS_TREE_OBJECTS_SZ(...) \
316 (sizeof((const struct uverbs_object_def * const []){__VA_ARGS__}) / \
317 sizeof(const struct uverbs_object_def *))
318#define _UVERBS_OBJECT_TREE(...) \
319 ((const struct uverbs_object_tree_def) { \
320 .num_objects = _UVERBS_TREE_OBJECTS_SZ(__VA_ARGS__), \
321 .objects = &(const struct uverbs_object_def * const []){__VA_ARGS__} })
322#define DECLARE_UVERBS_OBJECT_TREE(_name, ...) \
323 const struct uverbs_object_tree_def _name = \
324 _UVERBS_OBJECT_TREE(__VA_ARGS__)
325
fac9658c
MB
326/* =================================================
327 * Parsing infrastructure
328 * =================================================
329 */
330
331struct uverbs_ptr_attr {
8762d149
MB
332 /*
333 * If UVERBS_ATTR_SPEC_F_ALLOC_AND_COPY is set then the 'ptr' is
334 * used.
335 */
336 union {
337 void *ptr;
338 u64 data;
339 };
fac9658c
MB
340 u16 len;
341 /* Combination of bits from enum UVERBS_ATTR_F_XXXX */
342 u16 flags;
494c5580 343 u8 enum_id;
fac9658c
MB
344};
345
f43dbebf
MB
346struct uverbs_obj_attr {
347 struct ib_uobject *uobject;
348};
349
350struct uverbs_attr {
fac9658c
MB
351 /*
352 * pointer to the user-space given attribute, in order to write the
353 * new uobject's id or update flags.
354 */
355 struct ib_uverbs_attr __user *uattr;
356 union {
357 struct uverbs_ptr_attr ptr_attr;
358 struct uverbs_obj_attr obj_attr;
359 };
f43dbebf
MB
360};
361
362struct uverbs_attr_bundle_hash {
363 /* if bit i is set, it means attrs[i] contains valid information */
364 unsigned long *valid_bitmap;
365 size_t num_attrs;
366 /*
367 * arrays of attributes, each element corresponds to the specification
368 * of the attribute in the same index.
369 */
370 struct uverbs_attr *attrs;
371};
372
373struct uverbs_attr_bundle {
374 size_t num_buckets;
375 struct uverbs_attr_bundle_hash hash[];
376};
377
378static inline bool uverbs_attr_is_valid_in_hash(const struct uverbs_attr_bundle_hash *attrs_hash,
379 unsigned int idx)
380{
381 return test_bit(idx, attrs_hash->valid_bitmap);
382}
383
35410306
MB
384static inline bool uverbs_attr_is_valid(const struct uverbs_attr_bundle *attrs_bundle,
385 unsigned int idx)
386{
387 u16 idx_bucket = idx >> UVERBS_ID_NS_SHIFT;
388
389 if (attrs_bundle->num_buckets <= idx_bucket)
390 return false;
391
392 return uverbs_attr_is_valid_in_hash(&attrs_bundle->hash[idx_bucket],
393 idx & ~UVERBS_ID_NS_MASK);
394}
395
41b2a71f
MB
396#define IS_UVERBS_COPY_ERR(_ret) ((_ret) && (_ret) != -ENOENT)
397
d70724f1
MB
398static inline const struct uverbs_attr *uverbs_attr_get(const struct uverbs_attr_bundle *attrs_bundle,
399 u16 idx)
400{
401 u16 idx_bucket = idx >> UVERBS_ID_NS_SHIFT;
402
403 if (!uverbs_attr_is_valid(attrs_bundle, idx))
404 return ERR_PTR(-ENOENT);
405
406 return &attrs_bundle->hash[idx_bucket].attrs[idx & ~UVERBS_ID_NS_MASK];
407}
408
494c5580
MB
409static inline int uverbs_attr_get_enum_id(const struct uverbs_attr_bundle *attrs_bundle,
410 u16 idx)
411{
412 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
413
414 if (IS_ERR(attr))
415 return PTR_ERR(attr);
416
417 return attr->ptr_attr.enum_id;
418}
419
be934cca
AL
420static inline void *uverbs_attr_get_obj(const struct uverbs_attr_bundle *attrs_bundle,
421 u16 idx)
422{
f4602cbb 423 const struct uverbs_attr *attr;
be934cca 424
f4602cbb
JG
425 attr = uverbs_attr_get(attrs_bundle, idx);
426 if (IS_ERR(attr))
427 return ERR_CAST(attr);
be934cca 428
f4602cbb 429 return attr->obj_attr.uobject->object;
be934cca
AL
430}
431
3efa3812
MB
432static inline struct ib_uobject *uverbs_attr_get_uobject(const struct uverbs_attr_bundle *attrs_bundle,
433 u16 idx)
434{
435 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
436
437 if (IS_ERR(attr))
438 return ERR_CAST(attr);
439
440 return attr->obj_attr.uobject;
441}
442
8762d149
MB
443static inline int
444uverbs_attr_get_len(const struct uverbs_attr_bundle *attrs_bundle, u16 idx)
445{
446 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
447
448 if (IS_ERR(attr))
449 return PTR_ERR(attr);
450
451 return attr->ptr_attr.len;
452}
453
d70724f1 454static inline int uverbs_copy_to(const struct uverbs_attr_bundle *attrs_bundle,
89d9e8d3 455 size_t idx, const void *from, size_t size)
d70724f1
MB
456{
457 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
458 u16 flags;
89d9e8d3 459 size_t min_size;
d70724f1
MB
460
461 if (IS_ERR(attr))
462 return PTR_ERR(attr);
463
89d9e8d3 464 min_size = min_t(size_t, attr->ptr_attr.len, size);
2f36028c 465 if (copy_to_user(u64_to_user_ptr(attr->ptr_attr.data), from, min_size))
89d9e8d3
MB
466 return -EFAULT;
467
d70724f1 468 flags = attr->ptr_attr.flags | UVERBS_ATTR_F_VALID_OUTPUT;
89d9e8d3
MB
469 if (put_user(flags, &attr->uattr->flags))
470 return -EFAULT;
471
472 return 0;
d70724f1
MB
473}
474
89d9e8d3
MB
475static inline bool uverbs_attr_ptr_is_inline(const struct uverbs_attr *attr)
476{
477 return attr->ptr_attr.len <= sizeof(attr->ptr_attr.data);
478}
479
8762d149
MB
480static inline void *uverbs_attr_get_alloced_ptr(
481 const struct uverbs_attr_bundle *attrs_bundle, u16 idx)
482{
483 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
484
485 if (IS_ERR(attr))
486 return (void *)attr;
487
488 return uverbs_attr_ptr_is_inline(attr) ? (void *)&attr->ptr_attr.data :
489 attr->ptr_attr.ptr;
490}
491
89d9e8d3 492static inline int _uverbs_copy_from(void *to,
d70724f1 493 const struct uverbs_attr_bundle *attrs_bundle,
89d9e8d3
MB
494 size_t idx,
495 size_t size)
d70724f1
MB
496{
497 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
498
499 if (IS_ERR(attr))
500 return PTR_ERR(attr);
501
89d9e8d3
MB
502 /*
503 * Validation ensures attr->ptr_attr.len >= size. If the caller is
c66db311
MB
504 * using UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO then it must call
505 * uverbs_copy_from_or_zero.
89d9e8d3
MB
506 */
507 if (unlikely(size < attr->ptr_attr.len))
508 return -EINVAL;
509
510 if (uverbs_attr_ptr_is_inline(attr))
d70724f1 511 memcpy(to, &attr->ptr_attr.data, attr->ptr_attr.len);
2f36028c
JG
512 else if (copy_from_user(to, u64_to_user_ptr(attr->ptr_attr.data),
513 attr->ptr_attr.len))
d70724f1
MB
514 return -EFAULT;
515
516 return 0;
517}
518
c66db311
MB
519static inline int _uverbs_copy_from_or_zero(void *to,
520 const struct uverbs_attr_bundle *attrs_bundle,
521 size_t idx,
522 size_t size)
523{
524 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
525 size_t min_size;
526
527 if (IS_ERR(attr))
528 return PTR_ERR(attr);
529
530 min_size = min_t(size_t, size, attr->ptr_attr.len);
531
532 if (uverbs_attr_ptr_is_inline(attr))
533 memcpy(to, &attr->ptr_attr.data, min_size);
534 else if (copy_from_user(to, u64_to_user_ptr(attr->ptr_attr.data),
535 min_size))
536 return -EFAULT;
537
538 if (size > min_size)
539 memset(to + min_size, 0, size - min_size);
540
541 return 0;
542}
543
d70724f1 544#define uverbs_copy_from(to, attrs_bundle, idx) \
89d9e8d3 545 _uverbs_copy_from(to, attrs_bundle, idx, sizeof(*to))
d70724f1 546
c66db311
MB
547#define uverbs_copy_from_or_zero(to, attrs_bundle, idx) \
548 _uverbs_copy_from_or_zero(to, attrs_bundle, idx, sizeof(*to))
549
118620d3
MB
550/* =================================================
551 * Definitions -> Specs infrastructure
552 * =================================================
553 */
554
555/*
556 * uverbs_alloc_spec_tree - Merges different common and driver specific feature
557 * into one parsing tree that every uverbs command will be parsed upon.
558 *
559 * @num_trees: Number of trees in the array @trees.
560 * @trees: Array of pointers to tree root definitions to merge. Each such tree
561 * possibly contains objects, methods and attributes definitions.
562 *
563 * Returns:
564 * uverbs_root_spec *: The root of the merged parsing tree.
565 * On error, we return an error code. Error is checked via IS_ERR.
566 *
567 * The following merges could take place:
568 * a. Two trees representing the same method with different handler
569 * -> We take the handler of the tree that its handler != NULL
570 * and its index in the trees array is greater. The incentive for that
571 * is that developers are expected to first merge common trees and then
572 * merge trees that gives specialized the behaviour.
573 * b. Two trees representing the same object with different
574 * type_attrs (struct uverbs_obj_type):
575 * -> We take the type_attrs of the tree that its type_attr != NULL
576 * and its index in the trees array is greater. This could be used
577 * in order to override the free function, allocation size, etc.
578 * c. Two trees representing the same method attribute (same id but possibly
579 * different attributes):
580 * -> ERROR (-ENOENT), we believe that's not the programmer's intent.
581 *
582 * An object without any methods is considered invalid and will abort the
583 * function with -ENOENT error.
584 */
52427112 585#if IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS)
118620d3
MB
586struct uverbs_root_spec *uverbs_alloc_spec_tree(unsigned int num_trees,
587 const struct uverbs_object_tree_def **trees);
588void uverbs_free_spec_tree(struct uverbs_root_spec *root);
52427112
MB
589#else
590static inline struct uverbs_root_spec *uverbs_alloc_spec_tree(unsigned int num_trees,
591 const struct uverbs_object_tree_def **trees)
592{
593 return NULL;
594}
595
596static inline void uverbs_free_spec_tree(struct uverbs_root_spec *root)
597{
598}
599#endif
a0aa309c 600
118620d3 601#endif