summaryrefslogtreecommitdiffstats
path: root/lib/xarray.c
diff options
context:
space:
mode:
authorMatthew Wilcox <willy@infradead.org>2019-02-20 11:30:49 -0500
committerMatthew Wilcox <willy@infradead.org>2019-02-20 17:08:54 -0500
commitb38f6c50270683abf35a388f82cafecce971a003 (patch)
tree0db0d39cf82d0f1996b28056668ebeabc8e58add /lib/xarray.c
parentf818b82b80164014d7ee3df89bb110808778c796 (diff)
XArray: Fix xa_release in allocating arrays
xa_cmpxchg() was a little too magic in turning ZERO entries into NULL, and would leave the entry set to the ZERO entry instead of releasing it for future use. After careful review of existing users of xa_cmpxchg(), change the semantics so that it does not translate either incoming argument from NULL into ZERO entries. Add several tests to the test-suite to make sure this problem doesn't come back. Reported-by: Jason Gunthorpe <jgg@ziepe.ca> Signed-off-by: Matthew Wilcox <willy@infradead.org>
Diffstat (limited to 'lib/xarray.c')
-rw-r--r--lib/xarray.c6
1 files changed, 1 insertions, 5 deletions
diff --git a/lib/xarray.c b/lib/xarray.c
index 89e37ac50850..b9a6cf42feee 100644
--- a/lib/xarray.c
+++ b/lib/xarray.c
@@ -1429,16 +1429,12 @@ void *__xa_cmpxchg(struct xarray *xa, unsigned long index,
1429 1429
1430 if (WARN_ON_ONCE(xa_is_advanced(entry))) 1430 if (WARN_ON_ONCE(xa_is_advanced(entry)))
1431 return XA_ERROR(-EINVAL); 1431 return XA_ERROR(-EINVAL);
1432 if (xa_track_free(xa) && !entry)
1433 entry = XA_ZERO_ENTRY;
1434 1432
1435 do { 1433 do {
1436 curr = xas_load(&xas); 1434 curr = xas_load(&xas);
1437 if (curr == XA_ZERO_ENTRY)
1438 curr = NULL;
1439 if (curr == old) { 1435 if (curr == old) {
1440 xas_store(&xas, entry); 1436 xas_store(&xas, entry);
1441 if (xa_track_free(xa)) 1437 if (xa_track_free(xa) && entry && !curr)
1442 xas_clear_mark(&xas, XA_FREE_MARK); 1438 xas_clear_mark(&xas, XA_FREE_MARK);
1443 } 1439 }
1444 } while (__xas_nomem(&xas, gfp)); 1440 } while (__xas_nomem(&xas, gfp));