aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/idr.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/idr.h')
-rw-r--r--include/linux/idr.h210
1 files changed, 143 insertions, 67 deletions
diff --git a/include/linux/idr.h b/include/linux/idr.h
index de7e190f1af4..2640c7e99e51 100644
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -17,69 +17,40 @@
17#include <linux/init.h> 17#include <linux/init.h>
18#include <linux/rcupdate.h> 18#include <linux/rcupdate.h>
19 19
20#if BITS_PER_LONG == 32 20/*
21# define IDR_BITS 5 21 * We want shallower trees and thus more bits covered at each layer. 8
22# define IDR_FULL 0xfffffffful 22 * bits gives us large enough first layer for most use cases and maximum
23/* We can only use two of the bits in the top level because there is 23 * tree depth of 4. Each idr_layer is slightly larger than 2k on 64bit and
24 only one possible bit in the top level (5 bits * 7 levels = 35 24 * 1k on 32bit.
25 bits, but you only use 31 bits in the id). */ 25 */
26# define TOP_LEVEL_FULL (IDR_FULL >> 30) 26#define IDR_BITS 8
27#elif BITS_PER_LONG == 64
28# define IDR_BITS 6
29# define IDR_FULL 0xfffffffffffffffful
30/* We can only use two of the bits in the top level because there is
31 only one possible bit in the top level (6 bits * 6 levels = 36
32 bits, but you only use 31 bits in the id). */
33# define TOP_LEVEL_FULL (IDR_FULL >> 62)
34#else
35# error "BITS_PER_LONG is not 32 or 64"
36#endif
37
38#define IDR_SIZE (1 << IDR_BITS) 27#define IDR_SIZE (1 << IDR_BITS)
39#define IDR_MASK ((1 << IDR_BITS)-1) 28#define IDR_MASK ((1 << IDR_BITS)-1)
40 29
41#define MAX_IDR_SHIFT (sizeof(int)*8 - 1)
42#define MAX_IDR_BIT (1U << MAX_IDR_SHIFT)
43#define MAX_IDR_MASK (MAX_IDR_BIT - 1)
44
45/* Leave the possibility of an incomplete final layer */
46#define MAX_IDR_LEVEL ((MAX_IDR_SHIFT + IDR_BITS - 1) / IDR_BITS)
47
48/* Number of id_layer structs to leave in free list */
49#define MAX_IDR_FREE (MAX_IDR_LEVEL * 2)
50
51struct idr_layer { 30struct idr_layer {
52 unsigned long bitmap; /* A zero bit means "space here" */ 31 int prefix; /* the ID prefix of this idr_layer */
32 DECLARE_BITMAP(bitmap, IDR_SIZE); /* A zero bit means "space here" */
53 struct idr_layer __rcu *ary[1<<IDR_BITS]; 33 struct idr_layer __rcu *ary[1<<IDR_BITS];
54 int count; /* When zero, we can release it */ 34 int count; /* When zero, we can release it */
55 int layer; /* distance from leaf */ 35 int layer; /* distance from leaf */
56 struct rcu_head rcu_head; 36 struct rcu_head rcu_head;
57}; 37};
58 38
59struct idr { 39struct idr {
60 struct idr_layer __rcu *top; 40 struct idr_layer __rcu *hint; /* the last layer allocated from */
61 struct idr_layer *id_free; 41 struct idr_layer __rcu *top;
62 int layers; /* only valid without concurrent changes */ 42 struct idr_layer *id_free;
63 int id_free_cnt; 43 int layers; /* only valid w/o concurrent changes */
64 spinlock_t lock; 44 int id_free_cnt;
45 spinlock_t lock;
65}; 46};
66 47
67#define IDR_INIT(name) \ 48#define IDR_INIT(name) \
68{ \ 49{ \
69 .top = NULL, \ 50 .lock = __SPIN_LOCK_UNLOCKED(name.lock), \
70 .id_free = NULL, \
71 .layers = 0, \
72 .id_free_cnt = 0, \
73 .lock = __SPIN_LOCK_UNLOCKED(name.lock), \
74} 51}
75#define DEFINE_IDR(name) struct idr name = IDR_INIT(name) 52#define DEFINE_IDR(name) struct idr name = IDR_INIT(name)
76 53
77/* Actions to be taken after a call to _idr_sub_alloc */
78#define IDR_NEED_TO_GROW -2
79#define IDR_NOMORE_SPACE -3
80
81#define _idr_rc_to_errno(rc) ((rc) == -1 ? -EAGAIN : -ENOSPC)
82
83/** 54/**
84 * DOC: idr sync 55 * DOC: idr sync
85 * idr synchronization (stolen from radix-tree.h) 56 * idr synchronization (stolen from radix-tree.h)
@@ -101,19 +72,124 @@ struct idr {
101 * This is what we export. 72 * This is what we export.
102 */ 73 */
103 74
104void *idr_find(struct idr *idp, int id); 75void *idr_find_slowpath(struct idr *idp, int id);
105int idr_pre_get(struct idr *idp, gfp_t gfp_mask); 76void idr_preload(gfp_t gfp_mask);
106int idr_get_new(struct idr *idp, void *ptr, int *id); 77int idr_alloc(struct idr *idp, void *ptr, int start, int end, gfp_t gfp_mask);
107int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id);
108int idr_for_each(struct idr *idp, 78int idr_for_each(struct idr *idp,
109 int (*fn)(int id, void *p, void *data), void *data); 79 int (*fn)(int id, void *p, void *data), void *data);
110void *idr_get_next(struct idr *idp, int *nextid); 80void *idr_get_next(struct idr *idp, int *nextid);
111void *idr_replace(struct idr *idp, void *ptr, int id); 81void *idr_replace(struct idr *idp, void *ptr, int id);
112void idr_remove(struct idr *idp, int id); 82void idr_remove(struct idr *idp, int id);
113void idr_remove_all(struct idr *idp); 83void idr_free(struct idr *idp, int id);
114void idr_destroy(struct idr *idp); 84void idr_destroy(struct idr *idp);
115void idr_init(struct idr *idp); 85void idr_init(struct idr *idp);
116 86
87/**
88 * idr_preload_end - end preload section started with idr_preload()
89 *
90 * Each idr_preload() should be matched with an invocation of this
91 * function. See idr_preload() for details.
92 */
93static inline void idr_preload_end(void)
94{
95 preempt_enable();
96}
97
98/**
99 * idr_find - return pointer for given id
100 * @idr: idr handle
101 * @id: lookup key
102 *
103 * Return the pointer given the id it has been registered with. A %NULL
104 * return indicates that @id is not valid or you passed %NULL in
105 * idr_get_new().
106 *
107 * This function can be called under rcu_read_lock(), given that the leaf
108 * pointers lifetimes are correctly managed.
109 */
110static inline void *idr_find(struct idr *idr, int id)
111{
112 struct idr_layer *hint = rcu_dereference_raw(idr->hint);
113
114 if (hint && (id & ~IDR_MASK) == hint->prefix)
115 return rcu_dereference_raw(hint->ary[id & IDR_MASK]);
116
117 return idr_find_slowpath(idr, id);
118}
119
120/**
121 * idr_for_each_entry - iterate over an idr's elements of a given type
122 * @idp: idr handle
123 * @entry: the type * to use as cursor
124 * @id: id entry's key
125 */
126#define idr_for_each_entry(idp, entry, id) \
127 for (id = 0, entry = (typeof(entry))idr_get_next((idp), &(id)); \
128 entry != NULL; \
129 ++id, entry = (typeof(entry))idr_get_next((idp), &(id)))
130
131/*
132 * Don't use the following functions. These exist only to suppress
133 * deprecated warnings on EXPORT_SYMBOL()s.
134 */
135int __idr_pre_get(struct idr *idp, gfp_t gfp_mask);
136int __idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id);
137void __idr_remove_all(struct idr *idp);
138
139/**
140 * idr_pre_get - reserve resources for idr allocation
141 * @idp: idr handle
142 * @gfp_mask: memory allocation flags
143 *
144 * Part of old alloc interface. This is going away. Use
145 * idr_preload[_end]() and idr_alloc() instead.
146 */
147static inline int __deprecated idr_pre_get(struct idr *idp, gfp_t gfp_mask)
148{
149 return __idr_pre_get(idp, gfp_mask);
150}
151
152/**
153 * idr_get_new_above - allocate new idr entry above or equal to a start id
154 * @idp: idr handle
155 * @ptr: pointer you want associated with the id
156 * @starting_id: id to start search at
157 * @id: pointer to the allocated handle
158 *
159 * Part of old alloc interface. This is going away. Use
160 * idr_preload[_end]() and idr_alloc() instead.
161 */
162static inline int __deprecated idr_get_new_above(struct idr *idp, void *ptr,
163 int starting_id, int *id)
164{
165 return __idr_get_new_above(idp, ptr, starting_id, id);
166}
167
168/**
169 * idr_get_new - allocate new idr entry
170 * @idp: idr handle
171 * @ptr: pointer you want associated with the id
172 * @id: pointer to the allocated handle
173 *
174 * Part of old alloc interface. This is going away. Use
175 * idr_preload[_end]() and idr_alloc() instead.
176 */
177static inline int __deprecated idr_get_new(struct idr *idp, void *ptr, int *id)
178{
179 return __idr_get_new_above(idp, ptr, 0, id);
180}
181
182/**
183 * idr_remove_all - remove all ids from the given idr tree
184 * @idp: idr handle
185 *
186 * If you're trying to destroy @idp, calling idr_destroy() is enough.
187 * This is going away. Don't use.
188 */
189static inline void __deprecated idr_remove_all(struct idr *idp)
190{
191 __idr_remove_all(idp);
192}
117 193
118/* 194/*
119 * IDA - IDR based id allocator, use when translation from id to 195 * IDA - IDR based id allocator, use when translation from id to
@@ -136,12 +212,11 @@ struct ida {
136 struct ida_bitmap *free_bitmap; 212 struct ida_bitmap *free_bitmap;
137}; 213};
138 214
139#define IDA_INIT(name) { .idr = IDR_INIT(name), .free_bitmap = NULL, } 215#define IDA_INIT(name) { .idr = IDR_INIT((name).idr), .free_bitmap = NULL, }
140#define DEFINE_IDA(name) struct ida name = IDA_INIT(name) 216#define DEFINE_IDA(name) struct ida name = IDA_INIT(name)
141 217
142int ida_pre_get(struct ida *ida, gfp_t gfp_mask); 218int ida_pre_get(struct ida *ida, gfp_t gfp_mask);
143int ida_get_new_above(struct ida *ida, int starting_id, int *p_id); 219int ida_get_new_above(struct ida *ida, int starting_id, int *p_id);
144int ida_get_new(struct ida *ida, int *p_id);
145void ida_remove(struct ida *ida, int id); 220void ida_remove(struct ida *ida, int id);
146void ida_destroy(struct ida *ida); 221void ida_destroy(struct ida *ida);
147void ida_init(struct ida *ida); 222void ida_init(struct ida *ida);
@@ -150,17 +225,18 @@ int ida_simple_get(struct ida *ida, unsigned int start, unsigned int end,
150 gfp_t gfp_mask); 225 gfp_t gfp_mask);
151void ida_simple_remove(struct ida *ida, unsigned int id); 226void ida_simple_remove(struct ida *ida, unsigned int id);
152 227
153void __init idr_init_cache(void);
154
155/** 228/**
156 * idr_for_each_entry - iterate over an idr's elements of a given type 229 * ida_get_new - allocate new ID
157 * @idp: idr handle 230 * @ida: idr handle
158 * @entry: the type * to use as cursor 231 * @p_id: pointer to the allocated handle
159 * @id: id entry's key 232 *
233 * Simple wrapper around ida_get_new_above() w/ @starting_id of zero.
160 */ 234 */
161#define idr_for_each_entry(idp, entry, id) \ 235static inline int ida_get_new(struct ida *ida, int *p_id)
162 for (id = 0, entry = (typeof(entry))idr_get_next((idp), &(id)); \ 236{
163 entry != NULL; \ 237 return ida_get_new_above(ida, 0, p_id);
164 ++id, entry = (typeof(entry))idr_get_next((idp), &(id))) 238}
239
240void __init idr_init_cache(void);
165 241
166#endif /* __IDR_H__ */ 242#endif /* __IDR_H__ */