You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1021 lines
25 KiB

  1. // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2. /* Copyright (c) 2018 Mellanox Technologies. All rights reserved */
  3. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  4. #include <linux/kernel.h>
  5. #include <linux/module.h>
  6. #include <linux/slab.h>
  7. #include <linux/random.h>
  8. #include <linux/objagg.h>
  9. struct tokey {
  10. unsigned int id;
  11. };
  12. #define NUM_KEYS 32
  13. static int key_id_index(unsigned int key_id)
  14. {
  15. if (key_id >= NUM_KEYS) {
  16. WARN_ON(1);
  17. return 0;
  18. }
  19. return key_id;
  20. }
  21. #define BUF_LEN 128
  22. struct world {
  23. unsigned int root_count;
  24. unsigned int delta_count;
  25. char next_root_buf[BUF_LEN];
  26. struct objagg_obj *objagg_objs[NUM_KEYS];
  27. unsigned int key_refs[NUM_KEYS];
  28. };
  29. struct root {
  30. struct tokey key;
  31. char buf[BUF_LEN];
  32. };
  33. struct delta {
  34. unsigned int key_id_diff;
  35. };
  36. static struct objagg_obj *world_obj_get(struct world *world,
  37. struct objagg *objagg,
  38. unsigned int key_id)
  39. {
  40. struct objagg_obj *objagg_obj;
  41. struct tokey key;
  42. int err;
  43. key.id = key_id;
  44. objagg_obj = objagg_obj_get(objagg, &key);
  45. if (IS_ERR(objagg_obj)) {
  46. pr_err("Key %u: Failed to get object.\n", key_id);
  47. return objagg_obj;
  48. }
  49. if (!world->key_refs[key_id_index(key_id)]) {
  50. world->objagg_objs[key_id_index(key_id)] = objagg_obj;
  51. } else if (world->objagg_objs[key_id_index(key_id)] != objagg_obj) {
  52. pr_err("Key %u: God another object for the same key.\n",
  53. key_id);
  54. err = -EINVAL;
  55. goto err_key_id_check;
  56. }
  57. world->key_refs[key_id_index(key_id)]++;
  58. return objagg_obj;
  59. err_key_id_check:
  60. objagg_obj_put(objagg, objagg_obj);
  61. return ERR_PTR(err);
  62. }
  63. static void world_obj_put(struct world *world, struct objagg *objagg,
  64. unsigned int key_id)
  65. {
  66. struct objagg_obj *objagg_obj;
  67. if (!world->key_refs[key_id_index(key_id)])
  68. return;
  69. objagg_obj = world->objagg_objs[key_id_index(key_id)];
  70. objagg_obj_put(objagg, objagg_obj);
  71. world->key_refs[key_id_index(key_id)]--;
  72. }
  73. #define MAX_KEY_ID_DIFF 5
  74. static bool delta_check(void *priv, const void *parent_obj, const void *obj)
  75. {
  76. const struct tokey *parent_key = parent_obj;
  77. const struct tokey *key = obj;
  78. int diff = key->id - parent_key->id;
  79. return diff >= 0 && diff <= MAX_KEY_ID_DIFF;
  80. }
  81. static void *delta_create(void *priv, void *parent_obj, void *obj)
  82. {
  83. struct tokey *parent_key = parent_obj;
  84. struct world *world = priv;
  85. struct tokey *key = obj;
  86. int diff = key->id - parent_key->id;
  87. struct delta *delta;
  88. if (!delta_check(priv, parent_obj, obj))
  89. return ERR_PTR(-EINVAL);
  90. delta = kzalloc(sizeof(*delta), GFP_KERNEL);
  91. if (!delta)
  92. return ERR_PTR(-ENOMEM);
  93. delta->key_id_diff = diff;
  94. world->delta_count++;
  95. return delta;
  96. }
  97. static void delta_destroy(void *priv, void *delta_priv)
  98. {
  99. struct delta *delta = delta_priv;
  100. struct world *world = priv;
  101. world->delta_count--;
  102. kfree(delta);
  103. }
  104. static void *root_create(void *priv, void *obj, unsigned int id)
  105. {
  106. struct world *world = priv;
  107. struct tokey *key = obj;
  108. struct root *root;
  109. root = kzalloc(sizeof(*root), GFP_KERNEL);
  110. if (!root)
  111. return ERR_PTR(-ENOMEM);
  112. memcpy(&root->key, key, sizeof(root->key));
  113. memcpy(root->buf, world->next_root_buf, sizeof(root->buf));
  114. world->root_count++;
  115. return root;
  116. }
  117. static void root_destroy(void *priv, void *root_priv)
  118. {
  119. struct root *root = root_priv;
  120. struct world *world = priv;
  121. world->root_count--;
  122. kfree(root);
  123. }
  124. static int test_nodelta_obj_get(struct world *world, struct objagg *objagg,
  125. unsigned int key_id, bool should_create_root)
  126. {
  127. unsigned int orig_root_count = world->root_count;
  128. struct objagg_obj *objagg_obj;
  129. const struct root *root;
  130. int err;
  131. if (should_create_root)
  132. prandom_bytes(world->next_root_buf,
  133. sizeof(world->next_root_buf));
  134. objagg_obj = world_obj_get(world, objagg, key_id);
  135. if (IS_ERR(objagg_obj)) {
  136. pr_err("Key %u: Failed to get object.\n", key_id);
  137. return PTR_ERR(objagg_obj);
  138. }
  139. if (should_create_root) {
  140. if (world->root_count != orig_root_count + 1) {
  141. pr_err("Key %u: Root was not created\n", key_id);
  142. err = -EINVAL;
  143. goto err_check_root_count;
  144. }
  145. } else {
  146. if (world->root_count != orig_root_count) {
  147. pr_err("Key %u: Root was incorrectly created\n",
  148. key_id);
  149. err = -EINVAL;
  150. goto err_check_root_count;
  151. }
  152. }
  153. root = objagg_obj_root_priv(objagg_obj);
  154. if (root->key.id != key_id) {
  155. pr_err("Key %u: Root has unexpected key id\n", key_id);
  156. err = -EINVAL;
  157. goto err_check_key_id;
  158. }
  159. if (should_create_root &&
  160. memcmp(world->next_root_buf, root->buf, sizeof(root->buf))) {
  161. pr_err("Key %u: Buffer does not match the expected content\n",
  162. key_id);
  163. err = -EINVAL;
  164. goto err_check_buf;
  165. }
  166. return 0;
  167. err_check_buf:
  168. err_check_key_id:
  169. err_check_root_count:
  170. objagg_obj_put(objagg, objagg_obj);
  171. return err;
  172. }
  173. static int test_nodelta_obj_put(struct world *world, struct objagg *objagg,
  174. unsigned int key_id, bool should_destroy_root)
  175. {
  176. unsigned int orig_root_count = world->root_count;
  177. world_obj_put(world, objagg, key_id);
  178. if (should_destroy_root) {
  179. if (world->root_count != orig_root_count - 1) {
  180. pr_err("Key %u: Root was not destroyed\n", key_id);
  181. return -EINVAL;
  182. }
  183. } else {
  184. if (world->root_count != orig_root_count) {
  185. pr_err("Key %u: Root was incorrectly destroyed\n",
  186. key_id);
  187. return -EINVAL;
  188. }
  189. }
  190. return 0;
  191. }
  192. static int check_stats_zero(struct objagg *objagg)
  193. {
  194. const struct objagg_stats *stats;
  195. int err = 0;
  196. stats = objagg_stats_get(objagg);
  197. if (IS_ERR(stats))
  198. return PTR_ERR(stats);
  199. if (stats->stats_info_count != 0) {
  200. pr_err("Stats: Object count is not zero while it should be\n");
  201. err = -EINVAL;
  202. }
  203. objagg_stats_put(stats);
  204. return err;
  205. }
  206. static int check_stats_nodelta(struct objagg *objagg)
  207. {
  208. const struct objagg_stats *stats;
  209. int i;
  210. int err;
  211. stats = objagg_stats_get(objagg);
  212. if (IS_ERR(stats))
  213. return PTR_ERR(stats);
  214. if (stats->stats_info_count != NUM_KEYS) {
  215. pr_err("Stats: Unexpected object count (%u expected, %u returned)\n",
  216. NUM_KEYS, stats->stats_info_count);
  217. err = -EINVAL;
  218. goto stats_put;
  219. }
  220. for (i = 0; i < stats->stats_info_count; i++) {
  221. if (stats->stats_info[i].stats.user_count != 2) {
  222. pr_err("Stats: incorrect user count\n");
  223. err = -EINVAL;
  224. goto stats_put;
  225. }
  226. if (stats->stats_info[i].stats.delta_user_count != 2) {
  227. pr_err("Stats: incorrect delta user count\n");
  228. err = -EINVAL;
  229. goto stats_put;
  230. }
  231. }
  232. err = 0;
  233. stats_put:
  234. objagg_stats_put(stats);
  235. return err;
  236. }
  237. static bool delta_check_dummy(void *priv, const void *parent_obj,
  238. const void *obj)
  239. {
  240. return false;
  241. }
  242. static void *delta_create_dummy(void *priv, void *parent_obj, void *obj)
  243. {
  244. return ERR_PTR(-EOPNOTSUPP);
  245. }
  246. static void delta_destroy_dummy(void *priv, void *delta_priv)
  247. {
  248. }
  249. static const struct objagg_ops nodelta_ops = {
  250. .obj_size = sizeof(struct tokey),
  251. .delta_check = delta_check_dummy,
  252. .delta_create = delta_create_dummy,
  253. .delta_destroy = delta_destroy_dummy,
  254. .root_create = root_create,
  255. .root_destroy = root_destroy,
  256. };
  257. static int test_nodelta(void)
  258. {
  259. struct world world = {};
  260. struct objagg *objagg;
  261. int i;
  262. int err;
  263. objagg = objagg_create(&nodelta_ops, NULL, &world);
  264. if (IS_ERR(objagg))
  265. return PTR_ERR(objagg);
  266. err = check_stats_zero(objagg);
  267. if (err)
  268. goto err_stats_first_zero;
  269. /* First round of gets, the root objects should be created */
  270. for (i = 0; i < NUM_KEYS; i++) {
  271. err = test_nodelta_obj_get(&world, objagg, i, true);
  272. if (err)
  273. goto err_obj_first_get;
  274. }
  275. /* Do the second round of gets, all roots are already created,
  276. * make sure that no new root is created
  277. */
  278. for (i = 0; i < NUM_KEYS; i++) {
  279. err = test_nodelta_obj_get(&world, objagg, i, false);
  280. if (err)
  281. goto err_obj_second_get;
  282. }
  283. err = check_stats_nodelta(objagg);
  284. if (err)
  285. goto err_stats_nodelta;
  286. for (i = NUM_KEYS - 1; i >= 0; i--) {
  287. err = test_nodelta_obj_put(&world, objagg, i, false);
  288. if (err)
  289. goto err_obj_first_put;
  290. }
  291. for (i = NUM_KEYS - 1; i >= 0; i--) {
  292. err = test_nodelta_obj_put(&world, objagg, i, true);
  293. if (err)
  294. goto err_obj_second_put;
  295. }
  296. err = check_stats_zero(objagg);
  297. if (err)
  298. goto err_stats_second_zero;
  299. objagg_destroy(objagg);
  300. return 0;
  301. err_stats_nodelta:
  302. err_obj_first_put:
  303. err_obj_second_get:
  304. for (i--; i >= 0; i--)
  305. world_obj_put(&world, objagg, i);
  306. i = NUM_KEYS;
  307. err_obj_first_get:
  308. err_obj_second_put:
  309. for (i--; i >= 0; i--)
  310. world_obj_put(&world, objagg, i);
  311. err_stats_first_zero:
  312. err_stats_second_zero:
  313. objagg_destroy(objagg);
  314. return err;
  315. }
  316. static const struct objagg_ops delta_ops = {
  317. .obj_size = sizeof(struct tokey),
  318. .delta_check = delta_check,
  319. .delta_create = delta_create,
  320. .delta_destroy = delta_destroy,
  321. .root_create = root_create,
  322. .root_destroy = root_destroy,
  323. };
  324. enum action {
  325. ACTION_GET,
  326. ACTION_PUT,
  327. };
  328. enum expect_delta {
  329. EXPECT_DELTA_SAME,
  330. EXPECT_DELTA_INC,
  331. EXPECT_DELTA_DEC,
  332. };
  333. enum expect_root {
  334. EXPECT_ROOT_SAME,
  335. EXPECT_ROOT_INC,
  336. EXPECT_ROOT_DEC,
  337. };
  338. struct expect_stats_info {
  339. struct objagg_obj_stats stats;
  340. bool is_root;
  341. unsigned int key_id;
  342. };
  343. struct expect_stats {
  344. unsigned int info_count;
  345. struct expect_stats_info info[NUM_KEYS];
  346. };
  347. struct action_item {
  348. unsigned int key_id;
  349. enum action action;
  350. enum expect_delta expect_delta;
  351. enum expect_root expect_root;
  352. struct expect_stats expect_stats;
  353. };
  354. #define EXPECT_STATS(count, ...) \
  355. { \
  356. .info_count = count, \
  357. .info = { __VA_ARGS__ } \
  358. }
  359. #define ROOT(key_id, user_count, delta_user_count) \
  360. {{user_count, delta_user_count}, true, key_id}
  361. #define DELTA(key_id, user_count) \
  362. {{user_count, user_count}, false, key_id}
  363. static const struct action_item action_items[] = {
  364. {
  365. 1, ACTION_GET, EXPECT_DELTA_SAME, EXPECT_ROOT_INC,
  366. EXPECT_STATS(1, ROOT(1, 1, 1)),
  367. }, /* r: 1 d: */
  368. {
  369. 7, ACTION_GET, EXPECT_DELTA_SAME, EXPECT_ROOT_INC,
  370. EXPECT_STATS(2, ROOT(1, 1, 1), ROOT(7, 1, 1)),
  371. }, /* r: 1, 7 d: */
  372. {
  373. 3, ACTION_GET, EXPECT_DELTA_INC, EXPECT_ROOT_SAME,
  374. EXPECT_STATS(3, ROOT(1, 1, 2), ROOT(7, 1, 1),
  375. DELTA(3, 1)),
  376. }, /* r: 1, 7 d: 3^1 */
  377. {
  378. 5, ACTION_GET, EXPECT_DELTA_INC, EXPECT_ROOT_SAME,
  379. EXPECT_STATS(4, ROOT(1, 1, 3), ROOT(7, 1, 1),
  380. DELTA(3, 1), DELTA(5, 1)),
  381. }, /* r: 1, 7 d: 3^1, 5^1 */
  382. {
  383. 3, ACTION_GET, EXPECT_DELTA_SAME, EXPECT_ROOT_SAME,
  384. EXPECT_STATS(4, ROOT(1, 1, 4), ROOT(7, 1, 1),
  385. DELTA(3, 2), DELTA(5, 1)),
  386. }, /* r: 1, 7 d: 3^1, 3^1, 5^1 */
  387. {
  388. 1, ACTION_GET, EXPECT_DELTA_SAME, EXPECT_ROOT_SAME,
  389. EXPECT_STATS(4, ROOT(1, 2, 5), ROOT(7, 1, 1),
  390. DELTA(3, 2), DELTA(5, 1)),
  391. }, /* r: 1, 1, 7 d: 3^1, 3^1, 5^1 */
  392. {
  393. 30, ACTION_GET, EXPECT_DELTA_SAME, EXPECT_ROOT_INC,
  394. EXPECT_STATS(5, ROOT(1, 2, 5), ROOT(7, 1, 1), ROOT(30, 1, 1),
  395. DELTA(3, 2), DELTA(5, 1)),
  396. }, /* r: 1, 1, 7, 30 d: 3^1, 3^1, 5^1 */
  397. {
  398. 8, ACTION_GET, EXPECT_DELTA_INC, EXPECT_ROOT_SAME,
  399. EXPECT_STATS(6, ROOT(1, 2, 5), ROOT(7, 1, 2), ROOT(30, 1, 1),
  400. DELTA(3, 2), DELTA(5, 1), DELTA(8, 1)),
  401. }, /* r: 1, 1, 7, 30 d: 3^1, 3^1, 5^1, 8^7 */
  402. {
  403. 8, ACTION_GET, EXPECT_DELTA_SAME, EXPECT_ROOT_SAME,
  404. EXPECT_STATS(6, ROOT(1, 2, 5), ROOT(7, 1, 3), ROOT(30, 1, 1),
  405. DELTA(3, 2), DELTA(8, 2), DELTA(5, 1)),
  406. }, /* r: 1, 1, 7, 30 d: 3^1, 3^1, 5^1, 8^7, 8^7 */
  407. {
  408. 3, ACTION_PUT, EXPECT_DELTA_SAME, EXPECT_ROOT_SAME,
  409. EXPECT_STATS(6, ROOT(1, 2, 4), ROOT(7, 1, 3), ROOT(30, 1, 1),
  410. DELTA(8, 2), DELTA(3, 1), DELTA(5, 1)),
  411. }, /* r: 1, 1, 7, 30 d: 3^1, 5^1, 8^7, 8^7 */
  412. {
  413. 3, ACTION_PUT, EXPECT_DELTA_DEC, EXPECT_ROOT_SAME,
  414. EXPECT_STATS(5, ROOT(1, 2, 3), ROOT(7, 1, 3), ROOT(30, 1, 1),
  415. DELTA(8, 2), DELTA(5, 1)),
  416. }, /* r: 1, 1, 7, 30 d: 5^1, 8^7, 8^7 */
  417. {
  418. 1, ACTION_PUT, EXPECT_DELTA_SAME, EXPECT_ROOT_SAME,
  419. EXPECT_STATS(5, ROOT(7, 1, 3), ROOT(1, 1, 2), ROOT(30, 1, 1),
  420. DELTA(8, 2), DELTA(5, 1)),
  421. }, /* r: 1, 7, 30 d: 5^1, 8^7, 8^7 */
  422. {
  423. 1, ACTION_PUT, EXPECT_DELTA_SAME, EXPECT_ROOT_SAME,
  424. EXPECT_STATS(5, ROOT(7, 1, 3), ROOT(30, 1, 1), ROOT(1, 0, 1),
  425. DELTA(8, 2), DELTA(5, 1)),
  426. }, /* r: 7, 30 d: 5^1, 8^7, 8^7 */
  427. {
  428. 5, ACTION_PUT, EXPECT_DELTA_DEC, EXPECT_ROOT_DEC,
  429. EXPECT_STATS(3, ROOT(7, 1, 3), ROOT(30, 1, 1),
  430. DELTA(8, 2)),
  431. }, /* r: 7, 30 d: 8^7, 8^7 */
  432. {
  433. 5, ACTION_GET, EXPECT_DELTA_SAME, EXPECT_ROOT_INC,
  434. EXPECT_STATS(4, ROOT(7, 1, 3), ROOT(30, 1, 1), ROOT(5, 1, 1),
  435. DELTA(8, 2)),
  436. }, /* r: 7, 30, 5 d: 8^7, 8^7 */
  437. {
  438. 6, ACTION_GET, EXPECT_DELTA_INC, EXPECT_ROOT_SAME,
  439. EXPECT_STATS(5, ROOT(7, 1, 3), ROOT(5, 1, 2), ROOT(30, 1, 1),
  440. DELTA(8, 2), DELTA(6, 1)),
  441. }, /* r: 7, 30, 5 d: 8^7, 8^7, 6^5 */
  442. {
  443. 8, ACTION_GET, EXPECT_DELTA_SAME, EXPECT_ROOT_SAME,
  444. EXPECT_STATS(5, ROOT(7, 1, 4), ROOT(5, 1, 2), ROOT(30, 1, 1),
  445. DELTA(8, 3), DELTA(6, 1)),
  446. }, /* r: 7, 30, 5 d: 8^7, 8^7, 8^7, 6^5 */
  447. {
  448. 8, ACTION_PUT, EXPECT_DELTA_SAME, EXPECT_ROOT_SAME,
  449. EXPECT_STATS(5, ROOT(7, 1, 3), ROOT(5, 1, 2), ROOT(30, 1, 1),
  450. DELTA(8, 2), DELTA(6, 1)),
  451. }, /* r: 7, 30, 5 d: 8^7, 8^7, 6^5 */
  452. {
  453. 8, ACTION_PUT, EXPECT_DELTA_SAME, EXPECT_ROOT_SAME,
  454. EXPECT_STATS(5, ROOT(7, 1, 2), ROOT(5, 1, 2), ROOT(30, 1, 1),
  455. DELTA(8, 1), DELTA(6, 1)),
  456. }, /* r: 7, 30, 5 d: 8^7, 6^5 */
  457. {
  458. 8, ACTION_PUT, EXPECT_DELTA_DEC, EXPECT_ROOT_SAME,
  459. EXPECT_STATS(4, ROOT(5, 1, 2), ROOT(7, 1, 1), ROOT(30, 1, 1),
  460. DELTA(6, 1)),
  461. }, /* r: 7, 30, 5 d: 6^5 */
  462. {
  463. 8, ACTION_GET, EXPECT_DELTA_INC, EXPECT_ROOT_SAME,
  464. EXPECT_STATS(5, ROOT(5, 1, 3), ROOT(7, 1, 1), ROOT(30, 1, 1),
  465. DELTA(6, 1), DELTA(8, 1)),
  466. }, /* r: 7, 30, 5 d: 6^5, 8^5 */
  467. {
  468. 7, ACTION_PUT, EXPECT_DELTA_SAME, EXPECT_ROOT_DEC,
  469. EXPECT_STATS(4, ROOT(5, 1, 3), ROOT(30, 1, 1),
  470. DELTA(6, 1), DELTA(8, 1)),
  471. }, /* r: 30, 5 d: 6^5, 8^5 */
  472. {
  473. 30, ACTION_PUT, EXPECT_DELTA_SAME, EXPECT_ROOT_DEC,
  474. EXPECT_STATS(3, ROOT(5, 1, 3),
  475. DELTA(6, 1), DELTA(8, 1)),
  476. }, /* r: 5 d: 6^5, 8^5 */
  477. {
  478. 5, ACTION_PUT, EXPECT_DELTA_SAME, EXPECT_ROOT_SAME,
  479. EXPECT_STATS(3, ROOT(5, 0, 2),
  480. DELTA(6, 1), DELTA(8, 1)),
  481. }, /* r: d: 6^5, 8^5 */
  482. {
  483. 6, ACTION_PUT, EXPECT_DELTA_DEC, EXPECT_ROOT_SAME,
  484. EXPECT_STATS(2, ROOT(5, 0, 1),
  485. DELTA(8, 1)),
  486. }, /* r: d: 6^5 */
  487. {
  488. 8, ACTION_PUT, EXPECT_DELTA_DEC, EXPECT_ROOT_DEC,
  489. EXPECT_STATS(0, ),
  490. }, /* r: d: */
  491. };
  492. static int check_expect(struct world *world,
  493. const struct action_item *action_item,
  494. unsigned int orig_delta_count,
  495. unsigned int orig_root_count)
  496. {
  497. unsigned int key_id = action_item->key_id;
  498. switch (action_item->expect_delta) {
  499. case EXPECT_DELTA_SAME:
  500. if (orig_delta_count != world->delta_count) {
  501. pr_err("Key %u: Delta count changed while expected to remain the same.\n",
  502. key_id);
  503. return -EINVAL;
  504. }
  505. break;
  506. case EXPECT_DELTA_INC:
  507. if (WARN_ON(action_item->action == ACTION_PUT))
  508. return -EINVAL;
  509. if (orig_delta_count + 1 != world->delta_count) {
  510. pr_err("Key %u: Delta count was not incremented.\n",
  511. key_id);
  512. return -EINVAL;
  513. }
  514. break;
  515. case EXPECT_DELTA_DEC:
  516. if (WARN_ON(action_item->action == ACTION_GET))
  517. return -EINVAL;
  518. if (orig_delta_count - 1 != world->delta_count) {
  519. pr_err("Key %u: Delta count was not decremented.\n",
  520. key_id);
  521. return -EINVAL;
  522. }
  523. break;
  524. }
  525. switch (action_item->expect_root) {
  526. case EXPECT_ROOT_SAME:
  527. if (orig_root_count != world->root_count) {
  528. pr_err("Key %u: Root count changed while expected to remain the same.\n",
  529. key_id);
  530. return -EINVAL;
  531. }
  532. break;
  533. case EXPECT_ROOT_INC:
  534. if (WARN_ON(action_item->action == ACTION_PUT))
  535. return -EINVAL;
  536. if (orig_root_count + 1 != world->root_count) {
  537. pr_err("Key %u: Root count was not incremented.\n",
  538. key_id);
  539. return -EINVAL;
  540. }
  541. break;
  542. case EXPECT_ROOT_DEC:
  543. if (WARN_ON(action_item->action == ACTION_GET))
  544. return -EINVAL;
  545. if (orig_root_count - 1 != world->root_count) {
  546. pr_err("Key %u: Root count was not decremented.\n",
  547. key_id);
  548. return -EINVAL;
  549. }
  550. }
  551. return 0;
  552. }
  553. static unsigned int obj_to_key_id(struct objagg_obj *objagg_obj)
  554. {
  555. const struct tokey *root_key;
  556. const struct delta *delta;
  557. unsigned int key_id;
  558. root_key = objagg_obj_root_priv(objagg_obj);
  559. key_id = root_key->id;
  560. delta = objagg_obj_delta_priv(objagg_obj);
  561. if (delta)
  562. key_id += delta->key_id_diff;
  563. return key_id;
  564. }
  565. static int
  566. check_expect_stats_nums(const struct objagg_obj_stats_info *stats_info,
  567. const struct expect_stats_info *expect_stats_info,
  568. const char **errmsg)
  569. {
  570. if (stats_info->is_root != expect_stats_info->is_root) {
  571. if (errmsg)
  572. *errmsg = "Incorrect root/delta indication";
  573. return -EINVAL;
  574. }
  575. if (stats_info->stats.user_count !=
  576. expect_stats_info->stats.user_count) {
  577. if (errmsg)
  578. *errmsg = "Incorrect user count";
  579. return -EINVAL;
  580. }
  581. if (stats_info->stats.delta_user_count !=
  582. expect_stats_info->stats.delta_user_count) {
  583. if (errmsg)
  584. *errmsg = "Incorrect delta user count";
  585. return -EINVAL;
  586. }
  587. return 0;
  588. }
  589. static int
  590. check_expect_stats_key_id(const struct objagg_obj_stats_info *stats_info,
  591. const struct expect_stats_info *expect_stats_info,
  592. const char **errmsg)
  593. {
  594. if (obj_to_key_id(stats_info->objagg_obj) !=
  595. expect_stats_info->key_id) {
  596. if (errmsg)
  597. *errmsg = "incorrect key id";
  598. return -EINVAL;
  599. }
  600. return 0;
  601. }
  602. static int check_expect_stats_neigh(const struct objagg_stats *stats,
  603. const struct expect_stats *expect_stats,
  604. int pos)
  605. {
  606. int i;
  607. int err;
  608. for (i = pos - 1; i >= 0; i--) {
  609. err = check_expect_stats_nums(&stats->stats_info[i],
  610. &expect_stats->info[pos], NULL);
  611. if (err)
  612. break;
  613. err = check_expect_stats_key_id(&stats->stats_info[i],
  614. &expect_stats->info[pos], NULL);
  615. if (!err)
  616. return 0;
  617. }
  618. for (i = pos + 1; i < stats->stats_info_count; i++) {
  619. err = check_expect_stats_nums(&stats->stats_info[i],
  620. &expect_stats->info[pos], NULL);
  621. if (err)
  622. break;
  623. err = check_expect_stats_key_id(&stats->stats_info[i],
  624. &expect_stats->info[pos], NULL);
  625. if (!err)
  626. return 0;
  627. }
  628. return -EINVAL;
  629. }
  630. static int __check_expect_stats(const struct objagg_stats *stats,
  631. const struct expect_stats *expect_stats,
  632. const char **errmsg)
  633. {
  634. int i;
  635. int err;
  636. if (stats->stats_info_count != expect_stats->info_count) {
  637. *errmsg = "Unexpected object count";
  638. return -EINVAL;
  639. }
  640. for (i = 0; i < stats->stats_info_count; i++) {
  641. err = check_expect_stats_nums(&stats->stats_info[i],
  642. &expect_stats->info[i], errmsg);
  643. if (err)
  644. return err;
  645. err = check_expect_stats_key_id(&stats->stats_info[i],
  646. &expect_stats->info[i], errmsg);
  647. if (err) {
  648. /* It is possible that one of the neighbor stats with
  649. * same numbers have the correct key id, so check it
  650. */
  651. err = check_expect_stats_neigh(stats, expect_stats, i);
  652. if (err)
  653. return err;
  654. }
  655. }
  656. return 0;
  657. }
  658. static int check_expect_stats(struct objagg *objagg,
  659. const struct expect_stats *expect_stats,
  660. const char **errmsg)
  661. {
  662. const struct objagg_stats *stats;
  663. int err;
  664. stats = objagg_stats_get(objagg);
  665. if (IS_ERR(stats)) {
  666. *errmsg = "objagg_stats_get() failed.";
  667. return PTR_ERR(stats);
  668. }
  669. err = __check_expect_stats(stats, expect_stats, errmsg);
  670. objagg_stats_put(stats);
  671. return err;
  672. }
  673. static int test_delta_action_item(struct world *world,
  674. struct objagg *objagg,
  675. const struct action_item *action_item,
  676. bool inverse)
  677. {
  678. unsigned int orig_delta_count = world->delta_count;
  679. unsigned int orig_root_count = world->root_count;
  680. unsigned int key_id = action_item->key_id;
  681. enum action action = action_item->action;
  682. struct objagg_obj *objagg_obj;
  683. const char *errmsg;
  684. int err;
  685. if (inverse)
  686. action = action == ACTION_GET ? ACTION_PUT : ACTION_GET;
  687. switch (action) {
  688. case ACTION_GET:
  689. objagg_obj = world_obj_get(world, objagg, key_id);
  690. if (IS_ERR(objagg_obj))
  691. return PTR_ERR(objagg_obj);
  692. break;
  693. case ACTION_PUT:
  694. world_obj_put(world, objagg, key_id);
  695. break;
  696. }
  697. if (inverse)
  698. return 0;
  699. err = check_expect(world, action_item,
  700. orig_delta_count, orig_root_count);
  701. if (err)
  702. goto errout;
  703. err = check_expect_stats(objagg, &action_item->expect_stats, &errmsg);
  704. if (err) {
  705. pr_err("Key %u: Stats: %s\n", action_item->key_id, errmsg);
  706. goto errout;
  707. }
  708. return 0;
  709. errout:
  710. /* This can only happen when action is not inversed.
  711. * So in case of an error, cleanup by doing inverse action.
  712. */
  713. test_delta_action_item(world, objagg, action_item, true);
  714. return err;
  715. }
  716. static int test_delta(void)
  717. {
  718. struct world world = {};
  719. struct objagg *objagg;
  720. int i;
  721. int err;
  722. objagg = objagg_create(&delta_ops, NULL, &world);
  723. if (IS_ERR(objagg))
  724. return PTR_ERR(objagg);
  725. for (i = 0; i < ARRAY_SIZE(action_items); i++) {
  726. err = test_delta_action_item(&world, objagg,
  727. &action_items[i], false);
  728. if (err)
  729. goto err_do_action_item;
  730. }
  731. objagg_destroy(objagg);
  732. return 0;
  733. err_do_action_item:
  734. for (i--; i >= 0; i--)
  735. test_delta_action_item(&world, objagg, &action_items[i], true);
  736. objagg_destroy(objagg);
  737. return err;
  738. }
  739. struct hints_case {
  740. const unsigned int *key_ids;
  741. size_t key_ids_count;
  742. struct expect_stats expect_stats;
  743. struct expect_stats expect_stats_hints;
  744. };
  745. static const unsigned int hints_case_key_ids[] = {
  746. 1, 7, 3, 5, 3, 1, 30, 8, 8, 5, 6, 8,
  747. };
  748. static const struct hints_case hints_case = {
  749. .key_ids = hints_case_key_ids,
  750. .key_ids_count = ARRAY_SIZE(hints_case_key_ids),
  751. .expect_stats =
  752. EXPECT_STATS(7, ROOT(1, 2, 7), ROOT(7, 1, 4), ROOT(30, 1, 1),
  753. DELTA(8, 3), DELTA(3, 2),
  754. DELTA(5, 2), DELTA(6, 1)),
  755. .expect_stats_hints =
  756. EXPECT_STATS(7, ROOT(3, 2, 9), ROOT(1, 2, 2), ROOT(30, 1, 1),
  757. DELTA(8, 3), DELTA(5, 2),
  758. DELTA(6, 1), DELTA(7, 1)),
  759. };
  760. static void __pr_debug_stats(const struct objagg_stats *stats)
  761. {
  762. int i;
  763. for (i = 0; i < stats->stats_info_count; i++)
  764. pr_debug("Stat index %d key %u: u %d, d %d, %s\n", i,
  765. obj_to_key_id(stats->stats_info[i].objagg_obj),
  766. stats->stats_info[i].stats.user_count,
  767. stats->stats_info[i].stats.delta_user_count,
  768. stats->stats_info[i].is_root ? "root" : "noroot");
  769. }
  770. static void pr_debug_stats(struct objagg *objagg)
  771. {
  772. const struct objagg_stats *stats;
  773. stats = objagg_stats_get(objagg);
  774. if (IS_ERR(stats))
  775. return;
  776. __pr_debug_stats(stats);
  777. objagg_stats_put(stats);
  778. }
  779. static void pr_debug_hints_stats(struct objagg_hints *objagg_hints)
  780. {
  781. const struct objagg_stats *stats;
  782. stats = objagg_hints_stats_get(objagg_hints);
  783. if (IS_ERR(stats))
  784. return;
  785. __pr_debug_stats(stats);
  786. objagg_stats_put(stats);
  787. }
  788. static int check_expect_hints_stats(struct objagg_hints *objagg_hints,
  789. const struct expect_stats *expect_stats,
  790. const char **errmsg)
  791. {
  792. const struct objagg_stats *stats;
  793. int err;
  794. stats = objagg_hints_stats_get(objagg_hints);
  795. if (IS_ERR(stats))
  796. return PTR_ERR(stats);
  797. err = __check_expect_stats(stats, expect_stats, errmsg);
  798. objagg_stats_put(stats);
  799. return err;
  800. }
  801. static int test_hints_case(const struct hints_case *hints_case)
  802. {
  803. struct objagg_obj *objagg_obj;
  804. struct objagg_hints *hints;
  805. struct world world2 = {};
  806. struct world world = {};
  807. struct objagg *objagg2;
  808. struct objagg *objagg;
  809. const char *errmsg;
  810. int i;
  811. int err;
  812. objagg = objagg_create(&delta_ops, NULL, &world);
  813. if (IS_ERR(objagg))
  814. return PTR_ERR(objagg);
  815. for (i = 0; i < hints_case->key_ids_count; i++) {
  816. objagg_obj = world_obj_get(&world, objagg,
  817. hints_case->key_ids[i]);
  818. if (IS_ERR(objagg_obj)) {
  819. err = PTR_ERR(objagg_obj);
  820. goto err_world_obj_get;
  821. }
  822. }
  823. pr_debug_stats(objagg);
  824. err = check_expect_stats(objagg, &hints_case->expect_stats, &errmsg);
  825. if (err) {
  826. pr_err("Stats: %s\n", errmsg);
  827. goto err_check_expect_stats;
  828. }
  829. hints = objagg_hints_get(objagg, OBJAGG_OPT_ALGO_SIMPLE_GREEDY);
  830. if (IS_ERR(hints)) {
  831. err = PTR_ERR(hints);
  832. goto err_hints_get;
  833. }
  834. pr_debug_hints_stats(hints);
  835. err = check_expect_hints_stats(hints, &hints_case->expect_stats_hints,
  836. &errmsg);
  837. if (err) {
  838. pr_err("Hints stats: %s\n", errmsg);
  839. goto err_check_expect_hints_stats;
  840. }
  841. objagg2 = objagg_create(&delta_ops, hints, &world2);
  842. if (IS_ERR(objagg2))
  843. return PTR_ERR(objagg2);
  844. for (i = 0; i < hints_case->key_ids_count; i++) {
  845. objagg_obj = world_obj_get(&world2, objagg2,
  846. hints_case->key_ids[i]);
  847. if (IS_ERR(objagg_obj)) {
  848. err = PTR_ERR(objagg_obj);
  849. goto err_world2_obj_get;
  850. }
  851. }
  852. pr_debug_stats(objagg2);
  853. err = check_expect_stats(objagg2, &hints_case->expect_stats_hints,
  854. &errmsg);
  855. if (err) {
  856. pr_err("Stats2: %s\n", errmsg);
  857. goto err_check_expect_stats2;
  858. }
  859. err = 0;
  860. err_check_expect_stats2:
  861. err_world2_obj_get:
  862. for (i--; i >= 0; i--)
  863. world_obj_put(&world2, objagg, hints_case->key_ids[i]);
  864. i = hints_case->key_ids_count;
  865. objagg_destroy(objagg2);
  866. err_check_expect_hints_stats:
  867. objagg_hints_put(hints);
  868. err_hints_get:
  869. err_check_expect_stats:
  870. err_world_obj_get:
  871. for (i--; i >= 0; i--)
  872. world_obj_put(&world, objagg, hints_case->key_ids[i]);
  873. objagg_destroy(objagg);
  874. return err;
  875. }
  876. static int test_hints(void)
  877. {
  878. return test_hints_case(&hints_case);
  879. }
  880. static int __init test_objagg_init(void)
  881. {
  882. int err;
  883. err = test_nodelta();
  884. if (err)
  885. return err;
  886. err = test_delta();
  887. if (err)
  888. return err;
  889. return test_hints();
  890. }
  891. static void __exit test_objagg_exit(void)
  892. {
  893. }
  894. module_init(test_objagg_init);
  895. module_exit(test_objagg_exit);
  896. MODULE_LICENSE("Dual BSD/GPL");
  897. MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>");
  898. MODULE_DESCRIPTION("Test module for objagg");