aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/xarray.h
diff options
context:
space:
mode:
authorMatthew Wilcox <willy@infradead.org>2019-01-02 13:57:03 -0500
committerMatthew Wilcox <willy@infradead.org>2019-01-06 22:12:58 -0500
commitb0606fed6eece16a421034eca0bbea9a08b90e91 (patch)
treef705b58760a60fce2d6f03a934a5038154505c1b /include/linux/xarray.h
parent76b4e52995654af260f14558e0e07b5b039ae202 (diff)
XArray: Honour reserved entries in xa_insert
xa_insert() should treat reserved entries as occupied, not as available. Also, it should treat requests to insert a NULL pointer as a request to reserve the slot. Add xa_insert_bh() and xa_insert_irq() for completeness. Signed-off-by: Matthew Wilcox <willy@infradead.org>
Diffstat (limited to 'include/linux/xarray.h')
-rw-r--r--include/linux/xarray.h110
1 files changed, 71 insertions, 39 deletions
diff --git a/include/linux/xarray.h b/include/linux/xarray.h
index 435c25b29079..12244aa98a69 100644
--- a/include/linux/xarray.h
+++ b/include/linux/xarray.h
@@ -463,40 +463,13 @@ void *__xa_erase(struct xarray *, unsigned long index);
463void *__xa_store(struct xarray *, unsigned long index, void *entry, gfp_t); 463void *__xa_store(struct xarray *, unsigned long index, void *entry, gfp_t);
464void *__xa_cmpxchg(struct xarray *, unsigned long index, void *old, 464void *__xa_cmpxchg(struct xarray *, unsigned long index, void *old,
465 void *entry, gfp_t); 465 void *entry, gfp_t);
466int __xa_insert(struct xarray *, unsigned long index, void *entry, gfp_t);
466int __xa_alloc(struct xarray *, u32 *id, u32 max, void *entry, gfp_t); 467int __xa_alloc(struct xarray *, u32 *id, u32 max, void *entry, gfp_t);
467int __xa_reserve(struct xarray *, unsigned long index, gfp_t); 468int __xa_reserve(struct xarray *, unsigned long index, gfp_t);
468void __xa_set_mark(struct xarray *, unsigned long index, xa_mark_t); 469void __xa_set_mark(struct xarray *, unsigned long index, xa_mark_t);
469void __xa_clear_mark(struct xarray *, unsigned long index, xa_mark_t); 470void __xa_clear_mark(struct xarray *, unsigned long index, xa_mark_t);
470 471
471/** 472/**
472 * __xa_insert() - Store this entry in the XArray unless another entry is
473 * already present.
474 * @xa: XArray.
475 * @index: Index into array.
476 * @entry: New entry.
477 * @gfp: Memory allocation flags.
478 *
479 * If you would rather see the existing entry in the array, use __xa_cmpxchg().
480 * This function is for users who don't care what the entry is, only that
481 * one is present.
482 *
483 * Context: Any context. Expects xa_lock to be held on entry. May
484 * release and reacquire xa_lock if the @gfp flags permit.
485 * Return: 0 if the store succeeded. -EEXIST if another entry was present.
486 * -ENOMEM if memory could not be allocated.
487 */
488static inline int __xa_insert(struct xarray *xa, unsigned long index,
489 void *entry, gfp_t gfp)
490{
491 void *curr = __xa_cmpxchg(xa, index, NULL, entry, gfp);
492 if (!curr)
493 return 0;
494 if (xa_is_err(curr))
495 return xa_err(curr);
496 return -EEXIST;
497}
498
499/**
500 * xa_store_bh() - Store this entry in the XArray. 473 * xa_store_bh() - Store this entry in the XArray.
501 * @xa: XArray. 474 * @xa: XArray.
502 * @index: Index into array. 475 * @index: Index into array.
@@ -685,24 +658,83 @@ static inline void *xa_cmpxchg_irq(struct xarray *xa, unsigned long index,
685 * @entry: New entry. 658 * @entry: New entry.
686 * @gfp: Memory allocation flags. 659 * @gfp: Memory allocation flags.
687 * 660 *
688 * If you would rather see the existing entry in the array, use xa_cmpxchg(). 661 * Inserting a NULL entry will store a reserved entry (like xa_reserve())
689 * This function is for users who don't care what the entry is, only that 662 * if no entry is present. Inserting will fail if a reserved entry is
690 * one is present. 663 * present, even though loading from this index will return NULL.
691 * 664 *
692 * Context: Process context. Takes and releases the xa_lock. 665 * Context: Any context. Takes and releases the xa_lock. May sleep if
693 * May sleep if the @gfp flags permit. 666 * the @gfp flags permit.
694 * Return: 0 if the store succeeded. -EEXIST if another entry was present. 667 * Return: 0 if the store succeeded. -EEXIST if another entry was present.
695 * -ENOMEM if memory could not be allocated. 668 * -ENOMEM if memory could not be allocated.
696 */ 669 */
697static inline int xa_insert(struct xarray *xa, unsigned long index, 670static inline int xa_insert(struct xarray *xa, unsigned long index,
698 void *entry, gfp_t gfp) 671 void *entry, gfp_t gfp)
699{ 672{
700 void *curr = xa_cmpxchg(xa, index, NULL, entry, gfp); 673 int err;
701 if (!curr) 674
702 return 0; 675 xa_lock(xa);
703 if (xa_is_err(curr)) 676 err = __xa_insert(xa, index, entry, gfp);
704 return xa_err(curr); 677 xa_unlock(xa);
705 return -EEXIST; 678
679 return err;
680}
681
682/**
683 * xa_insert_bh() - Store this entry in the XArray unless another entry is
684 * already present.
685 * @xa: XArray.
686 * @index: Index into array.
687 * @entry: New entry.
688 * @gfp: Memory allocation flags.
689 *
690 * Inserting a NULL entry will store a reserved entry (like xa_reserve())
691 * if no entry is present. Inserting will fail if a reserved entry is
692 * present, even though loading from this index will return NULL.
693 *
694 * Context: Any context. Takes and releases the xa_lock while
695 * disabling softirqs. May sleep if the @gfp flags permit.
696 * Return: 0 if the store succeeded. -EEXIST if another entry was present.
697 * -ENOMEM if memory could not be allocated.
698 */
699static inline int xa_insert_bh(struct xarray *xa, unsigned long index,
700 void *entry, gfp_t gfp)
701{
702 int err;
703
704 xa_lock_bh(xa);
705 err = __xa_insert(xa, index, entry, gfp);
706 xa_unlock_bh(xa);
707
708 return err;
709}
710
711/**
712 * xa_insert_irq() - Store this entry in the XArray unless another entry is
713 * already present.
714 * @xa: XArray.
715 * @index: Index into array.
716 * @entry: New entry.
717 * @gfp: Memory allocation flags.
718 *
719 * Inserting a NULL entry will store a reserved entry (like xa_reserve())
720 * if no entry is present. Inserting will fail if a reserved entry is
721 * present, even though loading from this index will return NULL.
722 *
723 * Context: Process context. Takes and releases the xa_lock while
724 * disabling interrupts. May sleep if the @gfp flags permit.
725 * Return: 0 if the store succeeded. -EEXIST if another entry was present.
726 * -ENOMEM if memory could not be allocated.
727 */
728static inline int xa_insert_irq(struct xarray *xa, unsigned long index,
729 void *entry, gfp_t gfp)
730{
731 int err;
732
733 xa_lock_irq(xa);
734 err = __xa_insert(xa, index, entry, gfp);
735 xa_unlock_irq(xa);
736
737 return err;
706} 738}
707 739
708/** 740/**