diff options
Diffstat (limited to 'fs/btrfs/ulist.c')
-rw-r--r-- | fs/btrfs/ulist.c | 60 |
1 files changed, 51 insertions, 9 deletions
diff --git a/fs/btrfs/ulist.c b/fs/btrfs/ulist.c index 99be4c138db6..7b417e20efe2 100644 --- a/fs/btrfs/ulist.c +++ b/fs/btrfs/ulist.c | |||
@@ -5,7 +5,7 @@ | |||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/slab.h> | 7 | #include <linux/slab.h> |
8 | #include <linux/module.h> | 8 | #include <linux/export.h> |
9 | #include "ulist.h" | 9 | #include "ulist.h" |
10 | 10 | ||
11 | /* | 11 | /* |
@@ -53,6 +53,7 @@ void ulist_init(struct ulist *ulist) | |||
53 | ulist->nnodes = 0; | 53 | ulist->nnodes = 0; |
54 | ulist->nodes = ulist->int_nodes; | 54 | ulist->nodes = ulist->int_nodes; |
55 | ulist->nodes_alloced = ULIST_SIZE; | 55 | ulist->nodes_alloced = ULIST_SIZE; |
56 | ulist->root = RB_ROOT; | ||
56 | } | 57 | } |
57 | EXPORT_SYMBOL(ulist_init); | 58 | EXPORT_SYMBOL(ulist_init); |
58 | 59 | ||
@@ -72,6 +73,7 @@ void ulist_fini(struct ulist *ulist) | |||
72 | if (ulist->nodes_alloced > ULIST_SIZE) | 73 | if (ulist->nodes_alloced > ULIST_SIZE) |
73 | kfree(ulist->nodes); | 74 | kfree(ulist->nodes); |
74 | ulist->nodes_alloced = 0; /* in case ulist_fini is called twice */ | 75 | ulist->nodes_alloced = 0; /* in case ulist_fini is called twice */ |
76 | ulist->root = RB_ROOT; | ||
75 | } | 77 | } |
76 | EXPORT_SYMBOL(ulist_fini); | 78 | EXPORT_SYMBOL(ulist_fini); |
77 | 79 | ||
@@ -123,6 +125,45 @@ void ulist_free(struct ulist *ulist) | |||
123 | } | 125 | } |
124 | EXPORT_SYMBOL(ulist_free); | 126 | EXPORT_SYMBOL(ulist_free); |
125 | 127 | ||
128 | static struct ulist_node *ulist_rbtree_search(struct ulist *ulist, u64 val) | ||
129 | { | ||
130 | struct rb_node *n = ulist->root.rb_node; | ||
131 | struct ulist_node *u = NULL; | ||
132 | |||
133 | while (n) { | ||
134 | u = rb_entry(n, struct ulist_node, rb_node); | ||
135 | if (u->val < val) | ||
136 | n = n->rb_right; | ||
137 | else if (u->val > val) | ||
138 | n = n->rb_left; | ||
139 | else | ||
140 | return u; | ||
141 | } | ||
142 | return NULL; | ||
143 | } | ||
144 | |||
145 | static int ulist_rbtree_insert(struct ulist *ulist, struct ulist_node *ins) | ||
146 | { | ||
147 | struct rb_node **p = &ulist->root.rb_node; | ||
148 | struct rb_node *parent = NULL; | ||
149 | struct ulist_node *cur = NULL; | ||
150 | |||
151 | while (*p) { | ||
152 | parent = *p; | ||
153 | cur = rb_entry(parent, struct ulist_node, rb_node); | ||
154 | |||
155 | if (cur->val < ins->val) | ||
156 | p = &(*p)->rb_right; | ||
157 | else if (cur->val > ins->val) | ||
158 | p = &(*p)->rb_left; | ||
159 | else | ||
160 | return -EEXIST; | ||
161 | } | ||
162 | rb_link_node(&ins->rb_node, parent, p); | ||
163 | rb_insert_color(&ins->rb_node, &ulist->root); | ||
164 | return 0; | ||
165 | } | ||
166 | |||
126 | /** | 167 | /** |
127 | * ulist_add - add an element to the ulist | 168 | * ulist_add - add an element to the ulist |
128 | * @ulist: ulist to add the element to | 169 | * @ulist: ulist to add the element to |
@@ -151,14 +192,13 @@ int ulist_add(struct ulist *ulist, u64 val, u64 aux, gfp_t gfp_mask) | |||
151 | int ulist_add_merge(struct ulist *ulist, u64 val, u64 aux, | 192 | int ulist_add_merge(struct ulist *ulist, u64 val, u64 aux, |
152 | u64 *old_aux, gfp_t gfp_mask) | 193 | u64 *old_aux, gfp_t gfp_mask) |
153 | { | 194 | { |
154 | int i; | 195 | int ret = 0; |
155 | 196 | struct ulist_node *node = NULL; | |
156 | for (i = 0; i < ulist->nnodes; ++i) { | 197 | node = ulist_rbtree_search(ulist, val); |
157 | if (ulist->nodes[i].val == val) { | 198 | if (node) { |
158 | if (old_aux) | 199 | if (old_aux) |
159 | *old_aux = ulist->nodes[i].aux; | 200 | *old_aux = node->aux; |
160 | return 0; | 201 | return 0; |
161 | } | ||
162 | } | 202 | } |
163 | 203 | ||
164 | if (ulist->nnodes >= ulist->nodes_alloced) { | 204 | if (ulist->nnodes >= ulist->nodes_alloced) { |
@@ -187,6 +227,8 @@ int ulist_add_merge(struct ulist *ulist, u64 val, u64 aux, | |||
187 | } | 227 | } |
188 | ulist->nodes[ulist->nnodes].val = val; | 228 | ulist->nodes[ulist->nnodes].val = val; |
189 | ulist->nodes[ulist->nnodes].aux = aux; | 229 | ulist->nodes[ulist->nnodes].aux = aux; |
230 | ret = ulist_rbtree_insert(ulist, &ulist->nodes[ulist->nnodes]); | ||
231 | BUG_ON(ret); | ||
190 | ++ulist->nnodes; | 232 | ++ulist->nnodes; |
191 | 233 | ||
192 | return 1; | 234 | return 1; |