diff options
author | Matthew Wilcox (Oracle) | 2019-11-07 22:49:11 -0500 |
---|---|---|
committer | Matthew Wilcox (Oracle) | 2019-11-08 23:48:40 -0500 |
commit | 82a22311b7a68a78709699dc8c098953b70e4fd2 (patch) | |
tree | 60accb87ad1602692b42931ede847c3d1239478b /lib/xarray.c | |
parent | 0058b0a506e40d9a2c62015fe92eb64a44d78cd9 (diff) |
XArray: Fix xas_pause at ULONG_MAX
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>
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 1237c213f52b..bfaaa2c1f3fe 100644 --- a/lib/xarray.c +++ b/lib/xarray.c @@ -967,6 +967,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) { @@ -974,10 +975,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); @@ -1079,13 +1081,13 @@ 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_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; |