diff options
author | Matthew Wilcox (Oracle) <willy@infradead.org> | 2019-11-07 22:49:11 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-02-05 21:22:47 +0000 |
commit | 08022255a9ee926896e81ba63a83bb904efe446d (patch) | |
tree | 730f432f7a97b8708b007a9a834aabfb0b4bbae5 /lib/xarray.c | |
parent | b267caf5e51f207c68e67aee47380a6c8fde7840 (diff) |
XArray: Fix xas_pause at ULONG_MAX
[ Upstream commit 82a22311b7a68a78709699dc8c098953b70e4fd2 ]
If we were unlucky enough to call xas_pause() when the index was at
ULONG_MAX (or a multi-slot entry which ends at ULONG_MAX), we would
wrap the index back around to 0 and restart the iteration from the
beginning. Use the XAS_BOUNDS state to indicate that we should just
stop the iteration.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'lib/xarray.c')
-rw-r--r-- | lib/xarray.c | 8 |
1 files changed, 5 insertions, 3 deletions
diff --git a/lib/xarray.c b/lib/xarray.c index 47e17d46e5f8..1d9fab7db8da 100644 --- a/lib/xarray.c +++ b/lib/xarray.c @@ -968,6 +968,7 @@ void xas_pause(struct xa_state *xas) if (xas_invalid(xas)) return; + xas->xa_node = XAS_RESTART; if (node) { unsigned int offset = xas->xa_offset; while (++offset < XA_CHUNK_SIZE) { @@ -975,10 +976,11 @@ void xas_pause(struct xa_state *xas) break; } xas->xa_index += (offset - xas->xa_offset) << node->shift; + if (xas->xa_index == 0) + xas->xa_node = XAS_BOUNDS; } else { xas->xa_index++; } - xas->xa_node = XAS_RESTART; } EXPORT_SYMBOL_GPL(xas_pause); @@ -1080,7 +1082,7 @@ void *xas_find(struct xa_state *xas, unsigned long max) { void *entry; - if (xas_error(xas)) + if (xas_error(xas) || xas->xa_node == XAS_BOUNDS) return NULL; if (xas->xa_index > max) return set_bounds(xas); @@ -1088,7 +1090,7 @@ void *xas_find(struct xa_state *xas, unsigned long max) if (!xas->xa_node) { xas->xa_index = 1; return set_bounds(xas); - } else if (xas_top(xas->xa_node)) { + } else if (xas->xa_node == XAS_RESTART) { entry = xas_load(xas); if (entry || xas_not_node(xas->xa_node)) return entry; |