diff options
Diffstat (limited to 'lib/xarray.c')
-rw-r--r-- | lib/xarray.c | 139 |
1 files changed, 60 insertions, 79 deletions
diff --git a/lib/xarray.c b/lib/xarray.c index 8b176f009c08..bbacca576593 100644 --- a/lib/xarray.c +++ b/lib/xarray.c | |||
@@ -610,8 +610,8 @@ static int xas_expand(struct xa_state *xas, void *head) | |||
610 | * (see the xa_cmpxchg() implementation for an example). | 610 | * (see the xa_cmpxchg() implementation for an example). |
611 | * | 611 | * |
612 | * Return: If the slot already existed, returns the contents of this slot. | 612 | * Return: If the slot already existed, returns the contents of this slot. |
613 | * If the slot was newly created, returns NULL. If it failed to create the | 613 | * If the slot was newly created, returns %NULL. If it failed to create the |
614 | * slot, returns NULL and indicates the error in @xas. | 614 | * slot, returns %NULL and indicates the error in @xas. |
615 | */ | 615 | */ |
616 | static void *xas_create(struct xa_state *xas) | 616 | static void *xas_create(struct xa_state *xas) |
617 | { | 617 | { |
@@ -1334,44 +1334,31 @@ void *__xa_erase(struct xarray *xa, unsigned long index) | |||
1334 | XA_STATE(xas, xa, index); | 1334 | XA_STATE(xas, xa, index); |
1335 | return xas_result(&xas, xas_store(&xas, NULL)); | 1335 | return xas_result(&xas, xas_store(&xas, NULL)); |
1336 | } | 1336 | } |
1337 | EXPORT_SYMBOL_GPL(__xa_erase); | 1337 | EXPORT_SYMBOL(__xa_erase); |
1338 | 1338 | ||
1339 | /** | 1339 | /** |
1340 | * xa_store() - Store this entry in the XArray. | 1340 | * xa_erase() - Erase this entry from the XArray. |
1341 | * @xa: XArray. | 1341 | * @xa: XArray. |
1342 | * @index: Index into array. | 1342 | * @index: Index of entry. |
1343 | * @entry: New entry. | ||
1344 | * @gfp: Memory allocation flags. | ||
1345 | * | 1343 | * |
1346 | * After this function returns, loads from this index will return @entry. | 1344 | * This function is the equivalent of calling xa_store() with %NULL as |
1347 | * Storing into an existing multislot entry updates the entry of every index. | 1345 | * the third argument. The XArray does not need to allocate memory, so |
1348 | * The marks associated with @index are unaffected unless @entry is %NULL. | 1346 | * the user does not need to provide GFP flags. |
1349 | * | 1347 | * |
1350 | * Context: Process context. Takes and releases the xa_lock. May sleep | 1348 | * Context: Any context. Takes and releases the xa_lock. |
1351 | * if the @gfp flags permit. | 1349 | * Return: The entry which used to be at this index. |
1352 | * Return: The old entry at this index on success, xa_err(-EINVAL) if @entry | ||
1353 | * cannot be stored in an XArray, or xa_err(-ENOMEM) if memory allocation | ||
1354 | * failed. | ||
1355 | */ | 1350 | */ |
1356 | void *xa_store(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp) | 1351 | void *xa_erase(struct xarray *xa, unsigned long index) |
1357 | { | 1352 | { |
1358 | XA_STATE(xas, xa, index); | 1353 | void *entry; |
1359 | void *curr; | ||
1360 | |||
1361 | if (WARN_ON_ONCE(xa_is_internal(entry))) | ||
1362 | return XA_ERROR(-EINVAL); | ||
1363 | 1354 | ||
1364 | do { | 1355 | xa_lock(xa); |
1365 | xas_lock(&xas); | 1356 | entry = __xa_erase(xa, index); |
1366 | curr = xas_store(&xas, entry); | 1357 | xa_unlock(xa); |
1367 | if (xa_track_free(xa) && entry) | ||
1368 | xas_clear_mark(&xas, XA_FREE_MARK); | ||
1369 | xas_unlock(&xas); | ||
1370 | } while (xas_nomem(&xas, gfp)); | ||
1371 | 1358 | ||
1372 | return xas_result(&xas, curr); | 1359 | return entry; |
1373 | } | 1360 | } |
1374 | EXPORT_SYMBOL(xa_store); | 1361 | EXPORT_SYMBOL(xa_erase); |
1375 | 1362 | ||
1376 | /** | 1363 | /** |
1377 | * __xa_store() - Store this entry in the XArray. | 1364 | * __xa_store() - Store this entry in the XArray. |
@@ -1395,10 +1382,12 @@ void *__xa_store(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp) | |||
1395 | 1382 | ||
1396 | if (WARN_ON_ONCE(xa_is_internal(entry))) | 1383 | if (WARN_ON_ONCE(xa_is_internal(entry))) |
1397 | return XA_ERROR(-EINVAL); | 1384 | return XA_ERROR(-EINVAL); |
1385 | if (xa_track_free(xa) && !entry) | ||
1386 | entry = XA_ZERO_ENTRY; | ||
1398 | 1387 | ||
1399 | do { | 1388 | do { |
1400 | curr = xas_store(&xas, entry); | 1389 | curr = xas_store(&xas, entry); |
1401 | if (xa_track_free(xa) && entry) | 1390 | if (xa_track_free(xa)) |
1402 | xas_clear_mark(&xas, XA_FREE_MARK); | 1391 | xas_clear_mark(&xas, XA_FREE_MARK); |
1403 | } while (__xas_nomem(&xas, gfp)); | 1392 | } while (__xas_nomem(&xas, gfp)); |
1404 | 1393 | ||
@@ -1407,45 +1396,33 @@ void *__xa_store(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp) | |||
1407 | EXPORT_SYMBOL(__xa_store); | 1396 | EXPORT_SYMBOL(__xa_store); |
1408 | 1397 | ||
1409 | /** | 1398 | /** |
1410 | * xa_cmpxchg() - Conditionally replace an entry in the XArray. | 1399 | * xa_store() - Store this entry in the XArray. |
1411 | * @xa: XArray. | 1400 | * @xa: XArray. |
1412 | * @index: Index into array. | 1401 | * @index: Index into array. |
1413 | * @old: Old value to test against. | 1402 | * @entry: New entry. |
1414 | * @entry: New value to place in array. | ||
1415 | * @gfp: Memory allocation flags. | 1403 | * @gfp: Memory allocation flags. |
1416 | * | 1404 | * |
1417 | * If the entry at @index is the same as @old, replace it with @entry. | 1405 | * After this function returns, loads from this index will return @entry. |
1418 | * If the return value is equal to @old, then the exchange was successful. | 1406 | * Storing into an existing multislot entry updates the entry of every index. |
1407 | * The marks associated with @index are unaffected unless @entry is %NULL. | ||
1419 | * | 1408 | * |
1420 | * Context: Process context. Takes and releases the xa_lock. May sleep | 1409 | * Context: Any context. Takes and releases the xa_lock. |
1421 | * if the @gfp flags permit. | 1410 | * May sleep if the @gfp flags permit. |
1422 | * Return: The old value at this index or xa_err() if an error happened. | 1411 | * Return: The old entry at this index on success, xa_err(-EINVAL) if @entry |
1412 | * cannot be stored in an XArray, or xa_err(-ENOMEM) if memory allocation | ||
1413 | * failed. | ||
1423 | */ | 1414 | */ |
1424 | void *xa_cmpxchg(struct xarray *xa, unsigned long index, | 1415 | void *xa_store(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp) |
1425 | void *old, void *entry, gfp_t gfp) | ||
1426 | { | 1416 | { |
1427 | XA_STATE(xas, xa, index); | ||
1428 | void *curr; | 1417 | void *curr; |
1429 | 1418 | ||
1430 | if (WARN_ON_ONCE(xa_is_internal(entry))) | 1419 | xa_lock(xa); |
1431 | return XA_ERROR(-EINVAL); | 1420 | curr = __xa_store(xa, index, entry, gfp); |
1432 | 1421 | xa_unlock(xa); | |
1433 | do { | ||
1434 | xas_lock(&xas); | ||
1435 | curr = xas_load(&xas); | ||
1436 | if (curr == XA_ZERO_ENTRY) | ||
1437 | curr = NULL; | ||
1438 | if (curr == old) { | ||
1439 | xas_store(&xas, entry); | ||
1440 | if (xa_track_free(xa) && entry) | ||
1441 | xas_clear_mark(&xas, XA_FREE_MARK); | ||
1442 | } | ||
1443 | xas_unlock(&xas); | ||
1444 | } while (xas_nomem(&xas, gfp)); | ||
1445 | 1422 | ||
1446 | return xas_result(&xas, curr); | 1423 | return curr; |
1447 | } | 1424 | } |
1448 | EXPORT_SYMBOL(xa_cmpxchg); | 1425 | EXPORT_SYMBOL(xa_store); |
1449 | 1426 | ||
1450 | /** | 1427 | /** |
1451 | * __xa_cmpxchg() - Store this entry in the XArray. | 1428 | * __xa_cmpxchg() - Store this entry in the XArray. |
@@ -1471,6 +1448,8 @@ void *__xa_cmpxchg(struct xarray *xa, unsigned long index, | |||
1471 | 1448 | ||
1472 | if (WARN_ON_ONCE(xa_is_internal(entry))) | 1449 | if (WARN_ON_ONCE(xa_is_internal(entry))) |
1473 | return XA_ERROR(-EINVAL); | 1450 | return XA_ERROR(-EINVAL); |
1451 | if (xa_track_free(xa) && !entry) | ||
1452 | entry = XA_ZERO_ENTRY; | ||
1474 | 1453 | ||
1475 | do { | 1454 | do { |
1476 | curr = xas_load(&xas); | 1455 | curr = xas_load(&xas); |
@@ -1478,7 +1457,7 @@ void *__xa_cmpxchg(struct xarray *xa, unsigned long index, | |||
1478 | curr = NULL; | 1457 | curr = NULL; |
1479 | if (curr == old) { | 1458 | if (curr == old) { |
1480 | xas_store(&xas, entry); | 1459 | xas_store(&xas, entry); |
1481 | if (xa_track_free(xa) && entry) | 1460 | if (xa_track_free(xa)) |
1482 | xas_clear_mark(&xas, XA_FREE_MARK); | 1461 | xas_clear_mark(&xas, XA_FREE_MARK); |
1483 | } | 1462 | } |
1484 | } while (__xas_nomem(&xas, gfp)); | 1463 | } while (__xas_nomem(&xas, gfp)); |
@@ -1488,7 +1467,7 @@ void *__xa_cmpxchg(struct xarray *xa, unsigned long index, | |||
1488 | EXPORT_SYMBOL(__xa_cmpxchg); | 1467 | EXPORT_SYMBOL(__xa_cmpxchg); |
1489 | 1468 | ||
1490 | /** | 1469 | /** |
1491 | * xa_reserve() - Reserve this index in the XArray. | 1470 | * __xa_reserve() - Reserve this index in the XArray. |
1492 | * @xa: XArray. | 1471 | * @xa: XArray. |
1493 | * @index: Index into array. | 1472 | * @index: Index into array. |
1494 | * @gfp: Memory allocation flags. | 1473 | * @gfp: Memory allocation flags. |
@@ -1496,33 +1475,32 @@ EXPORT_SYMBOL(__xa_cmpxchg); | |||
1496 | * Ensures there is somewhere to store an entry at @index in the array. | 1475 | * Ensures there is somewhere to store an entry at @index in the array. |
1497 | * If there is already something stored at @index, this function does | 1476 | * If there is already something stored at @index, this function does |
1498 | * nothing. If there was nothing there, the entry is marked as reserved. | 1477 | * nothing. If there was nothing there, the entry is marked as reserved. |
1499 | * Loads from @index will continue to see a %NULL pointer until a | 1478 | * Loading from a reserved entry returns a %NULL pointer. |
1500 | * subsequent store to @index. | ||
1501 | * | 1479 | * |
1502 | * If you do not use the entry that you have reserved, call xa_release() | 1480 | * If you do not use the entry that you have reserved, call xa_release() |
1503 | * or xa_erase() to free any unnecessary memory. | 1481 | * or xa_erase() to free any unnecessary memory. |
1504 | * | 1482 | * |
1505 | * Context: Process context. Takes and releases the xa_lock, IRQ or BH safe | 1483 | * Context: Any context. Expects the xa_lock to be held on entry. May |
1506 | * if specified in XArray flags. May sleep if the @gfp flags permit. | 1484 | * release the lock, sleep and reacquire the lock if the @gfp flags permit. |
1507 | * Return: 0 if the reservation succeeded or -ENOMEM if it failed. | 1485 | * Return: 0 if the reservation succeeded or -ENOMEM if it failed. |
1508 | */ | 1486 | */ |
1509 | int xa_reserve(struct xarray *xa, unsigned long index, gfp_t gfp) | 1487 | int __xa_reserve(struct xarray *xa, unsigned long index, gfp_t gfp) |
1510 | { | 1488 | { |
1511 | XA_STATE(xas, xa, index); | 1489 | XA_STATE(xas, xa, index); |
1512 | unsigned int lock_type = xa_lock_type(xa); | ||
1513 | void *curr; | 1490 | void *curr; |
1514 | 1491 | ||
1515 | do { | 1492 | do { |
1516 | xas_lock_type(&xas, lock_type); | ||
1517 | curr = xas_load(&xas); | 1493 | curr = xas_load(&xas); |
1518 | if (!curr) | 1494 | if (!curr) { |
1519 | xas_store(&xas, XA_ZERO_ENTRY); | 1495 | xas_store(&xas, XA_ZERO_ENTRY); |
1520 | xas_unlock_type(&xas, lock_type); | 1496 | if (xa_track_free(xa)) |
1521 | } while (xas_nomem(&xas, gfp)); | 1497 | xas_clear_mark(&xas, XA_FREE_MARK); |
1498 | } | ||
1499 | } while (__xas_nomem(&xas, gfp)); | ||
1522 | 1500 | ||
1523 | return xas_error(&xas); | 1501 | return xas_error(&xas); |
1524 | } | 1502 | } |
1525 | EXPORT_SYMBOL(xa_reserve); | 1503 | EXPORT_SYMBOL(__xa_reserve); |
1526 | 1504 | ||
1527 | #ifdef CONFIG_XARRAY_MULTI | 1505 | #ifdef CONFIG_XARRAY_MULTI |
1528 | static void xas_set_range(struct xa_state *xas, unsigned long first, | 1506 | static void xas_set_range(struct xa_state *xas, unsigned long first, |
@@ -1587,8 +1565,9 @@ void *xa_store_range(struct xarray *xa, unsigned long first, | |||
1587 | do { | 1565 | do { |
1588 | xas_lock(&xas); | 1566 | xas_lock(&xas); |
1589 | if (entry) { | 1567 | if (entry) { |
1590 | unsigned int order = (last == ~0UL) ? 64 : | 1568 | unsigned int order = BITS_PER_LONG; |
1591 | ilog2(last + 1); | 1569 | if (last + 1) |
1570 | order = __ffs(last + 1); | ||
1592 | xas_set_order(&xas, last, order); | 1571 | xas_set_order(&xas, last, order); |
1593 | xas_create(&xas); | 1572 | xas_create(&xas); |
1594 | if (xas_error(&xas)) | 1573 | if (xas_error(&xas)) |
@@ -1662,7 +1641,7 @@ EXPORT_SYMBOL(__xa_alloc); | |||
1662 | * @index: Index of entry. | 1641 | * @index: Index of entry. |
1663 | * @mark: Mark number. | 1642 | * @mark: Mark number. |
1664 | * | 1643 | * |
1665 | * Attempting to set a mark on a NULL entry does not succeed. | 1644 | * Attempting to set a mark on a %NULL entry does not succeed. |
1666 | * | 1645 | * |
1667 | * Context: Any context. Expects xa_lock to be held on entry. | 1646 | * Context: Any context. Expects xa_lock to be held on entry. |
1668 | */ | 1647 | */ |
@@ -1674,7 +1653,7 @@ void __xa_set_mark(struct xarray *xa, unsigned long index, xa_mark_t mark) | |||
1674 | if (entry) | 1653 | if (entry) |
1675 | xas_set_mark(&xas, mark); | 1654 | xas_set_mark(&xas, mark); |
1676 | } | 1655 | } |
1677 | EXPORT_SYMBOL_GPL(__xa_set_mark); | 1656 | EXPORT_SYMBOL(__xa_set_mark); |
1678 | 1657 | ||
1679 | /** | 1658 | /** |
1680 | * __xa_clear_mark() - Clear this mark on this entry while locked. | 1659 | * __xa_clear_mark() - Clear this mark on this entry while locked. |
@@ -1692,7 +1671,7 @@ void __xa_clear_mark(struct xarray *xa, unsigned long index, xa_mark_t mark) | |||
1692 | if (entry) | 1671 | if (entry) |
1693 | xas_clear_mark(&xas, mark); | 1672 | xas_clear_mark(&xas, mark); |
1694 | } | 1673 | } |
1695 | EXPORT_SYMBOL_GPL(__xa_clear_mark); | 1674 | EXPORT_SYMBOL(__xa_clear_mark); |
1696 | 1675 | ||
1697 | /** | 1676 | /** |
1698 | * xa_get_mark() - Inquire whether this mark is set on this entry. | 1677 | * xa_get_mark() - Inquire whether this mark is set on this entry. |
@@ -1732,7 +1711,7 @@ EXPORT_SYMBOL(xa_get_mark); | |||
1732 | * @index: Index of entry. | 1711 | * @index: Index of entry. |
1733 | * @mark: Mark number. | 1712 | * @mark: Mark number. |
1734 | * | 1713 | * |
1735 | * Attempting to set a mark on a NULL entry does not succeed. | 1714 | * Attempting to set a mark on a %NULL entry does not succeed. |
1736 | * | 1715 | * |
1737 | * Context: Process context. Takes and releases the xa_lock. | 1716 | * Context: Process context. Takes and releases the xa_lock. |
1738 | */ | 1717 | */ |
@@ -1829,6 +1808,8 @@ void *xa_find_after(struct xarray *xa, unsigned long *indexp, | |||
1829 | entry = xas_find_marked(&xas, max, filter); | 1808 | entry = xas_find_marked(&xas, max, filter); |
1830 | else | 1809 | else |
1831 | entry = xas_find(&xas, max); | 1810 | entry = xas_find(&xas, max); |
1811 | if (xas.xa_node == XAS_BOUNDS) | ||
1812 | break; | ||
1832 | if (xas.xa_shift) { | 1813 | if (xas.xa_shift) { |
1833 | if (xas.xa_index & ((1UL << xas.xa_shift) - 1)) | 1814 | if (xas.xa_index & ((1UL << xas.xa_shift) - 1)) |
1834 | continue; | 1815 | continue; |
@@ -1899,7 +1880,7 @@ static unsigned int xas_extract_marked(struct xa_state *xas, void **dst, | |||
1899 | * | 1880 | * |
1900 | * The @filter may be an XArray mark value, in which case entries which are | 1881 | * The @filter may be an XArray mark value, in which case entries which are |
1901 | * marked with that mark will be copied. It may also be %XA_PRESENT, in | 1882 | * marked with that mark will be copied. It may also be %XA_PRESENT, in |
1902 | * which case all entries which are not NULL will be copied. | 1883 | * which case all entries which are not %NULL will be copied. |
1903 | * | 1884 | * |
1904 | * The entries returned may not represent a snapshot of the XArray at a | 1885 | * The entries returned may not represent a snapshot of the XArray at a |
1905 | * moment in time. For example, if another thread stores to index 5, then | 1886 | * moment in time. For example, if another thread stores to index 5, then |