66#include <linux/slab.h>
77#include <asm/timex.h>
88#include <linux/bitmap.h>
9+ #include <linux/maple_tree.h>
910
1011#define __param (type , name , init , msg ) \
1112 static type name = init; \
@@ -193,6 +194,121 @@ static int intersection_range_check(void)
193194 return 0 ;
194195}
195196
197+ #ifdef CONFIG_INTERVAL_TREE_SPAN_ITER
198+ /*
199+ * Helper function to get span of current position from maple tree point of
200+ * view.
201+ */
202+ static void mas_cur_span (struct ma_state * mas , struct interval_tree_span_iter * state )
203+ {
204+ unsigned long cur_start ;
205+ unsigned long cur_last ;
206+ int is_hole ;
207+
208+ if (mas -> status == ma_overflow )
209+ return ;
210+
211+ /* walk to current position */
212+ state -> is_hole = mas_walk (mas ) ? 0 : 1 ;
213+
214+ cur_start = mas -> index < state -> first_index ?
215+ state -> first_index : mas -> index ;
216+
217+ /* whether we have followers */
218+ do {
219+
220+ cur_last = mas -> last > state -> last_index ?
221+ state -> last_index : mas -> last ;
222+
223+ is_hole = mas_next_range (mas , state -> last_index ) ? 0 : 1 ;
224+
225+ } while (mas -> status != ma_overflow && is_hole == state -> is_hole );
226+
227+ if (state -> is_hole ) {
228+ state -> start_hole = cur_start ;
229+ state -> last_hole = cur_last ;
230+ } else {
231+ state -> start_used = cur_start ;
232+ state -> last_used = cur_last ;
233+ }
234+
235+ /* advance position for next round */
236+ if (mas -> status != ma_overflow )
237+ mas_set (mas , cur_last + 1 );
238+ }
239+
240+ static int span_iteration_check (void )
241+ {
242+ int i , j , k ;
243+ unsigned long start , last ;
244+ struct interval_tree_span_iter span , mas_span ;
245+
246+ DEFINE_MTREE (tree );
247+
248+ MA_STATE (mas , & tree , 0 , 0 );
249+
250+ printk (KERN_ALERT "interval tree span iteration\n" );
251+
252+ for (i = 0 ; i < search_loops ; i ++ ) {
253+ /* Initialize interval tree for each round */
254+ init ();
255+ for (j = 0 ; j < nnodes ; j ++ )
256+ interval_tree_insert (nodes + j , & root );
257+
258+ /* Put all the range into maple tree */
259+ mt_init_flags (& tree , MT_FLAGS_ALLOC_RANGE );
260+ mt_set_in_rcu (& tree );
261+
262+ for (j = 0 ; j < nnodes ; j ++ )
263+ WARN_ON_ONCE (mtree_store_range (& tree , nodes [j ].start ,
264+ nodes [j ].last , nodes + j , GFP_KERNEL ));
265+
266+ /* Let's try nsearches different ranges */
267+ for (k = 0 ; k < nsearches ; k ++ ) {
268+ /* Try whole range once */
269+ if (!k ) {
270+ start = 0UL ;
271+ last = ULONG_MAX ;
272+ } else {
273+ last = (prandom_u32_state (& rnd ) >> 4 ) % max_endpoint ;
274+ start = (prandom_u32_state (& rnd ) >> 4 ) % last ;
275+ }
276+
277+ mas_span .first_index = start ;
278+ mas_span .last_index = last ;
279+ mas_span .is_hole = -1 ;
280+ mas_set (& mas , start );
281+
282+ interval_tree_for_each_span (& span , & root , start , last ) {
283+ mas_cur_span (& mas , & mas_span );
284+
285+ WARN_ON_ONCE (span .is_hole != mas_span .is_hole );
286+
287+ if (span .is_hole ) {
288+ WARN_ON_ONCE (span .start_hole != mas_span .start_hole );
289+ WARN_ON_ONCE (span .last_hole != mas_span .last_hole );
290+ } else {
291+ WARN_ON_ONCE (span .start_used != mas_span .start_used );
292+ WARN_ON_ONCE (span .last_used != mas_span .last_used );
293+ }
294+ }
295+
296+ }
297+
298+ WARN_ON_ONCE (mas .status != ma_overflow );
299+
300+ /* Cleanup maple tree for each round */
301+ mtree_destroy (& tree );
302+ /* Cleanup interval tree for each round */
303+ for (j = 0 ; j < nnodes ; j ++ )
304+ interval_tree_remove (nodes + j , & root );
305+ }
306+ return 0 ;
307+ }
308+ #else
309+ static inline int span_iteration_check (void ) {return 0 ; }
310+ #endif
311+
196312static int interval_tree_test_init (void )
197313{
198314 nodes = kmalloc_array (nnodes , sizeof (struct interval_tree_node ),
@@ -211,6 +327,7 @@ static int interval_tree_test_init(void)
211327 basic_check ();
212328 search_check ();
213329 intersection_range_check ();
330+ span_iteration_check ();
214331
215332 kfree (queries );
216333 kfree (nodes );
0 commit comments