Commit 55f3f7ea authored by Matthew Wilcox's avatar Matthew Wilcox
Browse files

XArray: Add xa_cmpxchg_irq and xa_cmpxchg_bh



These convenience wrappers match the other _irq and _bh wrappers we
already have.  It turns out I'd already open-coded xa_cmpxchg_irq()
in the shmem code, so convert that.

Signed-off-by: default avatarMatthew Wilcox <willy@infradead.org>
parent eff3860b
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -187,6 +187,8 @@ Takes xa_lock internally:
 * :c:func:`xa_erase_bh`
 * :c:func:`xa_erase_irq`
 * :c:func:`xa_cmpxchg`
 * :c:func:`xa_cmpxchg_bh`
 * :c:func:`xa_cmpxchg_irq`
 * :c:func:`xa_store_range`
 * :c:func:`xa_alloc`
 * :c:func:`xa_alloc_bh`
@@ -263,7 +265,8 @@ using :c:func:`xa_lock_irqsave` in both the interrupt handler and process
context, or :c:func:`xa_lock_irq` in process context and :c:func:`xa_lock`
in the interrupt handler.  Some of the more common patterns have helper
functions such as :c:func:`xa_store_bh`, :c:func:`xa_store_irq`,
:c:func:`xa_erase_bh` and :c:func:`xa_erase_irq`.
:c:func:`xa_erase_bh`, :c:func:`xa_erase_irq`, :c:func:`xa_cmpxchg_bh`
and :c:func:`xa_cmpxchg_irq`.

Sometimes you need to protect access to the XArray with a mutex because
that lock sits above another mutex in the locking hierarchy.  That does
+54 −0
Original line number Diff line number Diff line
@@ -553,6 +553,60 @@ static inline void *xa_cmpxchg(struct xarray *xa, unsigned long index,
	return curr;
}

/**
 * xa_cmpxchg_bh() - Conditionally replace an entry in the XArray.
 * @xa: XArray.
 * @index: Index into array.
 * @old: Old value to test against.
 * @entry: New value to place in array.
 * @gfp: Memory allocation flags.
 *
 * This function is like calling xa_cmpxchg() except it disables softirqs
 * while holding the array lock.
 *
 * Context: Any context.  Takes and releases the xa_lock while
 * disabling softirqs.  May sleep if the @gfp flags permit.
 * Return: The old value at this index or xa_err() if an error happened.
 */
static inline void *xa_cmpxchg_bh(struct xarray *xa, unsigned long index,
			void *old, void *entry, gfp_t gfp)
{
	void *curr;

	xa_lock_bh(xa);
	curr = __xa_cmpxchg(xa, index, old, entry, gfp);
	xa_unlock_bh(xa);

	return curr;
}

/**
 * xa_cmpxchg_irq() - Conditionally replace an entry in the XArray.
 * @xa: XArray.
 * @index: Index into array.
 * @old: Old value to test against.
 * @entry: New value to place in array.
 * @gfp: Memory allocation flags.
 *
 * This function is like calling xa_cmpxchg() except it disables interrupts
 * while holding the array lock.
 *
 * Context: Process context.  Takes and releases the xa_lock while
 * disabling interrupts.  May sleep if the @gfp flags permit.
 * Return: The old value at this index or xa_err() if an error happened.
 */
static inline void *xa_cmpxchg_irq(struct xarray *xa, unsigned long index,
			void *old, void *entry, gfp_t gfp)
{
	void *curr;

	xa_lock_irq(xa);
	curr = __xa_cmpxchg(xa, index, old, entry, gfp);
	xa_unlock_irq(xa);

	return curr;
}

/**
 * xa_insert() - Store this entry in the XArray unless another entry is
 *			already present.
+1 −3
Original line number Diff line number Diff line
@@ -661,9 +661,7 @@ static int shmem_free_swap(struct address_space *mapping,
{
	void *old;

	xa_lock_irq(&mapping->i_pages);
	old = __xa_cmpxchg(&mapping->i_pages, index, radswap, NULL, 0);
	xa_unlock_irq(&mapping->i_pages);
	old = xa_cmpxchg_irq(&mapping->i_pages, index, radswap, NULL, 0);
	if (old != radswap)
		return -ENOENT;
	free_swap_and_cache(radix_to_swp_entry(radswap));