aboutsummaryrefslogtreecommitdiffstats
path: root/lib/xarray.c
diff options
context:
space:
mode:
authorMatthew Wilcox <willy@infradead.org>2018-10-26 14:43:22 -0400
committerMatthew Wilcox <willy@infradead.org>2019-02-06 13:13:24 -0500
commit3ccaf57a6a63ad171a951dcaddffc453b2414c7b (patch)
treefc2202432a5b50ee5507a2e240b439b2993c2c3f /lib/xarray.c
parentfd9dc93e36231fb6d520e0edd467058fad4fd12d (diff)
XArray: Add support for 1s-based allocation
A lot of places want to allocate IDs starting at 1 instead of 0. While the xa_alloc() API supports this, it's not very efficient if lots of IDs are allocated, due to having to walk down to the bottom of the tree to see if ID 1 is available, then all the way over to the next non-allocated ID. This method marks ID 0 as being occupied which wastes one slot in the XArray, but preserves xa_empty() as working. Signed-off-by: Matthew Wilcox <willy@infradead.org>
Diffstat (limited to 'lib/xarray.c')
-rw-r--r--lib/xarray.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/lib/xarray.c b/lib/xarray.c
index 1b97ca58bd15..468fb7b7963f 100644
--- a/lib/xarray.c
+++ b/lib/xarray.c
@@ -57,6 +57,11 @@ static inline bool xa_track_free(const struct xarray *xa)
57 return xa->xa_flags & XA_FLAGS_TRACK_FREE; 57 return xa->xa_flags & XA_FLAGS_TRACK_FREE;
58} 58}
59 59
60static inline bool xa_zero_busy(const struct xarray *xa)
61{
62 return xa->xa_flags & XA_FLAGS_ZERO_BUSY;
63}
64
60static inline void xa_mark_set(struct xarray *xa, xa_mark_t mark) 65static inline void xa_mark_set(struct xarray *xa, xa_mark_t mark)
61{ 66{
62 if (!(xa->xa_flags & XA_FLAGS_MARK(mark))) 67 if (!(xa->xa_flags & XA_FLAGS_MARK(mark)))
@@ -432,6 +437,8 @@ static void xas_shrink(struct xa_state *xas)
432 break; 437 break;
433 if (!xa_is_node(entry) && node->shift) 438 if (!xa_is_node(entry) && node->shift)
434 break; 439 break;
440 if (xa_is_zero(entry) && xa_zero_busy(xa))
441 entry = NULL;
435 xas->xa_node = XAS_BOUNDS; 442 xas->xa_node = XAS_BOUNDS;
436 443
437 RCU_INIT_POINTER(xa->xa_head, entry); 444 RCU_INIT_POINTER(xa->xa_head, entry);
@@ -628,6 +635,8 @@ static void *xas_create(struct xa_state *xas, bool allow_root)
628 if (xas_top(node)) { 635 if (xas_top(node)) {
629 entry = xa_head_locked(xa); 636 entry = xa_head_locked(xa);
630 xas->xa_node = NULL; 637 xas->xa_node = NULL;
638 if (!entry && xa_zero_busy(xa))
639 entry = XA_ZERO_ENTRY;
631 shift = xas_expand(xas, entry); 640 shift = xas_expand(xas, entry);
632 if (shift < 0) 641 if (shift < 0)
633 return NULL; 642 return NULL;
@@ -1942,6 +1951,8 @@ void xa_destroy(struct xarray *xa)
1942 entry = xa_head_locked(xa); 1951 entry = xa_head_locked(xa);
1943 RCU_INIT_POINTER(xa->xa_head, NULL); 1952 RCU_INIT_POINTER(xa->xa_head, NULL);
1944 xas_init_marks(&xas); 1953 xas_init_marks(&xas);
1954 if (xa_zero_busy(xa))
1955 xa_mark_clear(xa, XA_FREE_MARK);
1945 /* lockdep checks we're still holding the lock in xas_free_nodes() */ 1956 /* lockdep checks we're still holding the lock in xas_free_nodes() */
1946 if (xa_is_node(entry)) 1957 if (xa_is_node(entry))
1947 xas_free_nodes(&xas, xa_to_node(entry)); 1958 xas_free_nodes(&xas, xa_to_node(entry));