diff options
Diffstat (limited to 'lib/xarray.c')
-rw-r--r-- | lib/xarray.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/lib/xarray.c b/lib/xarray.c index c707388fb05e..89e37ac50850 100644 --- a/lib/xarray.c +++ b/lib/xarray.c | |||
@@ -1657,6 +1657,56 @@ int __xa_alloc(struct xarray *xa, u32 *id, void *entry, | |||
1657 | EXPORT_SYMBOL(__xa_alloc); | 1657 | EXPORT_SYMBOL(__xa_alloc); |
1658 | 1658 | ||
1659 | /** | 1659 | /** |
1660 | * __xa_alloc_cyclic() - Find somewhere to store this entry in the XArray. | ||
1661 | * @xa: XArray. | ||
1662 | * @id: Pointer to ID. | ||
1663 | * @entry: New entry. | ||
1664 | * @limit: Range of allocated ID. | ||
1665 | * @next: Pointer to next ID to allocate. | ||
1666 | * @gfp: Memory allocation flags. | ||
1667 | * | ||
1668 | * Finds an empty entry in @xa between @limit.min and @limit.max, | ||
1669 | * stores the index into the @id pointer, then stores the entry at | ||
1670 | * that index. A concurrent lookup will not see an uninitialised @id. | ||
1671 | * The search for an empty entry will start at @next and will wrap | ||
1672 | * around if necessary. | ||
1673 | * | ||
1674 | * Context: Any context. Expects xa_lock to be held on entry. May | ||
1675 | * release and reacquire xa_lock if @gfp flags permit. | ||
1676 | * Return: 0 if the allocation succeeded without wrapping. 1 if the | ||
1677 | * allocation succeeded after wrapping, -ENOMEM if memory could not be | ||
1678 | * allocated or -EBUSY if there are no free entries in @limit. | ||
1679 | */ | ||
1680 | int __xa_alloc_cyclic(struct xarray *xa, u32 *id, void *entry, | ||
1681 | struct xa_limit limit, u32 *next, gfp_t gfp) | ||
1682 | { | ||
1683 | u32 min = limit.min; | ||
1684 | int ret; | ||
1685 | |||
1686 | limit.min = max(min, *next); | ||
1687 | ret = __xa_alloc(xa, id, entry, limit, gfp); | ||
1688 | if ((xa->xa_flags & XA_FLAGS_ALLOC_WRAPPED) && ret == 0) { | ||
1689 | xa->xa_flags &= ~XA_FLAGS_ALLOC_WRAPPED; | ||
1690 | ret = 1; | ||
1691 | } | ||
1692 | |||
1693 | if (ret < 0 && limit.min > min) { | ||
1694 | limit.min = min; | ||
1695 | ret = __xa_alloc(xa, id, entry, limit, gfp); | ||
1696 | if (ret == 0) | ||
1697 | ret = 1; | ||
1698 | } | ||
1699 | |||
1700 | if (ret >= 0) { | ||
1701 | *next = *id + 1; | ||
1702 | if (*next == 0) | ||
1703 | xa->xa_flags |= XA_FLAGS_ALLOC_WRAPPED; | ||
1704 | } | ||
1705 | return ret; | ||
1706 | } | ||
1707 | EXPORT_SYMBOL(__xa_alloc_cyclic); | ||
1708 | |||
1709 | /** | ||
1660 | * __xa_set_mark() - Set this mark on this entry while locked. | 1710 | * __xa_set_mark() - Set this mark on this entry while locked. |
1661 | * @xa: XArray. | 1711 | * @xa: XArray. |
1662 | * @index: Index of entry. | 1712 | * @index: Index of entry. |