diff options
author | Matthew Wilcox <willy@infradead.org> | 2018-06-02 04:46:02 +0200 |
---|---|---|
committer | Matthew Wilcox <willy@infradead.org> | 2018-10-21 16:45:59 +0200 |
commit | 4e99d4e9579d3b950bf4b38d0d64eb1b9be78761 (patch) | |
tree | a3ecd9d06b4f0eb8bb05369887c9fbe133218e01 /lib/xarray.c | |
parent | xarray: Step through an XArray (diff) | |
download | linux-4e99d4e9579d3b950bf4b38d0d64eb1b9be78761.tar.xz linux-4e99d4e9579d3b950bf4b38d0d64eb1b9be78761.zip |
xarray: Add xas_for_each_conflict
This iterator iterates over each entry that is stored in the index or
indices specified by the xa_state. This is intended for use for a
conditional store of a multiindex entry, or to allow entries which are
about to be removed from the xarray to be disposed of properly.
Signed-off-by: Matthew Wilcox <willy@infradead.org>
Diffstat (limited to 'lib/xarray.c')
-rw-r--r-- | lib/xarray.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/lib/xarray.c b/lib/xarray.c index 303c46579598..41f8ebc651f5 100644 --- a/lib/xarray.c +++ b/lib/xarray.c @@ -1111,6 +1111,67 @@ max: EXPORT_SYMBOL_GPL(xas_find_marked); /** + * xas_find_conflict() - Find the next present entry in a range. + * @xas: XArray operation state. + * + * The @xas describes both a range and a position within that range. + * + * Context: Any context. Expects xa_lock to be held. + * Return: The next entry in the range covered by @xas or %NULL. + */ +void *xas_find_conflict(struct xa_state *xas) +{ + void *curr; + + if (xas_error(xas)) + return NULL; + + if (!xas->xa_node) + return NULL; + + if (xas_top(xas->xa_node)) { + curr = xas_start(xas); + if (!curr) + return NULL; + while (xa_is_node(curr)) { + struct xa_node *node = xa_to_node(curr); + curr = xas_descend(xas, node); + } + if (curr) + return curr; + } + + if (xas->xa_node->shift > xas->xa_shift) + return NULL; + + for (;;) { + if (xas->xa_node->shift == xas->xa_shift) { + if ((xas->xa_offset & xas->xa_sibs) == xas->xa_sibs) + break; + } else if (xas->xa_offset == XA_CHUNK_MASK) { + xas->xa_offset = xas->xa_node->offset; + xas->xa_node = xa_parent_locked(xas->xa, xas->xa_node); + if (!xas->xa_node) + break; + continue; + } + curr = xa_entry_locked(xas->xa, xas->xa_node, ++xas->xa_offset); + if (xa_is_sibling(curr)) + continue; + while (xa_is_node(curr)) { + xas->xa_node = xa_to_node(curr); + xas->xa_offset = 0; + curr = xa_entry_locked(xas->xa, xas->xa_node, 0); + } + if (curr) + return curr; + } + xas->xa_offset -= xas->xa_sibs; + return NULL; +} +EXPORT_SYMBOL_GPL(xas_find_conflict); + +/** * xa_init_flags() - Initialise an empty XArray with flags. * @xa: XArray. * @flags: XA_FLAG values. |