aboutsummaryrefslogtreecommitdiffstats
path: root/lib/xarray.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/xarray.c')
-rw-r--r--lib/xarray.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/lib/xarray.c b/lib/xarray.c
index ff37516fe832..546461914282 100644
--- a/lib/xarray.c
+++ b/lib/xarray.c
@@ -1266,6 +1266,8 @@ void *xa_load(struct xarray *xa, unsigned long index)
1266 rcu_read_lock(); 1266 rcu_read_lock();
1267 do { 1267 do {
1268 entry = xas_load(&xas); 1268 entry = xas_load(&xas);
1269 if (xa_is_zero(entry))
1270 entry = NULL;
1269 } while (xas_retry(&xas, entry)); 1271 } while (xas_retry(&xas, entry));
1270 rcu_read_unlock(); 1272 rcu_read_unlock();
1271 1273
@@ -1275,6 +1277,8 @@ EXPORT_SYMBOL(xa_load);
1275 1277
1276static void *xas_result(struct xa_state *xas, void *curr) 1278static void *xas_result(struct xa_state *xas, void *curr)
1277{ 1279{
1280 if (xa_is_zero(curr))
1281 return NULL;
1278 XA_NODE_BUG_ON(xas->xa_node, xa_is_internal(curr)); 1282 XA_NODE_BUG_ON(xas->xa_node, xa_is_internal(curr));
1279 if (xas_error(xas)) 1283 if (xas_error(xas))
1280 curr = xas->xa_node; 1284 curr = xas->xa_node;
@@ -1394,6 +1398,8 @@ void *xa_cmpxchg(struct xarray *xa, unsigned long index,
1394 do { 1398 do {
1395 xas_lock(&xas); 1399 xas_lock(&xas);
1396 curr = xas_load(&xas); 1400 curr = xas_load(&xas);
1401 if (curr == XA_ZERO_ENTRY)
1402 curr = NULL;
1397 if (curr == old) 1403 if (curr == old)
1398 xas_store(&xas, entry); 1404 xas_store(&xas, entry);
1399 xas_unlock(&xas); 1405 xas_unlock(&xas);
@@ -1430,6 +1436,8 @@ void *__xa_cmpxchg(struct xarray *xa, unsigned long index,
1430 1436
1431 do { 1437 do {
1432 curr = xas_load(&xas); 1438 curr = xas_load(&xas);
1439 if (curr == XA_ZERO_ENTRY)
1440 curr = NULL;
1433 if (curr == old) 1441 if (curr == old)
1434 xas_store(&xas, entry); 1442 xas_store(&xas, entry);
1435 } while (__xas_nomem(&xas, gfp)); 1443 } while (__xas_nomem(&xas, gfp));
@@ -1439,6 +1447,43 @@ void *__xa_cmpxchg(struct xarray *xa, unsigned long index,
1439EXPORT_SYMBOL(__xa_cmpxchg); 1447EXPORT_SYMBOL(__xa_cmpxchg);
1440 1448
1441/** 1449/**
1450 * xa_reserve() - Reserve this index in the XArray.
1451 * @xa: XArray.
1452 * @index: Index into array.
1453 * @gfp: Memory allocation flags.
1454 *
1455 * Ensures there is somewhere to store an entry at @index in the array.
1456 * If there is already something stored at @index, this function does
1457 * nothing. If there was nothing there, the entry is marked as reserved.
1458 * Loads from @index will continue to see a %NULL pointer until a
1459 * subsequent store to @index.
1460 *
1461 * If you do not use the entry that you have reserved, call xa_release()
1462 * or xa_erase() to free any unnecessary memory.
1463 *
1464 * Context: Process context. Takes and releases the xa_lock, IRQ or BH safe
1465 * if specified in XArray flags. May sleep if the @gfp flags permit.
1466 * Return: 0 if the reservation succeeded or -ENOMEM if it failed.
1467 */
1468int xa_reserve(struct xarray *xa, unsigned long index, gfp_t gfp)
1469{
1470 XA_STATE(xas, xa, index);
1471 unsigned int lock_type = xa_lock_type(xa);
1472 void *curr;
1473
1474 do {
1475 xas_lock_type(&xas, lock_type);
1476 curr = xas_load(&xas);
1477 if (!curr)
1478 xas_store(&xas, XA_ZERO_ENTRY);
1479 xas_unlock_type(&xas, lock_type);
1480 } while (xas_nomem(&xas, gfp));
1481
1482 return xas_error(&xas);
1483}
1484EXPORT_SYMBOL(xa_reserve);
1485
1486/**
1442 * __xa_set_mark() - Set this mark on this entry while locked. 1487 * __xa_set_mark() - Set this mark on this entry while locked.
1443 * @xa: XArray. 1488 * @xa: XArray.
1444 * @index: Index of entry. 1489 * @index: Index of entry.
@@ -1797,6 +1842,8 @@ void xa_dump_entry(const void *entry, unsigned long index, unsigned long shift)
1797 pr_cont("retry (%ld)\n", xa_to_internal(entry)); 1842 pr_cont("retry (%ld)\n", xa_to_internal(entry));
1798 else if (xa_is_sibling(entry)) 1843 else if (xa_is_sibling(entry))
1799 pr_cont("sibling (slot %ld)\n", xa_to_sibling(entry)); 1844 pr_cont("sibling (slot %ld)\n", xa_to_sibling(entry));
1845 else if (xa_is_zero(entry))
1846 pr_cont("zero (%ld)\n", xa_to_internal(entry));
1800 else 1847 else
1801 pr_cont("UNKNOWN ENTRY (%px)\n", entry); 1848 pr_cont("UNKNOWN ENTRY (%px)\n", entry);
1802} 1849}