aboutsummaryrefslogtreecommitdiffstats
path: root/lib/xarray.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/xarray.c')
-rw-r--r--lib/xarray.c163
1 files changed, 92 insertions, 71 deletions
diff --git a/lib/xarray.c b/lib/xarray.c
index 81c3171ddde9..6be3acbb861f 100644
--- a/lib/xarray.c
+++ b/lib/xarray.c
@@ -57,6 +57,11 @@ static inline bool xa_track_free(const struct xarray *xa)
57 return xa->xa_flags & XA_FLAGS_TRACK_FREE; 57 return xa->xa_flags & XA_FLAGS_TRACK_FREE;
58} 58}
59 59
60static inline bool xa_zero_busy(const struct xarray *xa)
61{
62 return xa->xa_flags & XA_FLAGS_ZERO_BUSY;
63}
64
60static inline void xa_mark_set(struct xarray *xa, xa_mark_t mark) 65static inline void xa_mark_set(struct xarray *xa, xa_mark_t mark)
61{ 66{
62 if (!(xa->xa_flags & XA_FLAGS_MARK(mark))) 67 if (!(xa->xa_flags & XA_FLAGS_MARK(mark)))
@@ -432,6 +437,8 @@ static void xas_shrink(struct xa_state *xas)
432 break; 437 break;
433 if (!xa_is_node(entry) && node->shift) 438 if (!xa_is_node(entry) && node->shift)
434 break; 439 break;
440 if (xa_is_zero(entry) && xa_zero_busy(xa))
441 entry = NULL;
435 xas->xa_node = XAS_BOUNDS; 442 xas->xa_node = XAS_BOUNDS;
436 443
437 RCU_INIT_POINTER(xa->xa_head, entry); 444 RCU_INIT_POINTER(xa->xa_head, entry);
@@ -628,6 +635,8 @@ static void *xas_create(struct xa_state *xas, bool allow_root)
628 if (xas_top(node)) { 635 if (xas_top(node)) {
629 entry = xa_head_locked(xa); 636 entry = xa_head_locked(xa);
630 xas->xa_node = NULL; 637 xas->xa_node = NULL;
638 if (!entry && xa_zero_busy(xa))
639 entry = XA_ZERO_ENTRY;
631 shift = xas_expand(xas, entry); 640 shift = xas_expand(xas, entry);
632 if (shift < 0) 641 if (shift < 0)
633 return NULL; 642 return NULL;
@@ -758,10 +767,12 @@ void *xas_store(struct xa_state *xas, void *entry)
758 void *first, *next; 767 void *first, *next;
759 bool value = xa_is_value(entry); 768 bool value = xa_is_value(entry);
760 769
761 if (entry) 770 if (entry) {
762 first = xas_create(xas, !xa_is_node(entry)); 771 bool allow_root = !xa_is_node(entry) && !xa_is_zero(entry);
763 else 772 first = xas_create(xas, allow_root);
773 } else {
764 first = xas_load(xas); 774 first = xas_load(xas);
775 }
765 776
766 if (xas_invalid(xas)) 777 if (xas_invalid(xas))
767 return first; 778 return first;
@@ -791,7 +802,7 @@ void *xas_store(struct xa_state *xas, void *entry)
791 * entry is set to NULL. 802 * entry is set to NULL.
792 */ 803 */
793 rcu_assign_pointer(*slot, entry); 804 rcu_assign_pointer(*slot, entry);
794 if (xa_is_node(next)) 805 if (xa_is_node(next) && (!node || node->shift))
795 xas_free_nodes(xas, xa_to_node(next)); 806 xas_free_nodes(xas, xa_to_node(next));
796 if (!node) 807 if (!node)
797 break; 808 break;
@@ -1294,13 +1305,12 @@ static void *xas_result(struct xa_state *xas, void *curr)
1294 * @xa: XArray. 1305 * @xa: XArray.
1295 * @index: Index into array. 1306 * @index: Index into array.
1296 * 1307 *
1297 * If the entry at this index is a multi-index entry then all indices will 1308 * After this function returns, loading from @index will return %NULL.
1298 * be erased, and the entry will no longer be a multi-index entry. 1309 * If the index is part of a multi-index entry, all indices will be erased
1299 * This function expects the xa_lock to be held on entry. 1310 * and none of the entries will be part of a multi-index entry.
1300 * 1311 *
1301 * Context: Any context. Expects xa_lock to be held on entry. May 1312 * Context: Any context. Expects xa_lock to be held on entry.
1302 * release and reacquire xa_lock if @gfp flags permit. 1313 * Return: The entry which used to be at this index.
1303 * Return: The old entry at this index.
1304 */ 1314 */
1305void *__xa_erase(struct xarray *xa, unsigned long index) 1315void *__xa_erase(struct xarray *xa, unsigned long index)
1306{ 1316{
@@ -1314,9 +1324,9 @@ EXPORT_SYMBOL(__xa_erase);
1314 * @xa: XArray. 1324 * @xa: XArray.
1315 * @index: Index of entry. 1325 * @index: Index of entry.
1316 * 1326 *
1317 * This function is the equivalent of calling xa_store() with %NULL as 1327 * After this function returns, loading from @index will return %NULL.
1318 * the third argument. The XArray does not need to allocate memory, so 1328 * If the index is part of a multi-index entry, all indices will be erased
1319 * the user does not need to provide GFP flags. 1329 * and none of the entries will be part of a multi-index entry.
1320 * 1330 *
1321 * Context: Any context. Takes and releases the xa_lock. 1331 * Context: Any context. Takes and releases the xa_lock.
1322 * Return: The entry which used to be at this index. 1332 * Return: The entry which used to be at this index.
@@ -1421,16 +1431,12 @@ void *__xa_cmpxchg(struct xarray *xa, unsigned long index,
1421 1431
1422 if (WARN_ON_ONCE(xa_is_advanced(entry))) 1432 if (WARN_ON_ONCE(xa_is_advanced(entry)))
1423 return XA_ERROR(-EINVAL); 1433 return XA_ERROR(-EINVAL);
1424 if (xa_track_free(xa) && !entry)
1425 entry = XA_ZERO_ENTRY;
1426 1434
1427 do { 1435 do {
1428 curr = xas_load(&xas); 1436 curr = xas_load(&xas);
1429 if (curr == XA_ZERO_ENTRY)
1430 curr = NULL;
1431 if (curr == old) { 1437 if (curr == old) {
1432 xas_store(&xas, entry); 1438 xas_store(&xas, entry);
1433 if (xa_track_free(xa)) 1439 if (xa_track_free(xa) && entry && !curr)
1434 xas_clear_mark(&xas, XA_FREE_MARK); 1440 xas_clear_mark(&xas, XA_FREE_MARK);
1435 } 1441 }
1436 } while (__xas_nomem(&xas, gfp)); 1442 } while (__xas_nomem(&xas, gfp));
@@ -1452,7 +1458,7 @@ EXPORT_SYMBOL(__xa_cmpxchg);
1452 * 1458 *
1453 * Context: Any context. Expects xa_lock to be held on entry. May 1459 * Context: Any context. Expects xa_lock to be held on entry. May
1454 * release and reacquire xa_lock if @gfp flags permit. 1460 * release and reacquire xa_lock if @gfp flags permit.
1455 * Return: 0 if the store succeeded. -EEXIST if another entry was present. 1461 * Return: 0 if the store succeeded. -EBUSY if another entry was present.
1456 * -ENOMEM if memory could not be allocated. 1462 * -ENOMEM if memory could not be allocated.
1457 */ 1463 */
1458int __xa_insert(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp) 1464int __xa_insert(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp)
@@ -1472,7 +1478,7 @@ int __xa_insert(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp)
1472 if (xa_track_free(xa)) 1478 if (xa_track_free(xa))
1473 xas_clear_mark(&xas, XA_FREE_MARK); 1479 xas_clear_mark(&xas, XA_FREE_MARK);
1474 } else { 1480 } else {
1475 xas_set_err(&xas, -EEXIST); 1481 xas_set_err(&xas, -EBUSY);
1476 } 1482 }
1477 } while (__xas_nomem(&xas, gfp)); 1483 } while (__xas_nomem(&xas, gfp));
1478 1484
@@ -1480,42 +1486,6 @@ int __xa_insert(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp)
1480} 1486}
1481EXPORT_SYMBOL(__xa_insert); 1487EXPORT_SYMBOL(__xa_insert);
1482 1488
1483/**
1484 * __xa_reserve() - Reserve this index in the XArray.
1485 * @xa: XArray.
1486 * @index: Index into array.
1487 * @gfp: Memory allocation flags.
1488 *
1489 * Ensures there is somewhere to store an entry at @index in the array.
1490 * If there is already something stored at @index, this function does
1491 * nothing. If there was nothing there, the entry is marked as reserved.
1492 * Loading from a reserved entry returns a %NULL pointer.
1493 *
1494 * If you do not use the entry that you have reserved, call xa_release()
1495 * or xa_erase() to free any unnecessary memory.
1496 *
1497 * Context: Any context. Expects the xa_lock to be held on entry. May
1498 * release the lock, sleep and reacquire the lock if the @gfp flags permit.
1499 * Return: 0 if the reservation succeeded or -ENOMEM if it failed.
1500 */
1501int __xa_reserve(struct xarray *xa, unsigned long index, gfp_t gfp)
1502{
1503 XA_STATE(xas, xa, index);
1504 void *curr;
1505
1506 do {
1507 curr = xas_load(&xas);
1508 if (!curr) {
1509 xas_store(&xas, XA_ZERO_ENTRY);
1510 if (xa_track_free(xa))
1511 xas_clear_mark(&xas, XA_FREE_MARK);
1512 }
1513 } while (__xas_nomem(&xas, gfp));
1514
1515 return xas_error(&xas);
1516}
1517EXPORT_SYMBOL(__xa_reserve);
1518
1519#ifdef CONFIG_XARRAY_MULTI 1489#ifdef CONFIG_XARRAY_MULTI
1520static void xas_set_range(struct xa_state *xas, unsigned long first, 1490static void xas_set_range(struct xa_state *xas, unsigned long first,
1521 unsigned long last) 1491 unsigned long last)
@@ -1607,23 +1577,23 @@ EXPORT_SYMBOL(xa_store_range);
1607 * __xa_alloc() - Find somewhere to store this entry in the XArray. 1577 * __xa_alloc() - Find somewhere to store this entry in the XArray.
1608 * @xa: XArray. 1578 * @xa: XArray.
1609 * @id: Pointer to ID. 1579 * @id: Pointer to ID.
1610 * @max: Maximum ID to allocate (inclusive). 1580 * @limit: Range for allocated ID.
1611 * @entry: New entry. 1581 * @entry: New entry.
1612 * @gfp: Memory allocation flags. 1582 * @gfp: Memory allocation flags.
1613 * 1583 *
1614 * Allocates an unused ID in the range specified by @id and @max. 1584 * Finds an empty entry in @xa between @limit.min and @limit.max,
1615 * Updates the @id pointer with the index, then stores the entry at that 1585 * stores the index into the @id pointer, then stores the entry at
1616 * index. A concurrent lookup will not see an uninitialised @id. 1586 * that index. A concurrent lookup will not see an uninitialised @id.
1617 * 1587 *
1618 * Context: Any context. Expects xa_lock to be held on entry. May 1588 * Context: Any context. Expects xa_lock to be held on entry. May
1619 * release and reacquire xa_lock if @gfp flags permit. 1589 * release and reacquire xa_lock if @gfp flags permit.
1620 * Return: 0 on success, -ENOMEM if memory allocation fails or -ENOSPC if 1590 * Return: 0 on success, -ENOMEM if memory could not be allocated or
1621 * there is no more space in the XArray. 1591 * -EBUSY if there are no free entries in @limit.
1622 */ 1592 */
1623int __xa_alloc(struct xarray *xa, u32 *id, u32 max, void *entry, gfp_t gfp) 1593int __xa_alloc(struct xarray *xa, u32 *id, void *entry,
1594 struct xa_limit limit, gfp_t gfp)
1624{ 1595{
1625 XA_STATE(xas, xa, 0); 1596 XA_STATE(xas, xa, 0);
1626 int err;
1627 1597
1628 if (WARN_ON_ONCE(xa_is_advanced(entry))) 1598 if (WARN_ON_ONCE(xa_is_advanced(entry)))
1629 return -EINVAL; 1599 return -EINVAL;
@@ -1634,22 +1604,71 @@ int __xa_alloc(struct xarray *xa, u32 *id, u32 max, void *entry, gfp_t gfp)
1634 entry = XA_ZERO_ENTRY; 1604 entry = XA_ZERO_ENTRY;
1635 1605
1636 do { 1606 do {
1637 xas.xa_index = *id; 1607 xas.xa_index = limit.min;
1638 xas_find_marked(&xas, max, XA_FREE_MARK); 1608 xas_find_marked(&xas, limit.max, XA_FREE_MARK);
1639 if (xas.xa_node == XAS_RESTART) 1609 if (xas.xa_node == XAS_RESTART)
1640 xas_set_err(&xas, -ENOSPC); 1610 xas_set_err(&xas, -EBUSY);
1611 else
1612 *id = xas.xa_index;
1641 xas_store(&xas, entry); 1613 xas_store(&xas, entry);
1642 xas_clear_mark(&xas, XA_FREE_MARK); 1614 xas_clear_mark(&xas, XA_FREE_MARK);
1643 } while (__xas_nomem(&xas, gfp)); 1615 } while (__xas_nomem(&xas, gfp));
1644 1616
1645 err = xas_error(&xas); 1617 return xas_error(&xas);
1646 if (!err)
1647 *id = xas.xa_index;
1648 return err;
1649} 1618}
1650EXPORT_SYMBOL(__xa_alloc); 1619EXPORT_SYMBOL(__xa_alloc);
1651 1620
1652/** 1621/**
1622 * __xa_alloc_cyclic() - Find somewhere to store this entry in the XArray.
1623 * @xa: XArray.
1624 * @id: Pointer to ID.
1625 * @entry: New entry.
1626 * @limit: Range of allocated ID.
1627 * @next: Pointer to next ID to allocate.
1628 * @gfp: Memory allocation flags.
1629 *
1630 * Finds an empty entry in @xa between @limit.min and @limit.max,
1631 * stores the index into the @id pointer, then stores the entry at
1632 * that index. A concurrent lookup will not see an uninitialised @id.
1633 * The search for an empty entry will start at @next and will wrap
1634 * around if necessary.
1635 *
1636 * Context: Any context. Expects xa_lock to be held on entry. May
1637 * release and reacquire xa_lock if @gfp flags permit.
1638 * Return: 0 if the allocation succeeded without wrapping. 1 if the
1639 * allocation succeeded after wrapping, -ENOMEM if memory could not be
1640 * allocated or -EBUSY if there are no free entries in @limit.
1641 */
1642int __xa_alloc_cyclic(struct xarray *xa, u32 *id, void *entry,
1643 struct xa_limit limit, u32 *next, gfp_t gfp)
1644{
1645 u32 min = limit.min;
1646 int ret;
1647
1648 limit.min = max(min, *next);
1649 ret = __xa_alloc(xa, id, entry, limit, gfp);
1650 if ((xa->xa_flags & XA_FLAGS_ALLOC_WRAPPED) && ret == 0) {
1651 xa->xa_flags &= ~XA_FLAGS_ALLOC_WRAPPED;
1652 ret = 1;
1653 }
1654
1655 if (ret < 0 && limit.min > min) {
1656 limit.min = min;
1657 ret = __xa_alloc(xa, id, entry, limit, gfp);
1658 if (ret == 0)
1659 ret = 1;
1660 }
1661
1662 if (ret >= 0) {
1663 *next = *id + 1;
1664 if (*next == 0)
1665 xa->xa_flags |= XA_FLAGS_ALLOC_WRAPPED;
1666 }
1667 return ret;
1668}
1669EXPORT_SYMBOL(__xa_alloc_cyclic);
1670
1671/**
1653 * __xa_set_mark() - Set this mark on this entry while locked. 1672 * __xa_set_mark() - Set this mark on this entry while locked.
1654 * @xa: XArray. 1673 * @xa: XArray.
1655 * @index: Index of entry. 1674 * @index: Index of entry.
@@ -1943,6 +1962,8 @@ void xa_destroy(struct xarray *xa)
1943 entry = xa_head_locked(xa); 1962 entry = xa_head_locked(xa);
1944 RCU_INIT_POINTER(xa->xa_head, NULL); 1963 RCU_INIT_POINTER(xa->xa_head, NULL);
1945 xas_init_marks(&xas); 1964 xas_init_marks(&xas);
1965 if (xa_zero_busy(xa))
1966 xa_mark_clear(xa, XA_FREE_MARK);
1946 /* lockdep checks we're still holding the lock in xas_free_nodes() */ 1967 /* lockdep checks we're still holding the lock in xas_free_nodes() */
1947 if (xa_is_node(entry)) 1968 if (xa_is_node(entry))
1948 xas_free_nodes(&xas, xa_to_node(entry)); 1969 xas_free_nodes(&xas, xa_to_node(entry));