1
2
3
4
5
6
7#include <linux/slab.h>
8#include "ulist.h"
9#include "ctree.h"
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47void ulist_init(struct ulist *ulist)
48{
49 INIT_LIST_HEAD(&ulist->nodes);
50 ulist->root = RB_ROOT;
51 ulist->nnodes = 0;
52}
53
54
55
56
57
58
59
60
61void ulist_release(struct ulist *ulist)
62{
63 struct ulist_node *node;
64 struct ulist_node *next;
65
66 list_for_each_entry_safe(node, next, &ulist->nodes, list) {
67 kfree(node);
68 }
69 ulist->root = RB_ROOT;
70 INIT_LIST_HEAD(&ulist->nodes);
71}
72
73
74
75
76
77
78
79
80void ulist_reinit(struct ulist *ulist)
81{
82 ulist_release(ulist);
83 ulist_init(ulist);
84}
85
86
87
88
89
90
91
92struct ulist *ulist_alloc(gfp_t gfp_mask)
93{
94 struct ulist *ulist = kmalloc(sizeof(*ulist), gfp_mask);
95
96 if (!ulist)
97 return NULL;
98
99 ulist_init(ulist);
100
101 return ulist;
102}
103
104
105
106
107
108
109
110void ulist_free(struct ulist *ulist)
111{
112 if (!ulist)
113 return;
114 ulist_release(ulist);
115 kfree(ulist);
116}
117
118static struct ulist_node *ulist_rbtree_search(struct ulist *ulist, u64 val)
119{
120 struct rb_node *n = ulist->root.rb_node;
121 struct ulist_node *u = NULL;
122
123 while (n) {
124 u = rb_entry(n, struct ulist_node, rb_node);
125 if (u->val < val)
126 n = n->rb_right;
127 else if (u->val > val)
128 n = n->rb_left;
129 else
130 return u;
131 }
132 return NULL;
133}
134
135static void ulist_rbtree_erase(struct ulist *ulist, struct ulist_node *node)
136{
137 rb_erase(&node->rb_node, &ulist->root);
138 list_del(&node->list);
139 kfree(node);
140 BUG_ON(ulist->nnodes == 0);
141 ulist->nnodes--;
142}
143
144static int ulist_rbtree_insert(struct ulist *ulist, struct ulist_node *ins)
145{
146 struct rb_node **p = &ulist->root.rb_node;
147 struct rb_node *parent = NULL;
148 struct ulist_node *cur = NULL;
149
150 while (*p) {
151 parent = *p;
152 cur = rb_entry(parent, struct ulist_node, rb_node);
153
154 if (cur->val < ins->val)
155 p = &(*p)->rb_right;
156 else if (cur->val > ins->val)
157 p = &(*p)->rb_left;
158 else
159 return -EEXIST;
160 }
161 rb_link_node(&ins->rb_node, parent, p);
162 rb_insert_color(&ins->rb_node, &ulist->root);
163 return 0;
164}
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186int ulist_add(struct ulist *ulist, u64 val, u64 aux, gfp_t gfp_mask)
187{
188 return ulist_add_merge(ulist, val, aux, NULL, gfp_mask);
189}
190
191int ulist_add_merge(struct ulist *ulist, u64 val, u64 aux,
192 u64 *old_aux, gfp_t gfp_mask)
193{
194 int ret;
195 struct ulist_node *node;
196
197 node = ulist_rbtree_search(ulist, val);
198 if (node) {
199 if (old_aux)
200 *old_aux = node->aux;
201 return 0;
202 }
203 node = kmalloc(sizeof(*node), gfp_mask);
204 if (!node)
205 return -ENOMEM;
206
207 node->val = val;
208 node->aux = aux;
209
210 ret = ulist_rbtree_insert(ulist, node);
211 ASSERT(!ret);
212 list_add_tail(&node->list, &ulist->nodes);
213 ulist->nnodes++;
214
215 return 1;
216}
217
218
219
220
221
222
223
224
225
226
227
228int ulist_del(struct ulist *ulist, u64 val, u64 aux)
229{
230 struct ulist_node *node;
231
232 node = ulist_rbtree_search(ulist, val);
233
234 if (!node)
235 return 1;
236
237 if (node->aux != aux)
238 return 1;
239
240
241 ulist_rbtree_erase(ulist, node);
242 return 0;
243}
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261struct ulist_node *ulist_next(struct ulist *ulist, struct ulist_iterator *uiter)
262{
263 struct ulist_node *node;
264
265 if (list_empty(&ulist->nodes))
266 return NULL;
267 if (uiter->cur_list && uiter->cur_list->next == &ulist->nodes)
268 return NULL;
269 if (uiter->cur_list) {
270 uiter->cur_list = uiter->cur_list->next;
271 } else {
272 uiter->cur_list = ulist->nodes.next;
273 }
274 node = list_entry(uiter->cur_list, struct ulist_node, list);
275 return node;
276}
277