1*54a611b6SLiam R. Howlett.. SPDX-License-Identifier: GPL-2.0+ 2*54a611b6SLiam R. Howlett 3*54a611b6SLiam R. Howlett 4*54a611b6SLiam R. Howlett========== 5*54a611b6SLiam R. HowlettMaple Tree 6*54a611b6SLiam R. Howlett========== 7*54a611b6SLiam R. Howlett 8*54a611b6SLiam R. Howlett:Author: Liam R. Howlett 9*54a611b6SLiam R. Howlett 10*54a611b6SLiam R. HowlettOverview 11*54a611b6SLiam R. Howlett======== 12*54a611b6SLiam R. Howlett 13*54a611b6SLiam R. HowlettThe Maple Tree is a B-Tree data type which is optimized for storing 14*54a611b6SLiam R. Howlettnon-overlapping ranges, including ranges of size 1. The tree was designed to 15*54a611b6SLiam R. Howlettbe simple to use and does not require a user written search method. It 16*54a611b6SLiam R. Howlettsupports iterating over a range of entries and going to the previous or next 17*54a611b6SLiam R. Howlettentry in a cache-efficient manner. The tree can also be put into an RCU-safe 18*54a611b6SLiam R. Howlettmode of operation which allows reading and writing concurrently. Writers must 19*54a611b6SLiam R. Howlettsynchronize on a lock, which can be the default spinlock, or the user can set 20*54a611b6SLiam R. Howlettthe lock to an external lock of a different type. 21*54a611b6SLiam R. Howlett 22*54a611b6SLiam R. HowlettThe Maple Tree maintains a small memory footprint and was designed to use 23*54a611b6SLiam R. Howlettmodern processor cache efficiently. The majority of the users will be able to 24*54a611b6SLiam R. Howlettuse the normal API. An :ref:`maple-tree-advanced-api` exists for more complex 25*54a611b6SLiam R. Howlettscenarios. The most important usage of the Maple Tree is the tracking of the 26*54a611b6SLiam R. Howlettvirtual memory areas. 27*54a611b6SLiam R. Howlett 28*54a611b6SLiam R. HowlettThe Maple Tree can store values between ``0`` and ``ULONG_MAX``. The Maple 29*54a611b6SLiam R. HowlettTree reserves values with the bottom two bits set to '10' which are below 4096 30*54a611b6SLiam R. Howlett(ie 2, 6, 10 .. 4094) for internal use. If the entries may use reserved 31*54a611b6SLiam R. Howlettentries then the users can convert the entries using xa_mk_value() and convert 32*54a611b6SLiam R. Howlettthem back by calling xa_to_value(). If the user needs to use a reserved 33*54a611b6SLiam R. Howlettvalue, then the user can convert the value when using the 34*54a611b6SLiam R. Howlett:ref:`maple-tree-advanced-api`, but are blocked by the normal API. 35*54a611b6SLiam R. Howlett 36*54a611b6SLiam R. HowlettThe Maple Tree can also be configured to support searching for a gap of a given 37*54a611b6SLiam R. Howlettsize (or larger). 38*54a611b6SLiam R. Howlett 39*54a611b6SLiam R. HowlettPre-allocating of nodes is also supported using the 40*54a611b6SLiam R. Howlett:ref:`maple-tree-advanced-api`. This is useful for users who must guarantee a 41*54a611b6SLiam R. Howlettsuccessful store operation within a given 42*54a611b6SLiam R. Howlettcode segment when allocating cannot be done. Allocations of nodes are 43*54a611b6SLiam R. Howlettrelatively small at around 256 bytes. 44*54a611b6SLiam R. Howlett 45*54a611b6SLiam R. Howlett.. _maple-tree-normal-api: 46*54a611b6SLiam R. Howlett 47*54a611b6SLiam R. HowlettNormal API 48*54a611b6SLiam R. Howlett========== 49*54a611b6SLiam R. Howlett 50*54a611b6SLiam R. HowlettStart by initialising a maple tree, either with DEFINE_MTREE() for statically 51*54a611b6SLiam R. Howlettallocated maple trees or mt_init() for dynamically allocated ones. A 52*54a611b6SLiam R. Howlettfreshly-initialised maple tree contains a ``NULL`` pointer for the range ``0`` 53*54a611b6SLiam R. Howlett- ``ULONG_MAX``. There are currently two types of maple trees supported: the 54*54a611b6SLiam R. Howlettallocation tree and the regular tree. The regular tree has a higher branching 55*54a611b6SLiam R. Howlettfactor for internal nodes. The allocation tree has a lower branching factor 56*54a611b6SLiam R. Howlettbut allows the user to search for a gap of a given size or larger from either 57*54a611b6SLiam R. Howlett``0`` upwards or ``ULONG_MAX`` down. An allocation tree can be used by 58*54a611b6SLiam R. Howlettpassing in the ``MT_FLAGS_ALLOC_RANGE`` flag when initialising the tree. 59*54a611b6SLiam R. Howlett 60*54a611b6SLiam R. HowlettYou can then set entries using mtree_store() or mtree_store_range(). 61*54a611b6SLiam R. Howlettmtree_store() will overwrite any entry with the new entry and return 0 on 62*54a611b6SLiam R. Howlettsuccess or an error code otherwise. mtree_store_range() works in the same way 63*54a611b6SLiam R. Howlettbut takes a range. mtree_load() is used to retrieve the entry stored at a 64*54a611b6SLiam R. Howlettgiven index. You can use mtree_erase() to erase an entire range by only 65*54a611b6SLiam R. Howlettknowing one value within that range, or mtree_store() call with an entry of 66*54a611b6SLiam R. HowlettNULL may be used to partially erase a range or many ranges at once. 67*54a611b6SLiam R. Howlett 68*54a611b6SLiam R. HowlettIf you want to only store a new entry to a range (or index) if that range is 69*54a611b6SLiam R. Howlettcurrently ``NULL``, you can use mtree_insert_range() or mtree_insert() which 70*54a611b6SLiam R. Howlettreturn -EEXIST if the range is not empty. 71*54a611b6SLiam R. Howlett 72*54a611b6SLiam R. HowlettYou can search for an entry from an index upwards by using mt_find(). 73*54a611b6SLiam R. Howlett 74*54a611b6SLiam R. HowlettYou can walk each entry within a range by calling mt_for_each(). You must 75*54a611b6SLiam R. Howlettprovide a temporary variable to store a cursor. If you want to walk each 76*54a611b6SLiam R. Howlettelement of the tree then ``0`` and ``ULONG_MAX`` may be used as the range. If 77*54a611b6SLiam R. Howlettthe caller is going to hold the lock for the duration of the walk then it is 78*54a611b6SLiam R. Howlettworth looking at the mas_for_each() API in the :ref:`maple-tree-advanced-api` 79*54a611b6SLiam R. Howlettsection. 80*54a611b6SLiam R. Howlett 81*54a611b6SLiam R. HowlettSometimes it is necessary to ensure the next call to store to a maple tree does 82*54a611b6SLiam R. Howlettnot allocate memory, please see :ref:`maple-tree-advanced-api` for this use case. 83*54a611b6SLiam R. Howlett 84*54a611b6SLiam R. HowlettFinally, you can remove all entries from a maple tree by calling 85*54a611b6SLiam R. Howlettmtree_destroy(). If the maple tree entries are pointers, you may wish to free 86*54a611b6SLiam R. Howlettthe entries first. 87*54a611b6SLiam R. Howlett 88*54a611b6SLiam R. HowlettAllocating Nodes 89*54a611b6SLiam R. Howlett---------------- 90*54a611b6SLiam R. Howlett 91*54a611b6SLiam R. HowlettThe allocations are handled by the internal tree code. See 92*54a611b6SLiam R. Howlett:ref:`maple-tree-advanced-alloc` for other options. 93*54a611b6SLiam R. Howlett 94*54a611b6SLiam R. HowlettLocking 95*54a611b6SLiam R. Howlett------- 96*54a611b6SLiam R. Howlett 97*54a611b6SLiam R. HowlettYou do not have to worry about locking. See :ref:`maple-tree-advanced-locks` 98*54a611b6SLiam R. Howlettfor other options. 99*54a611b6SLiam R. Howlett 100*54a611b6SLiam R. HowlettThe Maple Tree uses RCU and an internal spinlock to synchronise access: 101*54a611b6SLiam R. Howlett 102*54a611b6SLiam R. HowlettTakes RCU read lock: 103*54a611b6SLiam R. Howlett * mtree_load() 104*54a611b6SLiam R. Howlett * mt_find() 105*54a611b6SLiam R. Howlett * mt_for_each() 106*54a611b6SLiam R. Howlett * mt_next() 107*54a611b6SLiam R. Howlett * mt_prev() 108*54a611b6SLiam R. Howlett 109*54a611b6SLiam R. HowlettTakes ma_lock internally: 110*54a611b6SLiam R. Howlett * mtree_store() 111*54a611b6SLiam R. Howlett * mtree_store_range() 112*54a611b6SLiam R. Howlett * mtree_insert() 113*54a611b6SLiam R. Howlett * mtree_insert_range() 114*54a611b6SLiam R. Howlett * mtree_erase() 115*54a611b6SLiam R. Howlett * mtree_destroy() 116*54a611b6SLiam R. Howlett * mt_set_in_rcu() 117*54a611b6SLiam R. Howlett * mt_clear_in_rcu() 118*54a611b6SLiam R. Howlett 119*54a611b6SLiam R. HowlettIf you want to take advantage of the internal lock to protect the data 120*54a611b6SLiam R. Howlettstructures that you are storing in the Maple Tree, you can call mtree_lock() 121*54a611b6SLiam R. Howlettbefore calling mtree_load(), then take a reference count on the object you 122*54a611b6SLiam R. Howletthave found before calling mtree_unlock(). This will prevent stores from 123*54a611b6SLiam R. Howlettremoving the object from the tree between looking up the object and 124*54a611b6SLiam R. Howlettincrementing the refcount. You can also use RCU to avoid dereferencing 125*54a611b6SLiam R. Howlettfreed memory, but an explanation of that is beyond the scope of this 126*54a611b6SLiam R. Howlettdocument. 127*54a611b6SLiam R. Howlett 128*54a611b6SLiam R. Howlett.. _maple-tree-advanced-api: 129*54a611b6SLiam R. Howlett 130*54a611b6SLiam R. HowlettAdvanced API 131*54a611b6SLiam R. Howlett============ 132*54a611b6SLiam R. Howlett 133*54a611b6SLiam R. HowlettThe advanced API offers more flexibility and better performance at the 134*54a611b6SLiam R. Howlettcost of an interface which can be harder to use and has fewer safeguards. 135*54a611b6SLiam R. HowlettYou must take care of your own locking while using the advanced API. 136*54a611b6SLiam R. HowlettYou can use the ma_lock, RCU or an external lock for protection. 137*54a611b6SLiam R. HowlettYou can mix advanced and normal operations on the same array, as long 138*54a611b6SLiam R. Howlettas the locking is compatible. The :ref:`maple-tree-normal-api` is implemented 139*54a611b6SLiam R. Howlettin terms of the advanced API. 140*54a611b6SLiam R. Howlett 141*54a611b6SLiam R. HowlettThe advanced API is based around the ma_state, this is where the 'mas' 142*54a611b6SLiam R. Howlettprefix originates. The ma_state struct keeps track of tree operations to make 143*54a611b6SLiam R. Howlettlife easier for both internal and external tree users. 144*54a611b6SLiam R. Howlett 145*54a611b6SLiam R. HowlettInitialising the maple tree is the same as in the :ref:`maple-tree-normal-api`. 146*54a611b6SLiam R. HowlettPlease see above. 147*54a611b6SLiam R. Howlett 148*54a611b6SLiam R. HowlettThe maple state keeps track of the range start and end in mas->index and 149*54a611b6SLiam R. Howlettmas->last, respectively. 150*54a611b6SLiam R. Howlett 151*54a611b6SLiam R. Howlettmas_walk() will walk the tree to the location of mas->index and set the 152*54a611b6SLiam R. Howlettmas->index and mas->last according to the range for the entry. 153*54a611b6SLiam R. Howlett 154*54a611b6SLiam R. HowlettYou can set entries using mas_store(). mas_store() will overwrite any entry 155*54a611b6SLiam R. Howlettwith the new entry and return the first existing entry that is overwritten. 156*54a611b6SLiam R. HowlettThe range is passed in as members of the maple state: index and last. 157*54a611b6SLiam R. Howlett 158*54a611b6SLiam R. HowlettYou can use mas_erase() to erase an entire range by setting index and 159*54a611b6SLiam R. Howlettlast of the maple state to the desired range to erase. This will erase 160*54a611b6SLiam R. Howlettthe first range that is found in that range, set the maple state index 161*54a611b6SLiam R. Howlettand last as the range that was erased and return the entry that existed 162*54a611b6SLiam R. Howlettat that location. 163*54a611b6SLiam R. Howlett 164*54a611b6SLiam R. HowlettYou can walk each entry within a range by using mas_for_each(). If you want 165*54a611b6SLiam R. Howlettto walk each element of the tree then ``0`` and ``ULONG_MAX`` may be used as 166*54a611b6SLiam R. Howlettthe range. If the lock needs to be periodically dropped, see the locking 167*54a611b6SLiam R. Howlettsection mas_pause(). 168*54a611b6SLiam R. Howlett 169*54a611b6SLiam R. HowlettUsing a maple state allows mas_next() and mas_prev() to function as if the 170*54a611b6SLiam R. Howletttree was a linked list. With such a high branching factor the amortized 171*54a611b6SLiam R. Howlettperformance penalty is outweighed by cache optimization. mas_next() will 172*54a611b6SLiam R. Howlettreturn the next entry which occurs after the entry at index. mas_prev() 173*54a611b6SLiam R. Howlettwill return the previous entry which occurs before the entry at index. 174*54a611b6SLiam R. Howlett 175*54a611b6SLiam R. Howlettmas_find() will find the first entry which exists at or above index on 176*54a611b6SLiam R. Howlettthe first call, and the next entry from every subsequent calls. 177*54a611b6SLiam R. Howlett 178*54a611b6SLiam R. Howlettmas_find_rev() will find the fist entry which exists at or below the last on 179*54a611b6SLiam R. Howlettthe first call, and the previous entry from every subsequent calls. 180*54a611b6SLiam R. Howlett 181*54a611b6SLiam R. HowlettIf the user needs to yield the lock during an operation, then the maple state 182*54a611b6SLiam R. Howlettmust be paused using mas_pause(). 183*54a611b6SLiam R. Howlett 184*54a611b6SLiam R. HowlettThere are a few extra interfaces provided when using an allocation tree. 185*54a611b6SLiam R. HowlettIf you wish to search for a gap within a range, then mas_empty_area() 186*54a611b6SLiam R. Howlettor mas_empty_area_rev() can be used. mas_empty_area() searches for a gap 187*54a611b6SLiam R. Howlettstarting at the lowest index given up to the maximum of the range. 188*54a611b6SLiam R. Howlettmas_empty_area_rev() searches for a gap starting at the highest index given 189*54a611b6SLiam R. Howlettand continues downward to the lower bound of the range. 190*54a611b6SLiam R. Howlett 191*54a611b6SLiam R. Howlett.. _maple-tree-advanced-alloc: 192*54a611b6SLiam R. Howlett 193*54a611b6SLiam R. HowlettAdvanced Allocating Nodes 194*54a611b6SLiam R. Howlett------------------------- 195*54a611b6SLiam R. Howlett 196*54a611b6SLiam R. HowlettAllocations are usually handled internally to the tree, however if allocations 197*54a611b6SLiam R. Howlettneed to occur before a write occurs then calling mas_expected_entries() will 198*54a611b6SLiam R. Howlettallocate the worst-case number of needed nodes to insert the provided number of 199*54a611b6SLiam R. Howlettranges. This also causes the tree to enter mass insertion mode. Once 200*54a611b6SLiam R. Howlettinsertions are complete calling mas_destroy() on the maple state will free the 201*54a611b6SLiam R. Howlettunused allocations. 202*54a611b6SLiam R. Howlett 203*54a611b6SLiam R. Howlett.. _maple-tree-advanced-locks: 204*54a611b6SLiam R. Howlett 205*54a611b6SLiam R. HowlettAdvanced Locking 206*54a611b6SLiam R. Howlett---------------- 207*54a611b6SLiam R. Howlett 208*54a611b6SLiam R. HowlettThe maple tree uses a spinlock by default, but external locks can be used for 209*54a611b6SLiam R. Howletttree updates as well. To use an external lock, the tree must be initialized 210*54a611b6SLiam R. Howlettwith the ``MT_FLAGS_LOCK_EXTERN flag``, this is usually done with the 211*54a611b6SLiam R. HowlettMTREE_INIT_EXT() #define, which takes an external lock as an argument. 212*54a611b6SLiam R. Howlett 213*54a611b6SLiam R. HowlettFunctions and structures 214*54a611b6SLiam R. Howlett======================== 215*54a611b6SLiam R. Howlett 216*54a611b6SLiam R. Howlett.. kernel-doc:: include/linux/maple_tree.h 217*54a611b6SLiam R. Howlett.. kernel-doc:: lib/maple_tree.c 218