blob: 845422368f48141ee290037579dda18a95cec351 [file] [log] [blame]
Chris Mason8ef97622007-03-26 10:15:30 -04001#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) {
Chris Masond6025572007-03-30 14:27:56 -040019 bits = kmalloc(BIT_ARRAY_BYTES, GFP_NOFS);
Chris Mason8ef97622007-03-26 10:15:30 -040020 if (!bits)
21 return -ENOMEM;
22 memset(bits + 1, 0, BIT_ARRAY_BYTES - sizeof(unsigned long));
23 bits[0] = slot;
Chris Masond6025572007-03-30 14:27:56 -040024 radix_tree_preload(GFP_NOFS);
Chris Mason8ef97622007-03-26 10:15:30 -040025 ret = radix_tree_insert(radix, slot, bits);
Chris Masond6025572007-03-30 14:27:56 -040026 radix_tree_preload_end();
Chris Mason8ef97622007-03-26 10:15:30 -040027 if (ret)
28 return ret;
29 }
30 set_bit(bit_slot, bits + 1);
31 return 0;
32}
33
34int test_radix_bit(struct radix_tree_root *radix, unsigned long bit)
35{
36 unsigned long *bits;
37 unsigned long slot;
38 int bit_slot;
39
40 slot = bit / BIT_RADIX_BITS_PER_ARRAY;
41 bit_slot = bit % BIT_RADIX_BITS_PER_ARRAY;
42
43 bits = radix_tree_lookup(radix, slot);
44 if (!bits)
45 return 0;
46 return test_bit(bit_slot, bits + 1);
47}
48
49int clear_radix_bit(struct radix_tree_root *radix, unsigned long bit)
50{
51 unsigned long *bits;
52 unsigned long slot;
53 int bit_slot;
54 int i;
55 int empty = 1;
56
57 slot = bit / BIT_RADIX_BITS_PER_ARRAY;
58 bit_slot = bit % BIT_RADIX_BITS_PER_ARRAY;
59
60 bits = radix_tree_lookup(radix, slot);
61 if (!bits)
62 return 0;
63 clear_bit(bit_slot, bits + 1);
Chris Masond6025572007-03-30 14:27:56 -040064#if 0
Chris Mason8ef97622007-03-26 10:15:30 -040065 for (i = 1; i < BIT_ARRAY_BYTES / sizeof(unsigned long); i++) {
66 if (bits[i]) {
67 empty = 0;
68 break;
69 }
70 }
71
72 if (empty) {
73 bits = radix_tree_delete(radix, slot);
Chris Masond6025572007-03-30 14:27:56 -040074 synchronize_rcu();
Chris Mason8ef97622007-03-26 10:15:30 -040075 BUG_ON(!bits);
Chris Masond6025572007-03-30 14:27:56 -040076 kfree(bits);
Chris Mason8ef97622007-03-26 10:15:30 -040077 }
Chris Masond6025572007-03-30 14:27:56 -040078#endif
Chris Mason8ef97622007-03-26 10:15:30 -040079 return 0;
80}
81
82int find_first_radix_bit(struct radix_tree_root *radix, unsigned long *retbits,
83 int nr)
84{
85 unsigned long *bits;
86 unsigned long *gang[4];
87 int found;
88 int ret;
89 int i;
90 int total_found = 0;
91
92 ret = radix_tree_gang_lookup(radix, (void *)&gang, 0, ARRAY_SIZE(gang));
93 for (i = 0; i < ret && nr > 0; i++) {
94 found = 0;
95 bits = gang[i];
96 while(nr > 0) {
97 found = find_next_bit(bits + 1,
98 BIT_RADIX_BITS_PER_ARRAY,
99 found);
100 if (found < BIT_RADIX_BITS_PER_ARRAY) {
101 *retbits = bits[0] *
102 BIT_RADIX_BITS_PER_ARRAY + found;
103 retbits++;
104 nr--;
105 total_found++;
106 found++;
107 } else
108 break;
109 }
110 }
111 return total_found;
112}