Btrfs: add a radix back bit tree
Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
committed by
David Woodhouse
parent
f7922033ef
commit
8ef97622ca
107
fs/btrfs/bit-radix.c
Normal file
107
fs/btrfs/bit-radix.c
Normal file
@@ -0,0 +1,107 @@
|
||||
#include <linux/module.h>
|
||||
#include "bit-radix.h"
|
||||
|
||||
#define BIT_ARRAY_BYTES 256
|
||||
#define BIT_RADIX_BITS_PER_ARRAY ((BIT_ARRAY_BYTES - sizeof(unsigned long)) * 8)
|
||||
|
||||
int set_radix_bit(struct radix_tree_root *radix, unsigned long bit)
|
||||
{
|
||||
unsigned long *bits;
|
||||
unsigned long slot;
|
||||
int bit_slot;
|
||||
int ret;
|
||||
|
||||
slot = bit / BIT_RADIX_BITS_PER_ARRAY;
|
||||
bit_slot = bit % BIT_RADIX_BITS_PER_ARRAY;
|
||||
|
||||
bits = radix_tree_lookup(radix, slot);
|
||||
if (!bits) {
|
||||
bits = kmalloc(BIT_ARRAY_BYTES, GFP_NOIO);
|
||||
if (!bits)
|
||||
return -ENOMEM;
|
||||
memset(bits + 1, 0, BIT_ARRAY_BYTES - sizeof(unsigned long));
|
||||
bits[0] = slot;
|
||||
ret = radix_tree_insert(radix, slot, bits);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
set_bit(bit_slot, bits + 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_radix_bit(struct radix_tree_root *radix, unsigned long bit)
|
||||
{
|
||||
unsigned long *bits;
|
||||
unsigned long slot;
|
||||
int bit_slot;
|
||||
|
||||
slot = bit / BIT_RADIX_BITS_PER_ARRAY;
|
||||
bit_slot = bit % BIT_RADIX_BITS_PER_ARRAY;
|
||||
|
||||
bits = radix_tree_lookup(radix, slot);
|
||||
if (!bits)
|
||||
return 0;
|
||||
return test_bit(bit_slot, bits + 1);
|
||||
}
|
||||
|
||||
int clear_radix_bit(struct radix_tree_root *radix, unsigned long bit)
|
||||
{
|
||||
unsigned long *bits;
|
||||
unsigned long slot;
|
||||
int bit_slot;
|
||||
int i;
|
||||
int empty = 1;
|
||||
|
||||
slot = bit / BIT_RADIX_BITS_PER_ARRAY;
|
||||
bit_slot = bit % BIT_RADIX_BITS_PER_ARRAY;
|
||||
|
||||
bits = radix_tree_lookup(radix, slot);
|
||||
if (!bits)
|
||||
return 0;
|
||||
clear_bit(bit_slot, bits + 1);
|
||||
|
||||
for (i = 1; i < BIT_ARRAY_BYTES / sizeof(unsigned long); i++) {
|
||||
if (bits[i]) {
|
||||
empty = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty) {
|
||||
bits = radix_tree_delete(radix, slot);
|
||||
BUG_ON(!bits);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int find_first_radix_bit(struct radix_tree_root *radix, unsigned long *retbits,
|
||||
int nr)
|
||||
{
|
||||
unsigned long *bits;
|
||||
unsigned long *gang[4];
|
||||
int found;
|
||||
int ret;
|
||||
int i;
|
||||
int total_found = 0;
|
||||
|
||||
ret = radix_tree_gang_lookup(radix, (void *)&gang, 0, ARRAY_SIZE(gang));
|
||||
for (i = 0; i < ret && nr > 0; i++) {
|
||||
found = 0;
|
||||
bits = gang[i];
|
||||
while(nr > 0) {
|
||||
found = find_next_bit(bits + 1,
|
||||
BIT_RADIX_BITS_PER_ARRAY,
|
||||
found);
|
||||
if (found < BIT_RADIX_BITS_PER_ARRAY) {
|
||||
*retbits = bits[0] *
|
||||
BIT_RADIX_BITS_PER_ARRAY + found;
|
||||
retbits++;
|
||||
nr--;
|
||||
total_found++;
|
||||
found++;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}
|
||||
return total_found;
|
||||
}
|
Reference in New Issue
Block a user