summaryrefslogblamecommitdiff
path: root/lib/test_maple_tree.c
blob: 8d4c92cbdd0cfa670e81964383c1511801c47338 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379


                                             
                                             
                                                    

                                                         



                             

                                         
                           

                                           























                                                                         





                               






                                                       

                                                                    



                                                                           
                                                                                




                                                                               
                                                                               




                                                        

                                                                          



                                                                  
                                                                              




                                                             

                                                                          



                                                                   
                                                                               



                                     
                                                                                



                                      
                         
                                                                          















                                                                           
                                                                           






                                                                           
                                                                    






                                          
      
 

                                                                      







                                                                            
                                                                    














                                                                                
                                                                     














                                                                                

                                                                        






                                                
                                                                   








                                                                     

                                                                   



                                                                    
                                                           












                                                    
 

                                                                          



















                                                                     
                  

                              
                                         



                                                                                   
      

 
                                                                               















                                                                     

                  

                              
                                         



                                                                            
      

 
                                                                     

















                                                      
                                                                          




                                        
                                                                          

                           
                           


                                        




                                            












                                                      
                                                                  







                                                  
                                                                 








                                                              
                        
























                                               
                          

 
                                                             

                              
                            
                          
                          







                                                                 











                              













































































                                                                               

                                                                      

                                                                 






                                          






























                                                                     

                                                                      

                                                                 





                                          




























































                                                                              
                                                               









































                                                               
 
                         
                                                                        
 
          


                                                       
           
 
                                              

























                                               
 
                                              









                                                                 
 







                                             
                                                  




                                                                       
 
                                         
                                               


                                                           
 




                                                                         
 
                                         
                                               


                                                                         
 

                                  
                                  


                                  
 





                                        
 





                                        
          
 


                                                    
 
                                
 




                                                                        
 






                                                                                

         
 


















                                                                                    
         
 


                                                  


                                                                                           










                                                                               

         

                                                                   
                                     

                                                               
 

                          
 
                                                                    
 




                                                       
 
                                              

























                                               
                                              




                                                                    
 







                                             
                                                  




                                                                          
 




                                                                          
 





                                                                      
 





                                                               
 





                                                                      
 





                                                               
 





                                                                            






                                                                             



                                                    

                                






                                                                        
                                         
      



                                                                                
 
 
 

                                                    
 









                                                                               
                                







                                                                                
      






                                                                               
                                
                     
                                         
      
         
 


                          
 
                                                               
 
                         
                                          







                                                      
 











                                                                       
 




                                                          
 





                                                                   

                          




                                                                   

                          


                                                        

                          






















                                                                   
                             
                                      

                          
 
 




                                                                       
 







                                                    

                          











                                                             

                          










                                                             

                          
 






                                                             
                          















                                                                                
 










                                                                      
                          
                             
 











                                                                      
                             
                                      

                          
                                 
                                                













                                                                      
                             
                                      

                          
                                                







                                                                      


                                                



                                                                      
         






                                                                


                                                










                                                                         
 




                                                                         

                          
 
                                                




                                                                      
         


                                                                       
 







                                                                

 
                                                                   
 


                                        
 
                                        
 










                                                                        
         

                          
 
 
                                                                   
 


                                 
 
                                        
 

                                        
 






                                                       
 






                                                                
 


                                               
 

                                     
 


                                               
 

                                     
 
                         
 
 
                                                                    
 

                                
 
 


                             
                                      


                                             
 


                                             
 


                                   
 


                                                
 




                                   
 
 

                             
 


                                             
 




                                             
 





                                                
 













                                                                               
 
                         
 
                          
 






                                                               
                                                                           
 



                                                                               
 
 
                         
 
 
                                                                      
 


                                       

                                                  


                           
 


                               
 



                                 
 
                                                  


                           
 


                               
 



                                 
 
                                                


                              
                                               



                                                       
 
                            
 
                                
 



                                   
 



                                                                      
 




                                        
 








                                                       
 




                                                                                
                        



                                                                    
 





                                        
 


                          
                        







                                                                                 
 



                                                                       
                        



                                                                      
 






                                                            
 






                                                                      
 






                                                                              
                        






                                                                      
 





                                                          
 







                                                                      

                          






                                                               
 
























                                                          
                                                                       
 
                          
 

                                                                                  
 
                                                         
                                      
                        

 
                             
                                                                   
 
                                                                        
 

                                                                            
 



                                                                       
         
 
      
 
                             
                                                                   
 
                                                           
 

                                                                            
 


                                                                      
 


                                       

         
      
 
                        
                                                              
 

                                            
 

                                                                            
 
                                                            
 


                                                      
         


                       
                                                             


                                             
 

                                                                            
 


                                     

         
 
      
 
                              
                                                                    
 


                                            
 




                                                                            
 


                                                               
                 

                          

         
 
      
 
                                                                         
                                                                
 
 


























                                                              
         





                              

 
                                                                  






















































                                                                      










                                                                        
                                                                      
 
 




                                   
 


                                                              
 










                                                        
         




                              

 
                       
                                                                

 




                                                 
 


                                                              
 

















                                                                
                 





                                      
         
 
      
 
                                                                 
 



                                




                                                                            
                                 
 


                                   
                                    


                                   
                                   
         
 


                                                              
 




                                               
 
         




                                       

         






                                       
 








                                     
 



                                                    
 



                                                    
 



                                                    
 



                                                    
 





                                                      
 



                                                   
 



                                                   
 









                                                          
 




                                                          
 



                                                          
 





                                                         
 

                                        
                                               
                                             
 



                                                         
 






                                                     
 



                                             
 


                                      

                                            
 





                              
 


                                      
                                     
                         
 
                          
 


                                                                
                        


                                   
                          

 
 

                                                                               
                                                                           











                                                              
                                                               














































                                                                            
                                                              






















































                                                                            
                                        
                                                      
                                        











































































































































































































































































                                                                                

                                                                          














                                                        

                                                                          
 

                                            
                                                                 









                                                                              









                                                              
                          



                                                        
                        




                                            
                          
                             

                            


                              
                                                                          
                                                            

              
                               





                                                        
                              

         

                          




                                                        
                              

         

                          
                                                               
                                                      


                                                        
                              

         

                          




                                                        
                              

         

                          
                                                    
                                                      


                                                        


                                  






                                                            



                                          

         
                          




                                                        

                               

         
                          
                                
                                                          


                                               


                                  
         

 
                                                                           

















                                                          
                                                                          









































































                                                                        
                                                                 








                                                                   
                                                                        









































                                                                               














































































































































































































































































































































































































































































































































































































































                                                                                         
                          
                                       
 


                                                           


















































                                                   
                                                   



                                                   











                                                   

                                                    






                                                   
      


























































                                                                               


















































                                                                    

























                                                   












                                                   














                                                   



                                                   



                                                   




                                                   



                                                   













                                                              
                                           







                                                           
// SPDX-License-Identifier: GPL-2.0+
/*
 * test_maple_tree.c: Test the maple tree API
 * Copyright (c) 2018-2022 Oracle Corporation
 * Author: Liam R. Howlett <Liam.Howlett@Oracle.com>
 *
 * Any tests that only require the interface of the tree.
 */

#include <linux/maple_tree.h>
#include <linux/module.h>

#define MTREE_ALLOC_MAX 0x2000000000000Ul
#define CONFIG_MAPLE_SEARCH
#define MAPLE_32BIT (MAPLE_NODE_SLOTS > 31)

#ifndef CONFIG_DEBUG_MAPLE_TREE
#define mt_dump(mt, fmt)		do {} while (0)
#define mt_validate(mt)			do {} while (0)
#define mt_cache_shrink()		do {} while (0)
#define mas_dump(mas)			do {} while (0)
#define mas_wr_dump(mas)		do {} while (0)
atomic_t maple_tree_tests_run;
atomic_t maple_tree_tests_passed;
#undef MT_BUG_ON

#define MT_BUG_ON(__tree, __x) do {					\
	atomic_inc(&maple_tree_tests_run);				\
	if (__x) {							\
		pr_info("BUG at %s:%d (%u)\n",				\
		__func__, __LINE__, __x);				\
		pr_info("Pass: %u Run:%u\n",				\
			atomic_read(&maple_tree_tests_passed),		\
			atomic_read(&maple_tree_tests_run));		\
	} else {							\
		atomic_inc(&maple_tree_tests_passed);			\
	}								\
} while (0)
#endif

/* #define BENCH_SLOT_STORE */
/* #define BENCH_NODE_STORE */
/* #define BENCH_AWALK */
/* #define BENCH_WALK */
/* #define BENCH_MT_FOR_EACH */
/* #define BENCH_FORK */

#ifdef __KERNEL__
#define mt_set_non_kernel(x)		do {} while (0)
#define mt_zero_nr_tallocated(x)	do {} while (0)
#else
#define cond_resched()			do {} while (0)
#endif
static int __init mtree_insert_index(struct maple_tree *mt,
				     unsigned long index, gfp_t gfp)
{
	return mtree_insert(mt, index, xa_mk_value(index & LONG_MAX), gfp);
}

static void __init mtree_erase_index(struct maple_tree *mt, unsigned long index)
{
	MT_BUG_ON(mt, mtree_erase(mt, index) != xa_mk_value(index & LONG_MAX));
	MT_BUG_ON(mt, mtree_load(mt, index) != NULL);
}

static int __init mtree_test_insert(struct maple_tree *mt, unsigned long index,
				void *ptr)
{
	return mtree_insert(mt, index, ptr, GFP_KERNEL);
}

static int __init mtree_test_store_range(struct maple_tree *mt,
			unsigned long start, unsigned long end, void *ptr)
{
	return mtree_store_range(mt, start, end, ptr, GFP_KERNEL);
}

static int __init mtree_test_store(struct maple_tree *mt, unsigned long start,
				void *ptr)
{
	return mtree_test_store_range(mt, start, start, ptr);
}

static int __init mtree_test_insert_range(struct maple_tree *mt,
			unsigned long start, unsigned long end, void *ptr)
{
	return mtree_insert_range(mt, start, end, ptr, GFP_KERNEL);
}

static void __init *mtree_test_load(struct maple_tree *mt, unsigned long index)
{
	return mtree_load(mt, index);
}

static void __init *mtree_test_erase(struct maple_tree *mt, unsigned long index)
{
	return mtree_erase(mt, index);
}

#if defined(CONFIG_64BIT)
static noinline void __init check_mtree_alloc_range(struct maple_tree *mt,
		unsigned long start, unsigned long end, unsigned long size,
		unsigned long expected, int eret, void *ptr)
{

	unsigned long result = expected + 1;
	int ret;

	ret = mtree_alloc_range(mt, &result, ptr, size, start, end,
			GFP_KERNEL);
	MT_BUG_ON(mt, ret != eret);
	if (ret)
		return;

	MT_BUG_ON(mt, result != expected);
}

static noinline void __init check_mtree_alloc_rrange(struct maple_tree *mt,
		unsigned long start, unsigned long end, unsigned long size,
		unsigned long expected, int eret, void *ptr)
{

	unsigned long result = expected + 1;
	int ret;

	ret = mtree_alloc_rrange(mt, &result, ptr, size, start, end,
			GFP_KERNEL);
	MT_BUG_ON(mt, ret != eret);
	if (ret)
		return;

	MT_BUG_ON(mt, result != expected);
}
#endif

static noinline void __init check_load(struct maple_tree *mt,
				       unsigned long index, void *ptr)
{
	void *ret = mtree_test_load(mt, index);

	if (ret != ptr)
		pr_err("Load %lu returned %p expect %p\n", index, ret, ptr);
	MT_BUG_ON(mt, ret != ptr);
}

static noinline void __init check_store_range(struct maple_tree *mt,
		unsigned long start, unsigned long end, void *ptr, int expected)
{
	int ret = -EINVAL;
	unsigned long i;

	ret = mtree_test_store_range(mt, start, end, ptr);
	MT_BUG_ON(mt, ret != expected);

	if (ret)
		return;

	for (i = start; i <= end; i++)
		check_load(mt, i, ptr);
}

static noinline void __init check_insert_range(struct maple_tree *mt,
		unsigned long start, unsigned long end, void *ptr, int expected)
{
	int ret = -EINVAL;
	unsigned long i;

	ret = mtree_test_insert_range(mt, start, end, ptr);
	MT_BUG_ON(mt, ret != expected);

	if (ret)
		return;

	for (i = start; i <= end; i++)
		check_load(mt, i, ptr);
}

static noinline void __init check_insert(struct maple_tree *mt,
					 unsigned long index, void *ptr)
{
	int ret = -EINVAL;

	ret = mtree_test_insert(mt, index, ptr);
	MT_BUG_ON(mt, ret != 0);
}

static noinline void __init check_dup_insert(struct maple_tree *mt,
				      unsigned long index, void *ptr)
{
	int ret = -EINVAL;

	ret = mtree_test_insert(mt, index, ptr);
	MT_BUG_ON(mt, ret != -EEXIST);
}


static noinline void __init check_index_load(struct maple_tree *mt,
					     unsigned long index)
{
	return check_load(mt, index, xa_mk_value(index & LONG_MAX));
}

static inline __init int not_empty(struct maple_node *node)
{
	int i;

	if (node->parent)
		return 1;

	for (i = 0; i < ARRAY_SIZE(node->slot); i++)
		if (node->slot[i])
			return 1;

	return 0;
}


static noinline void __init check_rev_seq(struct maple_tree *mt,
					  unsigned long max, bool verbose)
{
	unsigned long i = max, j;

	MT_BUG_ON(mt, !mtree_empty(mt));

	mt_zero_nr_tallocated();
	while (i) {
		MT_BUG_ON(mt, mtree_insert_index(mt, i, GFP_KERNEL));
		for (j = i; j <= max; j++)
			check_index_load(mt, j);

		check_load(mt, i - 1, NULL);
		mt_set_in_rcu(mt);
		MT_BUG_ON(mt, !mt_height(mt));
		mt_clear_in_rcu(mt);
		MT_BUG_ON(mt, !mt_height(mt));
		i--;
	}
	check_load(mt, max + 1, NULL);

#ifndef __KERNEL__
	if (verbose) {
		rcu_barrier();
		mt_dump(mt, mt_dump_dec);
		pr_info(" %s test of 0-%lu %luK in %d active (%d total)\n",
			__func__, max, mt_get_alloc_size()/1024, mt_nr_allocated(),
			mt_nr_tallocated());
	}
#endif
}

static noinline void __init check_seq(struct maple_tree *mt, unsigned long max,
		bool verbose)
{
	unsigned long i, j;

	MT_BUG_ON(mt, !mtree_empty(mt));

	mt_zero_nr_tallocated();
	for (i = 0; i <= max; i++) {
		MT_BUG_ON(mt, mtree_insert_index(mt, i, GFP_KERNEL));
		for (j = 0; j <= i; j++)
			check_index_load(mt, j);

		if (i)
			MT_BUG_ON(mt, !mt_height(mt));
		check_load(mt, i + 1, NULL);
	}

#ifndef __KERNEL__
	if (verbose) {
		rcu_barrier();
		mt_dump(mt, mt_dump_dec);
		pr_info(" seq test of 0-%lu %luK in %d active (%d total)\n",
			max, mt_get_alloc_size()/1024, mt_nr_allocated(),
			mt_nr_tallocated());
	}
#endif
}

static noinline void __init check_lb_not_empty(struct maple_tree *mt)
{
	unsigned long i, j;
	unsigned long huge = 4000UL * 1000 * 1000;


	i = huge;
	while (i > 4096) {
		check_insert(mt, i, (void *) i);
		for (j = huge; j >= i; j /= 2) {
			check_load(mt, j-1, NULL);
			check_load(mt, j, (void *) j);
			check_load(mt, j+1, NULL);
		}
		i /= 2;
	}
	mtree_destroy(mt);
}

static noinline void __init check_lower_bound_split(struct maple_tree *mt)
{
	MT_BUG_ON(mt, !mtree_empty(mt));
	check_lb_not_empty(mt);
}

static noinline void __init check_upper_bound_split(struct maple_tree *mt)
{
	unsigned long i, j;
	unsigned long huge;

	MT_BUG_ON(mt, !mtree_empty(mt));

	if (MAPLE_32BIT)
		huge = 2147483647UL;
	else
		huge = 4000UL * 1000 * 1000;

	i = 4096;
	while (i < huge) {
		check_insert(mt, i, (void *) i);
		for (j = i; j >= huge; j *= 2) {
			check_load(mt, j-1, NULL);
			check_load(mt, j, (void *) j);
			check_load(mt, j+1, NULL);
		}
		i *= 2;
	}
	mtree_destroy(mt);
}

static noinline void __init check_mid_split(struct maple_tree *mt)
{
	unsigned long huge = 8000UL * 1000 * 1000;

	check_insert(mt, huge, (void *) huge);
	check_insert(mt, 0, xa_mk_value(0));
	check_lb_not_empty(mt);
}

static noinline void __init check_rev_find(struct maple_tree *mt)
{
	int i, nr_entries = 200;
	void *val;
	MA_STATE(mas, mt, 0, 0);

	for (i = 0; i <= nr_entries; i++)
		mtree_store_range(mt, i*10, i*10 + 5,
				  xa_mk_value(i), GFP_KERNEL);

	rcu_read_lock();
	mas_set(&mas, 1000);
	val = mas_find_rev(&mas, 1000);
	MT_BUG_ON(mt, val != xa_mk_value(100));
	val = mas_find_rev(&mas, 1000);
	MT_BUG_ON(mt, val != NULL);

	mas_set(&mas, 999);
	val = mas_find_rev(&mas, 997);
	MT_BUG_ON(mt, val != NULL);

	mas_set(&mas, 1000);
	val = mas_find_rev(&mas, 900);
	MT_BUG_ON(mt, val != xa_mk_value(100));
	val = mas_find_rev(&mas, 900);
	MT_BUG_ON(mt, val != xa_mk_value(99));

	mas_set(&mas, 20);
	val = mas_find_rev(&mas, 0);
	MT_BUG_ON(mt, val != xa_mk_value(2));
	val = mas_find_rev(&mas, 0);
	MT_BUG_ON(mt, val != xa_mk_value(1));
	val = mas_find_rev(&mas, 0);
	MT_BUG_ON(mt, val != xa_mk_value(0));
	val = mas_find_rev(&mas, 0);
	MT_BUG_ON(mt, val != NULL);
	rcu_read_unlock();
}

static noinline void __init check_find(struct maple_tree *mt)
{
	unsigned long val = 0;
	unsigned long count;
	unsigned long max;
	unsigned long top;
	unsigned long last = 0, index = 0;
	void *entry, *entry2;

	MA_STATE(mas, mt, 0, 0);

	/* Insert 0. */
	MT_BUG_ON(mt, mtree_insert_index(mt, val++, GFP_KERNEL));

#if defined(CONFIG_64BIT)
	top = 4398046511104UL;
#else
	top = ULONG_MAX;
#endif

	if (MAPLE_32BIT) {
		count = 15;
	} else {
		count = 20;
	}

	for (int i = 0; i <= count; i++) {
		if (val != 64)
			MT_BUG_ON(mt, mtree_insert_index(mt, val, GFP_KERNEL));
		else
			MT_BUG_ON(mt, mtree_insert(mt, val,
				XA_ZERO_ENTRY, GFP_KERNEL));

		val <<= 2;
	}

	val = 0;
	mas_set(&mas, val);
	mas_lock(&mas);
	while ((entry = mas_find(&mas, 268435456)) != NULL) {
		if (val != 64)
			MT_BUG_ON(mt, xa_mk_value(val) != entry);
		else
			MT_BUG_ON(mt, entry != XA_ZERO_ENTRY);

		val <<= 2;
		/* For zero check. */
		if (!val)
			val = 1;
	}
	mas_unlock(&mas);

	val = 0;
	mas_set(&mas, val);
	mas_lock(&mas);
	mas_for_each(&mas, entry, ULONG_MAX) {
		if (val != 64)
			MT_BUG_ON(mt, xa_mk_value(val) != entry);
		else
			MT_BUG_ON(mt, entry != XA_ZERO_ENTRY);
		val <<= 2;
		/* For zero check. */
		if (!val)
			val = 1;
	}
	mas_unlock(&mas);

	/* Test mas_pause */
	val = 0;
	mas_set(&mas, val);
	mas_lock(&mas);
	mas_for_each(&mas, entry, ULONG_MAX) {
		if (val != 64)
			MT_BUG_ON(mt, xa_mk_value(val) != entry);
		else
			MT_BUG_ON(mt, entry != XA_ZERO_ENTRY);
		val <<= 2;
		/* For zero check. */
		if (!val)
			val = 1;

		mas_pause(&mas);
		mas_unlock(&mas);
		mas_lock(&mas);
	}
	mas_unlock(&mas);

	val = 0;
	max = 300; /* A value big enough to include XA_ZERO_ENTRY at 64. */
	mt_for_each(mt, entry, index, max) {
		MT_BUG_ON(mt, xa_mk_value(val) != entry);
		val <<= 2;
		if (val == 64) /* Skip zero entry. */
			val <<= 2;
		/* For zero check. */
		if (!val)
			val = 1;
	}

	val = 0;
	max = 0;
	index = 0;
	MT_BUG_ON(mt, mtree_insert_index(mt, ULONG_MAX, GFP_KERNEL));
	mt_for_each(mt, entry, index, ULONG_MAX) {
		if (val == top)
			MT_BUG_ON(mt, entry != xa_mk_value(LONG_MAX));
		else
			MT_BUG_ON(mt, xa_mk_value(val) != entry);

		/* Workaround for 32bit */
		if ((val << 2) < val)
			val = ULONG_MAX;
		else
			val <<= 2;

		if (val == 64) /* Skip zero entry. */
			val <<= 2;
		/* For zero check. */
		if (!val)
			val = 1;
		max++;
		MT_BUG_ON(mt, max > 25);
	}
	mtree_erase_index(mt, ULONG_MAX);

	mas_reset(&mas);
	index = 17;
	entry = mt_find(mt, &index, 512);
	MT_BUG_ON(mt, xa_mk_value(256) != entry);

	mas_reset(&mas);
	index = 17;
	entry = mt_find(mt, &index, 20);
	MT_BUG_ON(mt, entry != NULL);


	/* Range check.. */
	/* Insert ULONG_MAX */
	MT_BUG_ON(mt, mtree_insert_index(mt, ULONG_MAX, GFP_KERNEL));

	val = 0;
	mas_set(&mas, 0);
	mas_lock(&mas);
	mas_for_each(&mas, entry, ULONG_MAX) {
		if (val == 64)
			MT_BUG_ON(mt, entry != XA_ZERO_ENTRY);
		else if (val == top)
			MT_BUG_ON(mt, entry != xa_mk_value(LONG_MAX));
		else
			MT_BUG_ON(mt, xa_mk_value(val) != entry);

		/* Workaround for 32bit */
		if ((val << 2) < val)
			val = ULONG_MAX;
		else
			val <<= 2;

		/* For zero check. */
		if (!val)
			val = 1;
		mas_pause(&mas);
		mas_unlock(&mas);
		mas_lock(&mas);
	}
	mas_unlock(&mas);

	mas_set(&mas, 1048576);
	mas_lock(&mas);
	entry = mas_find(&mas, 1048576);
	mas_unlock(&mas);
	MT_BUG_ON(mas.tree, entry == NULL);

	/*
	 * Find last value.
	 * 1. get the expected value, leveraging the existence of an end entry
	 * 2. delete end entry
	 * 3. find the last value but searching for ULONG_MAX and then using
	 * prev
	 */
	/* First, get the expected result. */
	mas_lock(&mas);
	mas_reset(&mas);
	mas.index = ULONG_MAX; /* start at max.. */
	entry = mas_find(&mas, ULONG_MAX);
	entry = mas_prev(&mas, 0);
	index = mas.index;
	last = mas.last;

	/* Erase the last entry. */
	mas_reset(&mas);
	mas.index = ULONG_MAX;
	mas.last = ULONG_MAX;
	mas_erase(&mas);

	/* Get the previous value from MAS_START */
	mas_reset(&mas);
	entry2 = mas_prev(&mas, 0);

	/* Check results. */
	MT_BUG_ON(mt, entry != entry2);
	MT_BUG_ON(mt, index != mas.index);
	MT_BUG_ON(mt, last != mas.last);


	mas.node = MAS_NONE;
	mas.index = ULONG_MAX;
	mas.last = ULONG_MAX;
	entry2 = mas_prev(&mas, 0);
	MT_BUG_ON(mt, entry != entry2);

	mas_set(&mas, 0);
	MT_BUG_ON(mt, mas_prev(&mas, 0) != NULL);

	mas_unlock(&mas);
	mtree_destroy(mt);
}

static noinline void __init check_find_2(struct maple_tree *mt)
{
	unsigned long i, j;
	void *entry;

	MA_STATE(mas, mt, 0, 0);
	rcu_read_lock();
	mas_for_each(&mas, entry, ULONG_MAX)
		MT_BUG_ON(mt, true);
	rcu_read_unlock();

	for (i = 0; i < 256; i++) {
		mtree_insert_index(mt, i, GFP_KERNEL);
		j = 0;
		mas_set(&mas, 0);
		rcu_read_lock();
		mas_for_each(&mas, entry, ULONG_MAX) {
			MT_BUG_ON(mt, entry != xa_mk_value(j));
			j++;
		}
		rcu_read_unlock();
		MT_BUG_ON(mt, j != i + 1);
	}

	for (i = 0; i < 256; i++) {
		mtree_erase_index(mt, i);
		j = i + 1;
		mas_set(&mas, 0);
		rcu_read_lock();
		mas_for_each(&mas, entry, ULONG_MAX) {
			if (xa_is_zero(entry))
				continue;

			MT_BUG_ON(mt, entry != xa_mk_value(j));
			j++;
		}
		rcu_read_unlock();
		MT_BUG_ON(mt, j != 256);
	}

	/*MT_BUG_ON(mt, !mtree_empty(mt)); */
}


#if defined(CONFIG_64BIT)
static noinline void __init check_alloc_rev_range(struct maple_tree *mt)
{
	/*
	 * Generated by:
	 * cat /proc/self/maps | awk '{print $1}'|
	 * awk -F "-" '{printf "0x%s, 0x%s, ", $1, $2}'
	 */

	static const unsigned long range[] = {
	/*      Inclusive     , Exclusive. */
		0x565234af2000, 0x565234af4000,
		0x565234af4000, 0x565234af9000,
		0x565234af9000, 0x565234afb000,
		0x565234afc000, 0x565234afd000,
		0x565234afd000, 0x565234afe000,
		0x565235def000, 0x565235e10000,
		0x7f36d4bfd000, 0x7f36d4ee2000,
		0x7f36d4ee2000, 0x7f36d4f04000,
		0x7f36d4f04000, 0x7f36d504c000,
		0x7f36d504c000, 0x7f36d5098000,
		0x7f36d5098000, 0x7f36d5099000,
		0x7f36d5099000, 0x7f36d509d000,
		0x7f36d509d000, 0x7f36d509f000,
		0x7f36d509f000, 0x7f36d50a5000,
		0x7f36d50b9000, 0x7f36d50db000,
		0x7f36d50db000, 0x7f36d50dc000,
		0x7f36d50dc000, 0x7f36d50fa000,
		0x7f36d50fa000, 0x7f36d5102000,
		0x7f36d5102000, 0x7f36d5103000,
		0x7f36d5103000, 0x7f36d5104000,
		0x7f36d5104000, 0x7f36d5105000,
		0x7fff5876b000, 0x7fff5878d000,
		0x7fff5878e000, 0x7fff58791000,
		0x7fff58791000, 0x7fff58793000,
	};

	static const unsigned long holes[] = {
		/*
		 * Note: start of hole is INCLUSIVE
		 *        end of hole is EXCLUSIVE
		 *        (opposite of the above table.)
		 * Start of hole, end of hole,  size of hole (+1)
		 */
		0x565234afb000, 0x565234afc000, 0x1000,
		0x565234afe000, 0x565235def000, 0x12F1000,
		0x565235e10000, 0x7f36d4bfd000, 0x28E49EDED000,
	};

	/*
	 * req_range consists of 4 values.
	 * 1. min index
	 * 2. max index
	 * 3. size
	 * 4. number that should be returned.
	 * 5. return value
	 */
	static const unsigned long req_range[] = {
		0x565234af9000, /* Min */
		0x7fff58791000, /* Max */
		0x1000,         /* Size */
		0x7fff5878d << 12,  /* First rev hole of size 0x1000 */
		0,              /* Return value success. */

		0x0,            /* Min */
		0x565234AF0 << 12,    /* Max */
		0x3000,         /* Size */
		0x565234AEE << 12,  /* max - 3. */
		0,              /* Return value success. */

		0x0,            /* Min */
		-1,             /* Max */
		0x1000,         /* Size */
		562949953421311 << 12,/* First rev hole of size 0x1000 */
		0,              /* Return value success. */

		0x0,            /* Min */
		0x7F36D5109 << 12,    /* Max */
		0x4000,         /* Size */
		0x7F36D5106 << 12,    /* First rev hole of size 0x4000 */
		0,              /* Return value success. */

		/* Ascend test. */
		0x0,
		34148798628 << 12,
		19 << 12,
		34148797418 << 12,
		0x0,

		/* Too big test. */
		0x0,
		18446744073709551615UL,
		562915594369134UL << 12,
		0x0,
		-EBUSY,

		/* Single space test. */
		34148798725 << 12,
		34148798725 << 12,
		1 << 12,
		34148798725 << 12,
		0,
	};

	int i, range_count = ARRAY_SIZE(range);
	int req_range_count = ARRAY_SIZE(req_range);
	unsigned long min = 0;

	MA_STATE(mas, mt, 0, 0);

	mtree_store_range(mt, MTREE_ALLOC_MAX, ULONG_MAX, XA_ZERO_ENTRY,
			  GFP_KERNEL);
#define DEBUG_REV_RANGE 0
	for (i = 0; i < range_count; i += 2) {
		/* Inclusive, Inclusive (with the -1) */

#if DEBUG_REV_RANGE
		pr_debug("\t%s: Insert %lu-%lu\n", __func__, range[i] >> 12,
				(range[i + 1] >> 12) - 1);
#endif
		check_insert_range(mt, range[i] >> 12, (range[i + 1] >> 12) - 1,
				xa_mk_value(range[i] >> 12), 0);
		mt_validate(mt);
	}


	mas_lock(&mas);
	for (i = 0; i < ARRAY_SIZE(holes); i += 3) {
#if DEBUG_REV_RANGE
		pr_debug("Search from %lu-%lu for gap %lu should be at %lu\n",
				min, holes[i+1]>>12, holes[i+2]>>12,
				holes[i] >> 12);
#endif
		MT_BUG_ON(mt, mas_empty_area_rev(&mas, min,
					holes[i+1] >> 12,
					holes[i+2] >> 12));
#if DEBUG_REV_RANGE
		pr_debug("Found %lu %lu\n", mas.index, mas.last);
		pr_debug("gap %lu %lu\n", (holes[i] >> 12),
				(holes[i+1] >> 12));
#endif
		MT_BUG_ON(mt, mas.last + 1 != (holes[i+1] >> 12));
		MT_BUG_ON(mt, mas.index != (holes[i+1] >> 12) - (holes[i+2] >> 12));
		min = holes[i+1] >> 12;
		mas_reset(&mas);
	}

	mas_unlock(&mas);
	for (i = 0; i < req_range_count; i += 5) {
#if DEBUG_REV_RANGE
		pr_debug("\tReverse request %d between %lu-%lu size %lu, should get %lu\n",
				i, req_range[i] >> 12,
				(req_range[i + 1] >> 12),
				req_range[i+2] >> 12,
				req_range[i+3] >> 12);
#endif
		check_mtree_alloc_rrange(mt,
				req_range[i]   >> 12, /* start */
				req_range[i+1] >> 12, /* end */
				req_range[i+2] >> 12, /* size */
				req_range[i+3] >> 12, /* expected address */
				req_range[i+4],       /* expected return */
				xa_mk_value(req_range[i] >> 12)); /* pointer */
		mt_validate(mt);
	}

	mt_set_non_kernel(1);
	mtree_erase(mt, 34148798727); /* create a deleted range. */
	mtree_erase(mt, 34148798725);
	check_mtree_alloc_rrange(mt, 0, 34359052173, 210253414,
			34148798725, 0, mt);

	mtree_destroy(mt);
}

static noinline void __init check_alloc_range(struct maple_tree *mt)
{
	/*
	 * Generated by:
	 * cat /proc/self/maps|awk '{print $1}'|
	 * awk -F "-" '{printf "0x%s, 0x%s, ", $1, $2}'
	 */

	static const unsigned long range[] = {
	/*      Inclusive     , Exclusive. */
		0x565234af2000, 0x565234af4000,
		0x565234af4000, 0x565234af9000,
		0x565234af9000, 0x565234afb000,
		0x565234afc000, 0x565234afd000,
		0x565234afd000, 0x565234afe000,
		0x565235def000, 0x565235e10000,
		0x7f36d4bfd000, 0x7f36d4ee2000,
		0x7f36d4ee2000, 0x7f36d4f04000,
		0x7f36d4f04000, 0x7f36d504c000,
		0x7f36d504c000, 0x7f36d5098000,
		0x7f36d5098000, 0x7f36d5099000,
		0x7f36d5099000, 0x7f36d509d000,
		0x7f36d509d000, 0x7f36d509f000,
		0x7f36d509f000, 0x7f36d50a5000,
		0x7f36d50b9000, 0x7f36d50db000,
		0x7f36d50db000, 0x7f36d50dc000,
		0x7f36d50dc000, 0x7f36d50fa000,
		0x7f36d50fa000, 0x7f36d5102000,
		0x7f36d5102000, 0x7f36d5103000,
		0x7f36d5103000, 0x7f36d5104000,
		0x7f36d5104000, 0x7f36d5105000,
		0x7fff5876b000, 0x7fff5878d000,
		0x7fff5878e000, 0x7fff58791000,
		0x7fff58791000, 0x7fff58793000,
	};
	static const unsigned long holes[] = {
		/* Start of hole, end of hole,  size of hole (+1) */
		0x565234afb000, 0x565234afc000, 0x1000,
		0x565234afe000, 0x565235def000, 0x12F1000,
		0x565235e10000, 0x7f36d4bfd000, 0x28E49EDED000,
	};

	/*
	 * req_range consists of 4 values.
	 * 1. min index
	 * 2. max index
	 * 3. size
	 * 4. number that should be returned.
	 * 5. return value
	 */
	static const unsigned long req_range[] = {
		0x565234af9000, /* Min */
		0x7fff58791000, /* Max */
		0x1000,         /* Size */
		0x565234afb000, /* First hole in our data of size 1000. */
		0,              /* Return value success. */

		0x0,            /* Min */
		0x7fff58791000, /* Max */
		0x1F00,         /* Size */
		0x0,            /* First hole in our data of size 2000. */
		0,              /* Return value success. */

		/* Test ascend. */
		34148797436 << 12, /* Min */
		0x7fff587AF000,    /* Max */
		0x3000,         /* Size */
		34148798629 << 12,             /* Expected location */
		0,              /* Return value success. */

		/* Test failing. */
		34148798623 << 12,  /* Min */
		34148798683 << 12,  /* Max */
		0x15000,            /* Size */
		0,             /* Expected location */
		-EBUSY,              /* Return value failed. */

		/* Test filling entire gap. */
		34148798623 << 12,  /* Min */
		0x7fff587AF000,    /* Max */
		0x10000,           /* Size */
		34148798632 << 12,             /* Expected location */
		0,              /* Return value success. */

		/* Test walking off the end of root. */
		0,                  /* Min */
		-1,                 /* Max */
		-1,                 /* Size */
		0,                  /* Expected location */
		-EBUSY,             /* Return value failure. */

		/* Test looking for too large a hole across entire range. */
		0,                  /* Min */
		-1,                 /* Max */
		4503599618982063UL << 12,  /* Size */
		34359052178 << 12,  /* Expected location */
		-EBUSY,             /* Return failure. */

		/* Test a single entry */
		34148798648 << 12,		/* Min */
		34148798648 << 12,		/* Max */
		4096,			/* Size of 1 */
		34148798648 << 12,	/* Location is the same as min/max */
		0,			/* Success */
	};
	int i, range_count = ARRAY_SIZE(range);
	int req_range_count = ARRAY_SIZE(req_range);
	unsigned long min = 0x565234af2000;
	MA_STATE(mas, mt, 0, 0);

	mtree_store_range(mt, MTREE_ALLOC_MAX, ULONG_MAX, XA_ZERO_ENTRY,
			  GFP_KERNEL);
	for (i = 0; i < range_count; i += 2) {
#define DEBUG_ALLOC_RANGE 0
#if DEBUG_ALLOC_RANGE
		pr_debug("\tInsert %lu-%lu\n", range[i] >> 12,
			 (range[i + 1] >> 12) - 1);
		mt_dump(mt, mt_dump_hex);
#endif
		check_insert_range(mt, range[i] >> 12, (range[i + 1] >> 12) - 1,
				xa_mk_value(range[i] >> 12), 0);
		mt_validate(mt);
	}



	mas_lock(&mas);
	for (i = 0; i < ARRAY_SIZE(holes); i += 3) {

#if DEBUG_ALLOC_RANGE
		pr_debug("\tGet empty %lu-%lu size %lu (%lx-%lx)\n", min >> 12,
			holes[i+1] >> 12, holes[i+2] >> 12,
			min, holes[i+1]);
#endif
		MT_BUG_ON(mt, mas_empty_area(&mas, min >> 12,
					holes[i+1] >> 12,
					holes[i+2] >> 12));
		MT_BUG_ON(mt, mas.index != holes[i] >> 12);
		min = holes[i+1];
		mas_reset(&mas);
	}
	mas_unlock(&mas);
	for (i = 0; i < req_range_count; i += 5) {
#if DEBUG_ALLOC_RANGE
		pr_debug("\tTest %d: %lu-%lu size %lu expected %lu (%lu-%lu)\n",
			 i/5, req_range[i]   >> 12, req_range[i + 1]   >> 12,
			 req_range[i + 2]   >> 12, req_range[i + 3]   >> 12,
			 req_range[i], req_range[i+1]);
#endif
		check_mtree_alloc_range(mt,
				req_range[i]   >> 12, /* start */
				req_range[i+1] >> 12, /* end */
				req_range[i+2] >> 12, /* size */
				req_range[i+3] >> 12, /* expected address */
				req_range[i+4],       /* expected return */
				xa_mk_value(req_range[i] >> 12)); /* pointer */
		mt_validate(mt);
#if DEBUG_ALLOC_RANGE
		mt_dump(mt, mt_dump_hex);
#endif
	}

	mtree_destroy(mt);
}
#endif

static noinline void __init check_ranges(struct maple_tree *mt)
{
	int i, val, val2;
	static const unsigned long r[] = {
		10, 15,
		20, 25,
		17, 22, /* Overlaps previous range. */
		9, 1000, /* Huge. */
		100, 200,
		45, 168,
		118, 128,
			};

	MT_BUG_ON(mt, !mtree_empty(mt));
	check_insert_range(mt, r[0], r[1], xa_mk_value(r[0]), 0);
	check_insert_range(mt, r[2], r[3], xa_mk_value(r[2]), 0);
	check_insert_range(mt, r[4], r[5], xa_mk_value(r[4]), -EEXIST);
	MT_BUG_ON(mt, !mt_height(mt));
	/* Store */
	check_store_range(mt, r[4], r[5], xa_mk_value(r[4]), 0);
	check_store_range(mt, r[6], r[7], xa_mk_value(r[6]), 0);
	check_store_range(mt, r[8], r[9], xa_mk_value(r[8]), 0);
	MT_BUG_ON(mt, !mt_height(mt));
	mtree_destroy(mt);
	MT_BUG_ON(mt, mt_height(mt));

	check_seq(mt, 50, false);
	mt_set_non_kernel(4);
	check_store_range(mt, 5, 47,  xa_mk_value(47), 0);
	MT_BUG_ON(mt, !mt_height(mt));
	mtree_destroy(mt);

	/* Create tree of 1-100 */
	check_seq(mt, 100, false);
	/* Store 45-168 */
	mt_set_non_kernel(10);
	check_store_range(mt, r[10], r[11], xa_mk_value(r[10]), 0);
	MT_BUG_ON(mt, !mt_height(mt));
	mtree_destroy(mt);

	/* Create tree of 1-200 */
	check_seq(mt, 200, false);
	/* Store 45-168 */
	check_store_range(mt, r[10], r[11], xa_mk_value(r[10]), 0);
	MT_BUG_ON(mt, !mt_height(mt));
	mtree_destroy(mt);

	check_seq(mt, 30, false);
	check_store_range(mt, 6, 18, xa_mk_value(6), 0);
	MT_BUG_ON(mt, !mt_height(mt));
	mtree_destroy(mt);

	/* Overwrite across multiple levels. */
	/* Create tree of 1-400 */
	check_seq(mt, 400, false);
	mt_set_non_kernel(50);
	/* Store 118-128 */
	check_store_range(mt, r[12], r[13], xa_mk_value(r[12]), 0);
	mt_set_non_kernel(50);
	mtree_test_erase(mt, 140);
	mtree_test_erase(mt, 141);
	mtree_test_erase(mt, 142);
	mtree_test_erase(mt, 143);
	mtree_test_erase(mt, 130);
	mtree_test_erase(mt, 131);
	mtree_test_erase(mt, 132);
	mtree_test_erase(mt, 133);
	mtree_test_erase(mt, 134);
	mtree_test_erase(mt, 135);
	check_load(mt, r[12], xa_mk_value(r[12]));
	check_load(mt, r[13], xa_mk_value(r[12]));
	check_load(mt, r[13] - 1, xa_mk_value(r[12]));
	check_load(mt, r[13] + 1, xa_mk_value(r[13] + 1));
	check_load(mt, 135, NULL);
	check_load(mt, 140, NULL);
	mt_set_non_kernel(0);
	MT_BUG_ON(mt, !mt_height(mt));
	mtree_destroy(mt);



	/* Overwrite multiple levels at the end of the tree (slot 7) */
	mt_set_non_kernel(50);
	check_seq(mt, 400, false);
	check_store_range(mt, 353, 361, xa_mk_value(353), 0);
	check_store_range(mt, 347, 352, xa_mk_value(347), 0);

	check_load(mt, 346, xa_mk_value(346));
	for (i = 347; i <= 352; i++)
		check_load(mt, i, xa_mk_value(347));
	for (i = 353; i <= 361; i++)
		check_load(mt, i, xa_mk_value(353));
	check_load(mt, 362, xa_mk_value(362));
	mt_set_non_kernel(0);
	MT_BUG_ON(mt, !mt_height(mt));
	mtree_destroy(mt);

	mt_set_non_kernel(50);
	check_seq(mt, 400, false);
	check_store_range(mt, 352, 364, NULL, 0);
	check_store_range(mt, 351, 363, xa_mk_value(352), 0);
	check_load(mt, 350, xa_mk_value(350));
	check_load(mt, 351, xa_mk_value(352));
	for (i = 352; i <= 363; i++)
		check_load(mt, i, xa_mk_value(352));
	check_load(mt, 364, NULL);
	check_load(mt, 365, xa_mk_value(365));
	mt_set_non_kernel(0);
	MT_BUG_ON(mt, !mt_height(mt));
	mtree_destroy(mt);

	mt_set_non_kernel(5);
	check_seq(mt, 400, false);
	check_store_range(mt, 352, 364, NULL, 0);
	check_store_range(mt, 351, 364, xa_mk_value(352), 0);
	check_load(mt, 350, xa_mk_value(350));
	check_load(mt, 351, xa_mk_value(352));
	for (i = 352; i <= 364; i++)
		check_load(mt, i, xa_mk_value(352));
	check_load(mt, 365, xa_mk_value(365));
	mt_set_non_kernel(0);
	MT_BUG_ON(mt, !mt_height(mt));
	mtree_destroy(mt);


	mt_set_non_kernel(50);
	check_seq(mt, 400, false);
	check_store_range(mt, 362, 367, xa_mk_value(362), 0);
	check_store_range(mt, 353, 361, xa_mk_value(353), 0);
	mt_set_non_kernel(0);
	mt_validate(mt);
	MT_BUG_ON(mt, !mt_height(mt));
	mtree_destroy(mt);
	/*
	 * Interesting cases:
	 * 1. Overwrite the end of a node and end in the first entry of the next
	 * node.
	 * 2. Split a single range
	 * 3. Overwrite the start of a range
	 * 4. Overwrite the end of a range
	 * 5. Overwrite the entire range
	 * 6. Overwrite a range that causes multiple parent nodes to be
	 * combined
	 * 7. Overwrite a range that causes multiple parent nodes and part of
	 * root to be combined
	 * 8. Overwrite the whole tree
	 * 9. Try to overwrite the zero entry of an alloc tree.
	 * 10. Write a range larger than a nodes current pivot
	 */

	mt_set_non_kernel(50);
	for (i = 0; i <= 500; i++) {
		val = i*5;
		val2 = (i+1)*5;
		check_store_range(mt, val, val2, xa_mk_value(val), 0);
	}
	check_store_range(mt, 2400, 2400, xa_mk_value(2400), 0);
	check_store_range(mt, 2411, 2411, xa_mk_value(2411), 0);
	check_store_range(mt, 2412, 2412, xa_mk_value(2412), 0);
	check_store_range(mt, 2396, 2400, xa_mk_value(4052020), 0);
	check_store_range(mt, 2402, 2402, xa_mk_value(2402), 0);
	mtree_destroy(mt);
	mt_set_non_kernel(0);

	mt_set_non_kernel(50);
	for (i = 0; i <= 500; i++) {
		val = i*5;
		val2 = (i+1)*5;
		check_store_range(mt, val, val2, xa_mk_value(val), 0);
	}
	check_store_range(mt, 2422, 2422, xa_mk_value(2422), 0);
	check_store_range(mt, 2424, 2424, xa_mk_value(2424), 0);
	check_store_range(mt, 2425, 2425, xa_mk_value(2), 0);
	check_store_range(mt, 2460, 2470, NULL, 0);
	check_store_range(mt, 2435, 2460, xa_mk_value(2435), 0);
	check_store_range(mt, 2461, 2470, xa_mk_value(2461), 0);
	mt_set_non_kernel(0);
	MT_BUG_ON(mt, !mt_height(mt));
	mtree_destroy(mt);

	/* Test rebalance gaps */
	mt_init_flags(mt, MT_FLAGS_ALLOC_RANGE);
	mt_set_non_kernel(50);
	for (i = 0; i <= 50; i++) {
		val = i*10;
		val2 = (i+1)*10;
		check_store_range(mt, val, val2, xa_mk_value(val), 0);
	}
	check_store_range(mt, 161, 161, xa_mk_value(161), 0);
	check_store_range(mt, 162, 162, xa_mk_value(162), 0);
	check_store_range(mt, 163, 163, xa_mk_value(163), 0);
	check_store_range(mt, 240, 249, NULL, 0);
	mtree_erase(mt, 200);
	mtree_erase(mt, 210);
	mtree_erase(mt, 220);
	mtree_erase(mt, 230);
	mt_set_non_kernel(0);
	MT_BUG_ON(mt, !mt_height(mt));
	mtree_destroy(mt);

	mt_init_flags(mt, MT_FLAGS_ALLOC_RANGE);
	for (i = 0; i <= 500; i++) {
		val = i*10;
		val2 = (i+1)*10;
		check_store_range(mt, val, val2, xa_mk_value(val), 0);
	}
	check_store_range(mt, 4600, 4959, xa_mk_value(1), 0);
	mt_validate(mt);
	MT_BUG_ON(mt, !mt_height(mt));
	mtree_destroy(mt);

	mt_init_flags(mt, MT_FLAGS_ALLOC_RANGE);
	for (i = 0; i <= 500; i++) {
		val = i*10;
		val2 = (i+1)*10;
		check_store_range(mt, val, val2, xa_mk_value(val), 0);
	}
	check_store_range(mt, 4811, 4811, xa_mk_value(4811), 0);
	check_store_range(mt, 4812, 4812, xa_mk_value(4812), 0);
	check_store_range(mt, 4861, 4861, xa_mk_value(4861), 0);
	check_store_range(mt, 4862, 4862, xa_mk_value(4862), 0);
	check_store_range(mt, 4842, 4849, NULL, 0);
	mt_validate(mt);
	MT_BUG_ON(mt, !mt_height(mt));
	mtree_destroy(mt);

	mt_init_flags(mt, MT_FLAGS_ALLOC_RANGE);
	for (i = 0; i <= 1300; i++) {
		val = i*10;
		val2 = (i+1)*10;
		check_store_range(mt, val, val2, xa_mk_value(val), 0);
		MT_BUG_ON(mt, mt_height(mt) >= 4);
	}
	/*  Cause a 3 child split all the way up the tree. */
	for (i = 5; i < 215; i += 10)
		check_store_range(mt, 11450 + i, 11450 + i + 1, NULL, 0);
	for (i = 5; i < 65; i += 10)
		check_store_range(mt, 11770 + i, 11770 + i + 1, NULL, 0);

	MT_BUG_ON(mt, mt_height(mt) >= 4);
	for (i = 5; i < 45; i += 10)
		check_store_range(mt, 11700 + i, 11700 + i + 1, NULL, 0);
	if (!MAPLE_32BIT)
		MT_BUG_ON(mt, mt_height(mt) < 4);
	mtree_destroy(mt);


	mt_init_flags(mt, MT_FLAGS_ALLOC_RANGE);
	for (i = 0; i <= 1200; i++) {
		val = i*10;
		val2 = (i+1)*10;
		check_store_range(mt, val, val2, xa_mk_value(val), 0);
		MT_BUG_ON(mt, mt_height(mt) >= 4);
	}
	/* Fill parents and leaves before split. */
	for (i = 5; i < 455; i += 10)
		check_store_range(mt, 7800 + i, 7800 + i + 1, NULL, 0);

	for (i = 1; i < 16; i++)
		check_store_range(mt, 8185 + i, 8185 + i + 1,
				  xa_mk_value(8185+i), 0);
	MT_BUG_ON(mt, mt_height(mt) >= 4);
	/* triple split across multiple levels. */
	check_store_range(mt, 8184, 8184, xa_mk_value(8184), 0);
	if (!MAPLE_32BIT)
		MT_BUG_ON(mt, mt_height(mt) != 4);
}

static noinline void __init check_next_entry(struct maple_tree *mt)
{
	void *entry = NULL;
	unsigned long limit = 30, i = 0;
	MA_STATE(mas, mt, i, i);

	MT_BUG_ON(mt, !mtree_empty(mt));

	check_seq(mt, limit, false);
	rcu_read_lock();

	/* Check the first one and get ma_state in the correct state. */
	MT_BUG_ON(mt, mas_walk(&mas) != xa_mk_value(i++));
	for ( ; i <= limit + 1; i++) {
		entry = mas_next(&mas, limit);
		if (i > limit)
			MT_BUG_ON(mt, entry != NULL);
		else
			MT_BUG_ON(mt, xa_mk_value(i) != entry);
	}
	rcu_read_unlock();
	mtree_destroy(mt);
}

static noinline void __init check_prev_entry(struct maple_tree *mt)
{
	unsigned long index = 16;
	void *value;
	int i;

	MA_STATE(mas, mt, index, index);

	MT_BUG_ON(mt, !mtree_empty(mt));
	check_seq(mt, 30, false);

	rcu_read_lock();
	value = mas_find(&mas, ULONG_MAX);
	MT_BUG_ON(mt, value != xa_mk_value(index));
	value = mas_prev(&mas, 0);
	MT_BUG_ON(mt, value != xa_mk_value(index - 1));
	rcu_read_unlock();
	mtree_destroy(mt);

	/* Check limits on prev */
	mt_init_flags(mt, MT_FLAGS_ALLOC_RANGE);
	mas_lock(&mas);
	for (i = 0; i <= index; i++) {
		mas_set_range(&mas, i*10, i*10+5);
		mas_store_gfp(&mas, xa_mk_value(i), GFP_KERNEL);
	}

	mas_set(&mas, 20);
	value = mas_walk(&mas);
	MT_BUG_ON(mt, value != xa_mk_value(2));

	value = mas_prev(&mas, 19);
	MT_BUG_ON(mt, value != NULL);

	mas_set(&mas, 80);
	value = mas_walk(&mas);
	MT_BUG_ON(mt, value != xa_mk_value(8));

	value = mas_prev(&mas, 76);
	MT_BUG_ON(mt, value != NULL);

	mas_unlock(&mas);
}

static noinline void __init check_root_expand(struct maple_tree *mt)
{
	MA_STATE(mas, mt, 0, 0);
	void *ptr;


	mas_lock(&mas);
	mas_set(&mas, 3);
	ptr = mas_walk(&mas);
	MT_BUG_ON(mt, mas.index != 0);
	MT_BUG_ON(mt, ptr != NULL);
	MT_BUG_ON(mt, mas.index != 0);
	MT_BUG_ON(mt, mas.last != ULONG_MAX);

	ptr = &check_prev_entry;
	mas_set(&mas, 1);
	mas_store_gfp(&mas, ptr, GFP_KERNEL);

	mas_set(&mas, 0);
	ptr = mas_walk(&mas);
	MT_BUG_ON(mt, ptr != NULL);

	mas_set(&mas, 1);
	ptr = mas_walk(&mas);
	MT_BUG_ON(mt, ptr != &check_prev_entry);

	mas_set(&mas, 2);
	ptr = mas_walk(&mas);
	MT_BUG_ON(mt, ptr != NULL);
	mas_unlock(&mas);
	mtree_destroy(mt);


	mt_init_flags(mt, 0);
	mas_lock(&mas);

	mas_set(&mas, 0);
	ptr = &check_prev_entry;
	mas_store_gfp(&mas, ptr, GFP_KERNEL);

	mas_set(&mas, 5);
	ptr = mas_walk(&mas);
	MT_BUG_ON(mt, ptr != NULL);
	MT_BUG_ON(mt, mas.index != 1);
	MT_BUG_ON(mt, mas.last != ULONG_MAX);

	mas_set_range(&mas, 0, 100);
	ptr = mas_walk(&mas);
	MT_BUG_ON(mt, ptr != &check_prev_entry);
	MT_BUG_ON(mt, mas.last != 0);
	mas_unlock(&mas);
	mtree_destroy(mt);

	mt_init_flags(mt, 0);
	mas_lock(&mas);

	mas_set(&mas, 0);
	ptr = (void *)((unsigned long) check_prev_entry | 1UL);
	mas_store_gfp(&mas, ptr, GFP_KERNEL);
	ptr = mas_next(&mas, ULONG_MAX);
	MT_BUG_ON(mt, ptr != NULL);
	MT_BUG_ON(mt, (mas.index != 1) && (mas.last != ULONG_MAX));

	mas_set(&mas, 1);
	ptr = mas_prev(&mas, 0);
	MT_BUG_ON(mt, (mas.index != 0) && (mas.last != 0));
	MT_BUG_ON(mt, ptr != (void *)((unsigned long) check_prev_entry | 1UL));

	mas_unlock(&mas);

	mtree_destroy(mt);

	mt_init_flags(mt, 0);
	mas_lock(&mas);
	mas_set(&mas, 0);
	ptr = (void *)((unsigned long) check_prev_entry | 2UL);
	mas_store_gfp(&mas, ptr, GFP_KERNEL);
	ptr = mas_next(&mas, ULONG_MAX);
	MT_BUG_ON(mt, ptr != NULL);
	MT_BUG_ON(mt, (mas.index != ULONG_MAX) && (mas.last != ULONG_MAX));

	mas_set(&mas, 1);
	ptr = mas_prev(&mas, 0);
	MT_BUG_ON(mt, (mas.index != 0) && (mas.last != 0));
	MT_BUG_ON(mt, ptr != (void *)((unsigned long) check_prev_entry | 2UL));


	mas_unlock(&mas);
}

static noinline void __init check_gap_combining(struct maple_tree *mt)
{
	struct maple_enode *mn1, *mn2;
	void *entry;
	unsigned long singletons = 100;
	static const unsigned long *seq100;
	static const unsigned long seq100_64[] = {
		/* 0-5 */
		74, 75, 76,
		50, 100, 2,

		/* 6-12 */
		44, 45, 46, 43,
		20, 50, 3,

		/* 13-20*/
		80, 81, 82,
		76, 2, 79, 85, 4,
	};

	static const unsigned long seq100_32[] = {
		/* 0-5 */
		61, 62, 63,
		50, 100, 2,

		/* 6-12 */
		31, 32, 33, 30,
		20, 50, 3,

		/* 13-20*/
		80, 81, 82,
		76, 2, 79, 85, 4,
	};

	static const unsigned long seq2000[] = {
		1152, 1151,
		1100, 1200, 2,
	};
	static const unsigned long seq400[] = {
		286, 318,
		256, 260, 266, 270, 275, 280, 290, 398,
		286, 310,
	};

	unsigned long index;

	MA_STATE(mas, mt, 0, 0);

	if (MAPLE_32BIT)
		seq100 = seq100_32;
	else
		seq100 = seq100_64;

	index = seq100[0];
	mas_set(&mas, index);
	MT_BUG_ON(mt, !mtree_empty(mt));
	check_seq(mt, singletons, false); /* create 100 singletons. */

	mt_set_non_kernel(1);
	mtree_test_erase(mt, seq100[2]);
	check_load(mt, seq100[2], NULL);
	mtree_test_erase(mt, seq100[1]);
	check_load(mt, seq100[1], NULL);

	rcu_read_lock();
	entry = mas_find(&mas, ULONG_MAX);
	MT_BUG_ON(mt, entry != xa_mk_value(index));
	mn1 = mas.node;
	mas_next(&mas, ULONG_MAX);
	entry = mas_next(&mas, ULONG_MAX);
	MT_BUG_ON(mt, entry != xa_mk_value(index + 4));
	mn2 = mas.node;
	MT_BUG_ON(mt, mn1 == mn2); /* test the test. */

	/*
	 * At this point, there is a gap of 2 at index + 1 between seq100[3] and
	 * seq100[4]. Search for the gap.
	 */
	mt_set_non_kernel(1);
	mas_reset(&mas);
	MT_BUG_ON(mt, mas_empty_area_rev(&mas, seq100[3], seq100[4],
					     seq100[5]));
	MT_BUG_ON(mt, mas.index != index + 1);
	rcu_read_unlock();

	mtree_test_erase(mt, seq100[6]);
	check_load(mt, seq100[6], NULL);
	mtree_test_erase(mt, seq100[7]);
	check_load(mt, seq100[7], NULL);
	mtree_test_erase(mt, seq100[8]);
	index = seq100[9];

	rcu_read_lock();
	mas.index = index;
	mas.last = index;
	mas_reset(&mas);
	entry = mas_find(&mas, ULONG_MAX);
	MT_BUG_ON(mt, entry != xa_mk_value(index));
	mn1 = mas.node;
	entry = mas_next(&mas, ULONG_MAX);
	MT_BUG_ON(mt, entry != xa_mk_value(index + 4));
	mas_next(&mas, ULONG_MAX); /* go to the next entry. */
	mn2 = mas.node;
	MT_BUG_ON(mt, mn1 == mn2); /* test the next entry is in the next node. */

	/*
	 * At this point, there is a gap of 3 at seq100[6].  Find it by
	 * searching 20 - 50 for size 3.
	 */
	mas_reset(&mas);
	MT_BUG_ON(mt, mas_empty_area_rev(&mas, seq100[10], seq100[11],
					     seq100[12]));
	MT_BUG_ON(mt, mas.index != seq100[6]);
	rcu_read_unlock();

	mt_set_non_kernel(1);
	mtree_store(mt, seq100[13], NULL, GFP_KERNEL);
	check_load(mt, seq100[13], NULL);
	check_load(mt, seq100[14], xa_mk_value(seq100[14]));
	mtree_store(mt, seq100[14], NULL, GFP_KERNEL);
	check_load(mt, seq100[13], NULL);
	check_load(mt, seq100[14], NULL);

	mas_reset(&mas);
	rcu_read_lock();
	MT_BUG_ON(mt, mas_empty_area_rev(&mas, seq100[16], seq100[15],
					     seq100[17]));
	MT_BUG_ON(mt, mas.index != seq100[13]);
	mt_validate(mt);
	rcu_read_unlock();

	/*
	 * *DEPRECATED: no retries anymore* Test retry entry in the start of a
	 * gap.
	 */
	mt_set_non_kernel(2);
	mtree_test_store_range(mt, seq100[18], seq100[14], NULL);
	mtree_test_erase(mt, seq100[15]);
	mas_reset(&mas);
	rcu_read_lock();
	MT_BUG_ON(mt, mas_empty_area_rev(&mas, seq100[16], seq100[19],
					     seq100[20]));
	rcu_read_unlock();
	MT_BUG_ON(mt, mas.index != seq100[18]);
	mt_validate(mt);
	mtree_destroy(mt);

	/* seq 2000 tests are for multi-level tree gaps */
	mt_init_flags(mt, MT_FLAGS_ALLOC_RANGE);
	check_seq(mt, 2000, false);
	mt_set_non_kernel(1);
	mtree_test_erase(mt, seq2000[0]);
	mtree_test_erase(mt, seq2000[1]);

	mt_set_non_kernel(2);
	mas_reset(&mas);
	rcu_read_lock();
	MT_BUG_ON(mt, mas_empty_area_rev(&mas, seq2000[2], seq2000[3],
					     seq2000[4]));
	MT_BUG_ON(mt, mas.index != seq2000[1]);
	rcu_read_unlock();
	mt_validate(mt);
	mtree_destroy(mt);

	/* seq 400 tests rebalancing over two levels. */
	mt_set_non_kernel(99);
	mt_init_flags(mt, MT_FLAGS_ALLOC_RANGE);
	check_seq(mt, 400, false);
	mtree_test_store_range(mt, seq400[0], seq400[1], NULL);
	mt_set_non_kernel(0);
	mtree_destroy(mt);

	mt_init_flags(mt, MT_FLAGS_ALLOC_RANGE);
	check_seq(mt, 400, false);
	mt_set_non_kernel(50);
	mtree_test_store_range(mt, seq400[2], seq400[9],
			       xa_mk_value(seq400[2]));
	mtree_test_store_range(mt, seq400[3], seq400[9],
			       xa_mk_value(seq400[3]));
	mtree_test_store_range(mt, seq400[4], seq400[9],
			       xa_mk_value(seq400[4]));
	mtree_test_store_range(mt, seq400[5], seq400[9],
			       xa_mk_value(seq400[5]));
	mtree_test_store_range(mt, seq400[0], seq400[9],
			       xa_mk_value(seq400[0]));
	mtree_test_store_range(mt, seq400[6], seq400[9],
			       xa_mk_value(seq400[6]));
	mtree_test_store_range(mt, seq400[7], seq400[9],
			       xa_mk_value(seq400[7]));
	mtree_test_store_range(mt, seq400[8], seq400[9],
			       xa_mk_value(seq400[8]));
	mtree_test_store_range(mt, seq400[10], seq400[11],
			       xa_mk_value(seq400[10]));
	mt_validate(mt);
	mt_set_non_kernel(0);
	mtree_destroy(mt);
}
static noinline void __init check_node_overwrite(struct maple_tree *mt)
{
	int i, max = 4000;

	for (i = 0; i < max; i++)
		mtree_test_store_range(mt, i*100, i*100 + 50, xa_mk_value(i*100));

	mtree_test_store_range(mt, 319951, 367950, NULL);
	/*mt_dump(mt, mt_dump_dec); */
	mt_validate(mt);
}

#if defined(BENCH_SLOT_STORE)
static noinline void __init bench_slot_store(struct maple_tree *mt)
{
	int i, brk = 105, max = 1040, brk_start = 100, count = 20000000;

	for (i = 0; i < max; i += 10)
		mtree_store_range(mt, i, i + 5, xa_mk_value(i), GFP_KERNEL);

	for (i = 0; i < count; i++) {
		mtree_store_range(mt, brk, brk, NULL, GFP_KERNEL);
		mtree_store_range(mt, brk_start, brk, xa_mk_value(brk),
				  GFP_KERNEL);
	}
}
#endif

#if defined(BENCH_NODE_STORE)
static noinline void __init bench_node_store(struct maple_tree *mt)
{
	int i, overwrite = 76, max = 240, count = 20000000;

	for (i = 0; i < max; i += 10)
		mtree_store_range(mt, i, i + 5, xa_mk_value(i), GFP_KERNEL);

	for (i = 0; i < count; i++) {
		mtree_store_range(mt, overwrite,  overwrite + 15,
				  xa_mk_value(overwrite), GFP_KERNEL);

		overwrite += 5;
		if (overwrite >= 135)
			overwrite = 76;
	}
}
#endif

#if defined(BENCH_AWALK)
static noinline void __init bench_awalk(struct maple_tree *mt)
{
	int i, max = 2500, count = 50000000;
	MA_STATE(mas, mt, 1470, 1470);

	for (i = 0; i < max; i += 10)
		mtree_store_range(mt, i, i + 5, xa_mk_value(i), GFP_KERNEL);

	mtree_store_range(mt, 1470, 1475, NULL, GFP_KERNEL);

	for (i = 0; i < count; i++) {
		mas_empty_area_rev(&mas, 0, 2000, 10);
		mas_reset(&mas);
	}
}
#endif
#if defined(BENCH_WALK)
static noinline void __init bench_walk(struct maple_tree *mt)
{
	int i, max = 2500, count = 550000000;
	MA_STATE(mas, mt, 1470, 1470);

	for (i = 0; i < max; i += 10)
		mtree_store_range(mt, i, i + 5, xa_mk_value(i), GFP_KERNEL);

	for (i = 0; i < count; i++) {
		mas_walk(&mas);
		mas_reset(&mas);
	}

}
#endif

#if defined(BENCH_MT_FOR_EACH)
static noinline void __init bench_mt_for_each(struct maple_tree *mt)
{
	int i, count = 1000000;
	unsigned long max = 2500, index = 0;
	void *entry;

	for (i = 0; i < max; i += 5)
		mtree_store_range(mt, i, i + 4, xa_mk_value(i), GFP_KERNEL);

	for (i = 0; i < count; i++) {
		unsigned long j = 0;

		mt_for_each(mt, entry, index, max) {
			MT_BUG_ON(mt, entry != xa_mk_value(j));
			j += 5;
		}

		index = 0;
	}

}
#endif

/* check_forking - simulate the kernel forking sequence with the tree. */
static noinline void __init check_forking(struct maple_tree *mt)
{

	struct maple_tree newmt;
	int i, nr_entries = 134;
	void *val;
	MA_STATE(mas, mt, 0, 0);
	MA_STATE(newmas, mt, 0, 0);

	for (i = 0; i <= nr_entries; i++)
		mtree_store_range(mt, i*10, i*10 + 5,
				  xa_mk_value(i), GFP_KERNEL);

	mt_set_non_kernel(99999);
	mt_init_flags(&newmt, MT_FLAGS_ALLOC_RANGE);
	newmas.tree = &newmt;
	mas_reset(&newmas);
	mas_reset(&mas);
	mas_lock(&newmas);
	mas.index = 0;
	mas.last = 0;
	if (mas_expected_entries(&newmas, nr_entries)) {
		pr_err("OOM!");
		BUG_ON(1);
	}
	rcu_read_lock();
	mas_for_each(&mas, val, ULONG_MAX) {
		newmas.index = mas.index;
		newmas.last = mas.last;
		mas_store(&newmas, val);
	}
	rcu_read_unlock();
	mas_destroy(&newmas);
	mas_unlock(&newmas);
	mt_validate(&newmt);
	mt_set_non_kernel(0);
	mtree_destroy(&newmt);
}

static noinline void __init check_iteration(struct maple_tree *mt)
{
	int i, nr_entries = 125;
	void *val;
	MA_STATE(mas, mt, 0, 0);

	for (i = 0; i <= nr_entries; i++)
		mtree_store_range(mt, i * 10, i * 10 + 9,
				  xa_mk_value(i), GFP_KERNEL);

	mt_set_non_kernel(99999);

	i = 0;
	mas_lock(&mas);
	mas_for_each(&mas, val, 925) {
		MT_BUG_ON(mt, mas.index != i * 10);
		MT_BUG_ON(mt, mas.last != i * 10 + 9);
		/* Overwrite end of entry 92 */
		if (i == 92) {
			mas.index = 925;
			mas.last = 929;
			mas_store(&mas, val);
		}
		i++;
	}
	/* Ensure mas_find() gets the next value */
	val = mas_find(&mas, ULONG_MAX);
	MT_BUG_ON(mt, val != xa_mk_value(i));

	mas_set(&mas, 0);
	i = 0;
	mas_for_each(&mas, val, 785) {
		MT_BUG_ON(mt, mas.index != i * 10);
		MT_BUG_ON(mt, mas.last != i * 10 + 9);
		/* Overwrite start of entry 78 */
		if (i == 78) {
			mas.index = 780;
			mas.last = 785;
			mas_store(&mas, val);
		} else {
			i++;
		}
	}
	val = mas_find(&mas, ULONG_MAX);
	MT_BUG_ON(mt, val != xa_mk_value(i));

	mas_set(&mas, 0);
	i = 0;
	mas_for_each(&mas, val, 765) {
		MT_BUG_ON(mt, mas.index != i * 10);
		MT_BUG_ON(mt, mas.last != i * 10 + 9);
		/* Overwrite end of entry 76 and advance to the end */
		if (i == 76) {
			mas.index = 760;
			mas.last = 765;
			mas_store(&mas, val);
		}
		i++;
	}
	/* Make sure the next find returns the one after 765, 766-769 */
	val = mas_find(&mas, ULONG_MAX);
	MT_BUG_ON(mt, val != xa_mk_value(76));
	mas_unlock(&mas);
	mas_destroy(&mas);
	mt_set_non_kernel(0);
}

static noinline void __init check_mas_store_gfp(struct maple_tree *mt)
{

	struct maple_tree newmt;
	int i, nr_entries = 135;
	void *val;
	MA_STATE(mas, mt, 0, 0);
	MA_STATE(newmas, mt, 0, 0);

	for (i = 0; i <= nr_entries; i++)
		mtree_store_range(mt, i*10, i*10 + 5,
				  xa_mk_value(i), GFP_KERNEL);

	mt_set_non_kernel(99999);
	mt_init_flags(&newmt, MT_FLAGS_ALLOC_RANGE);
	newmas.tree = &newmt;
	rcu_read_lock();
	mas_lock(&newmas);
	mas_reset(&newmas);
	mas_set(&mas, 0);
	mas_for_each(&mas, val, ULONG_MAX) {
		newmas.index = mas.index;
		newmas.last = mas.last;
		mas_store_gfp(&newmas, val, GFP_KERNEL);
	}
	mas_unlock(&newmas);
	rcu_read_unlock();
	mt_validate(&newmt);
	mt_set_non_kernel(0);
	mtree_destroy(&newmt);
}

#if defined(BENCH_FORK)
static noinline void __init bench_forking(struct maple_tree *mt)
{

	struct maple_tree newmt;
	int i, nr_entries = 134, nr_fork = 80000;
	void *val;
	MA_STATE(mas, mt, 0, 0);
	MA_STATE(newmas, mt, 0, 0);

	for (i = 0; i <= nr_entries; i++)
		mtree_store_range(mt, i*10, i*10 + 5,
				  xa_mk_value(i), GFP_KERNEL);

	for (i = 0; i < nr_fork; i++) {
		mt_set_non_kernel(99999);
		mt_init_flags(&newmt, MT_FLAGS_ALLOC_RANGE);
		newmas.tree = &newmt;
		mas_reset(&newmas);
		mas_reset(&mas);
		mas.index = 0;
		mas.last = 0;
		rcu_read_lock();
		mas_lock(&newmas);
		if (mas_expected_entries(&newmas, nr_entries)) {
			printk("OOM!");
			BUG_ON(1);
		}
		mas_for_each(&mas, val, ULONG_MAX) {
			newmas.index = mas.index;
			newmas.last = mas.last;
			mas_store(&newmas, val);
		}
		mas_destroy(&newmas);
		mas_unlock(&newmas);
		rcu_read_unlock();
		mt_validate(&newmt);
		mt_set_non_kernel(0);
		mtree_destroy(&newmt);
	}
}
#endif

static noinline void __init next_prev_test(struct maple_tree *mt)
{
	int i, nr_entries;
	void *val;
	MA_STATE(mas, mt, 0, 0);
	struct maple_enode *mn;
	static const unsigned long *level2;
	static const unsigned long level2_64[] = { 707, 1000, 710, 715, 720,
						   725};
	static const unsigned long level2_32[] = { 1747, 2000, 1750, 1755,
						   1760, 1765};
	unsigned long last_index;

	if (MAPLE_32BIT) {
		nr_entries = 500;
		level2 = level2_32;
		last_index = 0x138e;
	} else {
		nr_entries = 200;
		level2 = level2_64;
		last_index = 0x7d6;
	}

	for (i = 0; i <= nr_entries; i++)
		mtree_store_range(mt, i*10, i*10 + 5,
				  xa_mk_value(i), GFP_KERNEL);

	mas_lock(&mas);
	for (i = 0; i <= nr_entries / 2; i++) {
		mas_next(&mas, 1000);
		if (mas_is_none(&mas))
			break;

	}
	mas_reset(&mas);
	mas_set(&mas, 0);
	i = 0;
	mas_for_each(&mas, val, 1000) {
		i++;
	}

	mas_reset(&mas);
	mas_set(&mas, 0);
	i = 0;
	mas_for_each(&mas, val, 1000) {
		mas_pause(&mas);
		i++;
	}

	/*
	 * 680 - 685 = 0x61a00001930c
	 * 686 - 689 = NULL;
	 * 690 - 695 = 0x61a00001930c
	 * Check simple next/prev
	 */
	mas_set(&mas, 686);
	val = mas_walk(&mas);
	MT_BUG_ON(mt, val != NULL);

	val = mas_next(&mas, 1000);
	MT_BUG_ON(mt, val != xa_mk_value(690 / 10));
	MT_BUG_ON(mt, mas.index != 690);
	MT_BUG_ON(mt, mas.last != 695);

	val = mas_prev(&mas, 0);
	MT_BUG_ON(mt, val != xa_mk_value(680 / 10));
	MT_BUG_ON(mt, mas.index != 680);
	MT_BUG_ON(mt, mas.last != 685);

	val = mas_next(&mas, 1000);
	MT_BUG_ON(mt, val != xa_mk_value(690 / 10));
	MT_BUG_ON(mt, mas.index != 690);
	MT_BUG_ON(mt, mas.last != 695);

	val = mas_next(&mas, 1000);
	MT_BUG_ON(mt, val != xa_mk_value(700 / 10));
	MT_BUG_ON(mt, mas.index != 700);
	MT_BUG_ON(mt, mas.last != 705);

	/* Check across node boundaries of the tree */
	mas_set(&mas, 70);
	val = mas_walk(&mas);
	MT_BUG_ON(mt, val != xa_mk_value(70 / 10));
	MT_BUG_ON(mt, mas.index != 70);
	MT_BUG_ON(mt, mas.last != 75);

	val = mas_next(&mas, 1000);
	MT_BUG_ON(mt, val != xa_mk_value(80 / 10));
	MT_BUG_ON(mt, mas.index != 80);
	MT_BUG_ON(mt, mas.last != 85);

	val = mas_prev(&mas, 70);
	MT_BUG_ON(mt, val != xa_mk_value(70 / 10));
	MT_BUG_ON(mt, mas.index != 70);
	MT_BUG_ON(mt, mas.last != 75);

	/* Check across two levels of the tree */
	mas_reset(&mas);
	mas_set(&mas, level2[0]);
	val = mas_walk(&mas);
	MT_BUG_ON(mt, val != NULL);
	val = mas_next(&mas, level2[1]);
	MT_BUG_ON(mt, val != xa_mk_value(level2[2] / 10));
	MT_BUG_ON(mt, mas.index != level2[2]);
	MT_BUG_ON(mt, mas.last != level2[3]);
	mn = mas.node;

	val = mas_next(&mas, level2[1]);
	MT_BUG_ON(mt, val != xa_mk_value(level2[4] / 10));
	MT_BUG_ON(mt, mas.index != level2[4]);
	MT_BUG_ON(mt, mas.last != level2[5]);
	MT_BUG_ON(mt, mn == mas.node);

	val = mas_prev(&mas, 0);
	MT_BUG_ON(mt, val != xa_mk_value(level2[2] / 10));
	MT_BUG_ON(mt, mas.index != level2[2]);
	MT_BUG_ON(mt, mas.last != level2[3]);

	/* Check running off the end and back on */
	mas_set(&mas, nr_entries * 10);
	val = mas_walk(&mas);
	MT_BUG_ON(mt, val != xa_mk_value(nr_entries));
	MT_BUG_ON(mt, mas.index != (nr_entries * 10));
	MT_BUG_ON(mt, mas.last != (nr_entries * 10 + 5));

	val = mas_next(&mas, ULONG_MAX);
	MT_BUG_ON(mt, val != NULL);
	MT_BUG_ON(mt, mas.index != last_index);
	MT_BUG_ON(mt, mas.last != ULONG_MAX);

	val = mas_prev(&mas, 0);
	MT_BUG_ON(mt, val != xa_mk_value(nr_entries));
	MT_BUG_ON(mt, mas.index != (nr_entries * 10));
	MT_BUG_ON(mt, mas.last != (nr_entries * 10 + 5));

	/* Check running off the start and back on */
	mas_reset(&mas);
	mas_set(&mas, 10);
	val = mas_walk(&mas);
	MT_BUG_ON(mt, val != xa_mk_value(1));
	MT_BUG_ON(mt, mas.index != 10);
	MT_BUG_ON(mt, mas.last != 15);

	val = mas_prev(&mas, 0);
	MT_BUG_ON(mt, val != xa_mk_value(0));
	MT_BUG_ON(mt, mas.index != 0);
	MT_BUG_ON(mt, mas.last != 5);

	val = mas_prev(&mas, 0);
	MT_BUG_ON(mt, val != NULL);
	MT_BUG_ON(mt, mas.index != 0);
	MT_BUG_ON(mt, mas.last != 5);
	MT_BUG_ON(mt, mas.node != MAS_NONE);

	mas.index = 0;
	mas.last = 5;
	mas_store(&mas, NULL);
	mas_reset(&mas);
	mas_set(&mas, 10);
	mas_walk(&mas);

	val = mas_prev(&mas, 0);
	MT_BUG_ON(mt, val != NULL);
	MT_BUG_ON(mt, mas.index != 0);
	MT_BUG_ON(mt, mas.last != 9);
	mas_unlock(&mas);

	mtree_destroy(mt);

	mt_init(mt);
	mtree_store_range(mt, 0, 0, xa_mk_value(0), GFP_KERNEL);
	mtree_store_range(mt, 5, 5, xa_mk_value(5), GFP_KERNEL);
	rcu_read_lock();
	mas_set(&mas, 5);
	val = mas_prev(&mas, 4);
	MT_BUG_ON(mt, val != NULL);
	rcu_read_unlock();
}



/* Test spanning writes that require balancing right sibling or right cousin */
static noinline void __init check_spanning_relatives(struct maple_tree *mt)
{

	unsigned long i, nr_entries = 1000;

	for (i = 0; i <= nr_entries; i++)
		mtree_store_range(mt, i*10, i*10 + 5,
				  xa_mk_value(i), GFP_KERNEL);


	mtree_store_range(mt, 9365, 9955, NULL, GFP_KERNEL);
}

static noinline void __init check_fuzzer(struct maple_tree *mt)
{
	/*
	 * 1. Causes a spanning rebalance of a single root node.
	 * Fixed by setting the correct limit in mast_cp_to_nodes() when the
	 * entire right side is consumed.
	 */
	mtree_test_insert(mt, 88, (void *)0xb1);
	mtree_test_insert(mt, 84, (void *)0xa9);
	mtree_test_insert(mt, 2,  (void *)0x5);
	mtree_test_insert(mt, 4,  (void *)0x9);
	mtree_test_insert(mt, 14, (void *)0x1d);
	mtree_test_insert(mt, 7,  (void *)0xf);
	mtree_test_insert(mt, 12, (void *)0x19);
	mtree_test_insert(mt, 18, (void *)0x25);
	mtree_test_store_range(mt, 8, 18, (void *)0x11);
	mtree_destroy(mt);


	/*
	 * 2. Cause a spanning rebalance of two nodes in root.
	 * Fixed by setting mast->r->max correctly.
	 */
	mt_init_flags(mt, 0);
	mtree_test_store(mt, 87, (void *)0xaf);
	mtree_test_store(mt, 0, (void *)0x1);
	mtree_test_load(mt, 4);
	mtree_test_insert(mt, 4, (void *)0x9);
	mtree_test_store(mt, 8, (void *)0x11);
	mtree_test_store(mt, 44, (void *)0x59);
	mtree_test_store(mt, 68, (void *)0x89);
	mtree_test_store(mt, 2, (void *)0x5);
	mtree_test_insert(mt, 43, (void *)0x57);
	mtree_test_insert(mt, 24, (void *)0x31);
	mtree_test_insert(mt, 844, (void *)0x699);
	mtree_test_store(mt, 84, (void *)0xa9);
	mtree_test_store(mt, 4, (void *)0x9);
	mtree_test_erase(mt, 4);
	mtree_test_load(mt, 5);
	mtree_test_erase(mt, 0);
	mtree_destroy(mt);

	/*
	 * 3. Cause a node overflow on copy
	 * Fixed by using the correct check for node size in mas_wr_modify()
	 * Also discovered issue with metadata setting.
	 */
	mt_init_flags(mt, 0);
	mtree_test_store_range(mt, 0, ULONG_MAX, (void *)0x1);
	mtree_test_store(mt, 4, (void *)0x9);
	mtree_test_erase(mt, 5);
	mtree_test_erase(mt, 0);
	mtree_test_erase(mt, 4);
	mtree_test_store(mt, 5, (void *)0xb);
	mtree_test_erase(mt, 5);
	mtree_test_store(mt, 5, (void *)0xb);
	mtree_test_erase(mt, 5);
	mtree_test_erase(mt, 4);
	mtree_test_store(mt, 4, (void *)0x9);
	mtree_test_store(mt, 444, (void *)0x379);
	mtree_test_store(mt, 0, (void *)0x1);
	mtree_test_load(mt, 0);
	mtree_test_store(mt, 5, (void *)0xb);
	mtree_test_erase(mt, 0);
	mtree_destroy(mt);

	/*
	 * 4. spanning store failure due to writing incorrect pivot value at
	 * last slot.
	 * Fixed by setting mast->r->max correctly in mast_cp_to_nodes()
	 *
	 */
	mt_init_flags(mt, 0);
	mtree_test_insert(mt, 261, (void *)0x20b);
	mtree_test_store(mt, 516, (void *)0x409);
	mtree_test_store(mt, 6, (void *)0xd);
	mtree_test_insert(mt, 5, (void *)0xb);
	mtree_test_insert(mt, 1256, (void *)0x9d1);
	mtree_test_store(mt, 4, (void *)0x9);
	mtree_test_erase(mt, 1);
	mtree_test_store(mt, 56, (void *)0x71);
	mtree_test_insert(mt, 1, (void *)0x3);
	mtree_test_store(mt, 24, (void *)0x31);
	mtree_test_erase(mt, 1);
	mtree_test_insert(mt, 2263, (void *)0x11af);
	mtree_test_insert(mt, 446, (void *)0x37d);
	mtree_test_store_range(mt, 6, 45, (void *)0xd);
	mtree_test_store_range(mt, 3, 446, (void *)0x7);
	mtree_destroy(mt);

	/*
	 * 5. mas_wr_extend_null() may overflow slots.
	 * Fix by checking against wr_mas->node_end.
	 */
	mt_init_flags(mt, 0);
	mtree_test_store(mt, 48, (void *)0x61);
	mtree_test_store(mt, 3, (void *)0x7);
	mtree_test_load(mt, 0);
	mtree_test_store(mt, 88, (void *)0xb1);
	mtree_test_store(mt, 81, (void *)0xa3);
	mtree_test_insert(mt, 0, (void *)0x1);
	mtree_test_insert(mt, 8, (void *)0x11);
	mtree_test_insert(mt, 4, (void *)0x9);
	mtree_test_insert(mt, 2480, (void *)0x1361);
	mtree_test_insert(mt, ULONG_MAX,
			  (void *)0xffffffffffffffff);
	mtree_test_erase(mt, ULONG_MAX);
	mtree_destroy(mt);

	/*
	 * 6.  When reusing a node with an implied pivot and the node is
	 * shrinking, old data would be left in the implied slot
	 * Fixed by checking the last pivot for the mas->max and clear
	 * accordingly.  This only affected the left-most node as that node is
	 * the only one allowed to end in NULL.
	 */
	mt_init_flags(mt, 0);
	mtree_test_erase(mt, 3);
	mtree_test_insert(mt, 22, (void *)0x2d);
	mtree_test_insert(mt, 15, (void *)0x1f);
	mtree_test_load(mt, 2);
	mtree_test_insert(mt, 1, (void *)0x3);
	mtree_test_insert(mt, 1, (void *)0x3);
	mtree_test_insert(mt, 5, (void *)0xb);
	mtree_test_erase(mt, 1);
	mtree_test_insert(mt, 1, (void *)0x3);
	mtree_test_insert(mt, 4, (void *)0x9);
	mtree_test_insert(mt, 1, (void *)0x3);
	mtree_test_erase(mt, 1);
	mtree_test_insert(mt, 2, (void *)0x5);
	mtree_test_insert(mt, 1, (void *)0x3);
	mtree_test_erase(mt, 3);
	mtree_test_insert(mt, 22, (void *)0x2d);
	mtree_test_insert(mt, 15, (void *)0x1f);
	mtree_test_insert(mt, 2, (void *)0x5);
	mtree_test_insert(mt, 1, (void *)0x3);
	mtree_test_insert(mt, 8, (void *)0x11);
	mtree_test_load(mt, 2);
	mtree_test_insert(mt, 1, (void *)0x3);
	mtree_test_insert(mt, 1, (void *)0x3);
	mtree_test_store(mt, 1, (void *)0x3);
	mtree_test_insert(mt, 5, (void *)0xb);
	mtree_test_erase(mt, 1);
	mtree_test_insert(mt, 1, (void *)0x3);
	mtree_test_insert(mt, 4, (void *)0x9);
	mtree_test_insert(mt, 1, (void *)0x3);
	mtree_test_erase(mt, 1);
	mtree_test_insert(mt, 2, (void *)0x5);
	mtree_test_insert(mt, 1, (void *)0x3);
	mtree_test_erase(mt, 3);
	mtree_test_insert(mt, 22, (void *)0x2d);
	mtree_test_insert(mt, 15, (void *)0x1f);
	mtree_test_insert(mt, 2, (void *)0x5);
	mtree_test_insert(mt, 1, (void *)0x3);
	mtree_test_insert(mt, 8, (void *)0x11);
	mtree_test_insert(mt, 12, (void *)0x19);
	mtree_test_erase(mt, 1);
	mtree_test_store_range(mt, 4, 62, (void *)0x9);
	mtree_test_erase(mt, 62);
	mtree_test_store_range(mt, 1, 0, (void *)0x3);
	mtree_test_insert(mt, 11, (void *)0x17);
	mtree_test_insert(mt, 3, (void *)0x7);
	mtree_test_insert(mt, 3, (void *)0x7);
	mtree_test_store(mt, 62, (void *)0x7d);
	mtree_test_erase(mt, 62);
	mtree_test_store_range(mt, 1, 15, (void *)0x3);
	mtree_test_erase(mt, 1);
	mtree_test_insert(mt, 22, (void *)0x2d);
	mtree_test_insert(mt, 12, (void *)0x19);
	mtree_test_erase(mt, 1);
	mtree_test_insert(mt, 3, (void *)0x7);
	mtree_test_store(mt, 62, (void *)0x7d);
	mtree_test_erase(mt, 62);
	mtree_test_insert(mt, 122, (void *)0xf5);
	mtree_test_store(mt, 3, (void *)0x7);
	mtree_test_insert(mt, 0, (void *)0x1);
	mtree_test_store_range(mt, 0, 1, (void *)0x1);
	mtree_test_insert(mt, 85, (void *)0xab);
	mtree_test_insert(mt, 72, (void *)0x91);
	mtree_test_insert(mt, 81, (void *)0xa3);
	mtree_test_insert(mt, 726, (void *)0x5ad);
	mtree_test_insert(mt, 0, (void *)0x1);
	mtree_test_insert(mt, 1, (void *)0x3);
	mtree_test_store(mt, 51, (void *)0x67);
	mtree_test_insert(mt, 611, (void *)0x4c7);
	mtree_test_insert(mt, 485, (void *)0x3cb);
	mtree_test_insert(mt, 1, (void *)0x3);
	mtree_test_erase(mt, 1);
	mtree_test_insert(mt, 0, (void *)0x1);
	mtree_test_insert(mt, 1, (void *)0x3);
	mtree_test_insert_range(mt, 26, 1, (void *)0x35);
	mtree_test_load(mt, 1);
	mtree_test_store_range(mt, 1, 22, (void *)0x3);
	mtree_test_insert(mt, 1, (void *)0x3);
	mtree_test_erase(mt, 1);
	mtree_test_load(mt, 53);
	mtree_test_load(mt, 1);
	mtree_test_store_range(mt, 1, 1, (void *)0x3);
	mtree_test_insert(mt, 222, (void *)0x1bd);
	mtree_test_insert(mt, 485, (void *)0x3cb);
	mtree_test_insert(mt, 1, (void *)0x3);
	mtree_test_erase(mt, 1);
	mtree_test_load(mt, 0);
	mtree_test_insert(mt, 21, (void *)0x2b);
	mtree_test_insert(mt, 3, (void *)0x7);
	mtree_test_store(mt, 621, (void *)0x4db);
	mtree_test_insert(mt, 0, (void *)0x1);
	mtree_test_erase(mt, 5);
	mtree_test_insert(mt, 1, (void *)0x3);
	mtree_test_store(mt, 62, (void *)0x7d);
	mtree_test_erase(mt, 62);
	mtree_test_store_range(mt, 1, 0, (void *)0x3);
	mtree_test_insert(mt, 22, (void *)0x2d);
	mtree_test_insert(mt, 12, (void *)0x19);
	mtree_test_erase(mt, 1);
	mtree_test_insert(mt, 1, (void *)0x3);
	mtree_test_store_range(mt, 4, 62, (void *)0x9);
	mtree_test_erase(mt, 62);
	mtree_test_erase(mt, 1);
	mtree_test_load(mt, 1);
	mtree_test_store_range(mt, 1, 22, (void *)0x3);
	mtree_test_insert(mt, 1, (void *)0x3);
	mtree_test_erase(mt, 1);
	mtree_test_load(mt, 53);
	mtree_test_load(mt, 1);
	mtree_test_store_range(mt, 1, 1, (void *)0x3);
	mtree_test_insert(mt, 222, (void *)0x1bd);
	mtree_test_insert(mt, 485, (void *)0x3cb);
	mtree_test_insert(mt, 1, (void *)0x3);
	mtree_test_erase(mt, 1);
	mtree_test_insert(mt, 1, (void *)0x3);
	mtree_test_load(mt, 0);
	mtree_test_load(mt, 0);
	mtree_destroy(mt);

	/*
	 * 7. Previous fix was incomplete, fix mas_resuse_node() clearing of old
	 * data by overwriting it first - that way metadata is of no concern.
	 */
	mt_init_flags(mt, 0);
	mtree_test_load(mt, 1);
	mtree_test_insert(mt, 102, (void *)0xcd);
	mtree_test_erase(mt, 2);
	mtree_test_erase(mt, 0);
	mtree_test_load(mt, 0);
	mtree_test_insert(mt, 4, (void *)0x9);
	mtree_test_insert(mt, 2, (void *)0x5);
	mtree_test_insert(mt, 110, (void *)0xdd);
	mtree_test_insert(mt, 1, (void *)0x3);
	mtree_test_insert_range(mt, 5, 0, (void *)0xb);
	mtree_test_erase(mt, 2);
	mtree_test_store(mt, 0, (void *)0x1);
	mtree_test_store(mt, 112, (void *)0xe1);
	mtree_test_insert(mt, 21, (void *)0x2b);
	mtree_test_store(mt, 1, (void *)0x3);
	mtree_test_insert_range(mt, 110, 2, (void *)0xdd);
	mtree_test_store(mt, 2, (void *)0x5);
	mtree_test_load(mt, 22);
	mtree_test_erase(mt, 2);
	mtree_test_store(mt, 210, (void *)0x1a5);
	mtree_test_store_range(mt, 0, 2, (void *)0x1);
	mtree_test_store(mt, 2, (void *)0x5);
	mtree_test_erase(mt, 2);
	mtree_test_erase(mt, 22);
	mtree_test_erase(mt, 1);
	mtree_test_erase(mt, 2);
	mtree_test_store(mt, 0, (void *)0x1);
	mtree_test_load(mt, 112);
	mtree_test_insert(mt, 2, (void *)0x5);
	mtree_test_erase(mt, 2);
	mtree_test_store(mt, 1, (void *)0x3);
	mtree_test_insert_range(mt, 1, 2, (void *)0x3);
	mtree_test_erase(mt, 0);
	mtree_test_erase(mt, 2);
	mtree_test_store(mt, 2, (void *)0x5);
	mtree_test_erase(mt, 0);
	mtree_test_erase(mt, 2);
	mtree_test_store(mt, 0, (void *)0x1);
	mtree_test_store(mt, 0, (void *)0x1);
	mtree_test_erase(mt, 2);
	mtree_test_store(mt, 2, (void *)0x5);
	mtree_test_erase(mt, 2);
	mtree_test_insert(mt, 2, (void *)0x5);
	mtree_test_insert_range(mt, 1, 2, (void *)0x3);
	mtree_test_erase(mt, 0);
	mtree_test_erase(mt, 2);
	mtree_test_store(mt, 0, (void *)0x1);
	mtree_test_load(mt, 112);
	mtree_test_store_range(mt, 110, 12, (void *)0xdd);
	mtree_test_store(mt, 2, (void *)0x5);
	mtree_test_load(mt, 110);
	mtree_test_insert_range(mt, 4, 71, (void *)0x9);
	mtree_test_load(mt, 2);
	mtree_test_store(mt, 2, (void *)0x5);
	mtree_test_insert_range(mt, 11, 22, (void *)0x17);
	mtree_test_erase(mt, 12);
	mtree_test_store(mt, 2, (void *)0x5);
	mtree_test_load(mt, 22);
	mtree_destroy(mt);


	/*
	 * 8.  When rebalancing or spanning_rebalance(), the max of the new node
	 * may be set incorrectly to the final pivot and not the right max.
	 * Fix by setting the left max to orig right max if the entire node is
	 * consumed.
	 */
	mt_init_flags(mt, 0);
	mtree_test_store(mt, 6, (void *)0xd);
	mtree_test_store(mt, 67, (void *)0x87);
	mtree_test_insert(mt, 15, (void *)0x1f);
	mtree_test_insert(mt, 6716, (void *)0x3479);
	mtree_test_store(mt, 61, (void *)0x7b);
	mtree_test_insert(mt, 13, (void *)0x1b);
	mtree_test_store(mt, 8, (void *)0x11);
	mtree_test_insert(mt, 1, (void *)0x3);
	mtree_test_load(mt, 0);
	mtree_test_erase(mt, 67167);
	mtree_test_insert_range(mt, 6, 7167, (void *)0xd);
	mtree_test_insert(mt, 6, (void *)0xd);
	mtree_test_erase(mt, 67);
	mtree_test_insert(mt, 1, (void *)0x3);
	mtree_test_erase(mt, 667167);
	mtree_test_insert(mt, 6, (void *)0xd);
	mtree_test_store(mt, 67, (void *)0x87);
	mtree_test_insert(mt, 5, (void *)0xb);
	mtree_test_erase(mt, 1);
	mtree_test_insert(mt, 6, (void *)0xd);
	mtree_test_erase(mt, 67);
	mtree_test_insert(mt, 15, (void *)0x1f);
	mtree_test_insert(mt, 67167, (void *)0x20cbf);
	mtree_test_insert(mt, 1, (void *)0x3);
	mtree_test_load(mt, 7);
	mtree_test_insert(mt, 16, (void *)0x21);
	mtree_test_insert(mt, 36, (void *)0x49);
	mtree_test_store(mt, 67, (void *)0x87);
	mtree_test_store(mt, 6, (void *)0xd);
	mtree_test_insert(mt, 367, (void *)0x2df);
	mtree_test_insert(mt, 115, (void *)0xe7);
	mtree_test_store(mt, 0, (void *)0x1);
	mtree_test_store_range(mt, 1, 3, (void *)0x3);
	mtree_test_store(mt, 1, (void *)0x3);
	mtree_test_erase(mt, 67167);
	mtree_test_insert_range(mt, 6, 47, (void *)0xd);
	mtree_test_store(mt, 1, (void *)0x3);
	mtree_test_insert_range(mt, 1, 67, (void *)0x3);
	mtree_test_load(mt, 67);
	mtree_test_insert(mt, 1, (void *)0x3);
	mtree_test_erase(mt, 67167);
	mtree_destroy(mt);

	/*
	 * 9. spanning store to the end of data caused an invalid metadata
	 * length which resulted in a crash eventually.
	 * Fix by checking if there is a value in pivot before incrementing the
	 * metadata end in mab_mas_cp().  To ensure this doesn't happen again,
	 * abstract the two locations this happens into a function called
	 * mas_leaf_set_meta().
	 */
	mt_init_flags(mt, 0);
	mtree_test_insert(mt, 21, (void *)0x2b);
	mtree_test_insert(mt, 12, (void *)0x19);
	mtree_test_insert(mt, 6, (void *)0xd);
	mtree_test_insert(mt, 8, (void *)0x11);
	mtree_test_insert(mt, 2, (void *)0x5);
	mtree_test_insert(mt, 91, (void *)0xb7);
	mtree_test_insert(mt, 18, (void *)0x25);
	mtree_test_insert(mt, 81, (void *)0xa3);
	mtree_test_store_range(mt, 0, 128, (void *)0x1);
	mtree_test_store(mt, 1, (void *)0x3);
	mtree_test_erase(mt, 8);
	mtree_test_insert(mt, 11, (void *)0x17);
	mtree_test_insert(mt, 8, (void *)0x11);
	mtree_test_insert(mt, 21, (void *)0x2b);
	mtree_test_insert(mt, 2, (void *)0x5);
	mtree_test_insert(mt, ULONG_MAX - 10, (void *)0xffffffffffffffeb);
	mtree_test_erase(mt, ULONG_MAX - 10);
	mtree_test_store_range(mt, 0, 281, (void *)0x1);
	mtree_test_erase(mt, 2);
	mtree_test_insert(mt, 1211, (void *)0x977);
	mtree_test_insert(mt, 111, (void *)0xdf);
	mtree_test_insert(mt, 13, (void *)0x1b);
	mtree_test_insert(mt, 211, (void *)0x1a7);
	mtree_test_insert(mt, 11, (void *)0x17);
	mtree_test_insert(mt, 5, (void *)0xb);
	mtree_test_insert(mt, 1218, (void *)0x985);
	mtree_test_insert(mt, 61, (void *)0x7b);
	mtree_test_store(mt, 1, (void *)0x3);
	mtree_test_insert(mt, 121, (void *)0xf3);
	mtree_test_insert(mt, 8, (void *)0x11);
	mtree_test_insert(mt, 21, (void *)0x2b);
	mtree_test_insert(mt, 2, (void *)0x5);
	mtree_test_insert(mt, ULONG_MAX - 10, (void *)0xffffffffffffffeb);
	mtree_test_erase(mt, ULONG_MAX - 10);
}

/* duplicate the tree with a specific gap */
static noinline void __init check_dup_gaps(struct maple_tree *mt,
				    unsigned long nr_entries, bool zero_start,
				    unsigned long gap)
{
	unsigned long i = 0;
	struct maple_tree newmt;
	int ret;
	void *tmp;
	MA_STATE(mas, mt, 0, 0);
	MA_STATE(newmas, &newmt, 0, 0);

	if (!zero_start)
		i = 1;

	mt_zero_nr_tallocated();
	for (; i <= nr_entries; i++)
		mtree_store_range(mt, i*10, (i+1)*10 - gap,
				  xa_mk_value(i), GFP_KERNEL);

	mt_init_flags(&newmt, MT_FLAGS_ALLOC_RANGE);
	mt_set_non_kernel(99999);
	mas_lock(&newmas);
	ret = mas_expected_entries(&newmas, nr_entries);
	mt_set_non_kernel(0);
	MT_BUG_ON(mt, ret != 0);

	rcu_read_lock();
	mas_for_each(&mas, tmp, ULONG_MAX) {
		newmas.index = mas.index;
		newmas.last = mas.last;
		mas_store(&newmas, tmp);
	}
	rcu_read_unlock();
	mas_destroy(&newmas);
	mas_unlock(&newmas);

	mtree_destroy(&newmt);
}

/* Duplicate many sizes of trees.  Mainly to test expected entry values */
static noinline void __init check_dup(struct maple_tree *mt)
{
	int i;
	int big_start = 100010;

	/* Check with a value at zero */
	for (i = 10; i < 1000; i++) {
		mt_init_flags(mt, MT_FLAGS_ALLOC_RANGE);
		check_dup_gaps(mt, i, true, 5);
		mtree_destroy(mt);
		rcu_barrier();
	}

	cond_resched();
	mt_cache_shrink();
	/* Check with a value at zero, no gap */
	for (i = 1000; i < 2000; i++) {
		mt_init_flags(mt, MT_FLAGS_ALLOC_RANGE);
		check_dup_gaps(mt, i, true, 0);
		mtree_destroy(mt);
		rcu_barrier();
	}

	cond_resched();
	mt_cache_shrink();
	/* Check with a value at zero and unreasonably large */
	for (i = big_start; i < big_start + 10; i++) {
		mt_init_flags(mt, MT_FLAGS_ALLOC_RANGE);
		check_dup_gaps(mt, i, true, 5);
		mtree_destroy(mt);
		rcu_barrier();
	}

	cond_resched();
	mt_cache_shrink();
	/* Small to medium size not starting at zero*/
	for (i = 200; i < 1000; i++) {
		mt_init_flags(mt, MT_FLAGS_ALLOC_RANGE);
		check_dup_gaps(mt, i, false, 5);
		mtree_destroy(mt);
		rcu_barrier();
	}

	cond_resched();
	mt_cache_shrink();
	/* Unreasonably large not starting at zero*/
	for (i = big_start; i < big_start + 10; i++) {
		mt_init_flags(mt, MT_FLAGS_ALLOC_RANGE);
		check_dup_gaps(mt, i, false, 5);
		mtree_destroy(mt);
		rcu_barrier();
		cond_resched();
		mt_cache_shrink();
	}

	/* Check non-allocation tree not starting at zero */
	for (i = 1500; i < 3000; i++) {
		mt_init_flags(mt, 0);
		check_dup_gaps(mt, i, false, 5);
		mtree_destroy(mt);
		rcu_barrier();
		cond_resched();
		if (i % 2 == 0)
			mt_cache_shrink();
	}

	mt_cache_shrink();
	/* Check non-allocation tree starting at zero */
	for (i = 200; i < 1000; i++) {
		mt_init_flags(mt, 0);
		check_dup_gaps(mt, i, true, 5);
		mtree_destroy(mt);
		rcu_barrier();
		cond_resched();
	}

	mt_cache_shrink();
	/* Unreasonably large */
	for (i = big_start + 5; i < big_start + 10; i++) {
		mt_init_flags(mt, 0);
		check_dup_gaps(mt, i, true, 5);
		mtree_destroy(mt);
		rcu_barrier();
		mt_cache_shrink();
		cond_resched();
	}
}

static noinline void __init check_bnode_min_spanning(struct maple_tree *mt)
{
	int i = 50;
	MA_STATE(mas, mt, 0, 0);

	mt_set_non_kernel(9999);
	mas_lock(&mas);
	do {
		mas_set_range(&mas, i*10, i*10+9);
		mas_store(&mas, check_bnode_min_spanning);
	} while (i--);

	mas_set_range(&mas, 240, 509);
	mas_store(&mas, NULL);
	mas_unlock(&mas);
	mas_destroy(&mas);
	mt_set_non_kernel(0);
}

static noinline void __init check_empty_area_window(struct maple_tree *mt)
{
	unsigned long i, nr_entries = 20;
	MA_STATE(mas, mt, 0, 0);

	for (i = 1; i <= nr_entries; i++)
		mtree_store_range(mt, i*10, i*10 + 9,
				  xa_mk_value(i), GFP_KERNEL);

	/* Create another hole besides the one at 0 */
	mtree_store_range(mt, 160, 169, NULL, GFP_KERNEL);

	/* Check lower bounds that don't fit */
	rcu_read_lock();
	MT_BUG_ON(mt, mas_empty_area_rev(&mas, 5, 90, 10) != -EBUSY);

	mas_reset(&mas);
	MT_BUG_ON(mt, mas_empty_area_rev(&mas, 6, 90, 5) != -EBUSY);

	/* Check lower bound that does fit */
	mas_reset(&mas);
	MT_BUG_ON(mt, mas_empty_area_rev(&mas, 5, 90, 5) != 0);
	MT_BUG_ON(mt, mas.index != 5);
	MT_BUG_ON(mt, mas.last != 9);
	rcu_read_unlock();

	/* Check one gap that doesn't fit and one that does */
	rcu_read_lock();
	mas_reset(&mas);
	MT_BUG_ON(mt, mas_empty_area_rev(&mas, 5, 217, 9) != 0);
	MT_BUG_ON(mt, mas.index != 161);
	MT_BUG_ON(mt, mas.last != 169);

	/* Check one gap that does fit above the min */
	mas_reset(&mas);
	MT_BUG_ON(mt, mas_empty_area_rev(&mas, 100, 218, 3) != 0);
	MT_BUG_ON(mt, mas.index != 216);
	MT_BUG_ON(mt, mas.last != 218);

	/* Check size that doesn't fit any gap */
	mas_reset(&mas);
	MT_BUG_ON(mt, mas_empty_area_rev(&mas, 100, 218, 16) != -EBUSY);

	/*
	 * Check size that doesn't fit the lower end of the window but
	 * does fit the gap
	 */
	mas_reset(&mas);
	MT_BUG_ON(mt, mas_empty_area_rev(&mas, 167, 200, 4) != -EBUSY);

	/*
	 * Check size that doesn't fit the upper end of the window but
	 * does fit the gap
	 */
	mas_reset(&mas);
	MT_BUG_ON(mt, mas_empty_area_rev(&mas, 100, 162, 4) != -EBUSY);

	/* Check mas_empty_area forward */
	mas_reset(&mas);
	MT_BUG_ON(mt, mas_empty_area(&mas, 0, 100, 9) != 0);
	MT_BUG_ON(mt, mas.index != 0);
	MT_BUG_ON(mt, mas.last != 8);

	mas_reset(&mas);
	MT_BUG_ON(mt, mas_empty_area(&mas, 0, 100, 4) != 0);
	MT_BUG_ON(mt, mas.index != 0);
	MT_BUG_ON(mt, mas.last != 3);

	mas_reset(&mas);
	MT_BUG_ON(mt, mas_empty_area(&mas, 0, 100, 11) != -EBUSY);

	mas_reset(&mas);
	MT_BUG_ON(mt, mas_empty_area(&mas, 5, 100, 6) != -EBUSY);

	mas_reset(&mas);
	MT_BUG_ON(mt, mas_empty_area(&mas, 0, 8, 10) != -EINVAL);

	mas_reset(&mas);
	mas_empty_area(&mas, 100, 165, 3);

	mas_reset(&mas);
	MT_BUG_ON(mt, mas_empty_area(&mas, 100, 163, 6) != -EBUSY);
	rcu_read_unlock();
}

static noinline void __init check_empty_area_fill(struct maple_tree *mt)
{
	const unsigned long max = 0x25D78000;
	unsigned long size;
	int loop, shift;
	MA_STATE(mas, mt, 0, 0);

	mt_set_non_kernel(99999);
	for (shift = 12; shift <= 16; shift++) {
		loop = 5000;
		size = 1 << shift;
		while (loop--) {
			mas_set(&mas, 0);
			mas_lock(&mas);
			MT_BUG_ON(mt, mas_empty_area(&mas, 0, max, size) != 0);
			MT_BUG_ON(mt, mas.last != mas.index + size - 1);
			mas_store_gfp(&mas, (void *)size, GFP_KERNEL);
			mas_unlock(&mas);
			mas_reset(&mas);
		}
	}

	/* No space left. */
	size = 0x1000;
	rcu_read_lock();
	MT_BUG_ON(mt, mas_empty_area(&mas, 0, max, size) != -EBUSY);
	rcu_read_unlock();

	/* Fill a depth 3 node to the maximum */
	for (unsigned long i = 629440511; i <= 629440800; i += 6)
		mtree_store_range(mt, i, i + 5, (void *)i, GFP_KERNEL);
	/* Make space in the second-last depth 4 node */
	mtree_erase(mt, 631668735);
	/* Make space in the last depth 4 node */
	mtree_erase(mt, 629506047);
	mas_reset(&mas);
	/* Search from just after the gap in the second-last depth 4 */
	rcu_read_lock();
	MT_BUG_ON(mt, mas_empty_area(&mas, 629506048, 690000000, 0x5000) != 0);
	rcu_read_unlock();
	mt_set_non_kernel(0);
}

/*
 * Check MAS_START, MAS_PAUSE, active (implied), and MAS_NONE transitions.
 *
 * The table below shows the single entry tree (0-0 pointer) and normal tree
 * with nodes.
 *
 * Function	ENTRY	Start		Result		index & last
 *     ┬          ┬       ┬               ┬                ┬
 *     │          │       │               │                └─ the final range
 *     │          │       │               └─ The node value after execution
 *     │          │       └─ The node value before execution
 *     │          └─ If the entry exists or does not exists (DNE)
 *     └─ The function name
 *
 * Function	ENTRY	Start		Result		index & last
 * mas_next()
 *  - after last
 *			Single entry tree at 0-0
 *			------------------------
 *		DNE	MAS_START	MAS_NONE	1 - oo
 *		DNE	MAS_PAUSE	MAS_NONE	1 - oo
 *		DNE	MAS_ROOT	MAS_NONE	1 - oo
 *			when index = 0
 *		DNE	MAS_NONE	MAS_ROOT	0
 *			when index > 0
 *		DNE	MAS_NONE	MAS_NONE	1 - oo
 *
 *			Normal tree
 *			-----------
 *		exists	MAS_START	active		range
 *		DNE	MAS_START	active		set to last range
 *		exists	MAS_PAUSE	active		range
 *		DNE	MAS_PAUSE	active		set to last range
 *		exists	MAS_NONE	active		range
 *		exists	active		active		range
 *		DNE	active		active		set to last range
 *
 * Function	ENTRY	Start		Result		index & last
 * mas_prev()
 * - before index
 *			Single entry tree at 0-0
 *			------------------------
 *				if index > 0
 *		exists	MAS_START	MAS_ROOT	0
 *		exists	MAS_PAUSE	MAS_ROOT	0
 *		exists	MAS_NONE	MAS_ROOT	0
 *
 *				if index == 0
 *		DNE	MAS_START	MAS_NONE	0
 *		DNE	MAS_PAUSE	MAS_NONE	0
 *		DNE	MAS_NONE	MAS_NONE	0
 *		DNE	MAS_ROOT	MAS_NONE	0
 *
 *			Normal tree
 *			-----------
 *		exists	MAS_START	active		range
 *		DNE	MAS_START	active		set to min
 *		exists	MAS_PAUSE	active		range
 *		DNE	MAS_PAUSE	active		set to min
 *		exists	MAS_NONE	active		range
 *		DNE	MAS_NONE	MAS_NONE	set to min
 *		any	MAS_ROOT	MAS_NONE	0
 *		exists	active		active		range
 *		DNE	active		active		last range
 *
 * Function	ENTRY	Start		Result		index & last
 * mas_find()
 *  - at index or next
 *			Single entry tree at 0-0
 *			------------------------
 *				if index >  0
 *		DNE	MAS_START	MAS_NONE	0
 *		DNE	MAS_PAUSE	MAS_NONE	0
 *		DNE	MAS_ROOT	MAS_NONE	0
 *		DNE	MAS_NONE	MAS_NONE	0
 *				if index ==  0
 *		exists	MAS_START	MAS_ROOT	0
 *		exists	MAS_PAUSE	MAS_ROOT	0
 *		exists	MAS_NONE	MAS_ROOT	0
 *
 *			Normal tree
 *			-----------
 *		exists	MAS_START	active		range
 *		DNE	MAS_START	active		set to max
 *		exists	MAS_PAUSE	active		range
 *		DNE	MAS_PAUSE	active		set to max
 *		exists	MAS_NONE	active		range
 *		exists	active		active		range
 *		DNE	active		active		last range (max < last)
 *
 * Function	ENTRY	Start		Result		index & last
 * mas_find_rev()
 *  - at index or before
 *			Single entry tree at 0-0
 *			------------------------
 *				if index >  0
 *		exists	MAS_START	MAS_ROOT	0
 *		exists	MAS_PAUSE	MAS_ROOT	0
 *		exists	MAS_NONE	MAS_ROOT	0
 *				if index ==  0
 *		DNE	MAS_START	MAS_NONE	0
 *		DNE	MAS_PAUSE	MAS_NONE	0
 *		DNE	MAS_NONE	MAS_NONE	0
 *		DNE	MAS_ROOT	MAS_NONE	0
 *
 *			Normal tree
 *			-----------
 *		exists	MAS_START	active		range
 *		DNE	MAS_START	active		set to min
 *		exists	MAS_PAUSE	active		range
 *		DNE	MAS_PAUSE	active		set to min
 *		exists	MAS_NONE	active		range
 *		exists	active		active		range
 *		DNE	active		active		last range (min > index)
 *
 * Function	ENTRY	Start		Result		index & last
 * mas_walk()
 * - Look up index
 *			Single entry tree at 0-0
 *			------------------------
 *				if index >  0
 *		DNE	MAS_START	MAS_ROOT	1 - oo
 *		DNE	MAS_PAUSE	MAS_ROOT	1 - oo
 *		DNE	MAS_NONE	MAS_ROOT	1 - oo
 *		DNE	MAS_ROOT	MAS_ROOT	1 - oo
 *				if index ==  0
 *		exists	MAS_START	MAS_ROOT	0
 *		exists	MAS_PAUSE	MAS_ROOT	0
 *		exists	MAS_NONE	MAS_ROOT	0
 *		exists	MAS_ROOT	MAS_ROOT	0
 *
 *			Normal tree
 *			-----------
 *		exists	MAS_START	active		range
 *		DNE	MAS_START	active		range of NULL
 *		exists	MAS_PAUSE	active		range
 *		DNE	MAS_PAUSE	active		range of NULL
 *		exists	MAS_NONE	active		range
 *		DNE	MAS_NONE	active		range of NULL
 *		exists	active		active		range
 *		DNE	active		active		range of NULL
 */

#define mas_active(x)		(((x).node != MAS_ROOT) && \
				 ((x).node != MAS_START) && \
				 ((x).node != MAS_PAUSE) && \
				 ((x).node != MAS_NONE))
static noinline void __init check_state_handling(struct maple_tree *mt)
{
	MA_STATE(mas, mt, 0, 0);
	void *entry, *ptr = (void *) 0x1234500;
	void *ptr2 = &ptr;
	void *ptr3 = &ptr2;

	/* Check MAS_ROOT First */
	mtree_store_range(mt, 0, 0, ptr, GFP_KERNEL);

	mas_lock(&mas);
	/* prev: Start -> none */
	entry = mas_prev(&mas, 0);
	MT_BUG_ON(mt, entry != NULL);
	MT_BUG_ON(mt, mas.node != MAS_NONE);

	/* prev: Start -> root */
	mas_set(&mas, 10);
	entry = mas_prev(&mas, 0);
	MT_BUG_ON(mt, entry != ptr);
	MT_BUG_ON(mt, mas.index != 0);
	MT_BUG_ON(mt, mas.last != 0);
	MT_BUG_ON(mt, mas.node != MAS_ROOT);

	/* prev: pause -> root */
	mas_set(&mas, 10);
	mas_pause(&mas);
	entry = mas_prev(&mas, 0);
	MT_BUG_ON(mt, entry != ptr);
	MT_BUG_ON(mt, mas.index != 0);
	MT_BUG_ON(mt, mas.last != 0);
	MT_BUG_ON(mt, mas.node != MAS_ROOT);

	/* next: start -> none */
	mas_set(&mas, 0);
	entry = mas_next(&mas, ULONG_MAX);
	MT_BUG_ON(mt, mas.index != 1);
	MT_BUG_ON(mt, mas.last != ULONG_MAX);
	MT_BUG_ON(mt, entry != NULL);
	MT_BUG_ON(mt, mas.node != MAS_NONE);

	/* next: start -> none */
	mas_set(&mas, 10);
	entry = mas_next(&mas, ULONG_MAX);
	MT_BUG_ON(mt, mas.index != 1);
	MT_BUG_ON(mt, mas.last != ULONG_MAX);
	MT_BUG_ON(mt, entry != NULL);
	MT_BUG_ON(mt, mas.node != MAS_NONE);

	/* find: start -> root */
	mas_set(&mas, 0);
	entry = mas_find(&mas, ULONG_MAX);
	MT_BUG_ON(mt, entry != ptr);
	MT_BUG_ON(mt, mas.index != 0);
	MT_BUG_ON(mt, mas.last != 0);
	MT_BUG_ON(mt, mas.node != MAS_ROOT);

	/* find: root -> none */
	entry = mas_find(&mas, ULONG_MAX);
	MT_BUG_ON(mt, entry != NULL);
	MT_BUG_ON(mt, mas.index != 1);
	MT_BUG_ON(mt, mas.last != ULONG_MAX);
	MT_BUG_ON(mt, mas.node != MAS_NONE);

	/* find: none -> none */
	entry = mas_find(&mas, ULONG_MAX);
	MT_BUG_ON(mt, entry != NULL);
	MT_BUG_ON(mt, mas.index != 1);
	MT_BUG_ON(mt, mas.last != ULONG_MAX);
	MT_BUG_ON(mt, mas.node != MAS_NONE);

	/* find: start -> none */
	mas_set(&mas, 10);
	entry = mas_find(&mas, ULONG_MAX);
	MT_BUG_ON(mt, entry != NULL);
	MT_BUG_ON(mt, mas.index != 1);
	MT_BUG_ON(mt, mas.last != ULONG_MAX);
	MT_BUG_ON(mt, mas.node != MAS_NONE);

	/* find_rev: none -> root */
	entry = mas_find_rev(&mas, 0);
	MT_BUG_ON(mt, entry != ptr);
	MT_BUG_ON(mt, mas.index != 0);
	MT_BUG_ON(mt, mas.last != 0);
	MT_BUG_ON(mt, mas.node != MAS_ROOT);

	/* find_rev: start -> root */
	mas_set(&mas, 0);
	entry = mas_find_rev(&mas, 0);
	MT_BUG_ON(mt, entry != ptr);
	MT_BUG_ON(mt, mas.index != 0);
	MT_BUG_ON(mt, mas.last != 0);
	MT_BUG_ON(mt, mas.node != MAS_ROOT);

	/* find_rev: root -> none */
	entry = mas_find_rev(&mas, 0);
	MT_BUG_ON(mt, entry != NULL);
	MT_BUG_ON(mt, mas.index != 0);
	MT_BUG_ON(mt, mas.last != 0);
	MT_BUG_ON(mt, mas.node != MAS_NONE);

	/* find_rev: none -> none */
	entry = mas_find_rev(&mas, 0);
	MT_BUG_ON(mt, entry != NULL);
	MT_BUG_ON(mt, mas.index != 0);
	MT_BUG_ON(mt, mas.last != 0);
	MT_BUG_ON(mt, mas.node != MAS_NONE);

	/* find_rev: start -> root */
	mas_set(&mas, 10);
	entry = mas_find_rev(&mas, 0);
	MT_BUG_ON(mt, entry != ptr);
	MT_BUG_ON(mt, mas.index != 0);
	MT_BUG_ON(mt, mas.last != 0);
	MT_BUG_ON(mt, mas.node != MAS_ROOT);

	/* walk: start -> none */
	mas_set(&mas, 10);
	entry = mas_walk(&mas);
	MT_BUG_ON(mt, entry != NULL);
	MT_BUG_ON(mt, mas.index != 1);
	MT_BUG_ON(mt, mas.last != ULONG_MAX);
	MT_BUG_ON(mt, mas.node != MAS_NONE);

	/* walk: pause -> none*/
	mas_set(&mas, 10);
	mas_pause(&mas);
	entry = mas_walk(&mas);
	MT_BUG_ON(mt, entry != NULL);
	MT_BUG_ON(mt, mas.index != 1);
	MT_BUG_ON(mt, mas.last != ULONG_MAX);
	MT_BUG_ON(mt, mas.node != MAS_NONE);

	/* walk: none -> none */
	mas.index = mas.last = 10;
	entry = mas_walk(&mas);
	MT_BUG_ON(mt, entry != NULL);
	MT_BUG_ON(mt, mas.index != 1);
	MT_BUG_ON(mt, mas.last != ULONG_MAX);
	MT_BUG_ON(mt, mas.node != MAS_NONE);

	/* walk: none -> none */
	entry = mas_walk(&mas);
	MT_BUG_ON(mt, entry != NULL);
	MT_BUG_ON(mt, mas.index != 1);
	MT_BUG_ON(mt, mas.last != ULONG_MAX);
	MT_BUG_ON(mt, mas.node != MAS_NONE);

	/* walk: start -> root */
	mas_set(&mas, 0);
	entry = mas_walk(&mas);
	MT_BUG_ON(mt, entry != ptr);
	MT_BUG_ON(mt, mas.index != 0);
	MT_BUG_ON(mt, mas.last != 0);
	MT_BUG_ON(mt, mas.node != MAS_ROOT);

	/* walk: pause -> root */
	mas_set(&mas, 0);
	mas_pause(&mas);
	entry = mas_walk(&mas);
	MT_BUG_ON(mt, entry != ptr);
	MT_BUG_ON(mt, mas.index != 0);
	MT_BUG_ON(mt, mas.last != 0);
	MT_BUG_ON(mt, mas.node != MAS_ROOT);

	/* walk: none -> root */
	mas.node = MAS_NONE;
	entry = mas_walk(&mas);
	MT_BUG_ON(mt, entry != ptr);
	MT_BUG_ON(mt, mas.index != 0);
	MT_BUG_ON(mt, mas.last != 0);
	MT_BUG_ON(mt, mas.node != MAS_ROOT);

	/* walk: root -> root */
	entry = mas_walk(&mas);
	MT_BUG_ON(mt, entry != ptr);
	MT_BUG_ON(mt, mas.index != 0);
	MT_BUG_ON(mt, mas.last != 0);
	MT_BUG_ON(mt, mas.node != MAS_ROOT);

	/* walk: root -> none */
	mas_set(&mas, 10);
	entry = mas_walk(&mas);
	MT_BUG_ON(mt, entry != NULL);
	MT_BUG_ON(mt, mas.index != 1);
	MT_BUG_ON(mt, mas.last != ULONG_MAX);
	MT_BUG_ON(mt, mas.node != MAS_NONE);

	/* walk: none -> root */
	mas.index = mas.last = 0;
	entry = mas_walk(&mas);
	MT_BUG_ON(mt, entry != ptr);
	MT_BUG_ON(mt, mas.index != 0);
	MT_BUG_ON(mt, mas.last != 0);
	MT_BUG_ON(mt, mas.node != MAS_ROOT);

	mas_unlock(&mas);

	/* Check when there is an actual node */
	mtree_store_range(mt, 0, 0, NULL, GFP_KERNEL);
	mtree_store_range(mt, 0x1000, 0x1500, ptr, GFP_KERNEL);
	mtree_store_range(mt, 0x2000, 0x2500, ptr2, GFP_KERNEL);
	mtree_store_range(mt, 0x3000, 0x3500, ptr3, GFP_KERNEL);

	mas_lock(&mas);

	/* next: start ->active */
	mas_set(&mas, 0);
	entry = mas_next(&mas, ULONG_MAX);
	MT_BUG_ON(mt, entry != ptr);
	MT_BUG_ON(mt, mas.index != 0x1000);
	MT_BUG_ON(mt, mas.last != 0x1500);
	MT_BUG_ON(mt, !mas_active(mas));

	/* next: pause ->active */
	mas_set(&mas, 0);
	mas_pause(&mas);
	entry = mas_next(&mas, ULONG_MAX);
	MT_BUG_ON(mt, entry != ptr);
	MT_BUG_ON(mt, mas.index != 0x1000);
	MT_BUG_ON(mt, mas.last != 0x1500);
	MT_BUG_ON(mt, !mas_active(mas));

	/* next: none ->active */
	mas.index = mas.last = 0;
	mas.offset = 0;
	mas.node = MAS_NONE;
	entry = mas_next(&mas, ULONG_MAX);
	MT_BUG_ON(mt, entry != ptr);
	MT_BUG_ON(mt, mas.index != 0x1000);
	MT_BUG_ON(mt, mas.last != 0x1500);
	MT_BUG_ON(mt, !mas_active(mas));

	/* next:active ->active */
	entry = mas_next(&mas, ULONG_MAX);
	MT_BUG_ON(mt, entry != ptr2);
	MT_BUG_ON(mt, mas.index != 0x2000);
	MT_BUG_ON(mt, mas.last != 0x2500);
	MT_BUG_ON(mt, !mas_active(mas));

	/* next:active -> active out of range*/
	entry = mas_next(&mas, 0x2999);
	MT_BUG_ON(mt, entry != NULL);
	MT_BUG_ON(mt, mas.index != 0x2501);
	MT_BUG_ON(mt, mas.last != 0x2fff);
	MT_BUG_ON(mt, !mas_active(mas));

	/* Continue after out of range*/
	entry = mas_next(&mas, ULONG_MAX);
	MT_BUG_ON(mt, entry != ptr3);
	MT_BUG_ON(mt, mas.index != 0x3000);
	MT_BUG_ON(mt, mas.last != 0x3500);
	MT_BUG_ON(mt, !mas_active(mas));

	/* next:active -> active out of range*/
	entry = mas_next(&mas, ULONG_MAX);
	MT_BUG_ON(mt, entry != NULL);
	MT_BUG_ON(mt, mas.index != 0x3501);
	MT_BUG_ON(mt, mas.last != ULONG_MAX);
	MT_BUG_ON(mt, !mas_active(mas));

	/* next: none -> active, skip value at location */
	mas_set(&mas, 0);
	entry = mas_next(&mas, ULONG_MAX);
	mas.node = MAS_NONE;
	mas.offset = 0;
	entry = mas_next(&mas, ULONG_MAX);
	MT_BUG_ON(mt, entry != ptr2);
	MT_BUG_ON(mt, mas.index != 0x2000);
	MT_BUG_ON(mt, mas.last != 0x2500);
	MT_BUG_ON(mt, !mas_active(mas));

	/* prev:active ->active */
	entry = mas_prev(&mas, 0);
	MT_BUG_ON(mt, entry != ptr);
	MT_BUG_ON(mt, mas.index != 0x1000);
	MT_BUG_ON(mt, mas.last != 0x1500);
	MT_BUG_ON(mt, !mas_active(mas));

	/* prev:active -> active out of range*/
	entry = mas_prev(&mas, 0);
	MT_BUG_ON(mt, entry != NULL);
	MT_BUG_ON(mt, mas.index != 0);
	MT_BUG_ON(mt, mas.last != 0x0FFF);
	MT_BUG_ON(mt, !mas_active(mas));

	/* prev: pause ->active */
	mas_set(&mas, 0x3600);
	entry = mas_prev(&mas, 0);
	MT_BUG_ON(mt, entry != ptr3);
	mas_pause(&mas);
	entry = mas_prev(&mas, 0);
	MT_BUG_ON(mt, entry != ptr2);
	MT_BUG_ON(mt, mas.index != 0x2000);
	MT_BUG_ON(mt, mas.last != 0x2500);
	MT_BUG_ON(mt, !mas_active(mas));

	/* prev:active -> active out of range*/
	entry = mas_prev(&mas, 0x1600);
	MT_BUG_ON(mt, entry != NULL);
	MT_BUG_ON(mt, mas.index != 0x1501);
	MT_BUG_ON(mt, mas.last != 0x1FFF);
	MT_BUG_ON(mt, !mas_active(mas));

	/* prev: active ->active, continue*/
	entry = mas_prev(&mas, 0);
	MT_BUG_ON(mt, entry != ptr);
	MT_BUG_ON(mt, mas.index != 0x1000);
	MT_BUG_ON(mt, mas.last != 0x1500);
	MT_BUG_ON(mt, !mas_active(mas));

	/* find: start ->active */
	mas_set(&mas, 0);
	entry = mas_find(&mas, ULONG_MAX);
	MT_BUG_ON(mt, entry != ptr);
	MT_BUG_ON(mt, mas.index != 0x1000);
	MT_BUG_ON(mt, mas.last != 0x1500);
	MT_BUG_ON(mt, !mas_active(mas));

	/* find: pause ->active */
	mas_set(&mas, 0);
	mas_pause(&mas);
	entry = mas_find(&mas, ULONG_MAX);
	MT_BUG_ON(mt, entry != ptr);
	MT_BUG_ON(mt, mas.index != 0x1000);
	MT_BUG_ON(mt, mas.last != 0x1500);
	MT_BUG_ON(mt, !mas_active(mas));

	/* find: start ->active on value */;
	mas_set(&mas, 1200);
	entry = mas_find(&mas, ULONG_MAX);
	MT_BUG_ON(mt, entry != ptr);
	MT_BUG_ON(mt, mas.index != 0x1000);
	MT_BUG_ON(mt, mas.last != 0x1500);
	MT_BUG_ON(mt, !mas_active(mas));

	/* find:active ->active */
	entry = mas_find(&mas, ULONG_MAX);
	MT_BUG_ON(mt, entry != ptr2);
	MT_BUG_ON(mt, mas.index != 0x2000);
	MT_BUG_ON(mt, mas.last != 0x2500);
	MT_BUG_ON(mt, !mas_active(mas));


	/* find:active -> active (NULL)*/
	entry = mas_find(&mas, 0x2700);
	MT_BUG_ON(mt, entry != NULL);
	MT_BUG_ON(mt, mas.index != 0x2501);
	MT_BUG_ON(mt, mas.last != 0x2FFF);
	MT_BUG_ON(mt, !mas_active(mas));

	/* find: none ->active */
	entry = mas_find(&mas, 0x5000);
	MT_BUG_ON(mt, entry != ptr3);
	MT_BUG_ON(mt, mas.index != 0x3000);
	MT_BUG_ON(mt, mas.last != 0x3500);
	MT_BUG_ON(mt, !mas_active(mas));

	/* find:active -> active (NULL) end*/
	entry = mas_find(&mas, ULONG_MAX);
	MT_BUG_ON(mt, entry != NULL);
	MT_BUG_ON(mt, mas.index != 0x3501);
	MT_BUG_ON(mt, mas.last != ULONG_MAX);
	MT_BUG_ON(mt, !mas_active(mas));

	/* find_rev: active (END) ->active */
	entry = mas_find_rev(&mas, 0);
	MT_BUG_ON(mt, entry != ptr3);
	MT_BUG_ON(mt, mas.index != 0x3000);
	MT_BUG_ON(mt, mas.last != 0x3500);
	MT_BUG_ON(mt, !mas_active(mas));

	/* find_rev:active ->active */
	entry = mas_find_rev(&mas, 0);
	MT_BUG_ON(mt, entry != ptr2);
	MT_BUG_ON(mt, mas.index != 0x2000);
	MT_BUG_ON(mt, mas.last != 0x2500);
	MT_BUG_ON(mt, !mas_active(mas));

	/* find_rev: pause ->active */
	mas_pause(&mas);
	entry = mas_find_rev(&mas, 0);
	MT_BUG_ON(mt, entry != ptr);
	MT_BUG_ON(mt, mas.index != 0x1000);
	MT_BUG_ON(mt, mas.last != 0x1500);
	MT_BUG_ON(mt, !mas_active(mas));

	/* find_rev:active -> active */
	entry = mas_find_rev(&mas, 0);
	MT_BUG_ON(mt, entry != NULL);
	MT_BUG_ON(mt, mas.index != 0);
	MT_BUG_ON(mt, mas.last != 0x0FFF);
	MT_BUG_ON(mt, !mas_active(mas));

	/* find_rev: start ->active */
	mas_set(&mas, 0x1200);
	entry = mas_find_rev(&mas, 0);
	MT_BUG_ON(mt, entry != ptr);
	MT_BUG_ON(mt, mas.index != 0x1000);
	MT_BUG_ON(mt, mas.last != 0x1500);
	MT_BUG_ON(mt, !mas_active(mas));

	/* mas_walk start ->active */
	mas_set(&mas, 0x1200);
	entry = mas_walk(&mas);
	MT_BUG_ON(mt, entry != ptr);
	MT_BUG_ON(mt, mas.index != 0x1000);
	MT_BUG_ON(mt, mas.last != 0x1500);
	MT_BUG_ON(mt, !mas_active(mas));

	/* mas_walk start ->active */
	mas_set(&mas, 0x1600);
	entry = mas_walk(&mas);
	MT_BUG_ON(mt, entry != NULL);
	MT_BUG_ON(mt, mas.index != 0x1501);
	MT_BUG_ON(mt, mas.last != 0x1fff);
	MT_BUG_ON(mt, !mas_active(mas));

	/* mas_walk pause ->active */
	mas_set(&mas, 0x1200);
	mas_pause(&mas);
	entry = mas_walk(&mas);
	MT_BUG_ON(mt, entry != ptr);
	MT_BUG_ON(mt, mas.index != 0x1000);
	MT_BUG_ON(mt, mas.last != 0x1500);
	MT_BUG_ON(mt, !mas_active(mas));

	/* mas_walk pause -> active */
	mas_set(&mas, 0x1600);
	mas_pause(&mas);
	entry = mas_walk(&mas);
	MT_BUG_ON(mt, entry != NULL);
	MT_BUG_ON(mt, mas.index != 0x1501);
	MT_BUG_ON(mt, mas.last != 0x1fff);
	MT_BUG_ON(mt, !mas_active(mas));

	/* mas_walk none -> active */
	mas_set(&mas, 0x1200);
	mas.node = MAS_NONE;
	entry = mas_walk(&mas);
	MT_BUG_ON(mt, entry != ptr);
	MT_BUG_ON(mt, mas.index != 0x1000);
	MT_BUG_ON(mt, mas.last != 0x1500);
	MT_BUG_ON(mt, !mas_active(mas));

	/* mas_walk none -> active */
	mas_set(&mas, 0x1600);
	mas.node = MAS_NONE;
	entry = mas_walk(&mas);
	MT_BUG_ON(mt, entry != NULL);
	MT_BUG_ON(mt, mas.index != 0x1501);
	MT_BUG_ON(mt, mas.last != 0x1fff);
	MT_BUG_ON(mt, !mas_active(mas));

	/* mas_walk active -> active */
	mas.index = 0x1200;
	mas.last = 0x1200;
	mas.offset = 0;
	entry = mas_walk(&mas);
	MT_BUG_ON(mt, entry != ptr);
	MT_BUG_ON(mt, mas.index != 0x1000);
	MT_BUG_ON(mt, mas.last != 0x1500);
	MT_BUG_ON(mt, !mas_active(mas));

	/* mas_walk active -> active */
	mas.index = 0x1600;
	mas.last = 0x1600;
	entry = mas_walk(&mas);
	MT_BUG_ON(mt, entry != NULL);
	MT_BUG_ON(mt, mas.index != 0x1501);
	MT_BUG_ON(mt, mas.last != 0x1fff);
	MT_BUG_ON(mt, !mas_active(mas));

	mas_unlock(&mas);
}

static DEFINE_MTREE(tree);
static int __init maple_tree_seed(void)
{
	unsigned long set[] = { 5015, 5014, 5017, 25, 1000,
				1001, 1002, 1003, 1005, 0,
				5003, 5002};
	void *ptr = &set;

	pr_info("\nTEST STARTING\n\n");

	mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
	check_root_expand(&tree);
	mtree_destroy(&tree);

#if defined(BENCH_SLOT_STORE)
#define BENCH
	mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
	bench_slot_store(&tree);
	mtree_destroy(&tree);
	goto skip;
#endif
#if defined(BENCH_NODE_STORE)
#define BENCH
	mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
	bench_node_store(&tree);
	mtree_destroy(&tree);
	goto skip;
#endif
#if defined(BENCH_AWALK)
#define BENCH
	mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
	bench_awalk(&tree);
	mtree_destroy(&tree);
	goto skip;
#endif
#if defined(BENCH_WALK)
#define BENCH
	mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
	bench_walk(&tree);
	mtree_destroy(&tree);
	goto skip;
#endif
#if defined(BENCH_FORK)
#define BENCH
	mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
	bench_forking(&tree);
	mtree_destroy(&tree);
	goto skip;
#endif
#if defined(BENCH_MT_FOR_EACH)
#define BENCH
	mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
	bench_mt_for_each(&tree);
	mtree_destroy(&tree);
	goto skip;
#endif

	mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
	check_iteration(&tree);
	mtree_destroy(&tree);

	mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
	check_forking(&tree);
	mtree_destroy(&tree);

	mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
	check_mas_store_gfp(&tree);
	mtree_destroy(&tree);

	/* Test ranges (store and insert) */
	mt_init_flags(&tree, 0);
	check_ranges(&tree);
	mtree_destroy(&tree);

#if defined(CONFIG_64BIT)
	/* These tests have ranges outside of 4GB */
	mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
	check_alloc_range(&tree);
	mtree_destroy(&tree);

	mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
	check_alloc_rev_range(&tree);
	mtree_destroy(&tree);
#endif

	mt_init_flags(&tree, 0);

	check_load(&tree, set[0], NULL);       /* See if 5015 -> NULL */

	check_insert(&tree, set[9], &tree);     /* Insert 0 */
	check_load(&tree, set[9], &tree);       /* See if 0 -> &tree */
	check_load(&tree, set[0], NULL);       /* See if 5015 -> NULL */

	check_insert(&tree, set[10], ptr);      /* Insert 5003 */
	check_load(&tree, set[9], &tree);       /* See if 0 -> &tree */
	check_load(&tree, set[11], NULL);       /* See if 5002 -> NULL */
	check_load(&tree, set[10], ptr);       /* See if 5003 -> ptr */

	/* Clear out the tree */
	mtree_destroy(&tree);

	/* Try to insert, insert a dup, and load back what was inserted. */
	mt_init_flags(&tree, 0);
	check_insert(&tree, set[0], &tree);     /* Insert 5015 */
	check_dup_insert(&tree, set[0], &tree); /* Insert 5015 again */
	check_load(&tree, set[0], &tree);       /* See if 5015 -> &tree */

	/*
	 * Second set of tests try to load a value that doesn't exist, inserts
	 * a second value, then loads the value again
	 */
	check_load(&tree, set[1], NULL);        /* See if 5014 -> NULL */
	check_insert(&tree, set[1], ptr);       /* insert 5014 -> ptr */
	check_load(&tree, set[1], ptr);         /* See if 5014 -> ptr */
	check_load(&tree, set[0], &tree);       /* See if 5015 -> &tree */
	/*
	 * Tree currently contains:
	 * p[0]: 14 -> (nil) p[1]: 15 -> ptr p[2]: 16 -> &tree p[3]: 0 -> (nil)
	 */
	check_insert(&tree, set[6], ptr);       /* insert 1002 -> ptr */
	check_insert(&tree, set[7], &tree);       /* insert 1003 -> &tree */

	check_load(&tree, set[0], &tree);       /* See if 5015 -> &tree */
	check_load(&tree, set[1], ptr);         /* See if 5014 -> ptr */
	check_load(&tree, set[6], ptr);         /* See if 1002 -> ptr */
	check_load(&tree, set[7], &tree);       /* 1003 = &tree ? */

	/* Clear out tree */
	mtree_destroy(&tree);

	mt_init_flags(&tree, 0);
	/* Test inserting into a NULL hole. */
	check_insert(&tree, set[5], ptr);       /* insert 1001 -> ptr */
	check_insert(&tree, set[7], &tree);       /* insert 1003 -> &tree */
	check_insert(&tree, set[6], ptr);       /* insert 1002 -> ptr */
	check_load(&tree, set[5], ptr);         /* See if 1001 -> ptr */
	check_load(&tree, set[6], ptr);         /* See if 1002 -> ptr */
	check_load(&tree, set[7], &tree);       /* See if 1003 -> &tree */

	/* Clear out the tree */
	mtree_destroy(&tree);

	mt_init_flags(&tree, 0);
	/*
	 *       set[] = {5015, 5014, 5017, 25, 1000,
	 *                1001, 1002, 1003, 1005, 0,
	 *                5003, 5002};
	 */

	check_insert(&tree, set[0], ptr); /* 5015 */
	check_insert(&tree, set[1], &tree); /* 5014 */
	check_insert(&tree, set[2], ptr); /* 5017 */
	check_insert(&tree, set[3], &tree); /* 25 */
	check_load(&tree, set[0], ptr);
	check_load(&tree, set[1], &tree);
	check_load(&tree, set[2], ptr);
	check_load(&tree, set[3], &tree);
	check_insert(&tree, set[4], ptr); /* 1000 < Should split. */
	check_load(&tree, set[0], ptr);
	check_load(&tree, set[1], &tree);
	check_load(&tree, set[2], ptr);
	check_load(&tree, set[3], &tree); /*25 */
	check_load(&tree, set[4], ptr);
	check_insert(&tree, set[5], &tree); /* 1001 */
	check_load(&tree, set[0], ptr);
	check_load(&tree, set[1], &tree);
	check_load(&tree, set[2], ptr);
	check_load(&tree, set[3], &tree);
	check_load(&tree, set[4], ptr);
	check_load(&tree, set[5], &tree);
	check_insert(&tree, set[6], ptr);
	check_load(&tree, set[0], ptr);
	check_load(&tree, set[1], &tree);
	check_load(&tree, set[2], ptr);
	check_load(&tree, set[3], &tree);
	check_load(&tree, set[4], ptr);
	check_load(&tree, set[5], &tree);
	check_load(&tree, set[6], ptr);
	check_insert(&tree, set[7], &tree);
	check_load(&tree, set[0], ptr);
	check_insert(&tree, set[8], ptr);

	check_insert(&tree, set[9], &tree);

	check_load(&tree, set[0], ptr);
	check_load(&tree, set[1], &tree);
	check_load(&tree, set[2], ptr);
	check_load(&tree, set[3], &tree);
	check_load(&tree, set[4], ptr);
	check_load(&tree, set[5], &tree);
	check_load(&tree, set[6], ptr);
	check_load(&tree, set[9], &tree);
	mtree_destroy(&tree);

	mt_init_flags(&tree, 0);
	check_seq(&tree, 16, false);
	mtree_destroy(&tree);

	mt_init_flags(&tree, 0);
	check_seq(&tree, 1000, true);
	mtree_destroy(&tree);

	mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
	check_rev_seq(&tree, 1000, true);
	mtree_destroy(&tree);

	check_lower_bound_split(&tree);
	check_upper_bound_split(&tree);
	check_mid_split(&tree);

	mt_init_flags(&tree, 0);
	check_next_entry(&tree);
	check_find(&tree);
	check_find_2(&tree);
	mtree_destroy(&tree);

	mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
	check_prev_entry(&tree);
	mtree_destroy(&tree);

	mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
	check_gap_combining(&tree);
	mtree_destroy(&tree);

	mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
	check_node_overwrite(&tree);
	mtree_destroy(&tree);

	mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
	next_prev_test(&tree);
	mtree_destroy(&tree);

	mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
	check_spanning_relatives(&tree);
	mtree_destroy(&tree);

	mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
	check_rev_find(&tree);
	mtree_destroy(&tree);

	mt_init_flags(&tree, 0);
	check_fuzzer(&tree);
	mtree_destroy(&tree);

	mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
	check_dup(&tree);
	mtree_destroy(&tree);

	mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
	check_bnode_min_spanning(&tree);
	mtree_destroy(&tree);

	mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
	check_empty_area_window(&tree);
	mtree_destroy(&tree);

	mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
	check_empty_area_fill(&tree);
	mtree_destroy(&tree);


	mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
	check_state_handling(&tree);
	mtree_destroy(&tree);

#if defined(BENCH)
skip:
#endif
	rcu_barrier();
	pr_info("maple_tree: %u of %u tests passed\n",
			atomic_read(&maple_tree_tests_passed),
			atomic_read(&maple_tree_tests_run));
	if (atomic_read(&maple_tree_tests_run) ==
	    atomic_read(&maple_tree_tests_passed))
		return 0;

	return -EINVAL;
}

static void __exit maple_tree_harvest(void)
{

}

module_init(maple_tree_seed);
module_exit(maple_tree_harvest);
MODULE_AUTHOR("Liam R. Howlett <Liam.Howlett@Oracle.com>");
MODULE_LICENSE("GPL");