XArray: Regularise xa_reserve
The xa_reserve() function was a little unusual in that it attempted to be callable for all kinds of locking scenarios. Make it look like the other APIs with __xa_reserve, xa_reserve_bh and xa_reserve_irq variants. Signed-off-by: Matthew Wilcox <willy@infradead.org>
This commit is contained in:
parent
fe2b51145c
commit
4c0608f4a0
@ -105,6 +105,15 @@ may result in the entry being marked at some, but not all of the other
|
||||
indices. Storing into one index may result in the entry retrieved by
|
||||
some, but not all of the other indices changing.
|
||||
|
||||
Sometimes you need to ensure that a subsequent call to :c:func:`xa_store`
|
||||
will not need to allocate memory. The :c:func:`xa_reserve` function
|
||||
will store a reserved entry at the indicated index. Users of the normal
|
||||
API will see this entry as containing ``NULL``. If you do not need to
|
||||
use the reserved entry, you can call :c:func:`xa_release` to remove the
|
||||
unused entry. If another user has stored to the entry in the meantime,
|
||||
:c:func:`xa_release` will do nothing; if instead you want the entry to
|
||||
become ``NULL``, you should use :c:func:`xa_erase`.
|
||||
|
||||
Finally, you can remove all entries from an XArray by calling
|
||||
:c:func:`xa_destroy`. If the XArray entries are pointers, you may wish
|
||||
to free the entries first. You can do this by iterating over all present
|
||||
@ -167,6 +176,9 @@ Takes xa_lock internally:
|
||||
* :c:func:`xa_alloc`
|
||||
* :c:func:`xa_alloc_bh`
|
||||
* :c:func:`xa_alloc_irq`
|
||||
* :c:func:`xa_reserve`
|
||||
* :c:func:`xa_reserve_bh`
|
||||
* :c:func:`xa_reserve_irq`
|
||||
* :c:func:`xa_destroy`
|
||||
* :c:func:`xa_set_mark`
|
||||
* :c:func:`xa_clear_mark`
|
||||
@ -177,6 +189,7 @@ Assumes xa_lock held on entry:
|
||||
* :c:func:`__xa_erase`
|
||||
* :c:func:`__xa_cmpxchg`
|
||||
* :c:func:`__xa_alloc`
|
||||
* :c:func:`__xa_reserve`
|
||||
* :c:func:`__xa_set_mark`
|
||||
* :c:func:`__xa_clear_mark`
|
||||
|
||||
|
@ -291,7 +291,6 @@ void *xa_load(struct xarray *, unsigned long index);
|
||||
void *xa_store(struct xarray *, unsigned long index, void *entry, gfp_t);
|
||||
void *xa_cmpxchg(struct xarray *, unsigned long index,
|
||||
void *old, void *entry, gfp_t);
|
||||
int xa_reserve(struct xarray *, unsigned long index, gfp_t);
|
||||
void *xa_store_range(struct xarray *, unsigned long first, unsigned long last,
|
||||
void *entry, gfp_t);
|
||||
bool xa_get_mark(struct xarray *, unsigned long index, xa_mark_t);
|
||||
@ -455,6 +454,7 @@ void *__xa_store(struct xarray *, unsigned long index, void *entry, gfp_t);
|
||||
void *__xa_cmpxchg(struct xarray *, unsigned long index, void *old,
|
||||
void *entry, gfp_t);
|
||||
int __xa_alloc(struct xarray *, u32 *id, u32 max, void *entry, gfp_t);
|
||||
int __xa_reserve(struct xarray *, unsigned long index, gfp_t);
|
||||
void __xa_set_mark(struct xarray *, unsigned long index, xa_mark_t);
|
||||
void __xa_clear_mark(struct xarray *, unsigned long index, xa_mark_t);
|
||||
|
||||
@ -621,6 +621,84 @@ static inline int xa_alloc_irq(struct xarray *xa, u32 *id, u32 max, void *entry,
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* xa_reserve() - Reserve this index in the XArray.
|
||||
* @xa: XArray.
|
||||
* @index: Index into array.
|
||||
* @gfp: Memory allocation flags.
|
||||
*
|
||||
* Ensures there is somewhere to store an entry at @index in the array.
|
||||
* If there is already something stored at @index, this function does
|
||||
* nothing. If there was nothing there, the entry is marked as reserved.
|
||||
* Loading from a reserved entry returns a %NULL pointer.
|
||||
*
|
||||
* If you do not use the entry that you have reserved, call xa_release()
|
||||
* or xa_erase() to free any unnecessary memory.
|
||||
*
|
||||
* Context: Any context. Takes and releases the xa_lock.
|
||||
* May sleep if the @gfp flags permit.
|
||||
* Return: 0 if the reservation succeeded or -ENOMEM if it failed.
|
||||
*/
|
||||
static inline
|
||||
int xa_reserve(struct xarray *xa, unsigned long index, gfp_t gfp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
xa_lock(xa);
|
||||
ret = __xa_reserve(xa, index, gfp);
|
||||
xa_unlock(xa);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* xa_reserve_bh() - Reserve this index in the XArray.
|
||||
* @xa: XArray.
|
||||
* @index: Index into array.
|
||||
* @gfp: Memory allocation flags.
|
||||
*
|
||||
* A softirq-disabling version of xa_reserve().
|
||||
*
|
||||
* Context: Any context. Takes and releases the xa_lock while
|
||||
* disabling softirqs.
|
||||
* Return: 0 if the reservation succeeded or -ENOMEM if it failed.
|
||||
*/
|
||||
static inline
|
||||
int xa_reserve_bh(struct xarray *xa, unsigned long index, gfp_t gfp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
xa_lock_bh(xa);
|
||||
ret = __xa_reserve(xa, index, gfp);
|
||||
xa_unlock_bh(xa);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* xa_reserve_irq() - Reserve this index in the XArray.
|
||||
* @xa: XArray.
|
||||
* @index: Index into array.
|
||||
* @gfp: Memory allocation flags.
|
||||
*
|
||||
* An interrupt-disabling version of xa_reserve().
|
||||
*
|
||||
* Context: Process context. Takes and releases the xa_lock while
|
||||
* disabling interrupts.
|
||||
* Return: 0 if the reservation succeeded or -ENOMEM if it failed.
|
||||
*/
|
||||
static inline
|
||||
int xa_reserve_irq(struct xarray *xa, unsigned long index, gfp_t gfp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
xa_lock_irq(xa);
|
||||
ret = __xa_reserve(xa, index, gfp);
|
||||
xa_unlock_irq(xa);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Everything below here is the Advanced API. Proceed with caution. */
|
||||
|
||||
/*
|
||||
|
@ -373,6 +373,12 @@ static noinline void check_reserve(struct xarray *xa)
|
||||
xa_erase_index(xa, 12345678);
|
||||
XA_BUG_ON(xa, !xa_empty(xa));
|
||||
|
||||
/* And so does xa_insert */
|
||||
xa_reserve(xa, 12345678, GFP_KERNEL);
|
||||
XA_BUG_ON(xa, xa_insert(xa, 12345678, xa_mk_value(12345678), 0) != 0);
|
||||
xa_erase_index(xa, 12345678);
|
||||
XA_BUG_ON(xa, !xa_empty(xa));
|
||||
|
||||
/* Can iterate through a reserved entry */
|
||||
xa_store_index(xa, 5, GFP_KERNEL);
|
||||
xa_reserve(xa, 6, GFP_KERNEL);
|
||||
|
18
lib/xarray.c
18
lib/xarray.c
@ -1488,7 +1488,7 @@ void *__xa_cmpxchg(struct xarray *xa, unsigned long index,
|
||||
EXPORT_SYMBOL(__xa_cmpxchg);
|
||||
|
||||
/**
|
||||
* xa_reserve() - Reserve this index in the XArray.
|
||||
* __xa_reserve() - Reserve this index in the XArray.
|
||||
* @xa: XArray.
|
||||
* @index: Index into array.
|
||||
* @gfp: Memory allocation flags.
|
||||
@ -1496,33 +1496,29 @@ EXPORT_SYMBOL(__xa_cmpxchg);
|
||||
* Ensures there is somewhere to store an entry at @index in the array.
|
||||
* If there is already something stored at @index, this function does
|
||||
* nothing. If there was nothing there, the entry is marked as reserved.
|
||||
* Loads from @index will continue to see a %NULL pointer until a
|
||||
* subsequent store to @index.
|
||||
* Loading from a reserved entry returns a %NULL pointer.
|
||||
*
|
||||
* If you do not use the entry that you have reserved, call xa_release()
|
||||
* or xa_erase() to free any unnecessary memory.
|
||||
*
|
||||
* Context: Process context. Takes and releases the xa_lock, IRQ or BH safe
|
||||
* if specified in XArray flags. May sleep if the @gfp flags permit.
|
||||
* Context: Any context. Expects the xa_lock to be held on entry. May
|
||||
* release the lock, sleep and reacquire the lock if the @gfp flags permit.
|
||||
* Return: 0 if the reservation succeeded or -ENOMEM if it failed.
|
||||
*/
|
||||
int xa_reserve(struct xarray *xa, unsigned long index, gfp_t gfp)
|
||||
int __xa_reserve(struct xarray *xa, unsigned long index, gfp_t gfp)
|
||||
{
|
||||
XA_STATE(xas, xa, index);
|
||||
unsigned int lock_type = xa_lock_type(xa);
|
||||
void *curr;
|
||||
|
||||
do {
|
||||
xas_lock_type(&xas, lock_type);
|
||||
curr = xas_load(&xas);
|
||||
if (!curr)
|
||||
xas_store(&xas, XA_ZERO_ENTRY);
|
||||
xas_unlock_type(&xas, lock_type);
|
||||
} while (xas_nomem(&xas, gfp));
|
||||
} while (__xas_nomem(&xas, gfp));
|
||||
|
||||
return xas_error(&xas);
|
||||
}
|
||||
EXPORT_SYMBOL(xa_reserve);
|
||||
EXPORT_SYMBOL(__xa_reserve);
|
||||
|
||||
#ifdef CONFIG_XARRAY_MULTI
|
||||
static void xas_set_range(struct xa_state *xas, unsigned long first,
|
||||
|
Loading…
Reference in New Issue
Block a user