0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 #include <linux/btree.h>
0041 #include <linux/cache.h>
0042 #include <linux/kernel.h>
0043 #include <linux/slab.h>
0044 #include <linux/module.h>
0045
0046 #define MAX(a, b) ((a) > (b) ? (a) : (b))
0047 #define NODESIZE MAX(L1_CACHE_BYTES, 128)
0048
0049 struct btree_geo {
0050 int keylen;
0051 int no_pairs;
0052 int no_longs;
0053 };
0054
0055 struct btree_geo btree_geo32 = {
0056 .keylen = 1,
0057 .no_pairs = NODESIZE / sizeof(long) / 2,
0058 .no_longs = NODESIZE / sizeof(long) / 2,
0059 };
0060 EXPORT_SYMBOL_GPL(btree_geo32);
0061
0062 #define LONG_PER_U64 (64 / BITS_PER_LONG)
0063 struct btree_geo btree_geo64 = {
0064 .keylen = LONG_PER_U64,
0065 .no_pairs = NODESIZE / sizeof(long) / (1 + LONG_PER_U64),
0066 .no_longs = LONG_PER_U64 * (NODESIZE / sizeof(long) / (1 + LONG_PER_U64)),
0067 };
0068 EXPORT_SYMBOL_GPL(btree_geo64);
0069
0070 struct btree_geo btree_geo128 = {
0071 .keylen = 2 * LONG_PER_U64,
0072 .no_pairs = NODESIZE / sizeof(long) / (1 + 2 * LONG_PER_U64),
0073 .no_longs = 2 * LONG_PER_U64 * (NODESIZE / sizeof(long) / (1 + 2 * LONG_PER_U64)),
0074 };
0075 EXPORT_SYMBOL_GPL(btree_geo128);
0076
0077 #define MAX_KEYLEN (2 * LONG_PER_U64)
0078
0079 static struct kmem_cache *btree_cachep;
0080
0081 void *btree_alloc(gfp_t gfp_mask, void *pool_data)
0082 {
0083 return kmem_cache_alloc(btree_cachep, gfp_mask);
0084 }
0085 EXPORT_SYMBOL_GPL(btree_alloc);
0086
0087 void btree_free(void *element, void *pool_data)
0088 {
0089 kmem_cache_free(btree_cachep, element);
0090 }
0091 EXPORT_SYMBOL_GPL(btree_free);
0092
0093 static unsigned long *btree_node_alloc(struct btree_head *head, gfp_t gfp)
0094 {
0095 unsigned long *node;
0096
0097 node = mempool_alloc(head->mempool, gfp);
0098 if (likely(node))
0099 memset(node, 0, NODESIZE);
0100 return node;
0101 }
0102
0103 static int longcmp(const unsigned long *l1, const unsigned long *l2, size_t n)
0104 {
0105 size_t i;
0106
0107 for (i = 0; i < n; i++) {
0108 if (l1[i] < l2[i])
0109 return -1;
0110 if (l1[i] > l2[i])
0111 return 1;
0112 }
0113 return 0;
0114 }
0115
0116 static unsigned long *longcpy(unsigned long *dest, const unsigned long *src,
0117 size_t n)
0118 {
0119 size_t i;
0120
0121 for (i = 0; i < n; i++)
0122 dest[i] = src[i];
0123 return dest;
0124 }
0125
0126 static unsigned long *longset(unsigned long *s, unsigned long c, size_t n)
0127 {
0128 size_t i;
0129
0130 for (i = 0; i < n; i++)
0131 s[i] = c;
0132 return s;
0133 }
0134
0135 static void dec_key(struct btree_geo *geo, unsigned long *key)
0136 {
0137 unsigned long val;
0138 int i;
0139
0140 for (i = geo->keylen - 1; i >= 0; i--) {
0141 val = key[i];
0142 key[i] = val - 1;
0143 if (val)
0144 break;
0145 }
0146 }
0147
0148 static unsigned long *bkey(struct btree_geo *geo, unsigned long *node, int n)
0149 {
0150 return &node[n * geo->keylen];
0151 }
0152
0153 static void *bval(struct btree_geo *geo, unsigned long *node, int n)
0154 {
0155 return (void *)node[geo->no_longs + n];
0156 }
0157
0158 static void setkey(struct btree_geo *geo, unsigned long *node, int n,
0159 unsigned long *key)
0160 {
0161 longcpy(bkey(geo, node, n), key, geo->keylen);
0162 }
0163
0164 static void setval(struct btree_geo *geo, unsigned long *node, int n,
0165 void *val)
0166 {
0167 node[geo->no_longs + n] = (unsigned long) val;
0168 }
0169
0170 static void clearpair(struct btree_geo *geo, unsigned long *node, int n)
0171 {
0172 longset(bkey(geo, node, n), 0, geo->keylen);
0173 node[geo->no_longs + n] = 0;
0174 }
0175
0176 static inline void __btree_init(struct btree_head *head)
0177 {
0178 head->node = NULL;
0179 head->height = 0;
0180 }
0181
0182 void btree_init_mempool(struct btree_head *head, mempool_t *mempool)
0183 {
0184 __btree_init(head);
0185 head->mempool = mempool;
0186 }
0187 EXPORT_SYMBOL_GPL(btree_init_mempool);
0188
0189 int btree_init(struct btree_head *head)
0190 {
0191 __btree_init(head);
0192 head->mempool = mempool_create(0, btree_alloc, btree_free, NULL);
0193 if (!head->mempool)
0194 return -ENOMEM;
0195 return 0;
0196 }
0197 EXPORT_SYMBOL_GPL(btree_init);
0198
0199 void btree_destroy(struct btree_head *head)
0200 {
0201 mempool_free(head->node, head->mempool);
0202 mempool_destroy(head->mempool);
0203 head->mempool = NULL;
0204 }
0205 EXPORT_SYMBOL_GPL(btree_destroy);
0206
0207 void *btree_last(struct btree_head *head, struct btree_geo *geo,
0208 unsigned long *key)
0209 {
0210 int height = head->height;
0211 unsigned long *node = head->node;
0212
0213 if (height == 0)
0214 return NULL;
0215
0216 for ( ; height > 1; height--)
0217 node = bval(geo, node, 0);
0218
0219 longcpy(key, bkey(geo, node, 0), geo->keylen);
0220 return bval(geo, node, 0);
0221 }
0222 EXPORT_SYMBOL_GPL(btree_last);
0223
0224 static int keycmp(struct btree_geo *geo, unsigned long *node, int pos,
0225 unsigned long *key)
0226 {
0227 return longcmp(bkey(geo, node, pos), key, geo->keylen);
0228 }
0229
0230 static int keyzero(struct btree_geo *geo, unsigned long *key)
0231 {
0232 int i;
0233
0234 for (i = 0; i < geo->keylen; i++)
0235 if (key[i])
0236 return 0;
0237
0238 return 1;
0239 }
0240
0241 static void *btree_lookup_node(struct btree_head *head, struct btree_geo *geo,
0242 unsigned long *key)
0243 {
0244 int i, height = head->height;
0245 unsigned long *node = head->node;
0246
0247 if (height == 0)
0248 return NULL;
0249
0250 for ( ; height > 1; height--) {
0251 for (i = 0; i < geo->no_pairs; i++)
0252 if (keycmp(geo, node, i, key) <= 0)
0253 break;
0254 if (i == geo->no_pairs)
0255 return NULL;
0256 node = bval(geo, node, i);
0257 if (!node)
0258 return NULL;
0259 }
0260 return node;
0261 }
0262
0263 void *btree_lookup(struct btree_head *head, struct btree_geo *geo,
0264 unsigned long *key)
0265 {
0266 int i;
0267 unsigned long *node;
0268
0269 node = btree_lookup_node(head, geo, key);
0270 if (!node)
0271 return NULL;
0272
0273 for (i = 0; i < geo->no_pairs; i++)
0274 if (keycmp(geo, node, i, key) == 0)
0275 return bval(geo, node, i);
0276 return NULL;
0277 }
0278 EXPORT_SYMBOL_GPL(btree_lookup);
0279
0280 int btree_update(struct btree_head *head, struct btree_geo *geo,
0281 unsigned long *key, void *val)
0282 {
0283 int i;
0284 unsigned long *node;
0285
0286 node = btree_lookup_node(head, geo, key);
0287 if (!node)
0288 return -ENOENT;
0289
0290 for (i = 0; i < geo->no_pairs; i++)
0291 if (keycmp(geo, node, i, key) == 0) {
0292 setval(geo, node, i, val);
0293 return 0;
0294 }
0295 return -ENOENT;
0296 }
0297 EXPORT_SYMBOL_GPL(btree_update);
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307 void *btree_get_prev(struct btree_head *head, struct btree_geo *geo,
0308 unsigned long *__key)
0309 {
0310 int i, height;
0311 unsigned long *node, *oldnode;
0312 unsigned long *retry_key = NULL, key[MAX_KEYLEN];
0313
0314 if (keyzero(geo, __key))
0315 return NULL;
0316
0317 if (head->height == 0)
0318 return NULL;
0319 longcpy(key, __key, geo->keylen);
0320 retry:
0321 dec_key(geo, key);
0322
0323 node = head->node;
0324 for (height = head->height ; height > 1; height--) {
0325 for (i = 0; i < geo->no_pairs; i++)
0326 if (keycmp(geo, node, i, key) <= 0)
0327 break;
0328 if (i == geo->no_pairs)
0329 goto miss;
0330 oldnode = node;
0331 node = bval(geo, node, i);
0332 if (!node)
0333 goto miss;
0334 retry_key = bkey(geo, oldnode, i);
0335 }
0336
0337 if (!node)
0338 goto miss;
0339
0340 for (i = 0; i < geo->no_pairs; i++) {
0341 if (keycmp(geo, node, i, key) <= 0) {
0342 if (bval(geo, node, i)) {
0343 longcpy(__key, bkey(geo, node, i), geo->keylen);
0344 return bval(geo, node, i);
0345 } else
0346 goto miss;
0347 }
0348 }
0349 miss:
0350 if (retry_key) {
0351 longcpy(key, retry_key, geo->keylen);
0352 retry_key = NULL;
0353 goto retry;
0354 }
0355 return NULL;
0356 }
0357 EXPORT_SYMBOL_GPL(btree_get_prev);
0358
0359 static int getpos(struct btree_geo *geo, unsigned long *node,
0360 unsigned long *key)
0361 {
0362 int i;
0363
0364 for (i = 0; i < geo->no_pairs; i++) {
0365 if (keycmp(geo, node, i, key) <= 0)
0366 break;
0367 }
0368 return i;
0369 }
0370
0371 static int getfill(struct btree_geo *geo, unsigned long *node, int start)
0372 {
0373 int i;
0374
0375 for (i = start; i < geo->no_pairs; i++)
0376 if (!bval(geo, node, i))
0377 break;
0378 return i;
0379 }
0380
0381
0382
0383
0384 static unsigned long *find_level(struct btree_head *head, struct btree_geo *geo,
0385 unsigned long *key, int level)
0386 {
0387 unsigned long *node = head->node;
0388 int i, height;
0389
0390 for (height = head->height; height > level; height--) {
0391 for (i = 0; i < geo->no_pairs; i++)
0392 if (keycmp(geo, node, i, key) <= 0)
0393 break;
0394
0395 if ((i == geo->no_pairs) || !bval(geo, node, i)) {
0396
0397
0398
0399 i--;
0400 setkey(geo, node, i, key);
0401 }
0402 BUG_ON(i < 0);
0403 node = bval(geo, node, i);
0404 }
0405 BUG_ON(!node);
0406 return node;
0407 }
0408
0409 static int btree_grow(struct btree_head *head, struct btree_geo *geo,
0410 gfp_t gfp)
0411 {
0412 unsigned long *node;
0413 int fill;
0414
0415 node = btree_node_alloc(head, gfp);
0416 if (!node)
0417 return -ENOMEM;
0418 if (head->node) {
0419 fill = getfill(geo, head->node, 0);
0420 setkey(geo, node, 0, bkey(geo, head->node, fill - 1));
0421 setval(geo, node, 0, head->node);
0422 }
0423 head->node = node;
0424 head->height++;
0425 return 0;
0426 }
0427
0428 static void btree_shrink(struct btree_head *head, struct btree_geo *geo)
0429 {
0430 unsigned long *node;
0431 int fill;
0432
0433 if (head->height <= 1)
0434 return;
0435
0436 node = head->node;
0437 fill = getfill(geo, node, 0);
0438 BUG_ON(fill > 1);
0439 head->node = bval(geo, node, 0);
0440 head->height--;
0441 mempool_free(node, head->mempool);
0442 }
0443
0444 static int btree_insert_level(struct btree_head *head, struct btree_geo *geo,
0445 unsigned long *key, void *val, int level,
0446 gfp_t gfp)
0447 {
0448 unsigned long *node;
0449 int i, pos, fill, err;
0450
0451 BUG_ON(!val);
0452 if (head->height < level) {
0453 err = btree_grow(head, geo, gfp);
0454 if (err)
0455 return err;
0456 }
0457
0458 retry:
0459 node = find_level(head, geo, key, level);
0460 pos = getpos(geo, node, key);
0461 fill = getfill(geo, node, pos);
0462
0463 BUG_ON(pos < fill && keycmp(geo, node, pos, key) == 0);
0464
0465 if (fill == geo->no_pairs) {
0466
0467 unsigned long *new;
0468
0469 new = btree_node_alloc(head, gfp);
0470 if (!new)
0471 return -ENOMEM;
0472 err = btree_insert_level(head, geo,
0473 bkey(geo, node, fill / 2 - 1),
0474 new, level + 1, gfp);
0475 if (err) {
0476 mempool_free(new, head->mempool);
0477 return err;
0478 }
0479 for (i = 0; i < fill / 2; i++) {
0480 setkey(geo, new, i, bkey(geo, node, i));
0481 setval(geo, new, i, bval(geo, node, i));
0482 setkey(geo, node, i, bkey(geo, node, i + fill / 2));
0483 setval(geo, node, i, bval(geo, node, i + fill / 2));
0484 clearpair(geo, node, i + fill / 2);
0485 }
0486 if (fill & 1) {
0487 setkey(geo, node, i, bkey(geo, node, fill - 1));
0488 setval(geo, node, i, bval(geo, node, fill - 1));
0489 clearpair(geo, node, fill - 1);
0490 }
0491 goto retry;
0492 }
0493 BUG_ON(fill >= geo->no_pairs);
0494
0495
0496 for (i = fill; i > pos; i--) {
0497 setkey(geo, node, i, bkey(geo, node, i - 1));
0498 setval(geo, node, i, bval(geo, node, i - 1));
0499 }
0500 setkey(geo, node, pos, key);
0501 setval(geo, node, pos, val);
0502
0503 return 0;
0504 }
0505
0506 int btree_insert(struct btree_head *head, struct btree_geo *geo,
0507 unsigned long *key, void *val, gfp_t gfp)
0508 {
0509 BUG_ON(!val);
0510 return btree_insert_level(head, geo, key, val, 1, gfp);
0511 }
0512 EXPORT_SYMBOL_GPL(btree_insert);
0513
0514 static void *btree_remove_level(struct btree_head *head, struct btree_geo *geo,
0515 unsigned long *key, int level);
0516 static void merge(struct btree_head *head, struct btree_geo *geo, int level,
0517 unsigned long *left, int lfill,
0518 unsigned long *right, int rfill,
0519 unsigned long *parent, int lpos)
0520 {
0521 int i;
0522
0523 for (i = 0; i < rfill; i++) {
0524
0525 setkey(geo, left, lfill + i, bkey(geo, right, i));
0526 setval(geo, left, lfill + i, bval(geo, right, i));
0527 }
0528
0529 setval(geo, parent, lpos, right);
0530 setval(geo, parent, lpos + 1, left);
0531
0532 btree_remove_level(head, geo, bkey(geo, parent, lpos), level + 1);
0533 mempool_free(right, head->mempool);
0534 }
0535
0536 static void rebalance(struct btree_head *head, struct btree_geo *geo,
0537 unsigned long *key, int level, unsigned long *child, int fill)
0538 {
0539 unsigned long *parent, *left = NULL, *right = NULL;
0540 int i, no_left, no_right;
0541
0542 if (fill == 0) {
0543
0544
0545
0546
0547 btree_remove_level(head, geo, key, level + 1);
0548 mempool_free(child, head->mempool);
0549 return;
0550 }
0551
0552 parent = find_level(head, geo, key, level + 1);
0553 i = getpos(geo, parent, key);
0554 BUG_ON(bval(geo, parent, i) != child);
0555
0556 if (i > 0) {
0557 left = bval(geo, parent, i - 1);
0558 no_left = getfill(geo, left, 0);
0559 if (fill + no_left <= geo->no_pairs) {
0560 merge(head, geo, level,
0561 left, no_left,
0562 child, fill,
0563 parent, i - 1);
0564 return;
0565 }
0566 }
0567 if (i + 1 < getfill(geo, parent, i)) {
0568 right = bval(geo, parent, i + 1);
0569 no_right = getfill(geo, right, 0);
0570 if (fill + no_right <= geo->no_pairs) {
0571 merge(head, geo, level,
0572 child, fill,
0573 right, no_right,
0574 parent, i);
0575 return;
0576 }
0577 }
0578
0579
0580
0581
0582
0583
0584
0585 }
0586
0587 static void *btree_remove_level(struct btree_head *head, struct btree_geo *geo,
0588 unsigned long *key, int level)
0589 {
0590 unsigned long *node;
0591 int i, pos, fill;
0592 void *ret;
0593
0594 if (level > head->height) {
0595
0596 head->height = 0;
0597 head->node = NULL;
0598 return NULL;
0599 }
0600
0601 node = find_level(head, geo, key, level);
0602 pos = getpos(geo, node, key);
0603 fill = getfill(geo, node, pos);
0604 if ((level == 1) && (keycmp(geo, node, pos, key) != 0))
0605 return NULL;
0606 ret = bval(geo, node, pos);
0607
0608
0609 for (i = pos; i < fill - 1; i++) {
0610 setkey(geo, node, i, bkey(geo, node, i + 1));
0611 setval(geo, node, i, bval(geo, node, i + 1));
0612 }
0613 clearpair(geo, node, fill - 1);
0614
0615 if (fill - 1 < geo->no_pairs / 2) {
0616 if (level < head->height)
0617 rebalance(head, geo, key, level, node, fill - 1);
0618 else if (fill - 1 == 1)
0619 btree_shrink(head, geo);
0620 }
0621
0622 return ret;
0623 }
0624
0625 void *btree_remove(struct btree_head *head, struct btree_geo *geo,
0626 unsigned long *key)
0627 {
0628 if (head->height == 0)
0629 return NULL;
0630
0631 return btree_remove_level(head, geo, key, 1);
0632 }
0633 EXPORT_SYMBOL_GPL(btree_remove);
0634
0635 int btree_merge(struct btree_head *target, struct btree_head *victim,
0636 struct btree_geo *geo, gfp_t gfp)
0637 {
0638 unsigned long key[MAX_KEYLEN];
0639 unsigned long dup[MAX_KEYLEN];
0640 void *val;
0641 int err;
0642
0643 BUG_ON(target == victim);
0644
0645 if (!(target->node)) {
0646
0647 target->node = victim->node;
0648 target->height = victim->height;
0649 __btree_init(victim);
0650 return 0;
0651 }
0652
0653
0654
0655
0656 for (;;) {
0657 if (!btree_last(victim, geo, key))
0658 break;
0659 val = btree_lookup(victim, geo, key);
0660 err = btree_insert(target, geo, key, val, gfp);
0661 if (err)
0662 return err;
0663
0664
0665 longcpy(dup, key, geo->keylen);
0666 btree_remove(victim, geo, dup);
0667 }
0668 return 0;
0669 }
0670 EXPORT_SYMBOL_GPL(btree_merge);
0671
0672 static size_t __btree_for_each(struct btree_head *head, struct btree_geo *geo,
0673 unsigned long *node, unsigned long opaque,
0674 void (*func)(void *elem, unsigned long opaque,
0675 unsigned long *key, size_t index,
0676 void *func2),
0677 void *func2, int reap, int height, size_t count)
0678 {
0679 int i;
0680 unsigned long *child;
0681
0682 for (i = 0; i < geo->no_pairs; i++) {
0683 child = bval(geo, node, i);
0684 if (!child)
0685 break;
0686 if (height > 1)
0687 count = __btree_for_each(head, geo, child, opaque,
0688 func, func2, reap, height - 1, count);
0689 else
0690 func(child, opaque, bkey(geo, node, i), count++,
0691 func2);
0692 }
0693 if (reap)
0694 mempool_free(node, head->mempool);
0695 return count;
0696 }
0697
0698 static void empty(void *elem, unsigned long opaque, unsigned long *key,
0699 size_t index, void *func2)
0700 {
0701 }
0702
0703 void visitorl(void *elem, unsigned long opaque, unsigned long *key,
0704 size_t index, void *__func)
0705 {
0706 visitorl_t func = __func;
0707
0708 func(elem, opaque, *key, index);
0709 }
0710 EXPORT_SYMBOL_GPL(visitorl);
0711
0712 void visitor32(void *elem, unsigned long opaque, unsigned long *__key,
0713 size_t index, void *__func)
0714 {
0715 visitor32_t func = __func;
0716 u32 *key = (void *)__key;
0717
0718 func(elem, opaque, *key, index);
0719 }
0720 EXPORT_SYMBOL_GPL(visitor32);
0721
0722 void visitor64(void *elem, unsigned long opaque, unsigned long *__key,
0723 size_t index, void *__func)
0724 {
0725 visitor64_t func = __func;
0726 u64 *key = (void *)__key;
0727
0728 func(elem, opaque, *key, index);
0729 }
0730 EXPORT_SYMBOL_GPL(visitor64);
0731
0732 void visitor128(void *elem, unsigned long opaque, unsigned long *__key,
0733 size_t index, void *__func)
0734 {
0735 visitor128_t func = __func;
0736 u64 *key = (void *)__key;
0737
0738 func(elem, opaque, key[0], key[1], index);
0739 }
0740 EXPORT_SYMBOL_GPL(visitor128);
0741
0742 size_t btree_visitor(struct btree_head *head, struct btree_geo *geo,
0743 unsigned long opaque,
0744 void (*func)(void *elem, unsigned long opaque,
0745 unsigned long *key,
0746 size_t index, void *func2),
0747 void *func2)
0748 {
0749 size_t count = 0;
0750
0751 if (!func2)
0752 func = empty;
0753 if (head->node)
0754 count = __btree_for_each(head, geo, head->node, opaque, func,
0755 func2, 0, head->height, 0);
0756 return count;
0757 }
0758 EXPORT_SYMBOL_GPL(btree_visitor);
0759
0760 size_t btree_grim_visitor(struct btree_head *head, struct btree_geo *geo,
0761 unsigned long opaque,
0762 void (*func)(void *elem, unsigned long opaque,
0763 unsigned long *key,
0764 size_t index, void *func2),
0765 void *func2)
0766 {
0767 size_t count = 0;
0768
0769 if (!func2)
0770 func = empty;
0771 if (head->node)
0772 count = __btree_for_each(head, geo, head->node, opaque, func,
0773 func2, 1, head->height, 0);
0774 __btree_init(head);
0775 return count;
0776 }
0777 EXPORT_SYMBOL_GPL(btree_grim_visitor);
0778
0779 static int __init btree_module_init(void)
0780 {
0781 btree_cachep = kmem_cache_create("btree_node", NODESIZE, 0,
0782 SLAB_HWCACHE_ALIGN, NULL);
0783 return 0;
0784 }
0785
0786 static void __exit btree_module_exit(void)
0787 {
0788 kmem_cache_destroy(btree_cachep);
0789 }
0790
0791
0792 module_init(btree_module_init);
0793 module_exit(btree_module_exit);
0794
0795 MODULE_AUTHOR("Joern Engel <joern@logfs.org>");
0796 MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
0797 MODULE_LICENSE("GPL");