mirror of
https://github.com/kdave/btrfs-progs
synced 2025-02-16 09:46:55 +00:00
add owner and type fields to the extents aand block headers
This commit is contained in:
parent
07eb5008f3
commit
2f2264fc2d
27
Makefile
27
Makefile
@ -8,7 +8,7 @@ objects = ctree.o disk-io.o radix-tree.o extent-tree.o print-tree.o \
|
||||
#
|
||||
# if you don't have sparse installed, use ls instead
|
||||
CHECKFLAGS=-D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ -Wbitwise \
|
||||
-Wcontext -Wcast-truncate -Wuninitialized -Wshadow -Wundef
|
||||
-Wuninitialized -Wshadow -Wundef
|
||||
check=sparse $(CHECKFLAGS)
|
||||
#check=ls
|
||||
|
||||
@ -16,32 +16,33 @@ check=sparse $(CHECKFLAGS)
|
||||
$(check) $<
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
all: bit-radix-test tester debug-tree quick-test dir-test tags mkfs.btrfs \
|
||||
btrfsctl
|
||||
all: tester debug-tree quick-test dir-test mkfs.btrfs \
|
||||
btrfsctl btrfsck
|
||||
|
||||
btrfsctl: ioctl.h btrfsctl.o
|
||||
btrfsctl: ioctl.h btrfsctl.o $(headers)
|
||||
gcc $(CFLAGS) -o btrfsctl btrfsctl.o
|
||||
|
||||
mkfs.btrfs: $(objects) mkfs.o
|
||||
btrfsck: btrfsck.o $(headers) bit-radix.o
|
||||
gcc $(CFLAGS) -o btrfsck btrfsck.o $(objects) bit-radix.o
|
||||
|
||||
mkfs.btrfs: $(objects) mkfs.o $(headers)
|
||||
gcc $(CFLAGS) -o mkfs.btrfs $(objects) mkfs.o -luuid
|
||||
|
||||
bit-radix-test: $(objects) bit-radix.o
|
||||
bit-radix-test: $(objects) bit-radix.o $(headers)
|
||||
gcc $(CFLAGS) -o bit-radix-test $(objects) bit-radix.o
|
||||
|
||||
debug-tree: $(objects) debug-tree.o
|
||||
debug-tree: $(objects) debug-tree.o $(headers)
|
||||
gcc $(CFLAGS) -o debug-tree $(objects) debug-tree.o -luuid
|
||||
|
||||
tester: $(objects) random-test.o
|
||||
tester: $(objects) random-test.o $(headers)
|
||||
gcc $(CFLAGS) -o tester $(objects) random-test.o
|
||||
|
||||
dir-test: $(objects) dir-test.o
|
||||
dir-test: $(objects) dir-test.o $(headers)
|
||||
gcc $(CFLAGS) -o dir-test $(objects) dir-test.o
|
||||
quick-test: $(objects) quick-test.o
|
||||
quick-test: $(objects) quick-test.o $(headers)
|
||||
gcc $(CFLAGS) -o quick-test $(objects) quick-test.o
|
||||
|
||||
$(objects): $(headers)
|
||||
|
||||
clean :
|
||||
rm debug-tree mkfs.btrfs btrfsctl *.o
|
||||
rm debug-tree mkfs.btrfs btrfsctl btrfsck *.o
|
||||
|
||||
|
||||
|
194
bit-radix.c
Normal file
194
bit-radix.c
Normal file
@ -0,0 +1,194 @@
|
||||
#include "kerncompat.h"
|
||||
#include "radix-tree.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 = malloc(BIT_ARRAY_BYTES);
|
||||
if (!bits)
|
||||
return -ENOMEM;
|
||||
memset(bits + 1, 0, BIT_ARRAY_BYTES - sizeof(unsigned long));
|
||||
bits[0] = slot;
|
||||
radix_tree_preload(GFP_NOFS);
|
||||
ret = radix_tree_insert(radix, slot, bits);
|
||||
radix_tree_preload_end();
|
||||
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);
|
||||
free(bits);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
|
||||
|
||||
/**
|
||||
* __ffs - find first bit in word.
|
||||
* @word: The word to search
|
||||
*
|
||||
* Undefined if no bit exists, so code should check against 0 first.
|
||||
*/
|
||||
static unsigned long __ffs(unsigned long word)
|
||||
{
|
||||
int num = 0;
|
||||
|
||||
#if BITS_PER_LONG == 64
|
||||
if ((word & 0xffffffff) == 0) {
|
||||
num += 32;
|
||||
word >>= 32;
|
||||
}
|
||||
#endif
|
||||
if ((word & 0xffff) == 0) {
|
||||
num += 16;
|
||||
word >>= 16;
|
||||
}
|
||||
if ((word & 0xff) == 0) {
|
||||
num += 8;
|
||||
word >>= 8;
|
||||
}
|
||||
if ((word & 0xf) == 0) {
|
||||
num += 4;
|
||||
word >>= 4;
|
||||
}
|
||||
if ((word & 0x3) == 0) {
|
||||
num += 2;
|
||||
word >>= 2;
|
||||
}
|
||||
if ((word & 0x1) == 0)
|
||||
num += 1;
|
||||
return num;
|
||||
}
|
||||
|
||||
/**
|
||||
* find_next_bit - find the next set bit in a memory region
|
||||
* @addr: The address to base the search on
|
||||
* @offset: The bitnumber to start searching at
|
||||
* @size: The maximum size to search
|
||||
*/
|
||||
unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
|
||||
unsigned long offset)
|
||||
{
|
||||
const unsigned long *p = addr + BITOP_WORD(offset);
|
||||
unsigned long result = offset & ~(BITS_PER_LONG-1);
|
||||
unsigned long tmp;
|
||||
|
||||
if (offset >= size)
|
||||
return size;
|
||||
size -= result;
|
||||
offset %= BITS_PER_LONG;
|
||||
if (offset) {
|
||||
tmp = *(p++);
|
||||
tmp &= (~0UL << offset);
|
||||
if (size < BITS_PER_LONG)
|
||||
goto found_first;
|
||||
if (tmp)
|
||||
goto found_middle;
|
||||
size -= BITS_PER_LONG;
|
||||
result += BITS_PER_LONG;
|
||||
}
|
||||
while (size & ~(BITS_PER_LONG-1)) {
|
||||
if ((tmp = *(p++)))
|
||||
goto found_middle;
|
||||
result += BITS_PER_LONG;
|
||||
size -= BITS_PER_LONG;
|
||||
}
|
||||
if (!size)
|
||||
return result;
|
||||
tmp = *p;
|
||||
|
||||
found_first:
|
||||
tmp &= (~0UL >> (BITS_PER_LONG - size));
|
||||
if (tmp == 0UL) /* Are any bits set? */
|
||||
return result + size; /* Nope. */
|
||||
found_middle:
|
||||
return result + __ffs(tmp);
|
||||
}
|
||||
|
||||
int find_first_radix_bit(struct radix_tree_root *radix, unsigned long *retbits,
|
||||
unsigned long start, int nr)
|
||||
{
|
||||
unsigned long *bits;
|
||||
unsigned long *gang[4];
|
||||
int found;
|
||||
int ret;
|
||||
int i;
|
||||
int total_found = 0;
|
||||
unsigned long slot;
|
||||
|
||||
slot = start / BIT_RADIX_BITS_PER_ARRAY;
|
||||
ret = radix_tree_gang_lookup(radix, (void **)gang, slot,
|
||||
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;
|
||||
}
|
168
btrfsck.c
Normal file
168
btrfsck.c
Normal file
@ -0,0 +1,168 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "kerncompat.h"
|
||||
#include "radix-tree.h"
|
||||
#include "ctree.h"
|
||||
#include "disk-io.h"
|
||||
#include "print-tree.h"
|
||||
#include "transaction.h"
|
||||
#include "bit-radix.h"
|
||||
|
||||
u64 blocks_used = 0;
|
||||
struct extent_record {
|
||||
u64 start;
|
||||
u64 nr;
|
||||
u64 owner;
|
||||
u32 refs;
|
||||
u8 type;
|
||||
};
|
||||
|
||||
static int add_extent_rec(struct radix_tree_root *extent_radix,
|
||||
u64 ref, u64 start, u64 nr, u64 owner, u8 type)
|
||||
{
|
||||
struct extent_record *rec;
|
||||
int ret = 0;
|
||||
rec = radix_tree_lookup(extent_radix, start);
|
||||
if (rec) {
|
||||
rec->refs++;
|
||||
if (owner != rec->owner) {
|
||||
fprintf(stderr, "warning, owner mismatch %Lu\n", start);
|
||||
ret = 1;
|
||||
}
|
||||
if (start != rec->start) {
|
||||
fprintf(stderr, "warning, start mismatch %Lu %Lu\n",
|
||||
rec->start, start);
|
||||
ret = 1;
|
||||
}
|
||||
if (type != rec->type) {
|
||||
fprintf(stderr, "type mismatch block %Lu %d %d\n",
|
||||
start, type, type);
|
||||
ret = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
rec = malloc(sizeof(*rec));
|
||||
rec->start = start;
|
||||
rec->nr = nr;
|
||||
rec->owner = owner;
|
||||
rec->type = type;
|
||||
ret = radix_tree_insert(extent_radix, start, rec);
|
||||
BUG_ON(ret);
|
||||
blocks_used += nr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int add_pending(struct radix_tree_root *pending,
|
||||
struct radix_tree_root *seen, u64 blocknr)
|
||||
{
|
||||
if (test_radix_bit(seen, blocknr))
|
||||
return -EEXIST;
|
||||
set_radix_bit(pending, blocknr);
|
||||
set_radix_bit(seen, blocknr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int run_next_block(struct btrfs_root *root,
|
||||
u64 *last,
|
||||
struct radix_tree_root *pending,
|
||||
struct radix_tree_root *seen,
|
||||
struct radix_tree_root *extent_radix)
|
||||
{
|
||||
struct btrfs_buffer *buf;
|
||||
u64 blocknr;
|
||||
int ret;
|
||||
int i;
|
||||
int nritems;
|
||||
struct btrfs_leaf *leaf;
|
||||
struct btrfs_node *node;
|
||||
unsigned long bits;
|
||||
|
||||
ret = find_first_radix_bit(pending, &bits, *last, 1);
|
||||
if (ret == 0) {
|
||||
ret = find_first_radix_bit(pending, &bits, 0, 1);
|
||||
if (ret == 0)
|
||||
return 1;
|
||||
}
|
||||
*last = bits;
|
||||
blocknr = bits;
|
||||
clear_radix_bit(pending, blocknr);
|
||||
buf = read_tree_block(root, blocknr);
|
||||
nritems = btrfs_header_nritems(&buf->node.header);
|
||||
if (btrfs_is_leaf(&buf->node)) {
|
||||
leaf = &buf->leaf;
|
||||
for (i = 0; i < nritems; i++) {
|
||||
struct btrfs_file_extent_item *fi;
|
||||
if (btrfs_disk_key_type(&leaf->items[i].key) !=
|
||||
BTRFS_EXTENT_DATA_KEY)
|
||||
continue;
|
||||
fi = btrfs_item_ptr(leaf, i,
|
||||
struct btrfs_file_extent_item);
|
||||
if (btrfs_file_extent_type(fi) !=
|
||||
BTRFS_FILE_EXTENT_REG)
|
||||
continue;
|
||||
ret = add_extent_rec(extent_radix, blocknr,
|
||||
btrfs_file_extent_disk_blocknr(fi),
|
||||
btrfs_file_extent_disk_num_blocks(fi),
|
||||
btrfs_disk_key_objectid(&leaf->items[i].key),
|
||||
BTRFS_EXTENT_FILE);
|
||||
BUG_ON(ret);
|
||||
}
|
||||
} else {
|
||||
node = &buf->node;
|
||||
for (i = 0; i < nritems; i++) {
|
||||
u64 ptr = btrfs_node_blockptr(node, i);
|
||||
ret = add_extent_rec(extent_radix, blocknr, ptr, 1,
|
||||
btrfs_header_owner(&node->header),
|
||||
BTRFS_EXTENT_TREE);
|
||||
BUG_ON(ret);
|
||||
add_pending(pending, seen, ptr);
|
||||
}
|
||||
}
|
||||
btrfs_block_release(root, buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int add_root_to_pending(struct btrfs_root *root,
|
||||
struct radix_tree_root *extent_radix,
|
||||
struct radix_tree_root *pending,
|
||||
struct radix_tree_root *seen)
|
||||
{
|
||||
add_pending(pending, seen, root->node->blocknr);
|
||||
add_extent_rec(extent_radix, 0, root->node->blocknr, 1,
|
||||
btrfs_header_owner(&root->node->node.header),
|
||||
BTRFS_EXTENT_TREE);
|
||||
return 0;
|
||||
}
|
||||
int main(int ac, char **av) {
|
||||
struct btrfs_super_block super;
|
||||
struct btrfs_root *root;
|
||||
struct radix_tree_root extent_radix;
|
||||
struct radix_tree_root seen;
|
||||
struct radix_tree_root pending;
|
||||
int ret;
|
||||
u64 last = 0;
|
||||
|
||||
radix_tree_init();
|
||||
|
||||
INIT_RADIX_TREE(&extent_radix, GFP_NOFS);
|
||||
init_bit_radix(&seen);
|
||||
init_bit_radix(&pending);
|
||||
|
||||
root = open_ctree(av[1], &super);
|
||||
add_root_to_pending(root, &extent_radix, &pending, &seen);
|
||||
add_root_to_pending(root->fs_info->tree_root,&extent_radix,
|
||||
&pending, &seen);
|
||||
add_root_to_pending(root->fs_info->dev_root, &extent_radix,
|
||||
&pending, &seen);
|
||||
add_root_to_pending(root->fs_info->extent_root, &extent_radix,
|
||||
&pending, &seen);
|
||||
while(1) {
|
||||
ret = run_next_block(root, &last, &pending,
|
||||
&seen, &extent_radix);
|
||||
if (ret != 0)
|
||||
break;
|
||||
}
|
||||
close_ctree(root, &super);
|
||||
printf("found %Lu blocks used\n", blocks_used);
|
||||
return 0;
|
||||
}
|
4
ctree.c
4
ctree.c
@ -49,6 +49,7 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||
cow = btrfs_alloc_free_block(trans, root);
|
||||
memcpy(&cow->node, &buf->node, root->blocksize);
|
||||
btrfs_set_header_blocknr(&cow->node.header, cow->blocknr);
|
||||
btrfs_set_header_owner(&cow->node.header, root->root_key.objectid);
|
||||
*cow_ret = cow;
|
||||
btrfs_inc_ref(trans, root, buf);
|
||||
if (buf == root->node) {
|
||||
@ -661,6 +662,7 @@ static int insert_new_root(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||
btrfs_set_header_nritems(&c->header, 1);
|
||||
btrfs_set_header_level(&c->header, level);
|
||||
btrfs_set_header_blocknr(&c->header, t->blocknr);
|
||||
btrfs_set_header_owner(&c->header, root->root_key.objectid);
|
||||
lower = &path->nodes[level-1]->node;
|
||||
if (btrfs_is_leaf(lower))
|
||||
lower_key = &((struct btrfs_leaf *)lower)->items[0].key;
|
||||
@ -746,6 +748,7 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||
btrfs_set_header_flags(&split->header, btrfs_header_flags(&c->header));
|
||||
btrfs_set_header_level(&split->header, btrfs_header_level(&c->header));
|
||||
btrfs_set_header_blocknr(&split->header, split_buffer->blocknr);
|
||||
btrfs_set_header_owner(&split->header, root->root_key.objectid);
|
||||
mid = (c_nritems + 1) / 2;
|
||||
memcpy(split->ptrs, c->ptrs + mid,
|
||||
(c_nritems - mid) * sizeof(struct btrfs_key_ptr));
|
||||
@ -1088,6 +1091,7 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||
btrfs_set_header_nritems(&right->header, nritems - mid);
|
||||
btrfs_set_header_blocknr(&right->header, right_buffer->blocknr);
|
||||
btrfs_set_header_level(&right->header, 0);
|
||||
btrfs_set_header_owner(&right->header, root->root_key.objectid);
|
||||
data_copy_size = btrfs_item_end(l->items + mid) -
|
||||
leaf_data_end(root, l);
|
||||
memcpy(right->items, l->items + mid,
|
||||
|
38
ctree.h
38
ctree.h
@ -58,6 +58,7 @@ struct btrfs_header {
|
||||
u8 fsid[16]; /* FS specific uuid */
|
||||
__le64 blocknr; /* which block this node is supposed to live in */
|
||||
__le64 generation;
|
||||
__le64 owner;
|
||||
__le16 nritems;
|
||||
__le16 flags;
|
||||
u8 level;
|
||||
@ -144,12 +145,17 @@ struct btrfs_path {
|
||||
int slots[BTRFS_MAX_LEVEL];
|
||||
};
|
||||
|
||||
/* values for the type field in btrfs_extent_item */
|
||||
#define BTRFS_EXTENT_TREE 1
|
||||
#define BTRFS_EXTENT_FILE 2
|
||||
/*
|
||||
* items in the extent btree are used to record the objectid of the
|
||||
* owner of the block and the number of references
|
||||
*/
|
||||
struct btrfs_extent_item {
|
||||
__le32 refs;
|
||||
__le64 owner;
|
||||
u8 type;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct btrfs_inode_timespec {
|
||||
@ -461,11 +467,32 @@ static inline void btrfs_set_extent_refs(struct btrfs_extent_item *ei, u32 val)
|
||||
ei->refs = cpu_to_le32(val);
|
||||
}
|
||||
|
||||
static inline u64 btrfs_extent_owner(struct btrfs_extent_item *ei)
|
||||
{
|
||||
return le64_to_cpu(ei->owner);
|
||||
}
|
||||
|
||||
static inline void btrfs_set_extent_owner(struct btrfs_extent_item *ei, u64 val)
|
||||
{
|
||||
ei->owner = cpu_to_le64(val);
|
||||
}
|
||||
|
||||
static inline u8 btrfs_extent_type(struct btrfs_extent_item *ei)
|
||||
{
|
||||
return ei->type;
|
||||
}
|
||||
|
||||
static inline void btrfs_set_extent_type(struct btrfs_extent_item *ei, u8 val)
|
||||
{
|
||||
ei->type = val;
|
||||
}
|
||||
|
||||
static inline u64 btrfs_node_blockptr(struct btrfs_node *n, int nr)
|
||||
{
|
||||
return le64_to_cpu(n->ptrs[nr].blockptr);
|
||||
}
|
||||
|
||||
|
||||
static inline void btrfs_set_node_blockptr(struct btrfs_node *n, int nr,
|
||||
u64 val)
|
||||
{
|
||||
@ -624,6 +651,17 @@ static inline void btrfs_set_header_generation(struct btrfs_header *h,
|
||||
h->generation = cpu_to_le64(val);
|
||||
}
|
||||
|
||||
static inline u64 btrfs_header_owner(struct btrfs_header *h)
|
||||
{
|
||||
return le64_to_cpu(h->owner);
|
||||
}
|
||||
|
||||
static inline void btrfs_set_header_owner(struct btrfs_header *h,
|
||||
u64 val)
|
||||
{
|
||||
h->owner = cpu_to_le64(val);
|
||||
}
|
||||
|
||||
static inline u16 btrfs_header_nritems(struct btrfs_header *h)
|
||||
{
|
||||
return le16_to_cpu(h->nritems);
|
||||
|
@ -294,6 +294,7 @@ static int __setup_root(struct btrfs_super_block *super,
|
||||
root->fs_info = fs_info;
|
||||
memset(&root->root_key, 0, sizeof(root->root_key));
|
||||
memset(&root->root_item, 0, sizeof(root->root_item));
|
||||
root->root_key.objectid = objectid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -394,7 +394,8 @@ error:
|
||||
* returns 0 if everything worked, non-zero otherwise.
|
||||
*/
|
||||
static int alloc_extent(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||
*root, u64 num_blocks, u64 search_start, u64
|
||||
*root, u64 owner, u8 type, u64 num_blocks,
|
||||
u64 search_start, u64
|
||||
search_end, struct btrfs_key *ins)
|
||||
{
|
||||
int ret;
|
||||
@ -405,6 +406,8 @@ static int alloc_extent(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||
struct btrfs_extent_item extent_item;
|
||||
|
||||
btrfs_set_extent_refs(&extent_item, 1);
|
||||
btrfs_set_extent_owner(&extent_item, owner);
|
||||
btrfs_set_extent_type(&extent_item, type);
|
||||
|
||||
if (root == extent_root) {
|
||||
BUG_ON(extent_root->fs_info->current_insert.offset == 0);
|
||||
@ -447,7 +450,8 @@ struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
|
||||
int ret;
|
||||
struct btrfs_buffer *buf;
|
||||
|
||||
ret = alloc_extent(trans, root, 1, 0, (unsigned long)-1, &ins);
|
||||
ret = alloc_extent(trans, root, root->root_key.objectid,
|
||||
BTRFS_EXTENT_TREE, 1, 0, (unsigned long)-1, &ins);
|
||||
if (ret) {
|
||||
BUG();
|
||||
return NULL;
|
||||
|
45
kerncompat.h
45
kerncompat.h
@ -48,23 +48,44 @@ struct page {
|
||||
static inline void preempt_enable(void) { do {; } while(0);}
|
||||
static inline void preempt_disable(void) { do {; } while(0);}
|
||||
|
||||
static inline void __set_bit(int bit, unsigned long *map) {
|
||||
unsigned long *p = map + bit / BITS_PER_LONG;
|
||||
bit = bit & (BITS_PER_LONG -1);
|
||||
*p |= 1UL << bit;
|
||||
#define BITOP_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
|
||||
#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
|
||||
|
||||
/**
|
||||
* __set_bit - Set a bit in memory
|
||||
* @nr: the bit to set
|
||||
* @addr: the address to start counting from
|
||||
*
|
||||
* Unlike set_bit(), this function is non-atomic and may be reordered.
|
||||
* If it's called on the same region of memory simultaneously, the effect
|
||||
* may be that only one operation succeeds.
|
||||
*/
|
||||
static inline void __set_bit(int nr, volatile unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BITOP_MASK(nr);
|
||||
unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
|
||||
|
||||
*p |= mask;
|
||||
}
|
||||
|
||||
static inline int test_bit(int bit, unsigned long *map) {
|
||||
unsigned long *p = map + bit / BITS_PER_LONG;
|
||||
bit = bit & (BITS_PER_LONG -1);
|
||||
return *p & (1UL << bit) ? 1 : 0;
|
||||
static inline void __clear_bit(int nr, volatile unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BITOP_MASK(nr);
|
||||
unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
|
||||
|
||||
*p &= ~mask;
|
||||
}
|
||||
|
||||
static inline void __clear_bit(int bit, unsigned long *map) {
|
||||
unsigned long *p = map + bit / BITS_PER_LONG;
|
||||
bit = bit & (BITS_PER_LONG -1);
|
||||
*p &= ~(1UL << bit);
|
||||
/**
|
||||
* test_bit - Determine whether a bit is set
|
||||
* @nr: bit number to test
|
||||
* @addr: Address to start counting from
|
||||
*/
|
||||
static inline int test_bit(int nr, const volatile unsigned long *addr)
|
||||
{
|
||||
return 1UL & (addr[BITOP_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
|
||||
}
|
||||
|
||||
#define BUG_ON(c) do { if (c) abort(); } while (0)
|
||||
|
||||
#define container_of(ptr, type, member) ({ \
|
||||
|
1
mkfs.c
1
mkfs.c
@ -141,6 +141,7 @@ int mkfs(int fd, char *pathname, u64 num_blocks, u32 blocksize)
|
||||
btrfs_set_header_blocknr(&empty_leaf->header, start_block + 1);
|
||||
btrfs_set_header_nritems(&empty_leaf->header, 2);
|
||||
btrfs_set_header_generation(&empty_leaf->header, 0);
|
||||
btrfs_set_header_owner(&empty_leaf->header, BTRFS_ROOT_TREE_OBJECTID);
|
||||
memcpy(empty_leaf->header.fsid, super.fsid,
|
||||
sizeof(empty_leaf->header.fsid));
|
||||
|
||||
|
16
print-tree.c
16
print-tree.c
@ -40,10 +40,11 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l)
|
||||
char *p;
|
||||
u32 type;
|
||||
|
||||
printf("leaf %Lu ptrs %d free space %d generation %Lu\n",
|
||||
printf("leaf %Lu ptrs %d free space %d generation %Lu owner %Lu\n",
|
||||
btrfs_header_blocknr(&l->header), nr,
|
||||
btrfs_leaf_free_space(root, l),
|
||||
btrfs_header_generation(&l->header));
|
||||
btrfs_header_generation(&l->header),
|
||||
btrfs_header_owner(&l->header));
|
||||
fflush(stdout);
|
||||
for (i = 0 ; i < nr ; i++) {
|
||||
item = l->items + i;
|
||||
@ -84,8 +85,10 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l)
|
||||
break;
|
||||
case BTRFS_EXTENT_ITEM_KEY:
|
||||
ei = btrfs_item_ptr(l, i, struct btrfs_extent_item);
|
||||
printf("\t\textent data refs %u\n",
|
||||
btrfs_extent_refs(ei));
|
||||
printf("\t\textent data refs %u type %d owner %Lu\n",
|
||||
btrfs_extent_refs(ei),
|
||||
btrfs_extent_type(ei),
|
||||
btrfs_extent_owner(ei));
|
||||
break;
|
||||
case BTRFS_CSUM_ITEM_KEY:
|
||||
ci = btrfs_item_ptr(l, i,
|
||||
@ -138,11 +141,12 @@ void btrfs_print_tree(struct btrfs_root *root, struct btrfs_buffer *t)
|
||||
btrfs_print_leaf(root, (struct btrfs_leaf *)c);
|
||||
return;
|
||||
}
|
||||
printf("node %Lu level %d ptrs %d free %u generation %Lu\n",
|
||||
printf("node %Lu level %d ptrs %d free %u generation %Lu owner %Lu\n",
|
||||
t->blocknr,
|
||||
btrfs_header_level(&c->header), nr,
|
||||
(u32)BTRFS_NODEPTRS_PER_BLOCK(root) - nr,
|
||||
btrfs_header_generation(&c->header));
|
||||
btrfs_header_generation(&c->header),
|
||||
btrfs_header_owner(&c->header));
|
||||
fflush(stdout);
|
||||
for (i = 0; i < nr; i++) {
|
||||
printf("\tkey %d (%Lu %x %Lu) block %Lu\n",
|
||||
|
Loading…
Reference in New Issue
Block a user