diff options
author | Matthew Wilcox <willy@infradead.org> | 2018-12-31 10:41:01 -0500 |
---|---|---|
committer | Matthew Wilcox <willy@infradead.org> | 2019-02-06 13:32:23 -0500 |
commit | a3e4d3f97ec844de005a679585c04c5c03dfbdb6 (patch) | |
tree | c4cda3a98cba2d9923e7356e587f6a958b2971d7 /include/linux/xarray.h | |
parent | 3ccaf57a6a63ad171a951dcaddffc453b2414c7b (diff) |
XArray: Redesign xa_alloc API
It was too easy to forget to initialise the start index. Add an
xa_limit data structure which can be used to pass min & max, and
define a couple of special values for common cases. Also add some
more tests cribbed from the IDR test suite. Change the return value
from -ENOSPC to -EBUSY to match xa_insert().
Signed-off-by: Matthew Wilcox <willy@infradead.org>
Diffstat (limited to 'include/linux/xarray.h')
-rw-r--r-- | include/linux/xarray.h | 80 |
1 files changed, 51 insertions, 29 deletions
diff --git a/include/linux/xarray.h b/include/linux/xarray.h index 99dd0838b4ba..883bb958e462 100644 --- a/include/linux/xarray.h +++ b/include/linux/xarray.h | |||
@@ -200,6 +200,27 @@ static inline int xa_err(void *entry) | |||
200 | return 0; | 200 | return 0; |
201 | } | 201 | } |
202 | 202 | ||
203 | /** | ||
204 | * struct xa_limit - Represents a range of IDs. | ||
205 | * @min: The lowest ID to allocate (inclusive). | ||
206 | * @max: The maximum ID to allocate (inclusive). | ||
207 | * | ||
208 | * This structure is used either directly or via the XA_LIMIT() macro | ||
209 | * to communicate the range of IDs that are valid for allocation. | ||
210 | * Two common ranges are predefined for you: | ||
211 | * * xa_limit_32b - [0 - UINT_MAX] | ||
212 | * * xa_limit_31b - [0 - INT_MAX] | ||
213 | */ | ||
214 | struct xa_limit { | ||
215 | u32 max; | ||
216 | u32 min; | ||
217 | }; | ||
218 | |||
219 | #define XA_LIMIT(_min, _max) (struct xa_limit) { .min = _min, .max = _max } | ||
220 | |||
221 | #define xa_limit_32b XA_LIMIT(0, UINT_MAX) | ||
222 | #define xa_limit_31b XA_LIMIT(0, INT_MAX) | ||
223 | |||
203 | typedef unsigned __bitwise xa_mark_t; | 224 | typedef unsigned __bitwise xa_mark_t; |
204 | #define XA_MARK_0 ((__force xa_mark_t)0U) | 225 | #define XA_MARK_0 ((__force xa_mark_t)0U) |
205 | #define XA_MARK_1 ((__force xa_mark_t)1U) | 226 | #define XA_MARK_1 ((__force xa_mark_t)1U) |
@@ -476,7 +497,8 @@ void *__xa_store(struct xarray *, unsigned long index, void *entry, gfp_t); | |||
476 | void *__xa_cmpxchg(struct xarray *, unsigned long index, void *old, | 497 | void *__xa_cmpxchg(struct xarray *, unsigned long index, void *old, |
477 | void *entry, gfp_t); | 498 | void *entry, gfp_t); |
478 | int __xa_insert(struct xarray *, unsigned long index, void *entry, gfp_t); | 499 | int __xa_insert(struct xarray *, unsigned long index, void *entry, gfp_t); |
479 | int __xa_alloc(struct xarray *, u32 *id, u32 max, void *entry, gfp_t); | 500 | int __must_check __xa_alloc(struct xarray *, u32 *id, void *entry, |
501 | struct xa_limit, gfp_t); | ||
480 | int __xa_reserve(struct xarray *, unsigned long index, gfp_t); | 502 | int __xa_reserve(struct xarray *, unsigned long index, gfp_t); |
481 | void __xa_set_mark(struct xarray *, unsigned long index, xa_mark_t); | 503 | void __xa_set_mark(struct xarray *, unsigned long index, xa_mark_t); |
482 | void __xa_clear_mark(struct xarray *, unsigned long index, xa_mark_t); | 504 | void __xa_clear_mark(struct xarray *, unsigned long index, xa_mark_t); |
@@ -753,26 +775,26 @@ static inline int xa_insert_irq(struct xarray *xa, unsigned long index, | |||
753 | * xa_alloc() - Find somewhere to store this entry in the XArray. | 775 | * xa_alloc() - Find somewhere to store this entry in the XArray. |
754 | * @xa: XArray. | 776 | * @xa: XArray. |
755 | * @id: Pointer to ID. | 777 | * @id: Pointer to ID. |
756 | * @max: Maximum ID to allocate (inclusive). | ||
757 | * @entry: New entry. | 778 | * @entry: New entry. |
779 | * @limit: Range of ID to allocate. | ||
758 | * @gfp: Memory allocation flags. | 780 | * @gfp: Memory allocation flags. |
759 | * | 781 | * |
760 | * Allocates an unused ID in the range specified by @id and @max. | 782 | * Finds an empty entry in @xa between @limit.min and @limit.max, |
761 | * Updates the @id pointer with the index, then stores the entry at that | 783 | * stores the index into the @id pointer, then stores the entry at |
762 | * index. A concurrent lookup will not see an uninitialised @id. | 784 | * that index. A concurrent lookup will not see an uninitialised @id. |
763 | * | 785 | * |
764 | * Context: Process context. Takes and releases the xa_lock. May sleep if | 786 | * Context: Any context. Takes and releases the xa_lock. May sleep if |
765 | * the @gfp flags permit. | 787 | * the @gfp flags permit. |
766 | * Return: 0 on success, -ENOMEM if memory allocation fails or -ENOSPC if | 788 | * Return: 0 on success, -ENOMEM if memory could not be allocated or |
767 | * there is no more space in the XArray. | 789 | * -EBUSY if there are no free entries in @limit. |
768 | */ | 790 | */ |
769 | static inline int xa_alloc(struct xarray *xa, u32 *id, u32 max, void *entry, | 791 | static inline __must_check int xa_alloc(struct xarray *xa, u32 *id, |
770 | gfp_t gfp) | 792 | void *entry, struct xa_limit limit, gfp_t gfp) |
771 | { | 793 | { |
772 | int err; | 794 | int err; |
773 | 795 | ||
774 | xa_lock(xa); | 796 | xa_lock(xa); |
775 | err = __xa_alloc(xa, id, max, entry, gfp); | 797 | err = __xa_alloc(xa, id, entry, limit, gfp); |
776 | xa_unlock(xa); | 798 | xa_unlock(xa); |
777 | 799 | ||
778 | return err; | 800 | return err; |
@@ -782,26 +804,26 @@ static inline int xa_alloc(struct xarray *xa, u32 *id, u32 max, void *entry, | |||
782 | * xa_alloc_bh() - Find somewhere to store this entry in the XArray. | 804 | * xa_alloc_bh() - Find somewhere to store this entry in the XArray. |
783 | * @xa: XArray. | 805 | * @xa: XArray. |
784 | * @id: Pointer to ID. | 806 | * @id: Pointer to ID. |
785 | * @max: Maximum ID to allocate (inclusive). | ||
786 | * @entry: New entry. | 807 | * @entry: New entry. |
808 | * @limit: Range of ID to allocate. | ||
787 | * @gfp: Memory allocation flags. | 809 | * @gfp: Memory allocation flags. |
788 | * | 810 | * |
789 | * Allocates an unused ID in the range specified by @id and @max. | 811 | * Finds an empty entry in @xa between @limit.min and @limit.max, |
790 | * Updates the @id pointer with the index, then stores the entry at that | 812 | * stores the index into the @id pointer, then stores the entry at |
791 | * index. A concurrent lookup will not see an uninitialised @id. | 813 | * that index. A concurrent lookup will not see an uninitialised @id. |
792 | * | 814 | * |
793 | * Context: Any context. Takes and releases the xa_lock while | 815 | * Context: Any context. Takes and releases the xa_lock while |
794 | * disabling softirqs. May sleep if the @gfp flags permit. | 816 | * disabling softirqs. May sleep if the @gfp flags permit. |
795 | * Return: 0 on success, -ENOMEM if memory allocation fails or -ENOSPC if | 817 | * Return: 0 on success, -ENOMEM if memory could not be allocated or |
796 | * there is no more space in the XArray. | 818 | * -EBUSY if there are no free entries in @limit. |
797 | */ | 819 | */ |
798 | static inline int xa_alloc_bh(struct xarray *xa, u32 *id, u32 max, void *entry, | 820 | static inline int __must_check xa_alloc_bh(struct xarray *xa, u32 *id, |
799 | gfp_t gfp) | 821 | void *entry, struct xa_limit limit, gfp_t gfp) |
800 | { | 822 | { |
801 | int err; | 823 | int err; |
802 | 824 | ||
803 | xa_lock_bh(xa); | 825 | xa_lock_bh(xa); |
804 | err = __xa_alloc(xa, id, max, entry, gfp); | 826 | err = __xa_alloc(xa, id, entry, limit, gfp); |
805 | xa_unlock_bh(xa); | 827 | xa_unlock_bh(xa); |
806 | 828 | ||
807 | return err; | 829 | return err; |
@@ -811,26 +833,26 @@ static inline int xa_alloc_bh(struct xarray *xa, u32 *id, u32 max, void *entry, | |||
811 | * xa_alloc_irq() - Find somewhere to store this entry in the XArray. | 833 | * xa_alloc_irq() - Find somewhere to store this entry in the XArray. |
812 | * @xa: XArray. | 834 | * @xa: XArray. |
813 | * @id: Pointer to ID. | 835 | * @id: Pointer to ID. |
814 | * @max: Maximum ID to allocate (inclusive). | ||
815 | * @entry: New entry. | 836 | * @entry: New entry. |
837 | * @limit: Range of ID to allocate. | ||
816 | * @gfp: Memory allocation flags. | 838 | * @gfp: Memory allocation flags. |
817 | * | 839 | * |
818 | * Allocates an unused ID in the range specified by @id and @max. | 840 | * Finds an empty entry in @xa between @limit.min and @limit.max, |
819 | * Updates the @id pointer with the index, then stores the entry at that | 841 | * stores the index into the @id pointer, then stores the entry at |
820 | * index. A concurrent lookup will not see an uninitialised @id. | 842 | * that index. A concurrent lookup will not see an uninitialised @id. |
821 | * | 843 | * |
822 | * Context: Process context. Takes and releases the xa_lock while | 844 | * Context: Process context. Takes and releases the xa_lock while |
823 | * disabling interrupts. May sleep if the @gfp flags permit. | 845 | * disabling interrupts. May sleep if the @gfp flags permit. |
824 | * Return: 0 on success, -ENOMEM if memory allocation fails or -ENOSPC if | 846 | * Return: 0 on success, -ENOMEM if memory could not be allocated or |
825 | * there is no more space in the XArray. | 847 | * -EBUSY if there are no free entries in @limit. |
826 | */ | 848 | */ |
827 | static inline int xa_alloc_irq(struct xarray *xa, u32 *id, u32 max, void *entry, | 849 | static inline int __must_check xa_alloc_irq(struct xarray *xa, u32 *id, |
828 | gfp_t gfp) | 850 | void *entry, struct xa_limit limit, gfp_t gfp) |
829 | { | 851 | { |
830 | int err; | 852 | int err; |
831 | 853 | ||
832 | xa_lock_irq(xa); | 854 | xa_lock_irq(xa); |
833 | err = __xa_alloc(xa, id, max, entry, gfp); | 855 | err = __xa_alloc(xa, id, entry, limit, gfp); |
834 | xa_unlock_irq(xa); | 856 | xa_unlock_irq(xa); |
835 | 857 | ||
836 | return err; | 858 | return err; |