aboutsummaryrefslogtreecommitdiffstats
path: root/lib/xarray.c
diff options
context:
space:
mode:
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));