diff options
author | Matthew Wilcox <willy@infradead.org> | 2018-11-05 16:15:56 -0500 |
---|---|---|
committer | Matthew Wilcox <willy@infradead.org> | 2018-11-05 16:38:09 -0500 |
commit | d9c480435add8257f9069941f0e6196647f6d746 (patch) | |
tree | 8e46a69188df371b24c83cf2181d42971336344b /lib/xarray.c | |
parent | 611f318637daa5710a1d7a0e7dc6cda23914094a (diff) |
XArray: Handle NULL pointers differently for allocation
For allocating XArrays, it makes sense to distinguish beteen erasing an
entry and storing NULL. Storing NULL keeps the index allocated with a
NULL pointer associated with it while xa_erase() frees the index. Some
existing IDR users rely on this ability.
Signed-off-by: Matthew Wilcox <willy@infradead.org>
Diffstat (limited to 'lib/xarray.c')
-rw-r--r-- | lib/xarray.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/lib/xarray.c b/lib/xarray.c index a9d28013f9dc..c3e2084aa313 100644 --- a/lib/xarray.c +++ b/lib/xarray.c | |||
@@ -1382,10 +1382,12 @@ void *__xa_store(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp) | |||
1382 | 1382 | ||
1383 | if (WARN_ON_ONCE(xa_is_internal(entry))) | 1383 | if (WARN_ON_ONCE(xa_is_internal(entry))) |
1384 | return XA_ERROR(-EINVAL); | 1384 | return XA_ERROR(-EINVAL); |
1385 | if (xa_track_free(xa) && !entry) | ||
1386 | entry = XA_ZERO_ENTRY; | ||
1385 | 1387 | ||
1386 | do { | 1388 | do { |
1387 | curr = xas_store(&xas, entry); | 1389 | curr = xas_store(&xas, entry); |
1388 | if (xa_track_free(xa) && entry) | 1390 | if (xa_track_free(xa)) |
1389 | xas_clear_mark(&xas, XA_FREE_MARK); | 1391 | xas_clear_mark(&xas, XA_FREE_MARK); |
1390 | } while (__xas_nomem(&xas, gfp)); | 1392 | } while (__xas_nomem(&xas, gfp)); |
1391 | 1393 | ||
@@ -1446,6 +1448,8 @@ void *__xa_cmpxchg(struct xarray *xa, unsigned long index, | |||
1446 | 1448 | ||
1447 | if (WARN_ON_ONCE(xa_is_internal(entry))) | 1449 | if (WARN_ON_ONCE(xa_is_internal(entry))) |
1448 | return XA_ERROR(-EINVAL); | 1450 | return XA_ERROR(-EINVAL); |
1451 | if (xa_track_free(xa) && !entry) | ||
1452 | entry = XA_ZERO_ENTRY; | ||
1449 | 1453 | ||
1450 | do { | 1454 | do { |
1451 | curr = xas_load(&xas); | 1455 | curr = xas_load(&xas); |
@@ -1453,7 +1457,7 @@ void *__xa_cmpxchg(struct xarray *xa, unsigned long index, | |||
1453 | curr = NULL; | 1457 | curr = NULL; |
1454 | if (curr == old) { | 1458 | if (curr == old) { |
1455 | xas_store(&xas, entry); | 1459 | xas_store(&xas, entry); |
1456 | if (xa_track_free(xa) && entry) | 1460 | if (xa_track_free(xa)) |
1457 | xas_clear_mark(&xas, XA_FREE_MARK); | 1461 | xas_clear_mark(&xas, XA_FREE_MARK); |
1458 | } | 1462 | } |
1459 | } while (__xas_nomem(&xas, gfp)); | 1463 | } while (__xas_nomem(&xas, gfp)); |
@@ -1487,8 +1491,11 @@ int __xa_reserve(struct xarray *xa, unsigned long index, gfp_t gfp) | |||
1487 | 1491 | ||
1488 | do { | 1492 | do { |
1489 | curr = xas_load(&xas); | 1493 | curr = xas_load(&xas); |
1490 | if (!curr) | 1494 | if (!curr) { |
1491 | xas_store(&xas, XA_ZERO_ENTRY); | 1495 | xas_store(&xas, XA_ZERO_ENTRY); |
1496 | if (xa_track_free(xa)) | ||
1497 | xas_clear_mark(&xas, XA_FREE_MARK); | ||
1498 | } | ||
1492 | } while (__xas_nomem(&xas, gfp)); | 1499 | } while (__xas_nomem(&xas, gfp)); |
1493 | 1500 | ||
1494 | return xas_error(&xas); | 1501 | return xas_error(&xas); |