18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 28c2ecf20Sopenharmony_ci/* Copyright (c) 2018 Mellanox Technologies. All rights reserved */ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/kernel.h> 78c2ecf20Sopenharmony_ci#include <linux/module.h> 88c2ecf20Sopenharmony_ci#include <linux/slab.h> 98c2ecf20Sopenharmony_ci#include <linux/random.h> 108c2ecf20Sopenharmony_ci#include <linux/objagg.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_cistruct tokey { 138c2ecf20Sopenharmony_ci unsigned int id; 148c2ecf20Sopenharmony_ci}; 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#define NUM_KEYS 32 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_cistatic int key_id_index(unsigned int key_id) 198c2ecf20Sopenharmony_ci{ 208c2ecf20Sopenharmony_ci if (key_id >= NUM_KEYS) { 218c2ecf20Sopenharmony_ci WARN_ON(1); 228c2ecf20Sopenharmony_ci return 0; 238c2ecf20Sopenharmony_ci } 248c2ecf20Sopenharmony_ci return key_id; 258c2ecf20Sopenharmony_ci} 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#define BUF_LEN 128 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cistruct world { 308c2ecf20Sopenharmony_ci unsigned int root_count; 318c2ecf20Sopenharmony_ci unsigned int delta_count; 328c2ecf20Sopenharmony_ci char next_root_buf[BUF_LEN]; 338c2ecf20Sopenharmony_ci struct objagg_obj *objagg_objs[NUM_KEYS]; 348c2ecf20Sopenharmony_ci unsigned int key_refs[NUM_KEYS]; 358c2ecf20Sopenharmony_ci}; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_cistruct root { 388c2ecf20Sopenharmony_ci struct tokey key; 398c2ecf20Sopenharmony_ci char buf[BUF_LEN]; 408c2ecf20Sopenharmony_ci}; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistruct delta { 438c2ecf20Sopenharmony_ci unsigned int key_id_diff; 448c2ecf20Sopenharmony_ci}; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_cistatic struct objagg_obj *world_obj_get(struct world *world, 478c2ecf20Sopenharmony_ci struct objagg *objagg, 488c2ecf20Sopenharmony_ci unsigned int key_id) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci struct objagg_obj *objagg_obj; 518c2ecf20Sopenharmony_ci struct tokey key; 528c2ecf20Sopenharmony_ci int err; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci key.id = key_id; 558c2ecf20Sopenharmony_ci objagg_obj = objagg_obj_get(objagg, &key); 568c2ecf20Sopenharmony_ci if (IS_ERR(objagg_obj)) { 578c2ecf20Sopenharmony_ci pr_err("Key %u: Failed to get object.\n", key_id); 588c2ecf20Sopenharmony_ci return objagg_obj; 598c2ecf20Sopenharmony_ci } 608c2ecf20Sopenharmony_ci if (!world->key_refs[key_id_index(key_id)]) { 618c2ecf20Sopenharmony_ci world->objagg_objs[key_id_index(key_id)] = objagg_obj; 628c2ecf20Sopenharmony_ci } else if (world->objagg_objs[key_id_index(key_id)] != objagg_obj) { 638c2ecf20Sopenharmony_ci pr_err("Key %u: God another object for the same key.\n", 648c2ecf20Sopenharmony_ci key_id); 658c2ecf20Sopenharmony_ci err = -EINVAL; 668c2ecf20Sopenharmony_ci goto err_key_id_check; 678c2ecf20Sopenharmony_ci } 688c2ecf20Sopenharmony_ci world->key_refs[key_id_index(key_id)]++; 698c2ecf20Sopenharmony_ci return objagg_obj; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_cierr_key_id_check: 728c2ecf20Sopenharmony_ci objagg_obj_put(objagg, objagg_obj); 738c2ecf20Sopenharmony_ci return ERR_PTR(err); 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_cistatic void world_obj_put(struct world *world, struct objagg *objagg, 778c2ecf20Sopenharmony_ci unsigned int key_id) 788c2ecf20Sopenharmony_ci{ 798c2ecf20Sopenharmony_ci struct objagg_obj *objagg_obj; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci if (!world->key_refs[key_id_index(key_id)]) 828c2ecf20Sopenharmony_ci return; 838c2ecf20Sopenharmony_ci objagg_obj = world->objagg_objs[key_id_index(key_id)]; 848c2ecf20Sopenharmony_ci objagg_obj_put(objagg, objagg_obj); 858c2ecf20Sopenharmony_ci world->key_refs[key_id_index(key_id)]--; 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci#define MAX_KEY_ID_DIFF 5 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistatic bool delta_check(void *priv, const void *parent_obj, const void *obj) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci const struct tokey *parent_key = parent_obj; 938c2ecf20Sopenharmony_ci const struct tokey *key = obj; 948c2ecf20Sopenharmony_ci int diff = key->id - parent_key->id; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci return diff >= 0 && diff <= MAX_KEY_ID_DIFF; 978c2ecf20Sopenharmony_ci} 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_cistatic void *delta_create(void *priv, void *parent_obj, void *obj) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci struct tokey *parent_key = parent_obj; 1028c2ecf20Sopenharmony_ci struct world *world = priv; 1038c2ecf20Sopenharmony_ci struct tokey *key = obj; 1048c2ecf20Sopenharmony_ci int diff = key->id - parent_key->id; 1058c2ecf20Sopenharmony_ci struct delta *delta; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci if (!delta_check(priv, parent_obj, obj)) 1088c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci delta = kzalloc(sizeof(*delta), GFP_KERNEL); 1118c2ecf20Sopenharmony_ci if (!delta) 1128c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 1138c2ecf20Sopenharmony_ci delta->key_id_diff = diff; 1148c2ecf20Sopenharmony_ci world->delta_count++; 1158c2ecf20Sopenharmony_ci return delta; 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_cistatic void delta_destroy(void *priv, void *delta_priv) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci struct delta *delta = delta_priv; 1218c2ecf20Sopenharmony_ci struct world *world = priv; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci world->delta_count--; 1248c2ecf20Sopenharmony_ci kfree(delta); 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_cistatic void *root_create(void *priv, void *obj, unsigned int id) 1288c2ecf20Sopenharmony_ci{ 1298c2ecf20Sopenharmony_ci struct world *world = priv; 1308c2ecf20Sopenharmony_ci struct tokey *key = obj; 1318c2ecf20Sopenharmony_ci struct root *root; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci root = kzalloc(sizeof(*root), GFP_KERNEL); 1348c2ecf20Sopenharmony_ci if (!root) 1358c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 1368c2ecf20Sopenharmony_ci memcpy(&root->key, key, sizeof(root->key)); 1378c2ecf20Sopenharmony_ci memcpy(root->buf, world->next_root_buf, sizeof(root->buf)); 1388c2ecf20Sopenharmony_ci world->root_count++; 1398c2ecf20Sopenharmony_ci return root; 1408c2ecf20Sopenharmony_ci} 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistatic void root_destroy(void *priv, void *root_priv) 1438c2ecf20Sopenharmony_ci{ 1448c2ecf20Sopenharmony_ci struct root *root = root_priv; 1458c2ecf20Sopenharmony_ci struct world *world = priv; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci world->root_count--; 1488c2ecf20Sopenharmony_ci kfree(root); 1498c2ecf20Sopenharmony_ci} 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_cistatic int test_nodelta_obj_get(struct world *world, struct objagg *objagg, 1528c2ecf20Sopenharmony_ci unsigned int key_id, bool should_create_root) 1538c2ecf20Sopenharmony_ci{ 1548c2ecf20Sopenharmony_ci unsigned int orig_root_count = world->root_count; 1558c2ecf20Sopenharmony_ci struct objagg_obj *objagg_obj; 1568c2ecf20Sopenharmony_ci const struct root *root; 1578c2ecf20Sopenharmony_ci int err; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci if (should_create_root) 1608c2ecf20Sopenharmony_ci prandom_bytes(world->next_root_buf, 1618c2ecf20Sopenharmony_ci sizeof(world->next_root_buf)); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci objagg_obj = world_obj_get(world, objagg, key_id); 1648c2ecf20Sopenharmony_ci if (IS_ERR(objagg_obj)) { 1658c2ecf20Sopenharmony_ci pr_err("Key %u: Failed to get object.\n", key_id); 1668c2ecf20Sopenharmony_ci return PTR_ERR(objagg_obj); 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci if (should_create_root) { 1698c2ecf20Sopenharmony_ci if (world->root_count != orig_root_count + 1) { 1708c2ecf20Sopenharmony_ci pr_err("Key %u: Root was not created\n", key_id); 1718c2ecf20Sopenharmony_ci err = -EINVAL; 1728c2ecf20Sopenharmony_ci goto err_check_root_count; 1738c2ecf20Sopenharmony_ci } 1748c2ecf20Sopenharmony_ci } else { 1758c2ecf20Sopenharmony_ci if (world->root_count != orig_root_count) { 1768c2ecf20Sopenharmony_ci pr_err("Key %u: Root was incorrectly created\n", 1778c2ecf20Sopenharmony_ci key_id); 1788c2ecf20Sopenharmony_ci err = -EINVAL; 1798c2ecf20Sopenharmony_ci goto err_check_root_count; 1808c2ecf20Sopenharmony_ci } 1818c2ecf20Sopenharmony_ci } 1828c2ecf20Sopenharmony_ci root = objagg_obj_root_priv(objagg_obj); 1838c2ecf20Sopenharmony_ci if (root->key.id != key_id) { 1848c2ecf20Sopenharmony_ci pr_err("Key %u: Root has unexpected key id\n", key_id); 1858c2ecf20Sopenharmony_ci err = -EINVAL; 1868c2ecf20Sopenharmony_ci goto err_check_key_id; 1878c2ecf20Sopenharmony_ci } 1888c2ecf20Sopenharmony_ci if (should_create_root && 1898c2ecf20Sopenharmony_ci memcmp(world->next_root_buf, root->buf, sizeof(root->buf))) { 1908c2ecf20Sopenharmony_ci pr_err("Key %u: Buffer does not match the expected content\n", 1918c2ecf20Sopenharmony_ci key_id); 1928c2ecf20Sopenharmony_ci err = -EINVAL; 1938c2ecf20Sopenharmony_ci goto err_check_buf; 1948c2ecf20Sopenharmony_ci } 1958c2ecf20Sopenharmony_ci return 0; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cierr_check_buf: 1988c2ecf20Sopenharmony_cierr_check_key_id: 1998c2ecf20Sopenharmony_cierr_check_root_count: 2008c2ecf20Sopenharmony_ci objagg_obj_put(objagg, objagg_obj); 2018c2ecf20Sopenharmony_ci return err; 2028c2ecf20Sopenharmony_ci} 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_cistatic int test_nodelta_obj_put(struct world *world, struct objagg *objagg, 2058c2ecf20Sopenharmony_ci unsigned int key_id, bool should_destroy_root) 2068c2ecf20Sopenharmony_ci{ 2078c2ecf20Sopenharmony_ci unsigned int orig_root_count = world->root_count; 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci world_obj_put(world, objagg, key_id); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci if (should_destroy_root) { 2128c2ecf20Sopenharmony_ci if (world->root_count != orig_root_count - 1) { 2138c2ecf20Sopenharmony_ci pr_err("Key %u: Root was not destroyed\n", key_id); 2148c2ecf20Sopenharmony_ci return -EINVAL; 2158c2ecf20Sopenharmony_ci } 2168c2ecf20Sopenharmony_ci } else { 2178c2ecf20Sopenharmony_ci if (world->root_count != orig_root_count) { 2188c2ecf20Sopenharmony_ci pr_err("Key %u: Root was incorrectly destroyed\n", 2198c2ecf20Sopenharmony_ci key_id); 2208c2ecf20Sopenharmony_ci return -EINVAL; 2218c2ecf20Sopenharmony_ci } 2228c2ecf20Sopenharmony_ci } 2238c2ecf20Sopenharmony_ci return 0; 2248c2ecf20Sopenharmony_ci} 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_cistatic int check_stats_zero(struct objagg *objagg) 2278c2ecf20Sopenharmony_ci{ 2288c2ecf20Sopenharmony_ci const struct objagg_stats *stats; 2298c2ecf20Sopenharmony_ci int err = 0; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci stats = objagg_stats_get(objagg); 2328c2ecf20Sopenharmony_ci if (IS_ERR(stats)) 2338c2ecf20Sopenharmony_ci return PTR_ERR(stats); 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci if (stats->stats_info_count != 0) { 2368c2ecf20Sopenharmony_ci pr_err("Stats: Object count is not zero while it should be\n"); 2378c2ecf20Sopenharmony_ci err = -EINVAL; 2388c2ecf20Sopenharmony_ci } 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci objagg_stats_put(stats); 2418c2ecf20Sopenharmony_ci return err; 2428c2ecf20Sopenharmony_ci} 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_cistatic int check_stats_nodelta(struct objagg *objagg) 2458c2ecf20Sopenharmony_ci{ 2468c2ecf20Sopenharmony_ci const struct objagg_stats *stats; 2478c2ecf20Sopenharmony_ci int i; 2488c2ecf20Sopenharmony_ci int err; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci stats = objagg_stats_get(objagg); 2518c2ecf20Sopenharmony_ci if (IS_ERR(stats)) 2528c2ecf20Sopenharmony_ci return PTR_ERR(stats); 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci if (stats->stats_info_count != NUM_KEYS) { 2558c2ecf20Sopenharmony_ci pr_err("Stats: Unexpected object count (%u expected, %u returned)\n", 2568c2ecf20Sopenharmony_ci NUM_KEYS, stats->stats_info_count); 2578c2ecf20Sopenharmony_ci err = -EINVAL; 2588c2ecf20Sopenharmony_ci goto stats_put; 2598c2ecf20Sopenharmony_ci } 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci for (i = 0; i < stats->stats_info_count; i++) { 2628c2ecf20Sopenharmony_ci if (stats->stats_info[i].stats.user_count != 2) { 2638c2ecf20Sopenharmony_ci pr_err("Stats: incorrect user count\n"); 2648c2ecf20Sopenharmony_ci err = -EINVAL; 2658c2ecf20Sopenharmony_ci goto stats_put; 2668c2ecf20Sopenharmony_ci } 2678c2ecf20Sopenharmony_ci if (stats->stats_info[i].stats.delta_user_count != 2) { 2688c2ecf20Sopenharmony_ci pr_err("Stats: incorrect delta user count\n"); 2698c2ecf20Sopenharmony_ci err = -EINVAL; 2708c2ecf20Sopenharmony_ci goto stats_put; 2718c2ecf20Sopenharmony_ci } 2728c2ecf20Sopenharmony_ci } 2738c2ecf20Sopenharmony_ci err = 0; 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_cistats_put: 2768c2ecf20Sopenharmony_ci objagg_stats_put(stats); 2778c2ecf20Sopenharmony_ci return err; 2788c2ecf20Sopenharmony_ci} 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_cistatic bool delta_check_dummy(void *priv, const void *parent_obj, 2818c2ecf20Sopenharmony_ci const void *obj) 2828c2ecf20Sopenharmony_ci{ 2838c2ecf20Sopenharmony_ci return false; 2848c2ecf20Sopenharmony_ci} 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_cistatic void *delta_create_dummy(void *priv, void *parent_obj, void *obj) 2878c2ecf20Sopenharmony_ci{ 2888c2ecf20Sopenharmony_ci return ERR_PTR(-EOPNOTSUPP); 2898c2ecf20Sopenharmony_ci} 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_cistatic void delta_destroy_dummy(void *priv, void *delta_priv) 2928c2ecf20Sopenharmony_ci{ 2938c2ecf20Sopenharmony_ci} 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_cistatic const struct objagg_ops nodelta_ops = { 2968c2ecf20Sopenharmony_ci .obj_size = sizeof(struct tokey), 2978c2ecf20Sopenharmony_ci .delta_check = delta_check_dummy, 2988c2ecf20Sopenharmony_ci .delta_create = delta_create_dummy, 2998c2ecf20Sopenharmony_ci .delta_destroy = delta_destroy_dummy, 3008c2ecf20Sopenharmony_ci .root_create = root_create, 3018c2ecf20Sopenharmony_ci .root_destroy = root_destroy, 3028c2ecf20Sopenharmony_ci}; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_cistatic int test_nodelta(void) 3058c2ecf20Sopenharmony_ci{ 3068c2ecf20Sopenharmony_ci struct world world = {}; 3078c2ecf20Sopenharmony_ci struct objagg *objagg; 3088c2ecf20Sopenharmony_ci int i; 3098c2ecf20Sopenharmony_ci int err; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci objagg = objagg_create(&nodelta_ops, NULL, &world); 3128c2ecf20Sopenharmony_ci if (IS_ERR(objagg)) 3138c2ecf20Sopenharmony_ci return PTR_ERR(objagg); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci err = check_stats_zero(objagg); 3168c2ecf20Sopenharmony_ci if (err) 3178c2ecf20Sopenharmony_ci goto err_stats_first_zero; 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci /* First round of gets, the root objects should be created */ 3208c2ecf20Sopenharmony_ci for (i = 0; i < NUM_KEYS; i++) { 3218c2ecf20Sopenharmony_ci err = test_nodelta_obj_get(&world, objagg, i, true); 3228c2ecf20Sopenharmony_ci if (err) 3238c2ecf20Sopenharmony_ci goto err_obj_first_get; 3248c2ecf20Sopenharmony_ci } 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci /* Do the second round of gets, all roots are already created, 3278c2ecf20Sopenharmony_ci * make sure that no new root is created 3288c2ecf20Sopenharmony_ci */ 3298c2ecf20Sopenharmony_ci for (i = 0; i < NUM_KEYS; i++) { 3308c2ecf20Sopenharmony_ci err = test_nodelta_obj_get(&world, objagg, i, false); 3318c2ecf20Sopenharmony_ci if (err) 3328c2ecf20Sopenharmony_ci goto err_obj_second_get; 3338c2ecf20Sopenharmony_ci } 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci err = check_stats_nodelta(objagg); 3368c2ecf20Sopenharmony_ci if (err) 3378c2ecf20Sopenharmony_ci goto err_stats_nodelta; 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci for (i = NUM_KEYS - 1; i >= 0; i--) { 3408c2ecf20Sopenharmony_ci err = test_nodelta_obj_put(&world, objagg, i, false); 3418c2ecf20Sopenharmony_ci if (err) 3428c2ecf20Sopenharmony_ci goto err_obj_first_put; 3438c2ecf20Sopenharmony_ci } 3448c2ecf20Sopenharmony_ci for (i = NUM_KEYS - 1; i >= 0; i--) { 3458c2ecf20Sopenharmony_ci err = test_nodelta_obj_put(&world, objagg, i, true); 3468c2ecf20Sopenharmony_ci if (err) 3478c2ecf20Sopenharmony_ci goto err_obj_second_put; 3488c2ecf20Sopenharmony_ci } 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci err = check_stats_zero(objagg); 3518c2ecf20Sopenharmony_ci if (err) 3528c2ecf20Sopenharmony_ci goto err_stats_second_zero; 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci objagg_destroy(objagg); 3558c2ecf20Sopenharmony_ci return 0; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_cierr_stats_nodelta: 3588c2ecf20Sopenharmony_cierr_obj_first_put: 3598c2ecf20Sopenharmony_cierr_obj_second_get: 3608c2ecf20Sopenharmony_ci for (i--; i >= 0; i--) 3618c2ecf20Sopenharmony_ci world_obj_put(&world, objagg, i); 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci i = NUM_KEYS; 3648c2ecf20Sopenharmony_cierr_obj_first_get: 3658c2ecf20Sopenharmony_cierr_obj_second_put: 3668c2ecf20Sopenharmony_ci for (i--; i >= 0; i--) 3678c2ecf20Sopenharmony_ci world_obj_put(&world, objagg, i); 3688c2ecf20Sopenharmony_cierr_stats_first_zero: 3698c2ecf20Sopenharmony_cierr_stats_second_zero: 3708c2ecf20Sopenharmony_ci objagg_destroy(objagg); 3718c2ecf20Sopenharmony_ci return err; 3728c2ecf20Sopenharmony_ci} 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_cistatic const struct objagg_ops delta_ops = { 3758c2ecf20Sopenharmony_ci .obj_size = sizeof(struct tokey), 3768c2ecf20Sopenharmony_ci .delta_check = delta_check, 3778c2ecf20Sopenharmony_ci .delta_create = delta_create, 3788c2ecf20Sopenharmony_ci .delta_destroy = delta_destroy, 3798c2ecf20Sopenharmony_ci .root_create = root_create, 3808c2ecf20Sopenharmony_ci .root_destroy = root_destroy, 3818c2ecf20Sopenharmony_ci}; 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_cienum action { 3848c2ecf20Sopenharmony_ci ACTION_GET, 3858c2ecf20Sopenharmony_ci ACTION_PUT, 3868c2ecf20Sopenharmony_ci}; 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_cienum expect_delta { 3898c2ecf20Sopenharmony_ci EXPECT_DELTA_SAME, 3908c2ecf20Sopenharmony_ci EXPECT_DELTA_INC, 3918c2ecf20Sopenharmony_ci EXPECT_DELTA_DEC, 3928c2ecf20Sopenharmony_ci}; 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_cienum expect_root { 3958c2ecf20Sopenharmony_ci EXPECT_ROOT_SAME, 3968c2ecf20Sopenharmony_ci EXPECT_ROOT_INC, 3978c2ecf20Sopenharmony_ci EXPECT_ROOT_DEC, 3988c2ecf20Sopenharmony_ci}; 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_cistruct expect_stats_info { 4018c2ecf20Sopenharmony_ci struct objagg_obj_stats stats; 4028c2ecf20Sopenharmony_ci bool is_root; 4038c2ecf20Sopenharmony_ci unsigned int key_id; 4048c2ecf20Sopenharmony_ci}; 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_cistruct expect_stats { 4078c2ecf20Sopenharmony_ci unsigned int info_count; 4088c2ecf20Sopenharmony_ci struct expect_stats_info info[NUM_KEYS]; 4098c2ecf20Sopenharmony_ci}; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_cistruct action_item { 4128c2ecf20Sopenharmony_ci unsigned int key_id; 4138c2ecf20Sopenharmony_ci enum action action; 4148c2ecf20Sopenharmony_ci enum expect_delta expect_delta; 4158c2ecf20Sopenharmony_ci enum expect_root expect_root; 4168c2ecf20Sopenharmony_ci struct expect_stats expect_stats; 4178c2ecf20Sopenharmony_ci}; 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci#define EXPECT_STATS(count, ...) \ 4208c2ecf20Sopenharmony_ci{ \ 4218c2ecf20Sopenharmony_ci .info_count = count, \ 4228c2ecf20Sopenharmony_ci .info = { __VA_ARGS__ } \ 4238c2ecf20Sopenharmony_ci} 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci#define ROOT(key_id, user_count, delta_user_count) \ 4268c2ecf20Sopenharmony_ci {{user_count, delta_user_count}, true, key_id} 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci#define DELTA(key_id, user_count) \ 4298c2ecf20Sopenharmony_ci {{user_count, user_count}, false, key_id} 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_cistatic const struct action_item action_items[] = { 4328c2ecf20Sopenharmony_ci { 4338c2ecf20Sopenharmony_ci 1, ACTION_GET, EXPECT_DELTA_SAME, EXPECT_ROOT_INC, 4348c2ecf20Sopenharmony_ci EXPECT_STATS(1, ROOT(1, 1, 1)), 4358c2ecf20Sopenharmony_ci }, /* r: 1 d: */ 4368c2ecf20Sopenharmony_ci { 4378c2ecf20Sopenharmony_ci 7, ACTION_GET, EXPECT_DELTA_SAME, EXPECT_ROOT_INC, 4388c2ecf20Sopenharmony_ci EXPECT_STATS(2, ROOT(1, 1, 1), ROOT(7, 1, 1)), 4398c2ecf20Sopenharmony_ci }, /* r: 1, 7 d: */ 4408c2ecf20Sopenharmony_ci { 4418c2ecf20Sopenharmony_ci 3, ACTION_GET, EXPECT_DELTA_INC, EXPECT_ROOT_SAME, 4428c2ecf20Sopenharmony_ci EXPECT_STATS(3, ROOT(1, 1, 2), ROOT(7, 1, 1), 4438c2ecf20Sopenharmony_ci DELTA(3, 1)), 4448c2ecf20Sopenharmony_ci }, /* r: 1, 7 d: 3^1 */ 4458c2ecf20Sopenharmony_ci { 4468c2ecf20Sopenharmony_ci 5, ACTION_GET, EXPECT_DELTA_INC, EXPECT_ROOT_SAME, 4478c2ecf20Sopenharmony_ci EXPECT_STATS(4, ROOT(1, 1, 3), ROOT(7, 1, 1), 4488c2ecf20Sopenharmony_ci DELTA(3, 1), DELTA(5, 1)), 4498c2ecf20Sopenharmony_ci }, /* r: 1, 7 d: 3^1, 5^1 */ 4508c2ecf20Sopenharmony_ci { 4518c2ecf20Sopenharmony_ci 3, ACTION_GET, EXPECT_DELTA_SAME, EXPECT_ROOT_SAME, 4528c2ecf20Sopenharmony_ci EXPECT_STATS(4, ROOT(1, 1, 4), ROOT(7, 1, 1), 4538c2ecf20Sopenharmony_ci DELTA(3, 2), DELTA(5, 1)), 4548c2ecf20Sopenharmony_ci }, /* r: 1, 7 d: 3^1, 3^1, 5^1 */ 4558c2ecf20Sopenharmony_ci { 4568c2ecf20Sopenharmony_ci 1, ACTION_GET, EXPECT_DELTA_SAME, EXPECT_ROOT_SAME, 4578c2ecf20Sopenharmony_ci EXPECT_STATS(4, ROOT(1, 2, 5), ROOT(7, 1, 1), 4588c2ecf20Sopenharmony_ci DELTA(3, 2), DELTA(5, 1)), 4598c2ecf20Sopenharmony_ci }, /* r: 1, 1, 7 d: 3^1, 3^1, 5^1 */ 4608c2ecf20Sopenharmony_ci { 4618c2ecf20Sopenharmony_ci 30, ACTION_GET, EXPECT_DELTA_SAME, EXPECT_ROOT_INC, 4628c2ecf20Sopenharmony_ci EXPECT_STATS(5, ROOT(1, 2, 5), ROOT(7, 1, 1), ROOT(30, 1, 1), 4638c2ecf20Sopenharmony_ci DELTA(3, 2), DELTA(5, 1)), 4648c2ecf20Sopenharmony_ci }, /* r: 1, 1, 7, 30 d: 3^1, 3^1, 5^1 */ 4658c2ecf20Sopenharmony_ci { 4668c2ecf20Sopenharmony_ci 8, ACTION_GET, EXPECT_DELTA_INC, EXPECT_ROOT_SAME, 4678c2ecf20Sopenharmony_ci EXPECT_STATS(6, ROOT(1, 2, 5), ROOT(7, 1, 2), ROOT(30, 1, 1), 4688c2ecf20Sopenharmony_ci DELTA(3, 2), DELTA(5, 1), DELTA(8, 1)), 4698c2ecf20Sopenharmony_ci }, /* r: 1, 1, 7, 30 d: 3^1, 3^1, 5^1, 8^7 */ 4708c2ecf20Sopenharmony_ci { 4718c2ecf20Sopenharmony_ci 8, ACTION_GET, EXPECT_DELTA_SAME, EXPECT_ROOT_SAME, 4728c2ecf20Sopenharmony_ci EXPECT_STATS(6, ROOT(1, 2, 5), ROOT(7, 1, 3), ROOT(30, 1, 1), 4738c2ecf20Sopenharmony_ci DELTA(3, 2), DELTA(8, 2), DELTA(5, 1)), 4748c2ecf20Sopenharmony_ci }, /* r: 1, 1, 7, 30 d: 3^1, 3^1, 5^1, 8^7, 8^7 */ 4758c2ecf20Sopenharmony_ci { 4768c2ecf20Sopenharmony_ci 3, ACTION_PUT, EXPECT_DELTA_SAME, EXPECT_ROOT_SAME, 4778c2ecf20Sopenharmony_ci EXPECT_STATS(6, ROOT(1, 2, 4), ROOT(7, 1, 3), ROOT(30, 1, 1), 4788c2ecf20Sopenharmony_ci DELTA(8, 2), DELTA(3, 1), DELTA(5, 1)), 4798c2ecf20Sopenharmony_ci }, /* r: 1, 1, 7, 30 d: 3^1, 5^1, 8^7, 8^7 */ 4808c2ecf20Sopenharmony_ci { 4818c2ecf20Sopenharmony_ci 3, ACTION_PUT, EXPECT_DELTA_DEC, EXPECT_ROOT_SAME, 4828c2ecf20Sopenharmony_ci EXPECT_STATS(5, ROOT(1, 2, 3), ROOT(7, 1, 3), ROOT(30, 1, 1), 4838c2ecf20Sopenharmony_ci DELTA(8, 2), DELTA(5, 1)), 4848c2ecf20Sopenharmony_ci }, /* r: 1, 1, 7, 30 d: 5^1, 8^7, 8^7 */ 4858c2ecf20Sopenharmony_ci { 4868c2ecf20Sopenharmony_ci 1, ACTION_PUT, EXPECT_DELTA_SAME, EXPECT_ROOT_SAME, 4878c2ecf20Sopenharmony_ci EXPECT_STATS(5, ROOT(7, 1, 3), ROOT(1, 1, 2), ROOT(30, 1, 1), 4888c2ecf20Sopenharmony_ci DELTA(8, 2), DELTA(5, 1)), 4898c2ecf20Sopenharmony_ci }, /* r: 1, 7, 30 d: 5^1, 8^7, 8^7 */ 4908c2ecf20Sopenharmony_ci { 4918c2ecf20Sopenharmony_ci 1, ACTION_PUT, EXPECT_DELTA_SAME, EXPECT_ROOT_SAME, 4928c2ecf20Sopenharmony_ci EXPECT_STATS(5, ROOT(7, 1, 3), ROOT(30, 1, 1), ROOT(1, 0, 1), 4938c2ecf20Sopenharmony_ci DELTA(8, 2), DELTA(5, 1)), 4948c2ecf20Sopenharmony_ci }, /* r: 7, 30 d: 5^1, 8^7, 8^7 */ 4958c2ecf20Sopenharmony_ci { 4968c2ecf20Sopenharmony_ci 5, ACTION_PUT, EXPECT_DELTA_DEC, EXPECT_ROOT_DEC, 4978c2ecf20Sopenharmony_ci EXPECT_STATS(3, ROOT(7, 1, 3), ROOT(30, 1, 1), 4988c2ecf20Sopenharmony_ci DELTA(8, 2)), 4998c2ecf20Sopenharmony_ci }, /* r: 7, 30 d: 8^7, 8^7 */ 5008c2ecf20Sopenharmony_ci { 5018c2ecf20Sopenharmony_ci 5, ACTION_GET, EXPECT_DELTA_SAME, EXPECT_ROOT_INC, 5028c2ecf20Sopenharmony_ci EXPECT_STATS(4, ROOT(7, 1, 3), ROOT(30, 1, 1), ROOT(5, 1, 1), 5038c2ecf20Sopenharmony_ci DELTA(8, 2)), 5048c2ecf20Sopenharmony_ci }, /* r: 7, 30, 5 d: 8^7, 8^7 */ 5058c2ecf20Sopenharmony_ci { 5068c2ecf20Sopenharmony_ci 6, ACTION_GET, EXPECT_DELTA_INC, EXPECT_ROOT_SAME, 5078c2ecf20Sopenharmony_ci EXPECT_STATS(5, ROOT(7, 1, 3), ROOT(5, 1, 2), ROOT(30, 1, 1), 5088c2ecf20Sopenharmony_ci DELTA(8, 2), DELTA(6, 1)), 5098c2ecf20Sopenharmony_ci }, /* r: 7, 30, 5 d: 8^7, 8^7, 6^5 */ 5108c2ecf20Sopenharmony_ci { 5118c2ecf20Sopenharmony_ci 8, ACTION_GET, EXPECT_DELTA_SAME, EXPECT_ROOT_SAME, 5128c2ecf20Sopenharmony_ci EXPECT_STATS(5, ROOT(7, 1, 4), ROOT(5, 1, 2), ROOT(30, 1, 1), 5138c2ecf20Sopenharmony_ci DELTA(8, 3), DELTA(6, 1)), 5148c2ecf20Sopenharmony_ci }, /* r: 7, 30, 5 d: 8^7, 8^7, 8^7, 6^5 */ 5158c2ecf20Sopenharmony_ci { 5168c2ecf20Sopenharmony_ci 8, ACTION_PUT, EXPECT_DELTA_SAME, EXPECT_ROOT_SAME, 5178c2ecf20Sopenharmony_ci EXPECT_STATS(5, ROOT(7, 1, 3), ROOT(5, 1, 2), ROOT(30, 1, 1), 5188c2ecf20Sopenharmony_ci DELTA(8, 2), DELTA(6, 1)), 5198c2ecf20Sopenharmony_ci }, /* r: 7, 30, 5 d: 8^7, 8^7, 6^5 */ 5208c2ecf20Sopenharmony_ci { 5218c2ecf20Sopenharmony_ci 8, ACTION_PUT, EXPECT_DELTA_SAME, EXPECT_ROOT_SAME, 5228c2ecf20Sopenharmony_ci EXPECT_STATS(5, ROOT(7, 1, 2), ROOT(5, 1, 2), ROOT(30, 1, 1), 5238c2ecf20Sopenharmony_ci DELTA(8, 1), DELTA(6, 1)), 5248c2ecf20Sopenharmony_ci }, /* r: 7, 30, 5 d: 8^7, 6^5 */ 5258c2ecf20Sopenharmony_ci { 5268c2ecf20Sopenharmony_ci 8, ACTION_PUT, EXPECT_DELTA_DEC, EXPECT_ROOT_SAME, 5278c2ecf20Sopenharmony_ci EXPECT_STATS(4, ROOT(5, 1, 2), ROOT(7, 1, 1), ROOT(30, 1, 1), 5288c2ecf20Sopenharmony_ci DELTA(6, 1)), 5298c2ecf20Sopenharmony_ci }, /* r: 7, 30, 5 d: 6^5 */ 5308c2ecf20Sopenharmony_ci { 5318c2ecf20Sopenharmony_ci 8, ACTION_GET, EXPECT_DELTA_INC, EXPECT_ROOT_SAME, 5328c2ecf20Sopenharmony_ci EXPECT_STATS(5, ROOT(5, 1, 3), ROOT(7, 1, 1), ROOT(30, 1, 1), 5338c2ecf20Sopenharmony_ci DELTA(6, 1), DELTA(8, 1)), 5348c2ecf20Sopenharmony_ci }, /* r: 7, 30, 5 d: 6^5, 8^5 */ 5358c2ecf20Sopenharmony_ci { 5368c2ecf20Sopenharmony_ci 7, ACTION_PUT, EXPECT_DELTA_SAME, EXPECT_ROOT_DEC, 5378c2ecf20Sopenharmony_ci EXPECT_STATS(4, ROOT(5, 1, 3), ROOT(30, 1, 1), 5388c2ecf20Sopenharmony_ci DELTA(6, 1), DELTA(8, 1)), 5398c2ecf20Sopenharmony_ci }, /* r: 30, 5 d: 6^5, 8^5 */ 5408c2ecf20Sopenharmony_ci { 5418c2ecf20Sopenharmony_ci 30, ACTION_PUT, EXPECT_DELTA_SAME, EXPECT_ROOT_DEC, 5428c2ecf20Sopenharmony_ci EXPECT_STATS(3, ROOT(5, 1, 3), 5438c2ecf20Sopenharmony_ci DELTA(6, 1), DELTA(8, 1)), 5448c2ecf20Sopenharmony_ci }, /* r: 5 d: 6^5, 8^5 */ 5458c2ecf20Sopenharmony_ci { 5468c2ecf20Sopenharmony_ci 5, ACTION_PUT, EXPECT_DELTA_SAME, EXPECT_ROOT_SAME, 5478c2ecf20Sopenharmony_ci EXPECT_STATS(3, ROOT(5, 0, 2), 5488c2ecf20Sopenharmony_ci DELTA(6, 1), DELTA(8, 1)), 5498c2ecf20Sopenharmony_ci }, /* r: d: 6^5, 8^5 */ 5508c2ecf20Sopenharmony_ci { 5518c2ecf20Sopenharmony_ci 6, ACTION_PUT, EXPECT_DELTA_DEC, EXPECT_ROOT_SAME, 5528c2ecf20Sopenharmony_ci EXPECT_STATS(2, ROOT(5, 0, 1), 5538c2ecf20Sopenharmony_ci DELTA(8, 1)), 5548c2ecf20Sopenharmony_ci }, /* r: d: 6^5 */ 5558c2ecf20Sopenharmony_ci { 5568c2ecf20Sopenharmony_ci 8, ACTION_PUT, EXPECT_DELTA_DEC, EXPECT_ROOT_DEC, 5578c2ecf20Sopenharmony_ci EXPECT_STATS(0, ), 5588c2ecf20Sopenharmony_ci }, /* r: d: */ 5598c2ecf20Sopenharmony_ci}; 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_cistatic int check_expect(struct world *world, 5628c2ecf20Sopenharmony_ci const struct action_item *action_item, 5638c2ecf20Sopenharmony_ci unsigned int orig_delta_count, 5648c2ecf20Sopenharmony_ci unsigned int orig_root_count) 5658c2ecf20Sopenharmony_ci{ 5668c2ecf20Sopenharmony_ci unsigned int key_id = action_item->key_id; 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci switch (action_item->expect_delta) { 5698c2ecf20Sopenharmony_ci case EXPECT_DELTA_SAME: 5708c2ecf20Sopenharmony_ci if (orig_delta_count != world->delta_count) { 5718c2ecf20Sopenharmony_ci pr_err("Key %u: Delta count changed while expected to remain the same.\n", 5728c2ecf20Sopenharmony_ci key_id); 5738c2ecf20Sopenharmony_ci return -EINVAL; 5748c2ecf20Sopenharmony_ci } 5758c2ecf20Sopenharmony_ci break; 5768c2ecf20Sopenharmony_ci case EXPECT_DELTA_INC: 5778c2ecf20Sopenharmony_ci if (WARN_ON(action_item->action == ACTION_PUT)) 5788c2ecf20Sopenharmony_ci return -EINVAL; 5798c2ecf20Sopenharmony_ci if (orig_delta_count + 1 != world->delta_count) { 5808c2ecf20Sopenharmony_ci pr_err("Key %u: Delta count was not incremented.\n", 5818c2ecf20Sopenharmony_ci key_id); 5828c2ecf20Sopenharmony_ci return -EINVAL; 5838c2ecf20Sopenharmony_ci } 5848c2ecf20Sopenharmony_ci break; 5858c2ecf20Sopenharmony_ci case EXPECT_DELTA_DEC: 5868c2ecf20Sopenharmony_ci if (WARN_ON(action_item->action == ACTION_GET)) 5878c2ecf20Sopenharmony_ci return -EINVAL; 5888c2ecf20Sopenharmony_ci if (orig_delta_count - 1 != world->delta_count) { 5898c2ecf20Sopenharmony_ci pr_err("Key %u: Delta count was not decremented.\n", 5908c2ecf20Sopenharmony_ci key_id); 5918c2ecf20Sopenharmony_ci return -EINVAL; 5928c2ecf20Sopenharmony_ci } 5938c2ecf20Sopenharmony_ci break; 5948c2ecf20Sopenharmony_ci } 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci switch (action_item->expect_root) { 5978c2ecf20Sopenharmony_ci case EXPECT_ROOT_SAME: 5988c2ecf20Sopenharmony_ci if (orig_root_count != world->root_count) { 5998c2ecf20Sopenharmony_ci pr_err("Key %u: Root count changed while expected to remain the same.\n", 6008c2ecf20Sopenharmony_ci key_id); 6018c2ecf20Sopenharmony_ci return -EINVAL; 6028c2ecf20Sopenharmony_ci } 6038c2ecf20Sopenharmony_ci break; 6048c2ecf20Sopenharmony_ci case EXPECT_ROOT_INC: 6058c2ecf20Sopenharmony_ci if (WARN_ON(action_item->action == ACTION_PUT)) 6068c2ecf20Sopenharmony_ci return -EINVAL; 6078c2ecf20Sopenharmony_ci if (orig_root_count + 1 != world->root_count) { 6088c2ecf20Sopenharmony_ci pr_err("Key %u: Root count was not incremented.\n", 6098c2ecf20Sopenharmony_ci key_id); 6108c2ecf20Sopenharmony_ci return -EINVAL; 6118c2ecf20Sopenharmony_ci } 6128c2ecf20Sopenharmony_ci break; 6138c2ecf20Sopenharmony_ci case EXPECT_ROOT_DEC: 6148c2ecf20Sopenharmony_ci if (WARN_ON(action_item->action == ACTION_GET)) 6158c2ecf20Sopenharmony_ci return -EINVAL; 6168c2ecf20Sopenharmony_ci if (orig_root_count - 1 != world->root_count) { 6178c2ecf20Sopenharmony_ci pr_err("Key %u: Root count was not decremented.\n", 6188c2ecf20Sopenharmony_ci key_id); 6198c2ecf20Sopenharmony_ci return -EINVAL; 6208c2ecf20Sopenharmony_ci } 6218c2ecf20Sopenharmony_ci } 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci return 0; 6248c2ecf20Sopenharmony_ci} 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_cistatic unsigned int obj_to_key_id(struct objagg_obj *objagg_obj) 6278c2ecf20Sopenharmony_ci{ 6288c2ecf20Sopenharmony_ci const struct tokey *root_key; 6298c2ecf20Sopenharmony_ci const struct delta *delta; 6308c2ecf20Sopenharmony_ci unsigned int key_id; 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci root_key = objagg_obj_root_priv(objagg_obj); 6338c2ecf20Sopenharmony_ci key_id = root_key->id; 6348c2ecf20Sopenharmony_ci delta = objagg_obj_delta_priv(objagg_obj); 6358c2ecf20Sopenharmony_ci if (delta) 6368c2ecf20Sopenharmony_ci key_id += delta->key_id_diff; 6378c2ecf20Sopenharmony_ci return key_id; 6388c2ecf20Sopenharmony_ci} 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_cistatic int 6418c2ecf20Sopenharmony_cicheck_expect_stats_nums(const struct objagg_obj_stats_info *stats_info, 6428c2ecf20Sopenharmony_ci const struct expect_stats_info *expect_stats_info, 6438c2ecf20Sopenharmony_ci const char **errmsg) 6448c2ecf20Sopenharmony_ci{ 6458c2ecf20Sopenharmony_ci if (stats_info->is_root != expect_stats_info->is_root) { 6468c2ecf20Sopenharmony_ci if (errmsg) 6478c2ecf20Sopenharmony_ci *errmsg = "Incorrect root/delta indication"; 6488c2ecf20Sopenharmony_ci return -EINVAL; 6498c2ecf20Sopenharmony_ci } 6508c2ecf20Sopenharmony_ci if (stats_info->stats.user_count != 6518c2ecf20Sopenharmony_ci expect_stats_info->stats.user_count) { 6528c2ecf20Sopenharmony_ci if (errmsg) 6538c2ecf20Sopenharmony_ci *errmsg = "Incorrect user count"; 6548c2ecf20Sopenharmony_ci return -EINVAL; 6558c2ecf20Sopenharmony_ci } 6568c2ecf20Sopenharmony_ci if (stats_info->stats.delta_user_count != 6578c2ecf20Sopenharmony_ci expect_stats_info->stats.delta_user_count) { 6588c2ecf20Sopenharmony_ci if (errmsg) 6598c2ecf20Sopenharmony_ci *errmsg = "Incorrect delta user count"; 6608c2ecf20Sopenharmony_ci return -EINVAL; 6618c2ecf20Sopenharmony_ci } 6628c2ecf20Sopenharmony_ci return 0; 6638c2ecf20Sopenharmony_ci} 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_cistatic int 6668c2ecf20Sopenharmony_cicheck_expect_stats_key_id(const struct objagg_obj_stats_info *stats_info, 6678c2ecf20Sopenharmony_ci const struct expect_stats_info *expect_stats_info, 6688c2ecf20Sopenharmony_ci const char **errmsg) 6698c2ecf20Sopenharmony_ci{ 6708c2ecf20Sopenharmony_ci if (obj_to_key_id(stats_info->objagg_obj) != 6718c2ecf20Sopenharmony_ci expect_stats_info->key_id) { 6728c2ecf20Sopenharmony_ci if (errmsg) 6738c2ecf20Sopenharmony_ci *errmsg = "incorrect key id"; 6748c2ecf20Sopenharmony_ci return -EINVAL; 6758c2ecf20Sopenharmony_ci } 6768c2ecf20Sopenharmony_ci return 0; 6778c2ecf20Sopenharmony_ci} 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_cistatic int check_expect_stats_neigh(const struct objagg_stats *stats, 6808c2ecf20Sopenharmony_ci const struct expect_stats *expect_stats, 6818c2ecf20Sopenharmony_ci int pos) 6828c2ecf20Sopenharmony_ci{ 6838c2ecf20Sopenharmony_ci int i; 6848c2ecf20Sopenharmony_ci int err; 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_ci for (i = pos - 1; i >= 0; i--) { 6878c2ecf20Sopenharmony_ci err = check_expect_stats_nums(&stats->stats_info[i], 6888c2ecf20Sopenharmony_ci &expect_stats->info[pos], NULL); 6898c2ecf20Sopenharmony_ci if (err) 6908c2ecf20Sopenharmony_ci break; 6918c2ecf20Sopenharmony_ci err = check_expect_stats_key_id(&stats->stats_info[i], 6928c2ecf20Sopenharmony_ci &expect_stats->info[pos], NULL); 6938c2ecf20Sopenharmony_ci if (!err) 6948c2ecf20Sopenharmony_ci return 0; 6958c2ecf20Sopenharmony_ci } 6968c2ecf20Sopenharmony_ci for (i = pos + 1; i < stats->stats_info_count; i++) { 6978c2ecf20Sopenharmony_ci err = check_expect_stats_nums(&stats->stats_info[i], 6988c2ecf20Sopenharmony_ci &expect_stats->info[pos], NULL); 6998c2ecf20Sopenharmony_ci if (err) 7008c2ecf20Sopenharmony_ci break; 7018c2ecf20Sopenharmony_ci err = check_expect_stats_key_id(&stats->stats_info[i], 7028c2ecf20Sopenharmony_ci &expect_stats->info[pos], NULL); 7038c2ecf20Sopenharmony_ci if (!err) 7048c2ecf20Sopenharmony_ci return 0; 7058c2ecf20Sopenharmony_ci } 7068c2ecf20Sopenharmony_ci return -EINVAL; 7078c2ecf20Sopenharmony_ci} 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_cistatic int __check_expect_stats(const struct objagg_stats *stats, 7108c2ecf20Sopenharmony_ci const struct expect_stats *expect_stats, 7118c2ecf20Sopenharmony_ci const char **errmsg) 7128c2ecf20Sopenharmony_ci{ 7138c2ecf20Sopenharmony_ci int i; 7148c2ecf20Sopenharmony_ci int err; 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_ci if (stats->stats_info_count != expect_stats->info_count) { 7178c2ecf20Sopenharmony_ci *errmsg = "Unexpected object count"; 7188c2ecf20Sopenharmony_ci return -EINVAL; 7198c2ecf20Sopenharmony_ci } 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_ci for (i = 0; i < stats->stats_info_count; i++) { 7228c2ecf20Sopenharmony_ci err = check_expect_stats_nums(&stats->stats_info[i], 7238c2ecf20Sopenharmony_ci &expect_stats->info[i], errmsg); 7248c2ecf20Sopenharmony_ci if (err) 7258c2ecf20Sopenharmony_ci return err; 7268c2ecf20Sopenharmony_ci err = check_expect_stats_key_id(&stats->stats_info[i], 7278c2ecf20Sopenharmony_ci &expect_stats->info[i], errmsg); 7288c2ecf20Sopenharmony_ci if (err) { 7298c2ecf20Sopenharmony_ci /* It is possible that one of the neighbor stats with 7308c2ecf20Sopenharmony_ci * same numbers have the correct key id, so check it 7318c2ecf20Sopenharmony_ci */ 7328c2ecf20Sopenharmony_ci err = check_expect_stats_neigh(stats, expect_stats, i); 7338c2ecf20Sopenharmony_ci if (err) 7348c2ecf20Sopenharmony_ci return err; 7358c2ecf20Sopenharmony_ci } 7368c2ecf20Sopenharmony_ci } 7378c2ecf20Sopenharmony_ci return 0; 7388c2ecf20Sopenharmony_ci} 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_cistatic int check_expect_stats(struct objagg *objagg, 7418c2ecf20Sopenharmony_ci const struct expect_stats *expect_stats, 7428c2ecf20Sopenharmony_ci const char **errmsg) 7438c2ecf20Sopenharmony_ci{ 7448c2ecf20Sopenharmony_ci const struct objagg_stats *stats; 7458c2ecf20Sopenharmony_ci int err; 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci stats = objagg_stats_get(objagg); 7488c2ecf20Sopenharmony_ci if (IS_ERR(stats)) { 7498c2ecf20Sopenharmony_ci *errmsg = "objagg_stats_get() failed."; 7508c2ecf20Sopenharmony_ci return PTR_ERR(stats); 7518c2ecf20Sopenharmony_ci } 7528c2ecf20Sopenharmony_ci err = __check_expect_stats(stats, expect_stats, errmsg); 7538c2ecf20Sopenharmony_ci objagg_stats_put(stats); 7548c2ecf20Sopenharmony_ci return err; 7558c2ecf20Sopenharmony_ci} 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_cistatic int test_delta_action_item(struct world *world, 7588c2ecf20Sopenharmony_ci struct objagg *objagg, 7598c2ecf20Sopenharmony_ci const struct action_item *action_item, 7608c2ecf20Sopenharmony_ci bool inverse) 7618c2ecf20Sopenharmony_ci{ 7628c2ecf20Sopenharmony_ci unsigned int orig_delta_count = world->delta_count; 7638c2ecf20Sopenharmony_ci unsigned int orig_root_count = world->root_count; 7648c2ecf20Sopenharmony_ci unsigned int key_id = action_item->key_id; 7658c2ecf20Sopenharmony_ci enum action action = action_item->action; 7668c2ecf20Sopenharmony_ci struct objagg_obj *objagg_obj; 7678c2ecf20Sopenharmony_ci const char *errmsg; 7688c2ecf20Sopenharmony_ci int err; 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_ci if (inverse) 7718c2ecf20Sopenharmony_ci action = action == ACTION_GET ? ACTION_PUT : ACTION_GET; 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci switch (action) { 7748c2ecf20Sopenharmony_ci case ACTION_GET: 7758c2ecf20Sopenharmony_ci objagg_obj = world_obj_get(world, objagg, key_id); 7768c2ecf20Sopenharmony_ci if (IS_ERR(objagg_obj)) 7778c2ecf20Sopenharmony_ci return PTR_ERR(objagg_obj); 7788c2ecf20Sopenharmony_ci break; 7798c2ecf20Sopenharmony_ci case ACTION_PUT: 7808c2ecf20Sopenharmony_ci world_obj_put(world, objagg, key_id); 7818c2ecf20Sopenharmony_ci break; 7828c2ecf20Sopenharmony_ci } 7838c2ecf20Sopenharmony_ci 7848c2ecf20Sopenharmony_ci if (inverse) 7858c2ecf20Sopenharmony_ci return 0; 7868c2ecf20Sopenharmony_ci err = check_expect(world, action_item, 7878c2ecf20Sopenharmony_ci orig_delta_count, orig_root_count); 7888c2ecf20Sopenharmony_ci if (err) 7898c2ecf20Sopenharmony_ci goto errout; 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci err = check_expect_stats(objagg, &action_item->expect_stats, &errmsg); 7928c2ecf20Sopenharmony_ci if (err) { 7938c2ecf20Sopenharmony_ci pr_err("Key %u: Stats: %s\n", action_item->key_id, errmsg); 7948c2ecf20Sopenharmony_ci goto errout; 7958c2ecf20Sopenharmony_ci } 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ci return 0; 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_cierrout: 8008c2ecf20Sopenharmony_ci /* This can only happen when action is not inversed. 8018c2ecf20Sopenharmony_ci * So in case of an error, cleanup by doing inverse action. 8028c2ecf20Sopenharmony_ci */ 8038c2ecf20Sopenharmony_ci test_delta_action_item(world, objagg, action_item, true); 8048c2ecf20Sopenharmony_ci return err; 8058c2ecf20Sopenharmony_ci} 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_cistatic int test_delta(void) 8088c2ecf20Sopenharmony_ci{ 8098c2ecf20Sopenharmony_ci struct world world = {}; 8108c2ecf20Sopenharmony_ci struct objagg *objagg; 8118c2ecf20Sopenharmony_ci int i; 8128c2ecf20Sopenharmony_ci int err; 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci objagg = objagg_create(&delta_ops, NULL, &world); 8158c2ecf20Sopenharmony_ci if (IS_ERR(objagg)) 8168c2ecf20Sopenharmony_ci return PTR_ERR(objagg); 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(action_items); i++) { 8198c2ecf20Sopenharmony_ci err = test_delta_action_item(&world, objagg, 8208c2ecf20Sopenharmony_ci &action_items[i], false); 8218c2ecf20Sopenharmony_ci if (err) 8228c2ecf20Sopenharmony_ci goto err_do_action_item; 8238c2ecf20Sopenharmony_ci } 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ci objagg_destroy(objagg); 8268c2ecf20Sopenharmony_ci return 0; 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_cierr_do_action_item: 8298c2ecf20Sopenharmony_ci for (i--; i >= 0; i--) 8308c2ecf20Sopenharmony_ci test_delta_action_item(&world, objagg, &action_items[i], true); 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci objagg_destroy(objagg); 8338c2ecf20Sopenharmony_ci return err; 8348c2ecf20Sopenharmony_ci} 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_cistruct hints_case { 8378c2ecf20Sopenharmony_ci const unsigned int *key_ids; 8388c2ecf20Sopenharmony_ci size_t key_ids_count; 8398c2ecf20Sopenharmony_ci struct expect_stats expect_stats; 8408c2ecf20Sopenharmony_ci struct expect_stats expect_stats_hints; 8418c2ecf20Sopenharmony_ci}; 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_cistatic const unsigned int hints_case_key_ids[] = { 8448c2ecf20Sopenharmony_ci 1, 7, 3, 5, 3, 1, 30, 8, 8, 5, 6, 8, 8458c2ecf20Sopenharmony_ci}; 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_cistatic const struct hints_case hints_case = { 8488c2ecf20Sopenharmony_ci .key_ids = hints_case_key_ids, 8498c2ecf20Sopenharmony_ci .key_ids_count = ARRAY_SIZE(hints_case_key_ids), 8508c2ecf20Sopenharmony_ci .expect_stats = 8518c2ecf20Sopenharmony_ci EXPECT_STATS(7, ROOT(1, 2, 7), ROOT(7, 1, 4), ROOT(30, 1, 1), 8528c2ecf20Sopenharmony_ci DELTA(8, 3), DELTA(3, 2), 8538c2ecf20Sopenharmony_ci DELTA(5, 2), DELTA(6, 1)), 8548c2ecf20Sopenharmony_ci .expect_stats_hints = 8558c2ecf20Sopenharmony_ci EXPECT_STATS(7, ROOT(3, 2, 9), ROOT(1, 2, 2), ROOT(30, 1, 1), 8568c2ecf20Sopenharmony_ci DELTA(8, 3), DELTA(5, 2), 8578c2ecf20Sopenharmony_ci DELTA(6, 1), DELTA(7, 1)), 8588c2ecf20Sopenharmony_ci}; 8598c2ecf20Sopenharmony_ci 8608c2ecf20Sopenharmony_cistatic void __pr_debug_stats(const struct objagg_stats *stats) 8618c2ecf20Sopenharmony_ci{ 8628c2ecf20Sopenharmony_ci int i; 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci for (i = 0; i < stats->stats_info_count; i++) 8658c2ecf20Sopenharmony_ci pr_debug("Stat index %d key %u: u %d, d %d, %s\n", i, 8668c2ecf20Sopenharmony_ci obj_to_key_id(stats->stats_info[i].objagg_obj), 8678c2ecf20Sopenharmony_ci stats->stats_info[i].stats.user_count, 8688c2ecf20Sopenharmony_ci stats->stats_info[i].stats.delta_user_count, 8698c2ecf20Sopenharmony_ci stats->stats_info[i].is_root ? "root" : "noroot"); 8708c2ecf20Sopenharmony_ci} 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_cistatic void pr_debug_stats(struct objagg *objagg) 8738c2ecf20Sopenharmony_ci{ 8748c2ecf20Sopenharmony_ci const struct objagg_stats *stats; 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_ci stats = objagg_stats_get(objagg); 8778c2ecf20Sopenharmony_ci if (IS_ERR(stats)) 8788c2ecf20Sopenharmony_ci return; 8798c2ecf20Sopenharmony_ci __pr_debug_stats(stats); 8808c2ecf20Sopenharmony_ci objagg_stats_put(stats); 8818c2ecf20Sopenharmony_ci} 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_cistatic void pr_debug_hints_stats(struct objagg_hints *objagg_hints) 8848c2ecf20Sopenharmony_ci{ 8858c2ecf20Sopenharmony_ci const struct objagg_stats *stats; 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci stats = objagg_hints_stats_get(objagg_hints); 8888c2ecf20Sopenharmony_ci if (IS_ERR(stats)) 8898c2ecf20Sopenharmony_ci return; 8908c2ecf20Sopenharmony_ci __pr_debug_stats(stats); 8918c2ecf20Sopenharmony_ci objagg_stats_put(stats); 8928c2ecf20Sopenharmony_ci} 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_cistatic int check_expect_hints_stats(struct objagg_hints *objagg_hints, 8958c2ecf20Sopenharmony_ci const struct expect_stats *expect_stats, 8968c2ecf20Sopenharmony_ci const char **errmsg) 8978c2ecf20Sopenharmony_ci{ 8988c2ecf20Sopenharmony_ci const struct objagg_stats *stats; 8998c2ecf20Sopenharmony_ci int err; 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci stats = objagg_hints_stats_get(objagg_hints); 9028c2ecf20Sopenharmony_ci if (IS_ERR(stats)) 9038c2ecf20Sopenharmony_ci return PTR_ERR(stats); 9048c2ecf20Sopenharmony_ci err = __check_expect_stats(stats, expect_stats, errmsg); 9058c2ecf20Sopenharmony_ci objagg_stats_put(stats); 9068c2ecf20Sopenharmony_ci return err; 9078c2ecf20Sopenharmony_ci} 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_cistatic int test_hints_case(const struct hints_case *hints_case) 9108c2ecf20Sopenharmony_ci{ 9118c2ecf20Sopenharmony_ci struct objagg_obj *objagg_obj; 9128c2ecf20Sopenharmony_ci struct objagg_hints *hints; 9138c2ecf20Sopenharmony_ci struct world world2 = {}; 9148c2ecf20Sopenharmony_ci struct world world = {}; 9158c2ecf20Sopenharmony_ci struct objagg *objagg2; 9168c2ecf20Sopenharmony_ci struct objagg *objagg; 9178c2ecf20Sopenharmony_ci const char *errmsg; 9188c2ecf20Sopenharmony_ci int i; 9198c2ecf20Sopenharmony_ci int err; 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci objagg = objagg_create(&delta_ops, NULL, &world); 9228c2ecf20Sopenharmony_ci if (IS_ERR(objagg)) 9238c2ecf20Sopenharmony_ci return PTR_ERR(objagg); 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_ci for (i = 0; i < hints_case->key_ids_count; i++) { 9268c2ecf20Sopenharmony_ci objagg_obj = world_obj_get(&world, objagg, 9278c2ecf20Sopenharmony_ci hints_case->key_ids[i]); 9288c2ecf20Sopenharmony_ci if (IS_ERR(objagg_obj)) { 9298c2ecf20Sopenharmony_ci err = PTR_ERR(objagg_obj); 9308c2ecf20Sopenharmony_ci goto err_world_obj_get; 9318c2ecf20Sopenharmony_ci } 9328c2ecf20Sopenharmony_ci } 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_ci pr_debug_stats(objagg); 9358c2ecf20Sopenharmony_ci err = check_expect_stats(objagg, &hints_case->expect_stats, &errmsg); 9368c2ecf20Sopenharmony_ci if (err) { 9378c2ecf20Sopenharmony_ci pr_err("Stats: %s\n", errmsg); 9388c2ecf20Sopenharmony_ci goto err_check_expect_stats; 9398c2ecf20Sopenharmony_ci } 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_ci hints = objagg_hints_get(objagg, OBJAGG_OPT_ALGO_SIMPLE_GREEDY); 9428c2ecf20Sopenharmony_ci if (IS_ERR(hints)) { 9438c2ecf20Sopenharmony_ci err = PTR_ERR(hints); 9448c2ecf20Sopenharmony_ci goto err_hints_get; 9458c2ecf20Sopenharmony_ci } 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci pr_debug_hints_stats(hints); 9488c2ecf20Sopenharmony_ci err = check_expect_hints_stats(hints, &hints_case->expect_stats_hints, 9498c2ecf20Sopenharmony_ci &errmsg); 9508c2ecf20Sopenharmony_ci if (err) { 9518c2ecf20Sopenharmony_ci pr_err("Hints stats: %s\n", errmsg); 9528c2ecf20Sopenharmony_ci goto err_check_expect_hints_stats; 9538c2ecf20Sopenharmony_ci } 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_ci objagg2 = objagg_create(&delta_ops, hints, &world2); 9568c2ecf20Sopenharmony_ci if (IS_ERR(objagg2)) 9578c2ecf20Sopenharmony_ci return PTR_ERR(objagg2); 9588c2ecf20Sopenharmony_ci 9598c2ecf20Sopenharmony_ci for (i = 0; i < hints_case->key_ids_count; i++) { 9608c2ecf20Sopenharmony_ci objagg_obj = world_obj_get(&world2, objagg2, 9618c2ecf20Sopenharmony_ci hints_case->key_ids[i]); 9628c2ecf20Sopenharmony_ci if (IS_ERR(objagg_obj)) { 9638c2ecf20Sopenharmony_ci err = PTR_ERR(objagg_obj); 9648c2ecf20Sopenharmony_ci goto err_world2_obj_get; 9658c2ecf20Sopenharmony_ci } 9668c2ecf20Sopenharmony_ci } 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_ci pr_debug_stats(objagg2); 9698c2ecf20Sopenharmony_ci err = check_expect_stats(objagg2, &hints_case->expect_stats_hints, 9708c2ecf20Sopenharmony_ci &errmsg); 9718c2ecf20Sopenharmony_ci if (err) { 9728c2ecf20Sopenharmony_ci pr_err("Stats2: %s\n", errmsg); 9738c2ecf20Sopenharmony_ci goto err_check_expect_stats2; 9748c2ecf20Sopenharmony_ci } 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_ci err = 0; 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_cierr_check_expect_stats2: 9798c2ecf20Sopenharmony_cierr_world2_obj_get: 9808c2ecf20Sopenharmony_ci for (i--; i >= 0; i--) 9818c2ecf20Sopenharmony_ci world_obj_put(&world2, objagg, hints_case->key_ids[i]); 9828c2ecf20Sopenharmony_ci i = hints_case->key_ids_count; 9838c2ecf20Sopenharmony_ci objagg_destroy(objagg2); 9848c2ecf20Sopenharmony_cierr_check_expect_hints_stats: 9858c2ecf20Sopenharmony_ci objagg_hints_put(hints); 9868c2ecf20Sopenharmony_cierr_hints_get: 9878c2ecf20Sopenharmony_cierr_check_expect_stats: 9888c2ecf20Sopenharmony_cierr_world_obj_get: 9898c2ecf20Sopenharmony_ci for (i--; i >= 0; i--) 9908c2ecf20Sopenharmony_ci world_obj_put(&world, objagg, hints_case->key_ids[i]); 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci objagg_destroy(objagg); 9938c2ecf20Sopenharmony_ci return err; 9948c2ecf20Sopenharmony_ci} 9958c2ecf20Sopenharmony_cistatic int test_hints(void) 9968c2ecf20Sopenharmony_ci{ 9978c2ecf20Sopenharmony_ci return test_hints_case(&hints_case); 9988c2ecf20Sopenharmony_ci} 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_cistatic int __init test_objagg_init(void) 10018c2ecf20Sopenharmony_ci{ 10028c2ecf20Sopenharmony_ci int err; 10038c2ecf20Sopenharmony_ci 10048c2ecf20Sopenharmony_ci err = test_nodelta(); 10058c2ecf20Sopenharmony_ci if (err) 10068c2ecf20Sopenharmony_ci return err; 10078c2ecf20Sopenharmony_ci err = test_delta(); 10088c2ecf20Sopenharmony_ci if (err) 10098c2ecf20Sopenharmony_ci return err; 10108c2ecf20Sopenharmony_ci return test_hints(); 10118c2ecf20Sopenharmony_ci} 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_cistatic void __exit test_objagg_exit(void) 10148c2ecf20Sopenharmony_ci{ 10158c2ecf20Sopenharmony_ci} 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_cimodule_init(test_objagg_init); 10188c2ecf20Sopenharmony_cimodule_exit(test_objagg_exit); 10198c2ecf20Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL"); 10208c2ecf20Sopenharmony_ciMODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>"); 10218c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Test module for objagg"); 1022