diff options
| author | Rusty Russell <rusty@rustcorp.com.au> | 2011-08-03 19:21:06 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-08-03 20:25:20 -0400 |
| commit | 88eca0207cf1574328c3ce8c3be537a9317261bb (patch) | |
| tree | 155b13f5df1e239fea2ad5512ef5b19865de4a9e /lib | |
| parent | a7295898a1d2e501427f557111c2b4bdfc90b1ed (diff) | |
ida: simplified functions for id allocation
The current hyper-optimized functions are overkill if you simply want to
allocate an id for a device. Create versions which use an internal
lock.
In followup patches, numerous drivers are converted to use this
interface.
Thanks to Tejun for feedback.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Acked-by: Tejun Heo <tj@kernel.org>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/idr.c | 67 |
1 files changed, 67 insertions, 0 deletions
| @@ -34,8 +34,10 @@ | |||
| 34 | #include <linux/err.h> | 34 | #include <linux/err.h> |
| 35 | #include <linux/string.h> | 35 | #include <linux/string.h> |
| 36 | #include <linux/idr.h> | 36 | #include <linux/idr.h> |
| 37 | #include <linux/spinlock.h> | ||
| 37 | 38 | ||
| 38 | static struct kmem_cache *idr_layer_cache; | 39 | static struct kmem_cache *idr_layer_cache; |
| 40 | static DEFINE_SPINLOCK(simple_ida_lock); | ||
| 39 | 41 | ||
| 40 | static struct idr_layer *get_from_free_list(struct idr *idp) | 42 | static struct idr_layer *get_from_free_list(struct idr *idp) |
| 41 | { | 43 | { |
| @@ -926,6 +928,71 @@ void ida_destroy(struct ida *ida) | |||
| 926 | EXPORT_SYMBOL(ida_destroy); | 928 | EXPORT_SYMBOL(ida_destroy); |
| 927 | 929 | ||
| 928 | /** | 930 | /** |
| 931 | * ida_simple_get - get a new id. | ||
| 932 | * @ida: the (initialized) ida. | ||
| 933 | * @start: the minimum id (inclusive, < 0x8000000) | ||
| 934 | * @end: the maximum id (exclusive, < 0x8000000 or 0) | ||
| 935 | * @gfp_mask: memory allocation flags | ||
| 936 | * | ||
| 937 | * Allocates an id in the range start <= id < end, or returns -ENOSPC. | ||
| 938 | * On memory allocation failure, returns -ENOMEM. | ||
| 939 | * | ||
| 940 | * Use ida_simple_remove() to get rid of an id. | ||
| 941 | */ | ||
| 942 | int ida_simple_get(struct ida *ida, unsigned int start, unsigned int end, | ||
| 943 | gfp_t gfp_mask) | ||
| 944 | { | ||
| 945 | int ret, id; | ||
| 946 | unsigned int max; | ||
| 947 | |||
| 948 | BUG_ON((int)start < 0); | ||
| 949 | BUG_ON((int)end < 0); | ||
| 950 | |||
| 951 | if (end == 0) | ||
| 952 | max = 0x80000000; | ||
| 953 | else { | ||
| 954 | BUG_ON(end < start); | ||
| 955 | max = end - 1; | ||
| 956 | } | ||
| 957 | |||
| 958 | again: | ||
| 959 | if (!ida_pre_get(ida, gfp_mask)) | ||
| 960 | return -ENOMEM; | ||
| 961 | |||
| 962 | spin_lock(&simple_ida_lock); | ||
| 963 | ret = ida_get_new_above(ida, start, &id); | ||
| 964 | if (!ret) { | ||
| 965 | if (id > max) { | ||
| 966 | ida_remove(ida, id); | ||
| 967 | ret = -ENOSPC; | ||
| 968 | } else { | ||
| 969 | ret = id; | ||
| 970 | } | ||
| 971 | } | ||
| 972 | spin_unlock(&simple_ida_lock); | ||
| 973 | |||
| 974 | if (unlikely(ret == -EAGAIN)) | ||
| 975 | goto again; | ||
| 976 | |||
| 977 | return ret; | ||
| 978 | } | ||
| 979 | EXPORT_SYMBOL(ida_simple_get); | ||
| 980 | |||
| 981 | /** | ||
| 982 | * ida_simple_remove - remove an allocated id. | ||
| 983 | * @ida: the (initialized) ida. | ||
| 984 | * @id: the id returned by ida_simple_get. | ||
| 985 | */ | ||
| 986 | void ida_simple_remove(struct ida *ida, unsigned int id) | ||
| 987 | { | ||
| 988 | BUG_ON((int)id < 0); | ||
| 989 | spin_lock(&simple_ida_lock); | ||
| 990 | ida_remove(ida, id); | ||
| 991 | spin_unlock(&simple_ida_lock); | ||
| 992 | } | ||
| 993 | EXPORT_SYMBOL(ida_simple_remove); | ||
| 994 | |||
| 995 | /** | ||
| 929 | * ida_init - initialize ida handle | 996 | * ida_init - initialize ida handle |
| 930 | * @ida: ida handle | 997 | * @ida: ida handle |
| 931 | * | 998 | * |
