objagg.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038
  1. // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2. /* Copyright (c) 2018 Mellanox Technologies. All rights reserved */
  3. #include <linux/module.h>
  4. #include <linux/slab.h>
  5. #include <linux/rhashtable.h>
  6. #include <linux/idr.h>
  7. #include <linux/list.h>
  8. #include <linux/sort.h>
  9. #include <linux/objagg.h>
  10. #define CREATE_TRACE_POINTS
  11. #include <trace/events/objagg.h>
  12. struct objagg_hints {
  13. struct rhashtable node_ht;
  14. struct rhashtable_params ht_params;
  15. struct list_head node_list;
  16. unsigned int node_count;
  17. unsigned int root_count;
  18. unsigned int refcount;
  19. const struct objagg_ops *ops;
  20. };
  21. struct objagg_hints_node {
  22. struct rhash_head ht_node; /* member of objagg_hints->node_ht */
  23. struct list_head list; /* member of objagg_hints->node_list */
  24. struct objagg_hints_node *parent;
  25. unsigned int root_id;
  26. struct objagg_obj_stats_info stats_info;
  27. unsigned long obj[];
  28. };
  29. static struct objagg_hints_node *
  30. objagg_hints_lookup(struct objagg_hints *objagg_hints, void *obj)
  31. {
  32. if (!objagg_hints)
  33. return NULL;
  34. return rhashtable_lookup_fast(&objagg_hints->node_ht, obj,
  35. objagg_hints->ht_params);
  36. }
  37. struct objagg {
  38. const struct objagg_ops *ops;
  39. void *priv;
  40. struct rhashtable obj_ht;
  41. struct rhashtable_params ht_params;
  42. struct list_head obj_list;
  43. unsigned int obj_count;
  44. struct ida root_ida;
  45. struct objagg_hints *hints;
  46. };
  47. struct objagg_obj {
  48. struct rhash_head ht_node; /* member of objagg->obj_ht */
  49. struct list_head list; /* member of objagg->obj_list */
  50. struct objagg_obj *parent; /* if the object is nested, this
  51. * holds pointer to parent, otherwise NULL
  52. */
  53. union {
  54. void *delta_priv; /* user delta private */
  55. void *root_priv; /* user root private */
  56. };
  57. unsigned int root_id;
  58. unsigned int refcount; /* counts number of users of this object
  59. * including nested objects
  60. */
  61. struct objagg_obj_stats stats;
  62. unsigned long obj[];
  63. };
  64. static unsigned int objagg_obj_ref_inc(struct objagg_obj *objagg_obj)
  65. {
  66. return ++objagg_obj->refcount;
  67. }
  68. static unsigned int objagg_obj_ref_dec(struct objagg_obj *objagg_obj)
  69. {
  70. return --objagg_obj->refcount;
  71. }
  72. static void objagg_obj_stats_inc(struct objagg_obj *objagg_obj)
  73. {
  74. objagg_obj->stats.user_count++;
  75. objagg_obj->stats.delta_user_count++;
  76. if (objagg_obj->parent)
  77. objagg_obj->parent->stats.delta_user_count++;
  78. }
  79. static void objagg_obj_stats_dec(struct objagg_obj *objagg_obj)
  80. {
  81. objagg_obj->stats.user_count--;
  82. objagg_obj->stats.delta_user_count--;
  83. if (objagg_obj->parent)
  84. objagg_obj->parent->stats.delta_user_count--;
  85. }
  86. static bool objagg_obj_is_root(const struct objagg_obj *objagg_obj)
  87. {
  88. /* Nesting is not supported, so we can use ->parent
  89. * to figure out if the object is root.
  90. */
  91. return !objagg_obj->parent;
  92. }
  93. /**
  94. * objagg_obj_root_priv - obtains root private for an object
  95. * @objagg_obj: objagg object instance
  96. *
  97. * Note: all locking must be provided by the caller.
  98. *
  99. * Either the object is root itself when the private is returned
  100. * directly, or the parent is root and its private is returned
  101. * instead.
  102. *
  103. * Returns a user private root pointer.
  104. */
  105. const void *objagg_obj_root_priv(const struct objagg_obj *objagg_obj)
  106. {
  107. if (objagg_obj_is_root(objagg_obj))
  108. return objagg_obj->root_priv;
  109. WARN_ON(!objagg_obj_is_root(objagg_obj->parent));
  110. return objagg_obj->parent->root_priv;
  111. }
  112. EXPORT_SYMBOL(objagg_obj_root_priv);
  113. /**
  114. * objagg_obj_delta_priv - obtains delta private for an object
  115. * @objagg_obj: objagg object instance
  116. *
  117. * Note: all locking must be provided by the caller.
  118. *
  119. * Returns user private delta pointer or NULL in case the passed
  120. * object is root.
  121. */
  122. const void *objagg_obj_delta_priv(const struct objagg_obj *objagg_obj)
  123. {
  124. if (objagg_obj_is_root(objagg_obj))
  125. return NULL;
  126. return objagg_obj->delta_priv;
  127. }
  128. EXPORT_SYMBOL(objagg_obj_delta_priv);
  129. /**
  130. * objagg_obj_raw - obtains object user private pointer
  131. * @objagg_obj: objagg object instance
  132. *
  133. * Note: all locking must be provided by the caller.
  134. *
  135. * Returns user private pointer as was passed to objagg_obj_get() by "obj" arg.
  136. */
  137. const void *objagg_obj_raw(const struct objagg_obj *objagg_obj)
  138. {
  139. return objagg_obj->obj;
  140. }
  141. EXPORT_SYMBOL(objagg_obj_raw);
  142. static struct objagg_obj *objagg_obj_lookup(struct objagg *objagg, void *obj)
  143. {
  144. return rhashtable_lookup_fast(&objagg->obj_ht, obj, objagg->ht_params);
  145. }
  146. static int objagg_obj_parent_assign(struct objagg *objagg,
  147. struct objagg_obj *objagg_obj,
  148. struct objagg_obj *parent,
  149. bool take_parent_ref)
  150. {
  151. void *delta_priv;
  152. if (WARN_ON(!objagg_obj_is_root(parent)))
  153. return -EINVAL;
  154. delta_priv = objagg->ops->delta_create(objagg->priv, parent->obj,
  155. objagg_obj->obj);
  156. if (IS_ERR(delta_priv))
  157. return PTR_ERR(delta_priv);
  158. /* User returned a delta private, that means that
  159. * our object can be aggregated into the parent.
  160. */
  161. objagg_obj->parent = parent;
  162. objagg_obj->delta_priv = delta_priv;
  163. if (take_parent_ref)
  164. objagg_obj_ref_inc(objagg_obj->parent);
  165. trace_objagg_obj_parent_assign(objagg, objagg_obj,
  166. parent,
  167. parent->refcount);
  168. return 0;
  169. }
  170. static int objagg_obj_parent_lookup_assign(struct objagg *objagg,
  171. struct objagg_obj *objagg_obj)
  172. {
  173. struct objagg_obj *objagg_obj_cur;
  174. int err;
  175. list_for_each_entry(objagg_obj_cur, &objagg->obj_list, list) {
  176. /* Nesting is not supported. In case the object
  177. * is not root, it cannot be assigned as parent.
  178. */
  179. if (!objagg_obj_is_root(objagg_obj_cur))
  180. continue;
  181. err = objagg_obj_parent_assign(objagg, objagg_obj,
  182. objagg_obj_cur, true);
  183. if (!err)
  184. return 0;
  185. }
  186. return -ENOENT;
  187. }
  188. static void __objagg_obj_put(struct objagg *objagg,
  189. struct objagg_obj *objagg_obj);
  190. static void objagg_obj_parent_unassign(struct objagg *objagg,
  191. struct objagg_obj *objagg_obj)
  192. {
  193. trace_objagg_obj_parent_unassign(objagg, objagg_obj,
  194. objagg_obj->parent,
  195. objagg_obj->parent->refcount);
  196. objagg->ops->delta_destroy(objagg->priv, objagg_obj->delta_priv);
  197. __objagg_obj_put(objagg, objagg_obj->parent);
  198. }
  199. static int objagg_obj_root_id_alloc(struct objagg *objagg,
  200. struct objagg_obj *objagg_obj,
  201. struct objagg_hints_node *hnode)
  202. {
  203. unsigned int min, max;
  204. int root_id;
  205. /* In case there are no hints available, the root id is invalid. */
  206. if (!objagg->hints) {
  207. objagg_obj->root_id = OBJAGG_OBJ_ROOT_ID_INVALID;
  208. return 0;
  209. }
  210. if (hnode) {
  211. min = hnode->root_id;
  212. max = hnode->root_id;
  213. } else {
  214. /* For objects with no hint, start after the last
  215. * hinted root_id.
  216. */
  217. min = objagg->hints->root_count;
  218. max = ~0;
  219. }
  220. root_id = ida_alloc_range(&objagg->root_ida, min, max, GFP_KERNEL);
  221. if (root_id < 0)
  222. return root_id;
  223. objagg_obj->root_id = root_id;
  224. return 0;
  225. }
  226. static void objagg_obj_root_id_free(struct objagg *objagg,
  227. struct objagg_obj *objagg_obj)
  228. {
  229. if (!objagg->hints)
  230. return;
  231. ida_free(&objagg->root_ida, objagg_obj->root_id);
  232. }
  233. static int objagg_obj_root_create(struct objagg *objagg,
  234. struct objagg_obj *objagg_obj,
  235. struct objagg_hints_node *hnode)
  236. {
  237. int err;
  238. err = objagg_obj_root_id_alloc(objagg, objagg_obj, hnode);
  239. if (err)
  240. return err;
  241. objagg_obj->root_priv = objagg->ops->root_create(objagg->priv,
  242. objagg_obj->obj,
  243. objagg_obj->root_id);
  244. if (IS_ERR(objagg_obj->root_priv)) {
  245. err = PTR_ERR(objagg_obj->root_priv);
  246. goto err_root_create;
  247. }
  248. trace_objagg_obj_root_create(objagg, objagg_obj);
  249. return 0;
  250. err_root_create:
  251. objagg_obj_root_id_free(objagg, objagg_obj);
  252. return err;
  253. }
  254. static void objagg_obj_root_destroy(struct objagg *objagg,
  255. struct objagg_obj *objagg_obj)
  256. {
  257. trace_objagg_obj_root_destroy(objagg, objagg_obj);
  258. objagg->ops->root_destroy(objagg->priv, objagg_obj->root_priv);
  259. objagg_obj_root_id_free(objagg, objagg_obj);
  260. }
  261. static struct objagg_obj *__objagg_obj_get(struct objagg *objagg, void *obj);
  262. static int objagg_obj_init_with_hints(struct objagg *objagg,
  263. struct objagg_obj *objagg_obj,
  264. bool *hint_found)
  265. {
  266. struct objagg_hints_node *hnode;
  267. struct objagg_obj *parent;
  268. int err;
  269. hnode = objagg_hints_lookup(objagg->hints, objagg_obj->obj);
  270. if (!hnode) {
  271. *hint_found = false;
  272. return 0;
  273. }
  274. *hint_found = true;
  275. if (!hnode->parent)
  276. return objagg_obj_root_create(objagg, objagg_obj, hnode);
  277. parent = __objagg_obj_get(objagg, hnode->parent->obj);
  278. if (IS_ERR(parent))
  279. return PTR_ERR(parent);
  280. err = objagg_obj_parent_assign(objagg, objagg_obj, parent, false);
  281. if (err) {
  282. *hint_found = false;
  283. err = 0;
  284. goto err_parent_assign;
  285. }
  286. return 0;
  287. err_parent_assign:
  288. objagg_obj_put(objagg, parent);
  289. return err;
  290. }
  291. static int objagg_obj_init(struct objagg *objagg,
  292. struct objagg_obj *objagg_obj)
  293. {
  294. bool hint_found;
  295. int err;
  296. /* First, try to use hints if they are available and
  297. * if they provide result.
  298. */
  299. err = objagg_obj_init_with_hints(objagg, objagg_obj, &hint_found);
  300. if (err)
  301. return err;
  302. if (hint_found)
  303. return 0;
  304. /* Try to find if the object can be aggregated under an existing one. */
  305. err = objagg_obj_parent_lookup_assign(objagg, objagg_obj);
  306. if (!err)
  307. return 0;
  308. /* If aggregation is not possible, make the object a root. */
  309. return objagg_obj_root_create(objagg, objagg_obj, NULL);
  310. }
  311. static void objagg_obj_fini(struct objagg *objagg,
  312. struct objagg_obj *objagg_obj)
  313. {
  314. if (!objagg_obj_is_root(objagg_obj))
  315. objagg_obj_parent_unassign(objagg, objagg_obj);
  316. else
  317. objagg_obj_root_destroy(objagg, objagg_obj);
  318. }
  319. static struct objagg_obj *objagg_obj_create(struct objagg *objagg, void *obj)
  320. {
  321. struct objagg_obj *objagg_obj;
  322. int err;
  323. objagg_obj = kzalloc(sizeof(*objagg_obj) + objagg->ops->obj_size,
  324. GFP_KERNEL);
  325. if (!objagg_obj)
  326. return ERR_PTR(-ENOMEM);
  327. objagg_obj_ref_inc(objagg_obj);
  328. memcpy(objagg_obj->obj, obj, objagg->ops->obj_size);
  329. err = objagg_obj_init(objagg, objagg_obj);
  330. if (err)
  331. goto err_obj_init;
  332. err = rhashtable_insert_fast(&objagg->obj_ht, &objagg_obj->ht_node,
  333. objagg->ht_params);
  334. if (err)
  335. goto err_ht_insert;
  336. list_add(&objagg_obj->list, &objagg->obj_list);
  337. objagg->obj_count++;
  338. trace_objagg_obj_create(objagg, objagg_obj);
  339. return objagg_obj;
  340. err_ht_insert:
  341. objagg_obj_fini(objagg, objagg_obj);
  342. err_obj_init:
  343. kfree(objagg_obj);
  344. return ERR_PTR(err);
  345. }
  346. static struct objagg_obj *__objagg_obj_get(struct objagg *objagg, void *obj)
  347. {
  348. struct objagg_obj *objagg_obj;
  349. /* First, try to find the object exactly as user passed it,
  350. * perhaps it is already in use.
  351. */
  352. objagg_obj = objagg_obj_lookup(objagg, obj);
  353. if (objagg_obj) {
  354. objagg_obj_ref_inc(objagg_obj);
  355. return objagg_obj;
  356. }
  357. return objagg_obj_create(objagg, obj);
  358. }
  359. /**
  360. * objagg_obj_get - gets an object within objagg instance
  361. * @objagg: objagg instance
  362. * @obj: user-specific private object pointer
  363. *
  364. * Note: all locking must be provided by the caller.
  365. *
  366. * Size of the "obj" memory is specified in "objagg->ops".
  367. *
  368. * There are 3 main options this function wraps:
  369. * 1) The object according to "obj" already exist. In that case
  370. * the reference counter is incremented and the object is returned.
  371. * 2) The object does not exist, but it can be aggregated within
  372. * another object. In that case, user ops->delta_create() is called
  373. * to obtain delta data and a new object is created with returned
  374. * user-delta private pointer.
  375. * 3) The object does not exist and cannot be aggregated into
  376. * any of the existing objects. In that case, user ops->root_create()
  377. * is called to create the root and a new object is created with
  378. * returned user-root private pointer.
  379. *
  380. * Returns a pointer to objagg object instance in case of success,
  381. * otherwise it returns pointer error using ERR_PTR macro.
  382. */
  383. struct objagg_obj *objagg_obj_get(struct objagg *objagg, void *obj)
  384. {
  385. struct objagg_obj *objagg_obj;
  386. objagg_obj = __objagg_obj_get(objagg, obj);
  387. if (IS_ERR(objagg_obj))
  388. return objagg_obj;
  389. objagg_obj_stats_inc(objagg_obj);
  390. trace_objagg_obj_get(objagg, objagg_obj, objagg_obj->refcount);
  391. return objagg_obj;
  392. }
  393. EXPORT_SYMBOL(objagg_obj_get);
  394. static void objagg_obj_destroy(struct objagg *objagg,
  395. struct objagg_obj *objagg_obj)
  396. {
  397. trace_objagg_obj_destroy(objagg, objagg_obj);
  398. --objagg->obj_count;
  399. list_del(&objagg_obj->list);
  400. rhashtable_remove_fast(&objagg->obj_ht, &objagg_obj->ht_node,
  401. objagg->ht_params);
  402. objagg_obj_fini(objagg, objagg_obj);
  403. kfree(objagg_obj);
  404. }
  405. static void __objagg_obj_put(struct objagg *objagg,
  406. struct objagg_obj *objagg_obj)
  407. {
  408. if (!objagg_obj_ref_dec(objagg_obj))
  409. objagg_obj_destroy(objagg, objagg_obj);
  410. }
  411. /**
  412. * objagg_obj_put - puts an object within objagg instance
  413. * @objagg: objagg instance
  414. * @objagg_obj: objagg object instance
  415. *
  416. * Note: all locking must be provided by the caller.
  417. *
  418. * Symmetric to objagg_obj_get().
  419. */
  420. void objagg_obj_put(struct objagg *objagg, struct objagg_obj *objagg_obj)
  421. {
  422. trace_objagg_obj_put(objagg, objagg_obj, objagg_obj->refcount);
  423. objagg_obj_stats_dec(objagg_obj);
  424. __objagg_obj_put(objagg, objagg_obj);
  425. }
  426. EXPORT_SYMBOL(objagg_obj_put);
  427. /**
  428. * objagg_create - creates a new objagg instance
  429. * @ops: user-specific callbacks
  430. * @objagg_hints: hints, can be NULL
  431. * @priv: pointer to a private data passed to the ops
  432. *
  433. * Note: all locking must be provided by the caller.
  434. *
  435. * The purpose of the library is to provide an infrastructure to
  436. * aggregate user-specified objects. Library does not care about the type
  437. * of the object. User fills-up ops which take care of the specific
  438. * user object manipulation.
  439. *
  440. * As a very stupid example, consider integer numbers. For example
  441. * number 8 as a root object. That can aggregate number 9 with delta 1,
  442. * number 10 with delta 2, etc. This example is implemented as
  443. * a part of a testing module in test_objagg.c file.
  444. *
  445. * Each objagg instance contains multiple trees. Each tree node is
  446. * represented by "an object". In the current implementation there can be
  447. * only roots and leafs nodes. Leaf nodes are called deltas.
  448. * But in general, this can be easily extended for intermediate nodes.
  449. * In that extension, a delta would be associated with all non-root
  450. * nodes.
  451. *
  452. * Returns a pointer to newly created objagg instance in case of success,
  453. * otherwise it returns pointer error using ERR_PTR macro.
  454. */
  455. struct objagg *objagg_create(const struct objagg_ops *ops,
  456. struct objagg_hints *objagg_hints, void *priv)
  457. {
  458. struct objagg *objagg;
  459. int err;
  460. if (WARN_ON(!ops || !ops->root_create || !ops->root_destroy ||
  461. !ops->delta_check || !ops->delta_create ||
  462. !ops->delta_destroy))
  463. return ERR_PTR(-EINVAL);
  464. objagg = kzalloc_obj(*objagg);
  465. if (!objagg)
  466. return ERR_PTR(-ENOMEM);
  467. objagg->ops = ops;
  468. if (objagg_hints) {
  469. objagg->hints = objagg_hints;
  470. objagg_hints->refcount++;
  471. }
  472. objagg->priv = priv;
  473. INIT_LIST_HEAD(&objagg->obj_list);
  474. objagg->ht_params.key_len = ops->obj_size;
  475. objagg->ht_params.key_offset = offsetof(struct objagg_obj, obj);
  476. objagg->ht_params.head_offset = offsetof(struct objagg_obj, ht_node);
  477. err = rhashtable_init(&objagg->obj_ht, &objagg->ht_params);
  478. if (err)
  479. goto err_rhashtable_init;
  480. ida_init(&objagg->root_ida);
  481. trace_objagg_create(objagg);
  482. return objagg;
  483. err_rhashtable_init:
  484. kfree(objagg);
  485. return ERR_PTR(err);
  486. }
  487. EXPORT_SYMBOL(objagg_create);
  488. /**
  489. * objagg_destroy - destroys a new objagg instance
  490. * @objagg: objagg instance
  491. *
  492. * Note: all locking must be provided by the caller.
  493. */
  494. void objagg_destroy(struct objagg *objagg)
  495. {
  496. trace_objagg_destroy(objagg);
  497. ida_destroy(&objagg->root_ida);
  498. WARN_ON(!list_empty(&objagg->obj_list));
  499. rhashtable_destroy(&objagg->obj_ht);
  500. if (objagg->hints)
  501. objagg_hints_put(objagg->hints);
  502. kfree(objagg);
  503. }
  504. EXPORT_SYMBOL(objagg_destroy);
  505. static int objagg_stats_info_sort_cmp_func(const void *a, const void *b)
  506. {
  507. const struct objagg_obj_stats_info *stats_info1 = a;
  508. const struct objagg_obj_stats_info *stats_info2 = b;
  509. if (stats_info1->is_root != stats_info2->is_root)
  510. return stats_info2->is_root - stats_info1->is_root;
  511. if (stats_info1->stats.delta_user_count !=
  512. stats_info2->stats.delta_user_count)
  513. return stats_info2->stats.delta_user_count -
  514. stats_info1->stats.delta_user_count;
  515. return stats_info2->stats.user_count - stats_info1->stats.user_count;
  516. }
  517. /**
  518. * objagg_stats_get - obtains stats of the objagg instance
  519. * @objagg: objagg instance
  520. *
  521. * Note: all locking must be provided by the caller.
  522. *
  523. * The returned structure contains statistics of all object
  524. * currently in use, ordered by following rules:
  525. * 1) Root objects are always on lower indexes than the rest.
  526. * 2) Objects with higher delta user count are always on lower
  527. * indexes.
  528. * 3) In case more objects have the same delta user count,
  529. * the objects are ordered by user count.
  530. *
  531. * Returns a pointer to stats instance in case of success,
  532. * otherwise it returns pointer error using ERR_PTR macro.
  533. */
  534. const struct objagg_stats *objagg_stats_get(struct objagg *objagg)
  535. {
  536. struct objagg_stats *objagg_stats;
  537. struct objagg_obj *objagg_obj;
  538. int i;
  539. objagg_stats = kzalloc_flex(*objagg_stats, stats_info,
  540. objagg->obj_count);
  541. if (!objagg_stats)
  542. return ERR_PTR(-ENOMEM);
  543. i = 0;
  544. list_for_each_entry(objagg_obj, &objagg->obj_list, list) {
  545. memcpy(&objagg_stats->stats_info[i].stats, &objagg_obj->stats,
  546. sizeof(objagg_stats->stats_info[0].stats));
  547. objagg_stats->stats_info[i].objagg_obj = objagg_obj;
  548. objagg_stats->stats_info[i].is_root =
  549. objagg_obj_is_root(objagg_obj);
  550. if (objagg_stats->stats_info[i].is_root)
  551. objagg_stats->root_count++;
  552. i++;
  553. }
  554. objagg_stats->stats_info_count = i;
  555. sort(objagg_stats->stats_info, objagg_stats->stats_info_count,
  556. sizeof(struct objagg_obj_stats_info),
  557. objagg_stats_info_sort_cmp_func, NULL);
  558. return objagg_stats;
  559. }
  560. EXPORT_SYMBOL(objagg_stats_get);
  561. /**
  562. * objagg_stats_put - puts stats of the objagg instance
  563. * @objagg_stats: objagg instance stats
  564. *
  565. * Note: all locking must be provided by the caller.
  566. */
  567. void objagg_stats_put(const struct objagg_stats *objagg_stats)
  568. {
  569. kfree(objagg_stats);
  570. }
  571. EXPORT_SYMBOL(objagg_stats_put);
  572. static struct objagg_hints_node *
  573. objagg_hints_node_create(struct objagg_hints *objagg_hints,
  574. struct objagg_obj *objagg_obj, size_t obj_size,
  575. struct objagg_hints_node *parent_hnode)
  576. {
  577. unsigned int user_count = objagg_obj->stats.user_count;
  578. struct objagg_hints_node *hnode;
  579. int err;
  580. hnode = kzalloc(sizeof(*hnode) + obj_size, GFP_KERNEL);
  581. if (!hnode)
  582. return ERR_PTR(-ENOMEM);
  583. memcpy(hnode->obj, &objagg_obj->obj, obj_size);
  584. hnode->stats_info.stats.user_count = user_count;
  585. hnode->stats_info.stats.delta_user_count = user_count;
  586. if (parent_hnode) {
  587. parent_hnode->stats_info.stats.delta_user_count += user_count;
  588. } else {
  589. hnode->root_id = objagg_hints->root_count++;
  590. hnode->stats_info.is_root = true;
  591. }
  592. hnode->stats_info.objagg_obj = objagg_obj;
  593. err = rhashtable_insert_fast(&objagg_hints->node_ht, &hnode->ht_node,
  594. objagg_hints->ht_params);
  595. if (err)
  596. goto err_ht_insert;
  597. list_add(&hnode->list, &objagg_hints->node_list);
  598. hnode->parent = parent_hnode;
  599. objagg_hints->node_count++;
  600. return hnode;
  601. err_ht_insert:
  602. kfree(hnode);
  603. return ERR_PTR(err);
  604. }
  605. static void objagg_hints_flush(struct objagg_hints *objagg_hints)
  606. {
  607. struct objagg_hints_node *hnode, *tmp;
  608. list_for_each_entry_safe(hnode, tmp, &objagg_hints->node_list, list) {
  609. list_del(&hnode->list);
  610. rhashtable_remove_fast(&objagg_hints->node_ht, &hnode->ht_node,
  611. objagg_hints->ht_params);
  612. kfree(hnode);
  613. }
  614. }
  615. struct objagg_tmp_node {
  616. struct objagg_obj *objagg_obj;
  617. bool crossed_out;
  618. };
  619. struct objagg_tmp_graph {
  620. struct objagg_tmp_node *nodes;
  621. unsigned long nodes_count;
  622. unsigned long *edges;
  623. };
  624. static int objagg_tmp_graph_edge_index(struct objagg_tmp_graph *graph,
  625. int parent_index, int index)
  626. {
  627. return index * graph->nodes_count + parent_index;
  628. }
  629. static void objagg_tmp_graph_edge_set(struct objagg_tmp_graph *graph,
  630. int parent_index, int index)
  631. {
  632. int edge_index = objagg_tmp_graph_edge_index(graph, index,
  633. parent_index);
  634. __set_bit(edge_index, graph->edges);
  635. }
  636. static bool objagg_tmp_graph_is_edge(struct objagg_tmp_graph *graph,
  637. int parent_index, int index)
  638. {
  639. int edge_index = objagg_tmp_graph_edge_index(graph, index,
  640. parent_index);
  641. return test_bit(edge_index, graph->edges);
  642. }
  643. static unsigned int objagg_tmp_graph_node_weight(struct objagg_tmp_graph *graph,
  644. unsigned int index)
  645. {
  646. struct objagg_tmp_node *node = &graph->nodes[index];
  647. unsigned int weight = node->objagg_obj->stats.user_count;
  648. int j;
  649. /* Node weight is sum of node users and all other nodes users
  650. * that this node can represent with delta.
  651. */
  652. for (j = 0; j < graph->nodes_count; j++) {
  653. if (!objagg_tmp_graph_is_edge(graph, index, j))
  654. continue;
  655. node = &graph->nodes[j];
  656. if (node->crossed_out)
  657. continue;
  658. weight += node->objagg_obj->stats.user_count;
  659. }
  660. return weight;
  661. }
  662. static int objagg_tmp_graph_node_max_weight(struct objagg_tmp_graph *graph)
  663. {
  664. struct objagg_tmp_node *node;
  665. unsigned int max_weight = 0;
  666. unsigned int weight;
  667. int max_index = -1;
  668. int i;
  669. for (i = 0; i < graph->nodes_count; i++) {
  670. node = &graph->nodes[i];
  671. if (node->crossed_out)
  672. continue;
  673. weight = objagg_tmp_graph_node_weight(graph, i);
  674. if (weight >= max_weight) {
  675. max_weight = weight;
  676. max_index = i;
  677. }
  678. }
  679. return max_index;
  680. }
  681. static struct objagg_tmp_graph *objagg_tmp_graph_create(struct objagg *objagg)
  682. {
  683. unsigned int nodes_count = objagg->obj_count;
  684. struct objagg_tmp_graph *graph;
  685. struct objagg_tmp_node *node;
  686. struct objagg_tmp_node *pnode;
  687. struct objagg_obj *objagg_obj;
  688. int i, j;
  689. graph = kzalloc_obj(*graph);
  690. if (!graph)
  691. return NULL;
  692. graph->nodes = kzalloc_objs(*graph->nodes, nodes_count);
  693. if (!graph->nodes)
  694. goto err_nodes_alloc;
  695. graph->nodes_count = nodes_count;
  696. graph->edges = bitmap_zalloc(nodes_count * nodes_count, GFP_KERNEL);
  697. if (!graph->edges)
  698. goto err_edges_alloc;
  699. i = 0;
  700. list_for_each_entry(objagg_obj, &objagg->obj_list, list) {
  701. node = &graph->nodes[i++];
  702. node->objagg_obj = objagg_obj;
  703. }
  704. /* Assemble a temporary graph. Insert edge X->Y in case Y can be
  705. * in delta of X.
  706. */
  707. for (i = 0; i < nodes_count; i++) {
  708. for (j = 0; j < nodes_count; j++) {
  709. if (i == j)
  710. continue;
  711. pnode = &graph->nodes[i];
  712. node = &graph->nodes[j];
  713. if (objagg->ops->delta_check(objagg->priv,
  714. pnode->objagg_obj->obj,
  715. node->objagg_obj->obj)) {
  716. objagg_tmp_graph_edge_set(graph, i, j);
  717. }
  718. }
  719. }
  720. return graph;
  721. err_edges_alloc:
  722. kfree(graph->nodes);
  723. err_nodes_alloc:
  724. kfree(graph);
  725. return NULL;
  726. }
  727. static void objagg_tmp_graph_destroy(struct objagg_tmp_graph *graph)
  728. {
  729. bitmap_free(graph->edges);
  730. kfree(graph->nodes);
  731. kfree(graph);
  732. }
  733. static int
  734. objagg_opt_simple_greedy_fillup_hints(struct objagg_hints *objagg_hints,
  735. struct objagg *objagg)
  736. {
  737. struct objagg_hints_node *hnode, *parent_hnode;
  738. struct objagg_tmp_graph *graph;
  739. struct objagg_tmp_node *node;
  740. int index;
  741. int j;
  742. int err;
  743. graph = objagg_tmp_graph_create(objagg);
  744. if (!graph)
  745. return -ENOMEM;
  746. /* Find the nodes from the ones that can accommodate most users
  747. * and cross them out of the graph. Save them to the hint list.
  748. */
  749. while ((index = objagg_tmp_graph_node_max_weight(graph)) != -1) {
  750. node = &graph->nodes[index];
  751. node->crossed_out = true;
  752. hnode = objagg_hints_node_create(objagg_hints,
  753. node->objagg_obj,
  754. objagg->ops->obj_size,
  755. NULL);
  756. if (IS_ERR(hnode)) {
  757. err = PTR_ERR(hnode);
  758. goto out;
  759. }
  760. parent_hnode = hnode;
  761. for (j = 0; j < graph->nodes_count; j++) {
  762. if (!objagg_tmp_graph_is_edge(graph, index, j))
  763. continue;
  764. node = &graph->nodes[j];
  765. if (node->crossed_out)
  766. continue;
  767. node->crossed_out = true;
  768. hnode = objagg_hints_node_create(objagg_hints,
  769. node->objagg_obj,
  770. objagg->ops->obj_size,
  771. parent_hnode);
  772. if (IS_ERR(hnode)) {
  773. err = PTR_ERR(hnode);
  774. goto out;
  775. }
  776. }
  777. }
  778. err = 0;
  779. out:
  780. objagg_tmp_graph_destroy(graph);
  781. return err;
  782. }
  783. struct objagg_opt_algo {
  784. int (*fillup_hints)(struct objagg_hints *objagg_hints,
  785. struct objagg *objagg);
  786. };
  787. static const struct objagg_opt_algo objagg_opt_simple_greedy = {
  788. .fillup_hints = objagg_opt_simple_greedy_fillup_hints,
  789. };
  790. static const struct objagg_opt_algo *objagg_opt_algos[] = {
  791. [OBJAGG_OPT_ALGO_SIMPLE_GREEDY] = &objagg_opt_simple_greedy,
  792. };
  793. /**
  794. * objagg_hints_get - obtains hints instance
  795. * @objagg: objagg instance
  796. * @opt_algo_type: type of hints finding algorithm
  797. *
  798. * Note: all locking must be provided by the caller.
  799. *
  800. * According to the algo type, the existing objects of objagg instance
  801. * are going to be went-through to assemble an optimal tree. We call this
  802. * tree hints. These hints can be later on used for creation of
  803. * a new objagg instance. There, the future object creations are going
  804. * to be consulted with these hints in order to find out, where exactly
  805. * the new object should be put as a root or delta.
  806. *
  807. * Returns a pointer to hints instance in case of success,
  808. * otherwise it returns pointer error using ERR_PTR macro.
  809. */
  810. struct objagg_hints *objagg_hints_get(struct objagg *objagg,
  811. enum objagg_opt_algo_type opt_algo_type)
  812. {
  813. const struct objagg_opt_algo *algo = objagg_opt_algos[opt_algo_type];
  814. struct objagg_hints *objagg_hints;
  815. int err;
  816. objagg_hints = kzalloc_obj(*objagg_hints);
  817. if (!objagg_hints)
  818. return ERR_PTR(-ENOMEM);
  819. objagg_hints->ops = objagg->ops;
  820. objagg_hints->refcount = 1;
  821. INIT_LIST_HEAD(&objagg_hints->node_list);
  822. objagg_hints->ht_params.key_len = objagg->ops->obj_size;
  823. objagg_hints->ht_params.key_offset =
  824. offsetof(struct objagg_hints_node, obj);
  825. objagg_hints->ht_params.head_offset =
  826. offsetof(struct objagg_hints_node, ht_node);
  827. err = rhashtable_init(&objagg_hints->node_ht, &objagg_hints->ht_params);
  828. if (err)
  829. goto err_rhashtable_init;
  830. err = algo->fillup_hints(objagg_hints, objagg);
  831. if (err)
  832. goto err_fillup_hints;
  833. if (WARN_ON(objagg_hints->node_count != objagg->obj_count)) {
  834. err = -EINVAL;
  835. goto err_node_count_check;
  836. }
  837. return objagg_hints;
  838. err_node_count_check:
  839. err_fillup_hints:
  840. objagg_hints_flush(objagg_hints);
  841. rhashtable_destroy(&objagg_hints->node_ht);
  842. err_rhashtable_init:
  843. kfree(objagg_hints);
  844. return ERR_PTR(err);
  845. }
  846. EXPORT_SYMBOL(objagg_hints_get);
  847. /**
  848. * objagg_hints_put - puts hints instance
  849. * @objagg_hints: objagg hints instance
  850. *
  851. * Note: all locking must be provided by the caller.
  852. */
  853. void objagg_hints_put(struct objagg_hints *objagg_hints)
  854. {
  855. if (--objagg_hints->refcount)
  856. return;
  857. objagg_hints_flush(objagg_hints);
  858. rhashtable_destroy(&objagg_hints->node_ht);
  859. kfree(objagg_hints);
  860. }
  861. EXPORT_SYMBOL(objagg_hints_put);
  862. /**
  863. * objagg_hints_stats_get - obtains stats of the hints instance
  864. * @objagg_hints: hints instance
  865. *
  866. * Note: all locking must be provided by the caller.
  867. *
  868. * The returned structure contains statistics of all objects
  869. * currently in use, ordered by following rules:
  870. * 1) Root objects are always on lower indexes than the rest.
  871. * 2) Objects with higher delta user count are always on lower
  872. * indexes.
  873. * 3) In case multiple objects have the same delta user count,
  874. * the objects are ordered by user count.
  875. *
  876. * Returns a pointer to stats instance in case of success,
  877. * otherwise it returns pointer error using ERR_PTR macro.
  878. */
  879. const struct objagg_stats *
  880. objagg_hints_stats_get(struct objagg_hints *objagg_hints)
  881. {
  882. struct objagg_stats *objagg_stats;
  883. struct objagg_hints_node *hnode;
  884. int i;
  885. objagg_stats = kzalloc_flex(*objagg_stats, stats_info,
  886. objagg_hints->node_count);
  887. if (!objagg_stats)
  888. return ERR_PTR(-ENOMEM);
  889. i = 0;
  890. list_for_each_entry(hnode, &objagg_hints->node_list, list) {
  891. memcpy(&objagg_stats->stats_info[i], &hnode->stats_info,
  892. sizeof(objagg_stats->stats_info[0]));
  893. if (objagg_stats->stats_info[i].is_root)
  894. objagg_stats->root_count++;
  895. i++;
  896. }
  897. objagg_stats->stats_info_count = i;
  898. sort(objagg_stats->stats_info, objagg_stats->stats_info_count,
  899. sizeof(struct objagg_obj_stats_info),
  900. objagg_stats_info_sort_cmp_func, NULL);
  901. return objagg_stats;
  902. }
  903. EXPORT_SYMBOL(objagg_hints_stats_get);
  904. MODULE_LICENSE("Dual BSD/GPL");
  905. MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>");
  906. MODULE_DESCRIPTION("Object aggregation manager");