aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/bit-radix.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-03-26 10:15:30 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-03-26 10:15:30 -0400
commit8ef97622caa2d5f78d1dc58ab918e2fbfa9b357a (patch)
tree6ae74ce8ff1ba7a6b8a522ed0ea3b37f17a6b305 /fs/btrfs/bit-radix.c
parentf7922033efe957f79ae57f6026e93c8148e7f7ed (diff)
Btrfs: add a radix back bit tree
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/bit-radix.c')
-rw-r--r--fs/btrfs/bit-radix.c107
1 files changed, 107 insertions, 0 deletions
diff --git a/fs/btrfs/bit-radix.c b/fs/btrfs/bit-radix.c
new file mode 100644
index 000000000000..43807cc3cce7
--- /dev/null
+++ b/fs/btrfs/bit-radix.c
@@ -0,0 +1,107 @@
1#include <linux/module.h>
2#include "bit-radix.h"
3
4#define BIT_ARRAY_BYTES 256
5#define BIT_RADIX_BITS_PER_ARRAY ((BIT_ARRAY_BYTES - sizeof(unsigned long)) * 8)
6
7int set_radix_bit(struct radix_tree_root *radix, unsigned long bit)
8{
9 unsigned long *bits;
10 unsigned long slot;
11 int bit_slot;
12 int ret;
13
14 slot = bit / BIT_RADIX_BITS_PER_ARRAY;
15 bit_slot = bit % BIT_RADIX_BITS_PER_ARRAY;
16
17 bits = radix_tree_lookup(radix, slot);
18 if (!bits) {
19 bits = kmalloc(BIT_ARRAY_BYTES, GFP_NOIO);
20 if (!bits)
21 return -ENOMEM;
22 memset(bits + 1, 0, BIT_ARRAY_BYTES - sizeof(unsigned long));
23 bits[0] = slot;
24 ret = radix_tree_insert(radix, slot, bits);
25 if (ret)
26 return ret;
27 }
28 set_bit(bit_slot, bits + 1);
29 return 0;
30}
31
32int test_radix_bit(struct radix_tree_root *radix, unsigned long bit)
33{
34 unsigned long *bits;
35 unsigned long slot;
36 int bit_slot;
37
38 slot = bit / BIT_RADIX_BITS_PER_ARRAY;
39 bit_slot = bit % BIT_RADIX_BITS_PER_ARRAY;
40
41 bits = radix_tree_lookup(radix, slot);
42 if (!bits)
43 return 0;
44 return test_bit(bit_slot, bits + 1);
45}
46
47int clear_radix_bit(struct radix_tree_root *radix, unsigned long bit)
48{
49 unsigned long *bits;
50 unsigned long slot;
51 int bit_slot;
52 int i;
53 int empty = 1;
54
55 slot = bit / BIT_RADIX_BITS_PER_ARRAY;
56 bit_slot = bit % BIT_RADIX_BITS_PER_ARRAY;
57
58 bits = radix_tree_lookup(radix, slot);
59 if (!bits)
60 return 0;
61 clear_bit(bit_slot, bits + 1);
62
63 for (i = 1; i < BIT_ARRAY_BYTES / sizeof(unsigned long); i++) {
64 if (bits[i]) {
65 empty = 0;
66 break;
67 }
68 }
69
70 if (empty) {
71 bits = radix_tree_delete(radix, slot);
72 BUG_ON(!bits);
73 }
74 return 0;
75}
76
77int find_first_radix_bit(struct radix_tree_root *radix, unsigned long *retbits,
78 int nr)
79{
80 unsigned long *bits;
81 unsigned long *gang[4];
82 int found;
83 int ret;
84 int i;
85 int total_found = 0;
86
87 ret = radix_tree_gang_lookup(radix, (void *)&gang, 0, ARRAY_SIZE(gang));
88 for (i = 0; i < ret && nr > 0; i++) {
89 found = 0;
90 bits = gang[i];
91 while(nr > 0) {
92 found = find_next_bit(bits + 1,
93 BIT_RADIX_BITS_PER_ARRAY,
94 found);
95 if (found < BIT_RADIX_BITS_PER_ARRAY) {
96 *retbits = bits[0] *
97 BIT_RADIX_BITS_PER_ARRAY + found;
98 retbits++;
99 nr--;
100 total_found++;
101 found++;
102 } else
103 break;
104 }
105 }
106 return total_found;
107}