Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

maple_tree: add test for mtree_dup()

Add test for mtree_dup().

Test by duplicating different maple trees and then comparing the two
trees. Includes tests for duplicating full trees and memory allocation
failures on different nodes.

Link: https://lkml.kernel.org/r/20231027033845.90608-6-zhangpeng.00@bytedance.com
Signed-off-by: Peng Zhang <zhangpeng.00@bytedance.com>
Reviewed-by: Liam R. Howlett <Liam.Howlett@oracle.com>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Mateusz Guzik <mjguzik@gmail.com>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Mike Christie <michael.christie@oracle.com>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Suren Baghdasaryan <surenb@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Peng Zhang and committed by
Andrew Morton
a2587a7e 46c99e26

+361
+361
tools/testing/radix-tree/maple.c
··· 35857 35857 mt_clear_in_rcu(mt); 35858 35858 } 35859 35859 35860 + /* 35861 + * Compares two nodes except for the addresses stored in the nodes. 35862 + * Returns zero if they are the same, otherwise returns non-zero. 35863 + */ 35864 + static int __init compare_node(struct maple_enode *enode_a, 35865 + struct maple_enode *enode_b) 35866 + { 35867 + struct maple_node *node_a, *node_b; 35868 + struct maple_node a, b; 35869 + void **slots_a, **slots_b; /* Do not use the rcu tag. */ 35870 + enum maple_type type; 35871 + int i; 35872 + 35873 + if (((unsigned long)enode_a & MAPLE_NODE_MASK) != 35874 + ((unsigned long)enode_b & MAPLE_NODE_MASK)) { 35875 + pr_err("The lower 8 bits of enode are different.\n"); 35876 + return -1; 35877 + } 35878 + 35879 + type = mte_node_type(enode_a); 35880 + node_a = mte_to_node(enode_a); 35881 + node_b = mte_to_node(enode_b); 35882 + a = *node_a; 35883 + b = *node_b; 35884 + 35885 + /* Do not compare addresses. */ 35886 + if (ma_is_root(node_a) || ma_is_root(node_b)) { 35887 + a.parent = (struct maple_pnode *)((unsigned long)a.parent & 35888 + MA_ROOT_PARENT); 35889 + b.parent = (struct maple_pnode *)((unsigned long)b.parent & 35890 + MA_ROOT_PARENT); 35891 + } else { 35892 + a.parent = (struct maple_pnode *)((unsigned long)a.parent & 35893 + MAPLE_NODE_MASK); 35894 + b.parent = (struct maple_pnode *)((unsigned long)b.parent & 35895 + MAPLE_NODE_MASK); 35896 + } 35897 + 35898 + if (a.parent != b.parent) { 35899 + pr_err("The lower 8 bits of parents are different. %p %p\n", 35900 + a.parent, b.parent); 35901 + return -1; 35902 + } 35903 + 35904 + /* 35905 + * If it is a leaf node, the slots do not contain the node address, and 35906 + * no special processing of slots is required. 35907 + */ 35908 + if (ma_is_leaf(type)) 35909 + goto cmp; 35910 + 35911 + slots_a = ma_slots(&a, type); 35912 + slots_b = ma_slots(&b, type); 35913 + 35914 + for (i = 0; i < mt_slots[type]; i++) { 35915 + if (!slots_a[i] && !slots_b[i]) 35916 + break; 35917 + 35918 + if (!slots_a[i] || !slots_b[i]) { 35919 + pr_err("The number of slots is different.\n"); 35920 + return -1; 35921 + } 35922 + 35923 + /* Do not compare addresses in slots. */ 35924 + ((unsigned long *)slots_a)[i] &= MAPLE_NODE_MASK; 35925 + ((unsigned long *)slots_b)[i] &= MAPLE_NODE_MASK; 35926 + } 35927 + 35928 + cmp: 35929 + /* 35930 + * Compare all contents of two nodes, including parent (except address), 35931 + * slots (except address), pivots, gaps and metadata. 35932 + */ 35933 + return memcmp(&a, &b, sizeof(struct maple_node)); 35934 + } 35935 + 35936 + /* 35937 + * Compare two trees and return 0 if they are the same, non-zero otherwise. 35938 + */ 35939 + static int __init compare_tree(struct maple_tree *mt_a, struct maple_tree *mt_b) 35940 + { 35941 + MA_STATE(mas_a, mt_a, 0, 0); 35942 + MA_STATE(mas_b, mt_b, 0, 0); 35943 + 35944 + if (mt_a->ma_flags != mt_b->ma_flags) { 35945 + pr_err("The flags of the two trees are different.\n"); 35946 + return -1; 35947 + } 35948 + 35949 + mas_dfs_preorder(&mas_a); 35950 + mas_dfs_preorder(&mas_b); 35951 + 35952 + if (mas_is_ptr(&mas_a) || mas_is_ptr(&mas_b)) { 35953 + if (!(mas_is_ptr(&mas_a) && mas_is_ptr(&mas_b))) { 35954 + pr_err("One is MAS_ROOT and the other is not.\n"); 35955 + return -1; 35956 + } 35957 + return 0; 35958 + } 35959 + 35960 + while (!mas_is_none(&mas_a) || !mas_is_none(&mas_b)) { 35961 + 35962 + if (mas_is_none(&mas_a) || mas_is_none(&mas_b)) { 35963 + pr_err("One is MAS_NONE and the other is not.\n"); 35964 + return -1; 35965 + } 35966 + 35967 + if (mas_a.min != mas_b.min || 35968 + mas_a.max != mas_b.max) { 35969 + pr_err("mas->min, mas->max do not match.\n"); 35970 + return -1; 35971 + } 35972 + 35973 + if (compare_node(mas_a.node, mas_b.node)) { 35974 + pr_err("The contents of nodes %p and %p are different.\n", 35975 + mas_a.node, mas_b.node); 35976 + mt_dump(mt_a, mt_dump_dec); 35977 + mt_dump(mt_b, mt_dump_dec); 35978 + return -1; 35979 + } 35980 + 35981 + mas_dfs_preorder(&mas_a); 35982 + mas_dfs_preorder(&mas_b); 35983 + } 35984 + 35985 + return 0; 35986 + } 35987 + 35988 + static __init void mas_subtree_max_range(struct ma_state *mas) 35989 + { 35990 + unsigned long limit = mas->max; 35991 + MA_STATE(newmas, mas->tree, 0, 0); 35992 + void *entry; 35993 + 35994 + mas_for_each(mas, entry, limit) { 35995 + if (mas->last - mas->index >= 35996 + newmas.last - newmas.index) { 35997 + newmas = *mas; 35998 + } 35999 + } 36000 + 36001 + *mas = newmas; 36002 + } 36003 + 36004 + /* 36005 + * build_full_tree() - Build a full tree. 36006 + * @mt: The tree to build. 36007 + * @flags: Use @flags to build the tree. 36008 + * @height: The height of the tree to build. 36009 + * 36010 + * Build a tree with full leaf nodes and internal nodes. Note that the height 36011 + * should not exceed 3, otherwise it will take a long time to build. 36012 + * Return: zero if the build is successful, non-zero if it fails. 36013 + */ 36014 + static __init int build_full_tree(struct maple_tree *mt, unsigned int flags, 36015 + int height) 36016 + { 36017 + MA_STATE(mas, mt, 0, 0); 36018 + unsigned long step; 36019 + int ret = 0, cnt = 1; 36020 + enum maple_type type; 36021 + 36022 + mt_init_flags(mt, flags); 36023 + mtree_insert_range(mt, 0, ULONG_MAX, xa_mk_value(5), GFP_KERNEL); 36024 + 36025 + mtree_lock(mt); 36026 + 36027 + while (1) { 36028 + mas_set(&mas, 0); 36029 + if (mt_height(mt) < height) { 36030 + mas.max = ULONG_MAX; 36031 + goto store; 36032 + } 36033 + 36034 + while (1) { 36035 + mas_dfs_preorder(&mas); 36036 + if (mas_is_none(&mas)) 36037 + goto unlock; 36038 + 36039 + type = mte_node_type(mas.node); 36040 + if (mas_data_end(&mas) + 1 < mt_slots[type]) { 36041 + mas_set(&mas, mas.min); 36042 + goto store; 36043 + } 36044 + } 36045 + store: 36046 + mas_subtree_max_range(&mas); 36047 + step = mas.last - mas.index; 36048 + if (step < 1) { 36049 + ret = -1; 36050 + goto unlock; 36051 + } 36052 + 36053 + step /= 2; 36054 + mas.last = mas.index + step; 36055 + mas_store_gfp(&mas, xa_mk_value(5), 36056 + GFP_KERNEL); 36057 + ++cnt; 36058 + } 36059 + unlock: 36060 + mtree_unlock(mt); 36061 + 36062 + MT_BUG_ON(mt, mt_height(mt) != height); 36063 + /* pr_info("height:%u number of elements:%d\n", mt_height(mt), cnt); */ 36064 + return ret; 36065 + } 36066 + 36067 + static noinline void __init check_mtree_dup(struct maple_tree *mt) 36068 + { 36069 + DEFINE_MTREE(new); 36070 + int i, j, ret, count = 0; 36071 + unsigned int rand_seed = 17, rand; 36072 + 36073 + /* store a value at [0, 0] */ 36074 + mt_init_flags(mt, 0); 36075 + mtree_store_range(mt, 0, 0, xa_mk_value(0), GFP_KERNEL); 36076 + ret = mtree_dup(mt, &new, GFP_KERNEL); 36077 + MT_BUG_ON(&new, ret); 36078 + mt_validate(&new); 36079 + if (compare_tree(mt, &new)) 36080 + MT_BUG_ON(&new, 1); 36081 + 36082 + mtree_destroy(mt); 36083 + mtree_destroy(&new); 36084 + 36085 + /* The two trees have different attributes. */ 36086 + mt_init_flags(mt, 0); 36087 + mt_init_flags(&new, MT_FLAGS_ALLOC_RANGE); 36088 + ret = mtree_dup(mt, &new, GFP_KERNEL); 36089 + MT_BUG_ON(&new, ret != -EINVAL); 36090 + mtree_destroy(mt); 36091 + mtree_destroy(&new); 36092 + 36093 + /* The new tree is not empty */ 36094 + mt_init_flags(mt, 0); 36095 + mt_init_flags(&new, 0); 36096 + mtree_store(&new, 5, xa_mk_value(5), GFP_KERNEL); 36097 + ret = mtree_dup(mt, &new, GFP_KERNEL); 36098 + MT_BUG_ON(&new, ret != -EINVAL); 36099 + mtree_destroy(mt); 36100 + mtree_destroy(&new); 36101 + 36102 + /* Test for duplicating full trees. */ 36103 + for (i = 1; i <= 3; i++) { 36104 + ret = build_full_tree(mt, 0, i); 36105 + MT_BUG_ON(mt, ret); 36106 + mt_init_flags(&new, 0); 36107 + 36108 + ret = mtree_dup(mt, &new, GFP_KERNEL); 36109 + MT_BUG_ON(&new, ret); 36110 + mt_validate(&new); 36111 + if (compare_tree(mt, &new)) 36112 + MT_BUG_ON(&new, 1); 36113 + 36114 + mtree_destroy(mt); 36115 + mtree_destroy(&new); 36116 + } 36117 + 36118 + for (i = 1; i <= 3; i++) { 36119 + ret = build_full_tree(mt, MT_FLAGS_ALLOC_RANGE, i); 36120 + MT_BUG_ON(mt, ret); 36121 + mt_init_flags(&new, MT_FLAGS_ALLOC_RANGE); 36122 + 36123 + ret = mtree_dup(mt, &new, GFP_KERNEL); 36124 + MT_BUG_ON(&new, ret); 36125 + mt_validate(&new); 36126 + if (compare_tree(mt, &new)) 36127 + MT_BUG_ON(&new, 1); 36128 + 36129 + mtree_destroy(mt); 36130 + mtree_destroy(&new); 36131 + } 36132 + 36133 + /* Test for normal duplicating. */ 36134 + for (i = 0; i < 1000; i += 3) { 36135 + if (i & 1) { 36136 + mt_init_flags(mt, 0); 36137 + mt_init_flags(&new, 0); 36138 + } else { 36139 + mt_init_flags(mt, MT_FLAGS_ALLOC_RANGE); 36140 + mt_init_flags(&new, MT_FLAGS_ALLOC_RANGE); 36141 + } 36142 + 36143 + for (j = 0; j < i; j++) { 36144 + mtree_store_range(mt, j * 10, j * 10 + 5, 36145 + xa_mk_value(j), GFP_KERNEL); 36146 + } 36147 + 36148 + ret = mtree_dup(mt, &new, GFP_KERNEL); 36149 + MT_BUG_ON(&new, ret); 36150 + mt_validate(&new); 36151 + if (compare_tree(mt, &new)) 36152 + MT_BUG_ON(&new, 1); 36153 + 36154 + mtree_destroy(mt); 36155 + mtree_destroy(&new); 36156 + } 36157 + 36158 + /* Test memory allocation failed. */ 36159 + mt_init_flags(mt, MT_FLAGS_ALLOC_RANGE); 36160 + for (i = 0; i < 30; i += 3) { 36161 + mtree_store_range(mt, j * 10, j * 10 + 5, 36162 + xa_mk_value(j), GFP_KERNEL); 36163 + } 36164 + 36165 + /* Failed at the first node. */ 36166 + mt_init_flags(&new, MT_FLAGS_ALLOC_RANGE); 36167 + mt_set_non_kernel(0); 36168 + ret = mtree_dup(mt, &new, GFP_NOWAIT); 36169 + mt_set_non_kernel(0); 36170 + MT_BUG_ON(&new, ret != -ENOMEM); 36171 + mtree_destroy(mt); 36172 + mtree_destroy(&new); 36173 + 36174 + /* Random maple tree fails at a random node. */ 36175 + for (i = 0; i < 1000; i += 3) { 36176 + if (i & 1) { 36177 + mt_init_flags(mt, 0); 36178 + mt_init_flags(&new, 0); 36179 + } else { 36180 + mt_init_flags(mt, MT_FLAGS_ALLOC_RANGE); 36181 + mt_init_flags(&new, MT_FLAGS_ALLOC_RANGE); 36182 + } 36183 + 36184 + for (j = 0; j < i; j++) { 36185 + mtree_store_range(mt, j * 10, j * 10 + 5, 36186 + xa_mk_value(j), GFP_KERNEL); 36187 + } 36188 + /* 36189 + * The rand() library function is not used, so we can generate 36190 + * the same random numbers on any platform. 36191 + */ 36192 + rand_seed = rand_seed * 1103515245 + 12345; 36193 + rand = rand_seed / 65536 % 128; 36194 + mt_set_non_kernel(rand); 36195 + 36196 + ret = mtree_dup(mt, &new, GFP_NOWAIT); 36197 + mt_set_non_kernel(0); 36198 + if (ret != 0) { 36199 + MT_BUG_ON(&new, ret != -ENOMEM); 36200 + count++; 36201 + mtree_destroy(mt); 36202 + continue; 36203 + } 36204 + 36205 + mt_validate(&new); 36206 + if (compare_tree(mt, &new)) 36207 + MT_BUG_ON(&new, 1); 36208 + 36209 + mtree_destroy(mt); 36210 + mtree_destroy(&new); 36211 + } 36212 + 36213 + /* pr_info("mtree_dup() fail %d times\n", count); */ 36214 + BUG_ON(!count); 36215 + } 36216 + 35860 36217 extern void test_kmem_cache_bulk(void); 35861 36218 35862 36219 void farmer_tests(void) ··· 36259 35902 36260 35903 mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE); 36261 35904 check_null_expand(&tree); 35905 + mtree_destroy(&tree); 35906 + 35907 + mt_init_flags(&tree, 0); 35908 + check_mtree_dup(&tree); 36262 35909 mtree_destroy(&tree); 36263 35910 36264 35911 /* RCU testing */