diff options
author | Matthew Wilcox (Oracle) <willy@infradead.org> | 2019-11-07 22:49:11 -0500 |
---|---|---|
committer | Matthew Wilcox (Oracle) <willy@infradead.org> | 2019-11-08 23:48:40 -0500 |
commit | 82a22311b7a68a78709699dc8c098953b70e4fd2 (patch) | |
tree | 60accb87ad1602692b42931ede847c3d1239478b /lib/test_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/test_xarray.c')
-rw-r--r-- | lib/test_xarray.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/lib/test_xarray.c b/lib/test_xarray.c index 7df4f7f395bf..c477f22a95cd 100644 --- a/lib/test_xarray.c +++ b/lib/test_xarray.c @@ -1132,6 +1132,27 @@ static noinline void check_move_tiny(struct xarray *xa) XA_BUG_ON(xa, !xa_empty(xa)); } +static noinline void check_move_max(struct xarray *xa) +{ + XA_STATE(xas, xa, 0); + + xa_store_index(xa, ULONG_MAX, GFP_KERNEL); + rcu_read_lock(); + XA_BUG_ON(xa, xas_find(&xas, ULONG_MAX) != xa_mk_index(ULONG_MAX)); + XA_BUG_ON(xa, xas_find(&xas, ULONG_MAX) != NULL); + rcu_read_unlock(); + + xas_set(&xas, 0); + rcu_read_lock(); + XA_BUG_ON(xa, xas_find(&xas, ULONG_MAX) != xa_mk_index(ULONG_MAX)); + xas_pause(&xas); + XA_BUG_ON(xa, xas_find(&xas, ULONG_MAX) != NULL); + rcu_read_unlock(); + + xa_erase_index(xa, ULONG_MAX); + XA_BUG_ON(xa, !xa_empty(xa)); +} + static noinline void check_move_small(struct xarray *xa, unsigned long idx) { XA_STATE(xas, xa, 0); @@ -1240,6 +1261,7 @@ static noinline void check_move(struct xarray *xa) xa_destroy(xa); check_move_tiny(xa); + check_move_max(xa); for (i = 0; i < 16; i++) check_move_small(xa, 1UL << i); |