uverbs_ioctl_merge.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664
  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. #include <rdma/uverbs_ioctl.h>
  33. #include <rdma/rdma_user_ioctl.h>
  34. #include <linux/bitops.h>
  35. #include "uverbs.h"
  36. #define UVERBS_NUM_NS (UVERBS_ID_NS_MASK >> UVERBS_ID_NS_SHIFT)
  37. #define GET_NS_ID(idx) (((idx) & UVERBS_ID_NS_MASK) >> UVERBS_ID_NS_SHIFT)
  38. #define GET_ID(idx) ((idx) & ~UVERBS_ID_NS_MASK)
  39. #define _for_each_element(elem, tmpi, tmpj, hashes, num_buckets_offset, \
  40. buckets_offset) \
  41. for (tmpj = 0, \
  42. elem = (*(const void ***)((hashes)[tmpi] + \
  43. (buckets_offset)))[0]; \
  44. tmpj < *(size_t *)((hashes)[tmpi] + (num_buckets_offset)); \
  45. tmpj++) \
  46. if ((elem = ((*(const void ***)(hashes[tmpi] + \
  47. (buckets_offset)))[tmpj])))
  48. /*
  49. * Iterate all elements of a few @hashes. The number of given hashes is
  50. * indicated by @num_hashes. The offset of the number of buckets in the hash is
  51. * represented by @num_buckets_offset, while the offset of the buckets array in
  52. * the hash structure is represented by @buckets_offset. tmpi and tmpj are two
  53. * short (or int) based indices that are given by the user. tmpi iterates over
  54. * the different hashes. @elem points the current element in the hashes[tmpi]
  55. * bucket we are looping on. To be honest, @hashes representation isn't exactly
  56. * a hash, but more a collection of elements. These elements' ids are treated
  57. * in a hash like manner, where the first upper bits are the bucket number.
  58. * These elements are later mapped into a perfect-hash.
  59. */
  60. #define for_each_element(elem, tmpi, tmpj, hashes, num_hashes, \
  61. num_buckets_offset, buckets_offset) \
  62. for (tmpi = 0; tmpi < (num_hashes); tmpi++) \
  63. _for_each_element(elem, tmpi, tmpj, hashes, num_buckets_offset,\
  64. buckets_offset)
  65. #define get_elements_iterators_entry_above(iters, num_elements, elements, \
  66. num_objects_fld, objects_fld, bucket,\
  67. min_id) \
  68. get_elements_above_id((const void **)iters, num_elements, \
  69. (const void **)(elements), \
  70. offsetof(typeof(**elements), \
  71. num_objects_fld), \
  72. offsetof(typeof(**elements), objects_fld),\
  73. offsetof(typeof(***(*elements)->objects_fld), id),\
  74. bucket, min_id)
  75. #define get_objects_above_id(iters, num_trees, trees, bucket, min_id) \
  76. get_elements_iterators_entry_above(iters, num_trees, trees, \
  77. num_objects, objects, bucket, min_id)
  78. #define get_methods_above_id(method_iters, num_iters, iters, bucket, min_id)\
  79. get_elements_iterators_entry_above(method_iters, num_iters, iters, \
  80. num_methods, methods, bucket, min_id)
  81. #define get_attrs_above_id(attrs_iters, num_iters, iters, bucket, min_id)\
  82. get_elements_iterators_entry_above(attrs_iters, num_iters, iters, \
  83. num_attrs, attrs, bucket, min_id)
  84. /*
  85. * get_elements_above_id get a few hashes represented by @elements and
  86. * @num_elements. The hashes fields are described by @num_offset, @data_offset
  87. * and @id_offset in the same way as required by for_each_element. The function
  88. * returns an array of @iters, represents an array of elements in the hashes
  89. * buckets, which their ids are the smallest ids in all hashes but are all
  90. * larger than the id given by min_id. Elements are only added to the iters
  91. * array if their id belongs to the bucket @bucket. The number of elements in
  92. * the returned array is returned by the function. @min_id is also updated to
  93. * reflect the new min_id of all elements in iters.
  94. */
  95. static size_t get_elements_above_id(const void **iters,
  96. unsigned int num_elements,
  97. const void **elements,
  98. size_t num_offset,
  99. size_t data_offset,
  100. size_t id_offset,
  101. u16 bucket,
  102. short *min_id)
  103. {
  104. size_t num_iters = 0;
  105. short min = SHRT_MAX;
  106. const void *elem;
  107. int i, j, last_stored = -1;
  108. unsigned int equal_min = 0;
  109. for_each_element(elem, i, j, elements, num_elements, num_offset,
  110. data_offset) {
  111. u16 id = *(u16 *)(elem + id_offset);
  112. if (GET_NS_ID(id) != bucket)
  113. continue;
  114. if (GET_ID(id) < *min_id ||
  115. (min != SHRT_MAX && GET_ID(id) > min))
  116. continue;
  117. /*
  118. * We first iterate all hashes represented by @elements. When
  119. * we do, we try to find an element @elem in the bucket @bucket
  120. * which its id is min. Since we can't ensure the user sorted
  121. * the elements in increasing order, we override this hash's
  122. * minimal id element we found, if a new element with a smaller
  123. * id was just found.
  124. */
  125. iters[last_stored == i ? num_iters - 1 : num_iters++] = elem;
  126. last_stored = i;
  127. if (min == GET_ID(id))
  128. equal_min++;
  129. else
  130. equal_min = 1;
  131. min = GET_ID(id);
  132. }
  133. /*
  134. * We only insert to our iters array an element, if its id is smaller
  135. * than all previous ids. Therefore, the final iters array is sorted so
  136. * that smaller ids are in the end of the array.
  137. * Therefore, we need to clean the beginning of the array to make sure
  138. * all ids of final elements are equal to min.
  139. */
  140. memmove(iters, iters + num_iters - equal_min, sizeof(*iters) * equal_min);
  141. *min_id = min;
  142. return equal_min;
  143. }
  144. #define find_max_element_entry_id(num_elements, elements, num_objects_fld, \
  145. objects_fld, bucket) \
  146. find_max_element_id(num_elements, (const void **)(elements), \
  147. offsetof(typeof(**elements), num_objects_fld), \
  148. offsetof(typeof(**elements), objects_fld), \
  149. offsetof(typeof(***(*elements)->objects_fld), id),\
  150. bucket)
  151. static short find_max_element_ns_id(unsigned int num_elements,
  152. const void **elements,
  153. size_t num_offset,
  154. size_t data_offset,
  155. size_t id_offset)
  156. {
  157. short max_ns = SHRT_MIN;
  158. const void *elem;
  159. int i, j;
  160. for_each_element(elem, i, j, elements, num_elements, num_offset,
  161. data_offset) {
  162. u16 id = *(u16 *)(elem + id_offset);
  163. if (GET_NS_ID(id) > max_ns)
  164. max_ns = GET_NS_ID(id);
  165. }
  166. return max_ns;
  167. }
  168. static short find_max_element_id(unsigned int num_elements,
  169. const void **elements,
  170. size_t num_offset,
  171. size_t data_offset,
  172. size_t id_offset,
  173. u16 bucket)
  174. {
  175. short max_id = SHRT_MIN;
  176. const void *elem;
  177. int i, j;
  178. for_each_element(elem, i, j, elements, num_elements, num_offset,
  179. data_offset) {
  180. u16 id = *(u16 *)(elem + id_offset);
  181. if (GET_NS_ID(id) == bucket &&
  182. GET_ID(id) > max_id)
  183. max_id = GET_ID(id);
  184. }
  185. return max_id;
  186. }
  187. #define find_max_element_entry_id(num_elements, elements, num_objects_fld, \
  188. objects_fld, bucket) \
  189. find_max_element_id(num_elements, (const void **)(elements), \
  190. offsetof(typeof(**elements), num_objects_fld), \
  191. offsetof(typeof(**elements), objects_fld), \
  192. offsetof(typeof(***(*elements)->objects_fld), id),\
  193. bucket)
  194. #define find_max_element_ns_entry_id(num_elements, elements, \
  195. num_objects_fld, objects_fld) \
  196. find_max_element_ns_id(num_elements, (const void **)(elements), \
  197. offsetof(typeof(**elements), num_objects_fld),\
  198. offsetof(typeof(**elements), objects_fld), \
  199. offsetof(typeof(***(*elements)->objects_fld), id))
  200. /*
  201. * find_max_xxxx_ns_id gets a few elements. Each element is described by an id
  202. * which its upper bits represents a namespace. It finds the max namespace. This
  203. * could be used in order to know how many buckets do we need to allocate. If no
  204. * elements exist, SHRT_MIN is returned. Namespace represents here different
  205. * buckets. The common example is "common bucket" and "driver bucket".
  206. *
  207. * find_max_xxxx_id gets a few elements and a bucket. Each element is described
  208. * by an id which its upper bits represent a namespace. It returns the max id
  209. * which is contained in the same namespace defined in @bucket. This could be
  210. * used in order to know how many elements do we need to allocate in the bucket.
  211. * If no elements exist, SHRT_MIN is returned.
  212. */
  213. #define find_max_object_id(num_trees, trees, bucket) \
  214. find_max_element_entry_id(num_trees, trees, num_objects,\
  215. objects, bucket)
  216. #define find_max_object_ns_id(num_trees, trees) \
  217. find_max_element_ns_entry_id(num_trees, trees, \
  218. num_objects, objects)
  219. #define find_max_method_id(num_iters, iters, bucket) \
  220. find_max_element_entry_id(num_iters, iters, num_methods,\
  221. methods, bucket)
  222. #define find_max_method_ns_id(num_iters, iters) \
  223. find_max_element_ns_entry_id(num_iters, iters, \
  224. num_methods, methods)
  225. #define find_max_attr_id(num_iters, iters, bucket) \
  226. find_max_element_entry_id(num_iters, iters, num_attrs, \
  227. attrs, bucket)
  228. #define find_max_attr_ns_id(num_iters, iters) \
  229. find_max_element_ns_entry_id(num_iters, iters, \
  230. num_attrs, attrs)
  231. static void free_method(struct uverbs_method_spec *method)
  232. {
  233. unsigned int i;
  234. if (!method)
  235. return;
  236. for (i = 0; i < method->num_buckets; i++)
  237. kfree(method->attr_buckets[i]);
  238. kfree(method);
  239. }
  240. #define IS_ATTR_OBJECT(attr) ((attr)->type == UVERBS_ATTR_TYPE_IDR || \
  241. (attr)->type == UVERBS_ATTR_TYPE_FD)
  242. /*
  243. * This function gets array of size @num_method_defs which contains pointers to
  244. * method definitions @method_defs. The function allocates an
  245. * uverbs_method_spec structure and initializes its number of buckets and the
  246. * elements in buckets to the correct attributes. While doing that, it
  247. * validates that there aren't conflicts between attributes of different
  248. * method_defs.
  249. */
  250. static struct uverbs_method_spec *build_method_with_attrs(const struct uverbs_method_def **method_defs,
  251. size_t num_method_defs)
  252. {
  253. int bucket_idx;
  254. int max_attr_buckets = 0;
  255. size_t num_attr_buckets = 0;
  256. int res = 0;
  257. struct uverbs_method_spec *method = NULL;
  258. const struct uverbs_attr_def **attr_defs;
  259. unsigned int num_of_singularities = 0;
  260. max_attr_buckets = find_max_attr_ns_id(num_method_defs, method_defs);
  261. if (max_attr_buckets >= 0)
  262. num_attr_buckets = max_attr_buckets + 1;
  263. method = kzalloc(struct_size(method, attr_buckets, num_attr_buckets),
  264. GFP_KERNEL);
  265. if (!method)
  266. return ERR_PTR(-ENOMEM);
  267. method->num_buckets = num_attr_buckets;
  268. attr_defs = kcalloc(num_method_defs, sizeof(*attr_defs), GFP_KERNEL);
  269. if (!attr_defs) {
  270. res = -ENOMEM;
  271. goto free_method;
  272. }
  273. for (bucket_idx = 0; bucket_idx < method->num_buckets; bucket_idx++) {
  274. short min_id = SHRT_MIN;
  275. int attr_max_bucket = 0;
  276. struct uverbs_attr_spec_hash *hash = NULL;
  277. attr_max_bucket = find_max_attr_id(num_method_defs, method_defs,
  278. bucket_idx);
  279. if (attr_max_bucket < 0)
  280. continue;
  281. hash = kzalloc(sizeof(*hash) +
  282. ALIGN(sizeof(*hash->attrs) * (attr_max_bucket + 1),
  283. sizeof(long)) +
  284. BITS_TO_LONGS(attr_max_bucket + 1) * sizeof(long),
  285. GFP_KERNEL);
  286. if (!hash) {
  287. res = -ENOMEM;
  288. goto free;
  289. }
  290. hash->num_attrs = attr_max_bucket + 1;
  291. method->num_child_attrs += hash->num_attrs;
  292. hash->mandatory_attrs_bitmask = (void *)(hash + 1) +
  293. ALIGN(sizeof(*hash->attrs) *
  294. (attr_max_bucket + 1),
  295. sizeof(long));
  296. method->attr_buckets[bucket_idx] = hash;
  297. do {
  298. size_t num_attr_defs;
  299. struct uverbs_attr_spec *attr;
  300. bool attr_obj_with_special_access;
  301. num_attr_defs =
  302. get_attrs_above_id(attr_defs,
  303. num_method_defs,
  304. method_defs,
  305. bucket_idx,
  306. &min_id);
  307. /* Last attr in bucket */
  308. if (!num_attr_defs)
  309. break;
  310. if (num_attr_defs > 1) {
  311. /*
  312. * We don't allow two attribute definitions for
  313. * the same attribute. This is usually a
  314. * programmer error. If required, it's better to
  315. * just add a new attribute to capture the new
  316. * semantics.
  317. */
  318. res = -EEXIST;
  319. goto free;
  320. }
  321. attr = &hash->attrs[min_id];
  322. memcpy(attr, &attr_defs[0]->attr, sizeof(*attr));
  323. attr_obj_with_special_access = IS_ATTR_OBJECT(attr) &&
  324. (attr->obj.access == UVERBS_ACCESS_NEW ||
  325. attr->obj.access == UVERBS_ACCESS_DESTROY);
  326. num_of_singularities += !!attr_obj_with_special_access;
  327. if (WARN(num_of_singularities > 1,
  328. "ib_uverbs: Method contains more than one object attr (%d) with new/destroy access\n",
  329. min_id) ||
  330. WARN(attr_obj_with_special_access &&
  331. !(attr->flags & UVERBS_ATTR_SPEC_F_MANDATORY),
  332. "ib_uverbs: Tried to merge attr (%d) but it's an object with new/destroy access but isn't mandatory\n",
  333. min_id) ||
  334. WARN(IS_ATTR_OBJECT(attr) &&
  335. attr->flags & UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO,
  336. "ib_uverbs: Tried to merge attr (%d) but it's an object with min_sz flag\n",
  337. min_id)) {
  338. res = -EINVAL;
  339. goto free;
  340. }
  341. if (attr->flags & UVERBS_ATTR_SPEC_F_MANDATORY)
  342. set_bit(min_id, hash->mandatory_attrs_bitmask);
  343. min_id++;
  344. } while (1);
  345. }
  346. kfree(attr_defs);
  347. return method;
  348. free:
  349. kfree(attr_defs);
  350. free_method:
  351. free_method(method);
  352. return ERR_PTR(res);
  353. }
  354. static void free_object(struct uverbs_object_spec *object)
  355. {
  356. unsigned int i, j;
  357. if (!object)
  358. return;
  359. for (i = 0; i < object->num_buckets; i++) {
  360. struct uverbs_method_spec_hash *method_buckets =
  361. object->method_buckets[i];
  362. if (!method_buckets)
  363. continue;
  364. for (j = 0; j < method_buckets->num_methods; j++)
  365. free_method(method_buckets->methods[j]);
  366. kfree(method_buckets);
  367. }
  368. kfree(object);
  369. }
  370. /*
  371. * This function gets array of size @num_object_defs which contains pointers to
  372. * object definitions @object_defs. The function allocated an
  373. * uverbs_object_spec structure and initialize its number of buckets and the
  374. * elements in buckets to the correct methods. While doing that, it
  375. * sorts out the correct relationship between conflicts in the same method.
  376. */
  377. static struct uverbs_object_spec *build_object_with_methods(const struct uverbs_object_def **object_defs,
  378. size_t num_object_defs)
  379. {
  380. u16 bucket_idx;
  381. int max_method_buckets = 0;
  382. u16 num_method_buckets = 0;
  383. int res = 0;
  384. struct uverbs_object_spec *object = NULL;
  385. const struct uverbs_method_def **method_defs;
  386. max_method_buckets = find_max_method_ns_id(num_object_defs, object_defs);
  387. if (max_method_buckets >= 0)
  388. num_method_buckets = max_method_buckets + 1;
  389. object = kzalloc(struct_size(object, method_buckets,
  390. num_method_buckets),
  391. GFP_KERNEL);
  392. if (!object)
  393. return ERR_PTR(-ENOMEM);
  394. object->num_buckets = num_method_buckets;
  395. method_defs = kcalloc(num_object_defs, sizeof(*method_defs), GFP_KERNEL);
  396. if (!method_defs) {
  397. res = -ENOMEM;
  398. goto free_object;
  399. }
  400. for (bucket_idx = 0; bucket_idx < object->num_buckets; bucket_idx++) {
  401. short min_id = SHRT_MIN;
  402. int methods_max_bucket = 0;
  403. struct uverbs_method_spec_hash *hash = NULL;
  404. methods_max_bucket = find_max_method_id(num_object_defs, object_defs,
  405. bucket_idx);
  406. if (methods_max_bucket < 0)
  407. continue;
  408. hash = kzalloc(struct_size(hash, methods,
  409. methods_max_bucket + 1),
  410. GFP_KERNEL);
  411. if (!hash) {
  412. res = -ENOMEM;
  413. goto free;
  414. }
  415. hash->num_methods = methods_max_bucket + 1;
  416. object->method_buckets[bucket_idx] = hash;
  417. do {
  418. size_t num_method_defs;
  419. struct uverbs_method_spec *method;
  420. int i;
  421. num_method_defs =
  422. get_methods_above_id(method_defs,
  423. num_object_defs,
  424. object_defs,
  425. bucket_idx,
  426. &min_id);
  427. /* Last method in bucket */
  428. if (!num_method_defs)
  429. break;
  430. method = build_method_with_attrs(method_defs,
  431. num_method_defs);
  432. if (IS_ERR(method)) {
  433. res = PTR_ERR(method);
  434. goto free;
  435. }
  436. /*
  437. * The last tree which is given as an argument to the
  438. * merge overrides previous method handler.
  439. * Therefore, we iterate backwards and search for the
  440. * first handler which != NULL. This also defines the
  441. * set of flags used for this handler.
  442. */
  443. for (i = num_method_defs - 1;
  444. i >= 0 && !method_defs[i]->handler; i--)
  445. ;
  446. hash->methods[min_id++] = method;
  447. /* NULL handler isn't allowed */
  448. if (WARN(i < 0,
  449. "ib_uverbs: tried to merge function id %d, but all handlers are NULL\n",
  450. min_id)) {
  451. res = -EINVAL;
  452. goto free;
  453. }
  454. method->handler = method_defs[i]->handler;
  455. method->flags = method_defs[i]->flags;
  456. } while (1);
  457. }
  458. kfree(method_defs);
  459. return object;
  460. free:
  461. kfree(method_defs);
  462. free_object:
  463. free_object(object);
  464. return ERR_PTR(res);
  465. }
  466. void uverbs_free_spec_tree(struct uverbs_root_spec *root)
  467. {
  468. unsigned int i, j;
  469. if (!root)
  470. return;
  471. for (i = 0; i < root->num_buckets; i++) {
  472. struct uverbs_object_spec_hash *object_hash =
  473. root->object_buckets[i];
  474. if (!object_hash)
  475. continue;
  476. for (j = 0; j < object_hash->num_objects; j++)
  477. free_object(object_hash->objects[j]);
  478. kfree(object_hash);
  479. }
  480. kfree(root);
  481. }
  482. EXPORT_SYMBOL(uverbs_free_spec_tree);
  483. struct uverbs_root_spec *uverbs_alloc_spec_tree(unsigned int num_trees,
  484. const struct uverbs_object_tree_def **trees)
  485. {
  486. u16 bucket_idx;
  487. short max_object_buckets = 0;
  488. size_t num_objects_buckets = 0;
  489. struct uverbs_root_spec *root_spec = NULL;
  490. const struct uverbs_object_def **object_defs;
  491. int i;
  492. int res = 0;
  493. max_object_buckets = find_max_object_ns_id(num_trees, trees);
  494. /*
  495. * Devices which don't want to support ib_uverbs, should just allocate
  496. * an empty parsing tree. Every user-space command won't hit any valid
  497. * entry in the parsing tree and thus will fail.
  498. */
  499. if (max_object_buckets >= 0)
  500. num_objects_buckets = max_object_buckets + 1;
  501. root_spec = kzalloc(struct_size(root_spec, object_buckets,
  502. num_objects_buckets),
  503. GFP_KERNEL);
  504. if (!root_spec)
  505. return ERR_PTR(-ENOMEM);
  506. root_spec->num_buckets = num_objects_buckets;
  507. object_defs = kcalloc(num_trees, sizeof(*object_defs),
  508. GFP_KERNEL);
  509. if (!object_defs) {
  510. res = -ENOMEM;
  511. goto free_root;
  512. }
  513. for (bucket_idx = 0; bucket_idx < root_spec->num_buckets; bucket_idx++) {
  514. short min_id = SHRT_MIN;
  515. short objects_max_bucket;
  516. struct uverbs_object_spec_hash *hash = NULL;
  517. objects_max_bucket = find_max_object_id(num_trees, trees,
  518. bucket_idx);
  519. if (objects_max_bucket < 0)
  520. continue;
  521. hash = kzalloc(struct_size(hash, objects,
  522. objects_max_bucket + 1),
  523. GFP_KERNEL);
  524. if (!hash) {
  525. res = -ENOMEM;
  526. goto free;
  527. }
  528. hash->num_objects = objects_max_bucket + 1;
  529. root_spec->object_buckets[bucket_idx] = hash;
  530. do {
  531. size_t num_object_defs;
  532. struct uverbs_object_spec *object;
  533. num_object_defs = get_objects_above_id(object_defs,
  534. num_trees,
  535. trees,
  536. bucket_idx,
  537. &min_id);
  538. /* Last object in bucket */
  539. if (!num_object_defs)
  540. break;
  541. object = build_object_with_methods(object_defs,
  542. num_object_defs);
  543. if (IS_ERR(object)) {
  544. res = PTR_ERR(object);
  545. goto free;
  546. }
  547. /*
  548. * The last tree which is given as an argument to the
  549. * merge overrides previous object's type_attrs.
  550. * Therefore, we iterate backwards and search for the
  551. * first type_attrs which != NULL.
  552. */
  553. for (i = num_object_defs - 1;
  554. i >= 0 && !object_defs[i]->type_attrs; i--)
  555. ;
  556. /*
  557. * NULL is a valid type_attrs. It means an object we
  558. * can't instantiate (like DEVICE).
  559. */
  560. object->type_attrs = i < 0 ? NULL :
  561. object_defs[i]->type_attrs;
  562. hash->objects[min_id++] = object;
  563. } while (1);
  564. }
  565. kfree(object_defs);
  566. return root_spec;
  567. free:
  568. kfree(object_defs);
  569. free_root:
  570. uverbs_free_spec_tree(root_spec);
  571. return ERR_PTR(res);
  572. }
  573. EXPORT_SYMBOL(uverbs_alloc_spec_tree);