@@ -4290,6 +4290,56 @@ static inline void *mas_insert(struct ma_state *mas, void *entry)
42904290
42914291}
42924292
4293+ /**
4294+ * mas_alloc_cyclic() - Internal call to find somewhere to store an entry
4295+ * @mas: The maple state.
4296+ * @startp: Pointer to ID.
4297+ * @range_lo: Lower bound of range to search.
4298+ * @range_hi: Upper bound of range to search.
4299+ * @entry: The entry to store.
4300+ * @next: Pointer to next ID to allocate.
4301+ * @gfp: The GFP_FLAGS to use for allocations.
4302+ *
4303+ * Return: 0 if the allocation succeeded without wrapping, 1 if the
4304+ * allocation succeeded after wrapping, or -EBUSY if there are no
4305+ * free entries.
4306+ */
4307+ int mas_alloc_cyclic (struct ma_state * mas , unsigned long * startp ,
4308+ void * entry , unsigned long range_lo , unsigned long range_hi ,
4309+ unsigned long * next , gfp_t gfp )
4310+ {
4311+ unsigned long min = range_lo ;
4312+ int ret = 0 ;
4313+
4314+ range_lo = max (min , * next );
4315+ ret = mas_empty_area (mas , range_lo , range_hi , 1 );
4316+ if ((mas -> tree -> ma_flags & MT_FLAGS_ALLOC_WRAPPED ) && ret == 0 ) {
4317+ mas -> tree -> ma_flags &= ~MT_FLAGS_ALLOC_WRAPPED ;
4318+ ret = 1 ;
4319+ }
4320+ if (ret < 0 && range_lo > min ) {
4321+ ret = mas_empty_area (mas , min , range_hi , 1 );
4322+ if (ret == 0 )
4323+ ret = 1 ;
4324+ }
4325+ if (ret < 0 )
4326+ return ret ;
4327+
4328+ do {
4329+ mas_insert (mas , entry );
4330+ } while (mas_nomem (mas , gfp ));
4331+ if (mas_is_err (mas ))
4332+ return xa_err (mas -> node );
4333+
4334+ * startp = mas -> index ;
4335+ * next = * startp + 1 ;
4336+ if (* next == 0 )
4337+ mas -> tree -> ma_flags |= MT_FLAGS_ALLOC_WRAPPED ;
4338+
4339+ return ret ;
4340+ }
4341+ EXPORT_SYMBOL (mas_alloc_cyclic );
4342+
42934343static __always_inline void mas_rewalk (struct ma_state * mas , unsigned long index )
42944344{
42954345retry :
@@ -6443,6 +6493,49 @@ int mtree_alloc_range(struct maple_tree *mt, unsigned long *startp,
64436493}
64446494EXPORT_SYMBOL (mtree_alloc_range );
64456495
6496+ /**
6497+ * mtree_alloc_cyclic() - Find somewhere to store this entry in the tree.
6498+ * @mt: The maple tree.
6499+ * @startp: Pointer to ID.
6500+ * @range_lo: Lower bound of range to search.
6501+ * @range_hi: Upper bound of range to search.
6502+ * @entry: The entry to store.
6503+ * @next: Pointer to next ID to allocate.
6504+ * @gfp: The GFP_FLAGS to use for allocations.
6505+ *
6506+ * Finds an empty entry in @mt after @next, stores the new index into
6507+ * the @id pointer, stores the entry at that index, then updates @next.
6508+ *
6509+ * @mt must be initialized with the MT_FLAGS_ALLOC_RANGE flag.
6510+ *
6511+ * Context: Any context. Takes and releases the mt.lock. May sleep if
6512+ * the @gfp flags permit.
6513+ *
6514+ * Return: 0 if the allocation succeeded without wrapping, 1 if the
6515+ * allocation succeeded after wrapping, -ENOMEM if memory could not be
6516+ * allocated, -EINVAL if @mt cannot be used, or -EBUSY if there are no
6517+ * free entries.
6518+ */
6519+ int mtree_alloc_cyclic (struct maple_tree * mt , unsigned long * startp ,
6520+ void * entry , unsigned long range_lo , unsigned long range_hi ,
6521+ unsigned long * next , gfp_t gfp )
6522+ {
6523+ int ret ;
6524+
6525+ MA_STATE (mas , mt , 0 , 0 );
6526+
6527+ if (!mt_is_alloc (mt ))
6528+ return - EINVAL ;
6529+ if (WARN_ON_ONCE (mt_is_reserved (entry )))
6530+ return - EINVAL ;
6531+ mtree_lock (mt );
6532+ ret = mas_alloc_cyclic (& mas , startp , entry , range_lo , range_hi ,
6533+ next , gfp );
6534+ mtree_unlock (mt );
6535+ return ret ;
6536+ }
6537+ EXPORT_SYMBOL (mtree_alloc_cyclic );
6538+
64466539int mtree_alloc_rrange (struct maple_tree * mt , unsigned long * startp ,
64476540 void * entry , unsigned long size , unsigned long min ,
64486541 unsigned long max , gfp_t gfp )
0 commit comments