aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/xarray.h
diff options
context:
space:
mode:
authorMatthew Wilcox <willy@infradead.org>2017-11-10 15:34:55 -0500
committerMatthew Wilcox <willy@infradead.org>2018-10-21 10:45:58 -0400
commit41aec91f55985e7f14ee75fe2f6e7bcfff0d0fae (patch)
tree4efdedeabd066e15a542b28f21a47731c5323b5b /include/linux/xarray.h
parent58d6ea3085f2e53714810a513c61629f6d2be0a6 (diff)
xarray: Add XArray conditional store operations
Like cmpxchg(), xa_cmpxchg will only store to the index if the current entry matches the old entry. It returns the current entry, which is usually more useful than the errno returned by radix_tree_insert(). For the users who really only want the errno, the xa_insert() wrapper provides a more convenient calling convention. Signed-off-by: Matthew Wilcox <willy@infradead.org>
Diffstat (limited to 'include/linux/xarray.h')
-rw-r--r--include/linux/xarray.h60
1 files changed, 60 insertions, 0 deletions
diff --git a/include/linux/xarray.h b/include/linux/xarray.h
index 15eab63286ed..7f740f675b96 100644
--- a/include/linux/xarray.h
+++ b/include/linux/xarray.h
@@ -275,6 +275,8 @@ struct xarray {
275void xa_init_flags(struct xarray *, gfp_t flags); 275void xa_init_flags(struct xarray *, gfp_t flags);
276void *xa_load(struct xarray *, unsigned long index); 276void *xa_load(struct xarray *, unsigned long index);
277void *xa_store(struct xarray *, unsigned long index, void *entry, gfp_t); 277void *xa_store(struct xarray *, unsigned long index, void *entry, gfp_t);
278void *xa_cmpxchg(struct xarray *, unsigned long index,
279 void *old, void *entry, gfp_t);
278bool xa_get_mark(struct xarray *, unsigned long index, xa_mark_t); 280bool xa_get_mark(struct xarray *, unsigned long index, xa_mark_t);
279void xa_set_mark(struct xarray *, unsigned long index, xa_mark_t); 281void xa_set_mark(struct xarray *, unsigned long index, xa_mark_t);
280void xa_clear_mark(struct xarray *, unsigned long index, xa_mark_t); 282void xa_clear_mark(struct xarray *, unsigned long index, xa_mark_t);
@@ -334,6 +336,34 @@ static inline void *xa_erase(struct xarray *xa, unsigned long index)
334 return xa_store(xa, index, NULL, 0); 336 return xa_store(xa, index, NULL, 0);
335} 337}
336 338
339/**
340 * xa_insert() - Store this entry in the XArray unless another entry is
341 * already present.
342 * @xa: XArray.
343 * @index: Index into array.
344 * @entry: New entry.
345 * @gfp: Memory allocation flags.
346 *
347 * If you would rather see the existing entry in the array, use xa_cmpxchg().
348 * This function is for users who don't care what the entry is, only that
349 * one is present.
350 *
351 * Context: Process context. Takes and releases the xa_lock.
352 * May sleep if the @gfp flags permit.
353 * Return: 0 if the store succeeded. -EEXIST if another entry was present.
354 * -ENOMEM if memory could not be allocated.
355 */
356static inline int xa_insert(struct xarray *xa, unsigned long index,
357 void *entry, gfp_t gfp)
358{
359 void *curr = xa_cmpxchg(xa, index, NULL, entry, gfp);
360 if (!curr)
361 return 0;
362 if (xa_is_err(curr))
363 return xa_err(curr);
364 return -EEXIST;
365}
366
337#define xa_trylock(xa) spin_trylock(&(xa)->xa_lock) 367#define xa_trylock(xa) spin_trylock(&(xa)->xa_lock)
338#define xa_lock(xa) spin_lock(&(xa)->xa_lock) 368#define xa_lock(xa) spin_lock(&(xa)->xa_lock)
339#define xa_unlock(xa) spin_unlock(&(xa)->xa_lock) 369#define xa_unlock(xa) spin_unlock(&(xa)->xa_lock)
@@ -355,10 +385,40 @@ static inline void *xa_erase(struct xarray *xa, unsigned long index)
355 */ 385 */
356void *__xa_erase(struct xarray *, unsigned long index); 386void *__xa_erase(struct xarray *, unsigned long index);
357void *__xa_store(struct xarray *, unsigned long index, void *entry, gfp_t); 387void *__xa_store(struct xarray *, unsigned long index, void *entry, gfp_t);
388void *__xa_cmpxchg(struct xarray *, unsigned long index, void *old,
389 void *entry, gfp_t);
358void __xa_set_mark(struct xarray *, unsigned long index, xa_mark_t); 390void __xa_set_mark(struct xarray *, unsigned long index, xa_mark_t);
359void __xa_clear_mark(struct xarray *, unsigned long index, xa_mark_t); 391void __xa_clear_mark(struct xarray *, unsigned long index, xa_mark_t);
360 392
361/** 393/**
394 * __xa_insert() - Store this entry in the XArray unless another entry is
395 * already present.
396 * @xa: XArray.
397 * @index: Index into array.
398 * @entry: New entry.
399 * @gfp: Memory allocation flags.
400 *
401 * If you would rather see the existing entry in the array, use __xa_cmpxchg().
402 * This function is for users who don't care what the entry is, only that
403 * one is present.
404 *
405 * Context: Any context. Expects xa_lock to be held on entry. May
406 * release and reacquire xa_lock if the @gfp flags permit.
407 * Return: 0 if the store succeeded. -EEXIST if another entry was present.
408 * -ENOMEM if memory could not be allocated.
409 */
410static inline int __xa_insert(struct xarray *xa, unsigned long index,
411 void *entry, gfp_t gfp)
412{
413 void *curr = __xa_cmpxchg(xa, index, NULL, entry, gfp);
414 if (!curr)
415 return 0;
416 if (xa_is_err(curr))
417 return xa_err(curr);
418 return -EEXIST;
419}
420
421/**
362 * xa_erase_bh() - Erase this entry from the XArray. 422 * xa_erase_bh() - Erase this entry from the XArray.
363 * @xa: XArray. 423 * @xa: XArray.
364 * @index: Index of entry. 424 * @index: Index of entry.