diff options
Diffstat (limited to 'lib/xarray.c')
-rw-r--r-- | lib/xarray.c | 11 |
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 | ||
60 | static inline bool xa_zero_busy(const struct xarray *xa) | ||
61 | { | ||
62 | return xa->xa_flags & XA_FLAGS_ZERO_BUSY; | ||
63 | } | ||
64 | |||
60 | static inline void xa_mark_set(struct xarray *xa, xa_mark_t mark) | 65 | static 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)); |