mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 06:50:58 +07:00
Btrfs: transaction handles everywhere
Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
parent
88fd146c27
commit
e089f05c18
@ -1,5 +1,5 @@
|
|||||||
CC=gcc
|
CC=gcc
|
||||||
CFLAGS = -g -Wall
|
CFLAGS = -g -Wall -Werror
|
||||||
headers = radix-tree.h ctree.h disk-io.h kerncompat.h print-tree.h list.h
|
headers = radix-tree.h ctree.h disk-io.h kerncompat.h print-tree.h list.h
|
||||||
objects = ctree.o disk-io.o radix-tree.o mkfs.o extent-tree.o print-tree.o \
|
objects = ctree.o disk-io.o radix-tree.o mkfs.o extent-tree.o print-tree.o \
|
||||||
root-tree.o dir-item.o hash.o file-item.o inode-item.o
|
root-tree.o dir-item.o hash.o file-item.o inode-item.o
|
||||||
@ -14,7 +14,7 @@ check=sparse $(CHECKFLAGS)
|
|||||||
$(check) $<
|
$(check) $<
|
||||||
$(CC) $(CFLAGS) -c $<
|
$(CC) $(CFLAGS) -c $<
|
||||||
|
|
||||||
all: tester debug-tree quick-test dir-test
|
all: tester debug-tree quick-test dir-test tags
|
||||||
|
|
||||||
debug-tree: $(objects) debug-tree.o
|
debug-tree: $(objects) debug-tree.o
|
||||||
gcc $(CFLAGS) -o debug-tree $(objects) debug-tree.o
|
gcc $(CFLAGS) -o debug-tree $(objects) debug-tree.o
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
* Add block mapping tree (simple dm layer)
|
* Add block mapping tree (simple dm layer)
|
||||||
* Add simple tree locking (semaphore per tree)
|
* Add simple tree locking (semaphore per tree)
|
||||||
* Make allocator smarter
|
* Make allocator smarter
|
||||||
|
* Only pin blocks allocated in this transaction
|
||||||
|
* Add transaction handles
|
||||||
* Do actual block accounting
|
* Do actual block accounting
|
||||||
* Check compat and incompat flags on the inode
|
* Check compat and incompat flags on the inode
|
||||||
* Port into the kernel
|
* Port into the kernel
|
||||||
|
204
fs/btrfs/ctree.c
204
fs/btrfs/ctree.c
@ -6,17 +6,18 @@
|
|||||||
#include "disk-io.h"
|
#include "disk-io.h"
|
||||||
#include "print-tree.h"
|
#include "print-tree.h"
|
||||||
|
|
||||||
static int split_node(struct btrfs_root *root, struct btrfs_path *path,
|
static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
int level);
|
*root, struct btrfs_path *path, int level);
|
||||||
static int split_leaf(struct btrfs_root *root, struct btrfs_path *path,
|
static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
int data_size);
|
*root, struct btrfs_path *path, int data_size);
|
||||||
static int push_node_left(struct btrfs_root *root, struct btrfs_buffer *dst,
|
static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
struct btrfs_buffer *src);
|
*root, struct btrfs_buffer *dst, struct btrfs_buffer
|
||||||
static int balance_node_right(struct btrfs_root *root,
|
*src);
|
||||||
struct btrfs_buffer *dst_buf,
|
static int balance_node_right(struct btrfs_trans_handle *trans, struct
|
||||||
|
btrfs_root *root, struct btrfs_buffer *dst_buf,
|
||||||
struct btrfs_buffer *src_buf);
|
struct btrfs_buffer *src_buf);
|
||||||
static int del_ptr(struct btrfs_root *root, struct btrfs_path *path, int level,
|
static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
int slot);
|
struct btrfs_path *path, int level, int slot);
|
||||||
|
|
||||||
inline void btrfs_init_path(struct btrfs_path *p)
|
inline void btrfs_init_path(struct btrfs_path *p)
|
||||||
{
|
{
|
||||||
@ -34,11 +35,10 @@ void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p)
|
|||||||
memset(p, 0, sizeof(*p));
|
memset(p, 0, sizeof(*p));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int btrfs_cow_block(struct btrfs_root *root,
|
static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
struct btrfs_buffer *buf,
|
*root, struct btrfs_buffer *buf, struct btrfs_buffer
|
||||||
struct btrfs_buffer *parent,
|
*parent, int parent_slot, struct btrfs_buffer
|
||||||
int parent_slot,
|
**cow_ret)
|
||||||
struct btrfs_buffer **cow_ret)
|
|
||||||
{
|
{
|
||||||
struct btrfs_buffer *cow;
|
struct btrfs_buffer *cow;
|
||||||
|
|
||||||
@ -46,22 +46,22 @@ static int btrfs_cow_block(struct btrfs_root *root,
|
|||||||
*cow_ret = buf;
|
*cow_ret = buf;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
cow = btrfs_alloc_free_block(root);
|
cow = btrfs_alloc_free_block(trans, root);
|
||||||
memcpy(&cow->node, &buf->node, root->blocksize);
|
memcpy(&cow->node, &buf->node, root->blocksize);
|
||||||
btrfs_set_header_blocknr(&cow->node.header, cow->blocknr);
|
btrfs_set_header_blocknr(&cow->node.header, cow->blocknr);
|
||||||
*cow_ret = cow;
|
*cow_ret = cow;
|
||||||
btrfs_inc_ref(root, buf);
|
btrfs_inc_ref(trans, root, buf);
|
||||||
if (buf == root->node) {
|
if (buf == root->node) {
|
||||||
root->node = cow;
|
root->node = cow;
|
||||||
cow->count++;
|
cow->count++;
|
||||||
if (buf != root->commit_root)
|
if (buf != root->commit_root)
|
||||||
btrfs_free_extent(root, buf->blocknr, 1, 1);
|
btrfs_free_extent(trans, root, buf->blocknr, 1, 1);
|
||||||
btrfs_block_release(root, buf);
|
btrfs_block_release(root, buf);
|
||||||
} else {
|
} else {
|
||||||
btrfs_set_node_blockptr(&parent->node, parent_slot,
|
btrfs_set_node_blockptr(&parent->node, parent_slot,
|
||||||
cow->blocknr);
|
cow->blocknr);
|
||||||
BUG_ON(list_empty(&parent->dirty));
|
BUG_ON(list_empty(&parent->dirty));
|
||||||
btrfs_free_extent(root, buf->blocknr, 1, 1);
|
btrfs_free_extent(trans, root, buf->blocknr, 1, 1);
|
||||||
}
|
}
|
||||||
btrfs_block_release(root, buf);
|
btrfs_block_release(root, buf);
|
||||||
return 0;
|
return 0;
|
||||||
@ -266,8 +266,8 @@ static struct btrfs_buffer *read_node_slot(struct btrfs_root *root,
|
|||||||
return read_tree_block(root, btrfs_node_blockptr(node, slot));
|
return read_tree_block(root, btrfs_node_blockptr(node, slot));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int balance_level(struct btrfs_root *root, struct btrfs_path *path,
|
static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
int level)
|
*root, struct btrfs_path *path, int level)
|
||||||
{
|
{
|
||||||
struct btrfs_buffer *right_buf;
|
struct btrfs_buffer *right_buf;
|
||||||
struct btrfs_buffer *mid_buf;
|
struct btrfs_buffer *mid_buf;
|
||||||
@ -310,8 +310,8 @@ static int balance_level(struct btrfs_root *root, struct btrfs_path *path,
|
|||||||
btrfs_block_release(root, mid_buf);
|
btrfs_block_release(root, mid_buf);
|
||||||
/* once for the root ptr */
|
/* once for the root ptr */
|
||||||
btrfs_block_release(root, mid_buf);
|
btrfs_block_release(root, mid_buf);
|
||||||
clean_tree_block(root, mid_buf);
|
clean_tree_block(trans, root, mid_buf);
|
||||||
return btrfs_free_extent(root, blocknr, 1, 1);
|
return btrfs_free_extent(trans, root, blocknr, 1, 1);
|
||||||
}
|
}
|
||||||
parent = &parent_buf->node;
|
parent = &parent_buf->node;
|
||||||
|
|
||||||
@ -324,11 +324,11 @@ static int balance_level(struct btrfs_root *root, struct btrfs_path *path,
|
|||||||
|
|
||||||
/* first, try to make some room in the middle buffer */
|
/* first, try to make some room in the middle buffer */
|
||||||
if (left_buf) {
|
if (left_buf) {
|
||||||
btrfs_cow_block(root, left_buf, parent_buf,
|
btrfs_cow_block(trans, root, left_buf, parent_buf, pslot - 1,
|
||||||
pslot - 1, &left_buf);
|
&left_buf);
|
||||||
left = &left_buf->node;
|
left = &left_buf->node;
|
||||||
orig_slot += btrfs_header_nritems(&left->header);
|
orig_slot += btrfs_header_nritems(&left->header);
|
||||||
wret = push_node_left(root, left_buf, mid_buf);
|
wret = push_node_left(trans, root, left_buf, mid_buf);
|
||||||
if (wret < 0)
|
if (wret < 0)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
}
|
}
|
||||||
@ -337,22 +337,23 @@ static int balance_level(struct btrfs_root *root, struct btrfs_path *path,
|
|||||||
* then try to empty the right most buffer into the middle
|
* then try to empty the right most buffer into the middle
|
||||||
*/
|
*/
|
||||||
if (right_buf) {
|
if (right_buf) {
|
||||||
btrfs_cow_block(root, right_buf, parent_buf,
|
btrfs_cow_block(trans, root, right_buf, parent_buf, pslot + 1,
|
||||||
pslot + 1, &right_buf);
|
&right_buf);
|
||||||
right = &right_buf->node;
|
right = &right_buf->node;
|
||||||
wret = push_node_left(root, mid_buf, right_buf);
|
wret = push_node_left(trans, root, mid_buf, right_buf);
|
||||||
if (wret < 0)
|
if (wret < 0)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
if (btrfs_header_nritems(&right->header) == 0) {
|
if (btrfs_header_nritems(&right->header) == 0) {
|
||||||
u64 blocknr = right_buf->blocknr;
|
u64 blocknr = right_buf->blocknr;
|
||||||
btrfs_block_release(root, right_buf);
|
btrfs_block_release(root, right_buf);
|
||||||
clean_tree_block(root, right_buf);
|
clean_tree_block(trans, root, right_buf);
|
||||||
right_buf = NULL;
|
right_buf = NULL;
|
||||||
right = NULL;
|
right = NULL;
|
||||||
wret = del_ptr(root, path, level + 1, pslot + 1);
|
wret = del_ptr(trans, root, path, level + 1, pslot +
|
||||||
|
1);
|
||||||
if (wret)
|
if (wret)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
wret = btrfs_free_extent(root, blocknr, 1, 1);
|
wret = btrfs_free_extent(trans, root, blocknr, 1, 1);
|
||||||
if (wret)
|
if (wret)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
} else {
|
} else {
|
||||||
@ -373,7 +374,7 @@ static int balance_level(struct btrfs_root *root, struct btrfs_path *path,
|
|||||||
* right
|
* right
|
||||||
*/
|
*/
|
||||||
BUG_ON(!left_buf);
|
BUG_ON(!left_buf);
|
||||||
wret = balance_node_right(root, mid_buf, left_buf);
|
wret = balance_node_right(trans, root, mid_buf, left_buf);
|
||||||
if (wret < 0)
|
if (wret < 0)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
BUG_ON(wret == 1);
|
BUG_ON(wret == 1);
|
||||||
@ -382,13 +383,13 @@ static int balance_level(struct btrfs_root *root, struct btrfs_path *path,
|
|||||||
/* we've managed to empty the middle node, drop it */
|
/* we've managed to empty the middle node, drop it */
|
||||||
u64 blocknr = mid_buf->blocknr;
|
u64 blocknr = mid_buf->blocknr;
|
||||||
btrfs_block_release(root, mid_buf);
|
btrfs_block_release(root, mid_buf);
|
||||||
clean_tree_block(root, mid_buf);
|
clean_tree_block(trans, root, mid_buf);
|
||||||
mid_buf = NULL;
|
mid_buf = NULL;
|
||||||
mid = NULL;
|
mid = NULL;
|
||||||
wret = del_ptr(root, path, level + 1, pslot);
|
wret = del_ptr(trans, root, path, level + 1, pslot);
|
||||||
if (wret)
|
if (wret)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
wret = btrfs_free_extent(root, blocknr, 1, 1);
|
wret = btrfs_free_extent(trans, root, blocknr, 1, 1);
|
||||||
if (wret)
|
if (wret)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
} else {
|
} else {
|
||||||
@ -438,8 +439,9 @@ static int balance_level(struct btrfs_root *root, struct btrfs_path *path,
|
|||||||
* tree. if ins_len < 0, nodes will be merged as we walk down the tree (if
|
* tree. if ins_len < 0, nodes will be merged as we walk down the tree (if
|
||||||
* possible)
|
* possible)
|
||||||
*/
|
*/
|
||||||
int btrfs_search_slot(struct btrfs_root *root, struct btrfs_key *key,
|
int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
struct btrfs_path *p, int ins_len, int cow)
|
*root, struct btrfs_key *key, struct btrfs_path *p, int
|
||||||
|
ins_len, int cow)
|
||||||
{
|
{
|
||||||
struct btrfs_buffer *b;
|
struct btrfs_buffer *b;
|
||||||
struct btrfs_buffer *cow_buf;
|
struct btrfs_buffer *cow_buf;
|
||||||
@ -455,8 +457,9 @@ int btrfs_search_slot(struct btrfs_root *root, struct btrfs_key *key,
|
|||||||
level = btrfs_header_level(&b->node.header);
|
level = btrfs_header_level(&b->node.header);
|
||||||
if (cow) {
|
if (cow) {
|
||||||
int wret;
|
int wret;
|
||||||
wret = btrfs_cow_block(root, b, p->nodes[level + 1],
|
wret = btrfs_cow_block(trans, root, b, p->nodes[level +
|
||||||
p->slots[level + 1], &cow_buf);
|
1], p->slots[level + 1],
|
||||||
|
&cow_buf);
|
||||||
b = cow_buf;
|
b = cow_buf;
|
||||||
}
|
}
|
||||||
BUG_ON(!cow && ins_len);
|
BUG_ON(!cow && ins_len);
|
||||||
@ -472,7 +475,7 @@ int btrfs_search_slot(struct btrfs_root *root, struct btrfs_key *key,
|
|||||||
p->slots[level] = slot;
|
p->slots[level] = slot;
|
||||||
if (ins_len > 0 && btrfs_header_nritems(&c->header) ==
|
if (ins_len > 0 && btrfs_header_nritems(&c->header) ==
|
||||||
BTRFS_NODEPTRS_PER_BLOCK(root)) {
|
BTRFS_NODEPTRS_PER_BLOCK(root)) {
|
||||||
int sret = split_node(root, p, level);
|
int sret = split_node(trans, root, p, level);
|
||||||
BUG_ON(sret > 0);
|
BUG_ON(sret > 0);
|
||||||
if (sret)
|
if (sret)
|
||||||
return sret;
|
return sret;
|
||||||
@ -480,7 +483,8 @@ int btrfs_search_slot(struct btrfs_root *root, struct btrfs_key *key,
|
|||||||
c = &b->node;
|
c = &b->node;
|
||||||
slot = p->slots[level];
|
slot = p->slots[level];
|
||||||
} else if (ins_len < 0) {
|
} else if (ins_len < 0) {
|
||||||
int sret = balance_level(root, p, level);
|
int sret = balance_level(trans, root, p,
|
||||||
|
level);
|
||||||
if (sret)
|
if (sret)
|
||||||
return sret;
|
return sret;
|
||||||
b = p->nodes[level];
|
b = p->nodes[level];
|
||||||
@ -496,7 +500,7 @@ int btrfs_search_slot(struct btrfs_root *root, struct btrfs_key *key,
|
|||||||
p->slots[level] = slot;
|
p->slots[level] = slot;
|
||||||
if (ins_len > 0 && btrfs_leaf_free_space(root, l) <
|
if (ins_len > 0 && btrfs_leaf_free_space(root, l) <
|
||||||
sizeof(struct btrfs_item) + ins_len) {
|
sizeof(struct btrfs_item) + ins_len) {
|
||||||
int sret = split_leaf(root, p, ins_len);
|
int sret = split_leaf(trans, root, p, ins_len);
|
||||||
BUG_ON(sret > 0);
|
BUG_ON(sret > 0);
|
||||||
if (sret)
|
if (sret)
|
||||||
return sret;
|
return sret;
|
||||||
@ -519,9 +523,9 @@ int btrfs_search_slot(struct btrfs_root *root, struct btrfs_key *key,
|
|||||||
* If this fails to write a tree block, it returns -1, but continues
|
* If this fails to write a tree block, it returns -1, but continues
|
||||||
* fixing up the blocks in ram so the tree is consistent.
|
* fixing up the blocks in ram so the tree is consistent.
|
||||||
*/
|
*/
|
||||||
static int fixup_low_keys(struct btrfs_root *root,
|
static int fixup_low_keys(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
struct btrfs_path *path, struct btrfs_disk_key *key,
|
*root, struct btrfs_path *path, struct btrfs_disk_key
|
||||||
int level)
|
*key, int level)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@ -546,8 +550,9 @@ static int fixup_low_keys(struct btrfs_root *root,
|
|||||||
* returns 0 if some ptrs were pushed left, < 0 if there was some horrible
|
* returns 0 if some ptrs were pushed left, < 0 if there was some horrible
|
||||||
* error, and > 0 if there was no room in the left hand block.
|
* error, and > 0 if there was no room in the left hand block.
|
||||||
*/
|
*/
|
||||||
static int push_node_left(struct btrfs_root *root, struct btrfs_buffer *dst_buf,
|
static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
struct btrfs_buffer *src_buf)
|
*root, struct btrfs_buffer *dst_buf, struct
|
||||||
|
btrfs_buffer *src_buf)
|
||||||
{
|
{
|
||||||
struct btrfs_node *src = &src_buf->node;
|
struct btrfs_node *src = &src_buf->node;
|
||||||
struct btrfs_node *dst = &dst_buf->node;
|
struct btrfs_node *dst = &dst_buf->node;
|
||||||
@ -589,8 +594,8 @@ static int push_node_left(struct btrfs_root *root, struct btrfs_buffer *dst_buf,
|
|||||||
*
|
*
|
||||||
* this will only push up to 1/2 the contents of the left node over
|
* this will only push up to 1/2 the contents of the left node over
|
||||||
*/
|
*/
|
||||||
static int balance_node_right(struct btrfs_root *root,
|
static int balance_node_right(struct btrfs_trans_handle *trans, struct
|
||||||
struct btrfs_buffer *dst_buf,
|
btrfs_root *root, struct btrfs_buffer *dst_buf,
|
||||||
struct btrfs_buffer *src_buf)
|
struct btrfs_buffer *src_buf)
|
||||||
{
|
{
|
||||||
struct btrfs_node *src = &src_buf->node;
|
struct btrfs_node *src = &src_buf->node;
|
||||||
@ -635,8 +640,8 @@ static int balance_node_right(struct btrfs_root *root,
|
|||||||
*
|
*
|
||||||
* returns zero on success or < 0 on failure.
|
* returns zero on success or < 0 on failure.
|
||||||
*/
|
*/
|
||||||
static int insert_new_root(struct btrfs_root *root,
|
static int insert_new_root(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
struct btrfs_path *path, int level)
|
*root, struct btrfs_path *path, int level)
|
||||||
{
|
{
|
||||||
struct btrfs_buffer *t;
|
struct btrfs_buffer *t;
|
||||||
struct btrfs_node *lower;
|
struct btrfs_node *lower;
|
||||||
@ -646,7 +651,7 @@ static int insert_new_root(struct btrfs_root *root,
|
|||||||
BUG_ON(path->nodes[level]);
|
BUG_ON(path->nodes[level]);
|
||||||
BUG_ON(path->nodes[level-1] != root->node);
|
BUG_ON(path->nodes[level-1] != root->node);
|
||||||
|
|
||||||
t = btrfs_alloc_free_block(root);
|
t = btrfs_alloc_free_block(trans, root);
|
||||||
c = &t->node;
|
c = &t->node;
|
||||||
memset(c, 0, root->blocksize);
|
memset(c, 0, root->blocksize);
|
||||||
btrfs_set_header_nritems(&c->header, 1);
|
btrfs_set_header_nritems(&c->header, 1);
|
||||||
@ -679,9 +684,9 @@ static int insert_new_root(struct btrfs_root *root,
|
|||||||
*
|
*
|
||||||
* returns zero on success and < 0 on any error
|
* returns zero on success and < 0 on any error
|
||||||
*/
|
*/
|
||||||
static int insert_ptr(struct btrfs_root *root,
|
static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
struct btrfs_path *path, struct btrfs_disk_key *key,
|
*root, struct btrfs_path *path, struct btrfs_disk_key
|
||||||
u64 blocknr, int slot, int level)
|
*key, u64 blocknr, int slot, int level)
|
||||||
{
|
{
|
||||||
struct btrfs_node *lower;
|
struct btrfs_node *lower;
|
||||||
int nritems;
|
int nritems;
|
||||||
@ -713,8 +718,8 @@ static int insert_ptr(struct btrfs_root *root,
|
|||||||
*
|
*
|
||||||
* returns 0 on success and < 0 on failure
|
* returns 0 on success and < 0 on failure
|
||||||
*/
|
*/
|
||||||
static int split_node(struct btrfs_root *root, struct btrfs_path *path,
|
static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
int level)
|
*root, struct btrfs_path *path, int level)
|
||||||
{
|
{
|
||||||
struct btrfs_buffer *t;
|
struct btrfs_buffer *t;
|
||||||
struct btrfs_node *c;
|
struct btrfs_node *c;
|
||||||
@ -729,12 +734,12 @@ static int split_node(struct btrfs_root *root, struct btrfs_path *path,
|
|||||||
c = &t->node;
|
c = &t->node;
|
||||||
if (t == root->node) {
|
if (t == root->node) {
|
||||||
/* trying to split the root, lets make a new one */
|
/* trying to split the root, lets make a new one */
|
||||||
ret = insert_new_root(root, path, level + 1);
|
ret = insert_new_root(trans, root, path, level + 1);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
c_nritems = btrfs_header_nritems(&c->header);
|
c_nritems = btrfs_header_nritems(&c->header);
|
||||||
split_buffer = btrfs_alloc_free_block(root);
|
split_buffer = btrfs_alloc_free_block(trans, root);
|
||||||
split = &split_buffer->node;
|
split = &split_buffer->node;
|
||||||
btrfs_set_header_flags(&split->header, btrfs_header_flags(&c->header));
|
btrfs_set_header_flags(&split->header, btrfs_header_flags(&c->header));
|
||||||
btrfs_set_header_blocknr(&split->header, split_buffer->blocknr);
|
btrfs_set_header_blocknr(&split->header, split_buffer->blocknr);
|
||||||
@ -748,7 +753,7 @@ static int split_node(struct btrfs_root *root, struct btrfs_path *path,
|
|||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
BUG_ON(list_empty(&t->dirty));
|
BUG_ON(list_empty(&t->dirty));
|
||||||
wret = insert_ptr(root, path, &split->ptrs[0].key,
|
wret = insert_ptr(trans, root, path, &split->ptrs[0].key,
|
||||||
split_buffer->blocknr, path->slots[level + 1] + 1,
|
split_buffer->blocknr, path->slots[level + 1] + 1,
|
||||||
level + 1);
|
level + 1);
|
||||||
if (wret)
|
if (wret)
|
||||||
@ -790,8 +795,8 @@ static int leaf_space_used(struct btrfs_leaf *l, int start, int nr)
|
|||||||
* returns 1 if the push failed because the other node didn't have enough
|
* returns 1 if the push failed because the other node didn't have enough
|
||||||
* room, 0 if everything worked out and < 0 if there were major errors.
|
* room, 0 if everything worked out and < 0 if there were major errors.
|
||||||
*/
|
*/
|
||||||
static int push_leaf_right(struct btrfs_root *root, struct btrfs_path *path,
|
static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
int data_size)
|
*root, struct btrfs_path *path, int data_size)
|
||||||
{
|
{
|
||||||
struct btrfs_buffer *left_buf = path->nodes[0];
|
struct btrfs_buffer *left_buf = path->nodes[0];
|
||||||
struct btrfs_leaf *left = &left_buf->leaf;
|
struct btrfs_leaf *left = &left_buf->leaf;
|
||||||
@ -824,7 +829,7 @@ static int push_leaf_right(struct btrfs_root *root, struct btrfs_path *path,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/* cow and double check */
|
/* cow and double check */
|
||||||
btrfs_cow_block(root, right_buf, upper, slot + 1, &right_buf);
|
btrfs_cow_block(trans, root, right_buf, upper, slot + 1, &right_buf);
|
||||||
right = &right_buf->leaf;
|
right = &right_buf->leaf;
|
||||||
free_space = btrfs_leaf_free_space(root, right);
|
free_space = btrfs_leaf_free_space(root, right);
|
||||||
if (free_space < data_size + sizeof(struct btrfs_item)) {
|
if (free_space < data_size + sizeof(struct btrfs_item)) {
|
||||||
@ -897,8 +902,8 @@ static int push_leaf_right(struct btrfs_root *root, struct btrfs_path *path,
|
|||||||
* push some data in the path leaf to the left, trying to free up at
|
* push some data in the path leaf to the left, trying to free up at
|
||||||
* least data_size bytes. returns zero if the push worked, nonzero otherwise
|
* least data_size bytes. returns zero if the push worked, nonzero otherwise
|
||||||
*/
|
*/
|
||||||
static int push_leaf_left(struct btrfs_root *root, struct btrfs_path *path,
|
static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
int data_size)
|
*root, struct btrfs_path *path, int data_size)
|
||||||
{
|
{
|
||||||
struct btrfs_buffer *right_buf = path->nodes[0];
|
struct btrfs_buffer *right_buf = path->nodes[0];
|
||||||
struct btrfs_leaf *right = &right_buf->leaf;
|
struct btrfs_leaf *right = &right_buf->leaf;
|
||||||
@ -931,7 +936,7 @@ static int push_leaf_left(struct btrfs_root *root, struct btrfs_path *path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* cow and double check */
|
/* cow and double check */
|
||||||
btrfs_cow_block(root, t, path->nodes[1], slot - 1, &t);
|
btrfs_cow_block(trans, root, t, path->nodes[1], slot - 1, &t);
|
||||||
left = &t->leaf;
|
left = &t->leaf;
|
||||||
free_space = btrfs_leaf_free_space(root, left);
|
free_space = btrfs_leaf_free_space(root, left);
|
||||||
if (free_space < data_size + sizeof(struct btrfs_item)) {
|
if (free_space < data_size + sizeof(struct btrfs_item)) {
|
||||||
@ -997,7 +1002,7 @@ static int push_leaf_left(struct btrfs_root *root, struct btrfs_path *path,
|
|||||||
BUG_ON(list_empty(&t->dirty));
|
BUG_ON(list_empty(&t->dirty));
|
||||||
BUG_ON(list_empty(&right_buf->dirty));
|
BUG_ON(list_empty(&right_buf->dirty));
|
||||||
|
|
||||||
wret = fixup_low_keys(root, path, &right->items[0].key, 1);
|
wret = fixup_low_keys(trans, root, path, &right->items[0].key, 1);
|
||||||
if (wret)
|
if (wret)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
|
|
||||||
@ -1021,8 +1026,8 @@ static int push_leaf_left(struct btrfs_root *root, struct btrfs_path *path,
|
|||||||
*
|
*
|
||||||
* returns 0 if all went well and < 0 on failure.
|
* returns 0 if all went well and < 0 on failure.
|
||||||
*/
|
*/
|
||||||
static int split_leaf(struct btrfs_root *root, struct btrfs_path *path,
|
static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
int data_size)
|
*root, struct btrfs_path *path, int data_size)
|
||||||
{
|
{
|
||||||
struct btrfs_buffer *l_buf;
|
struct btrfs_buffer *l_buf;
|
||||||
struct btrfs_leaf *l;
|
struct btrfs_leaf *l;
|
||||||
@ -1038,11 +1043,11 @@ static int split_leaf(struct btrfs_root *root, struct btrfs_path *path,
|
|||||||
int ret;
|
int ret;
|
||||||
int wret;
|
int wret;
|
||||||
|
|
||||||
wret = push_leaf_left(root, path, data_size);
|
wret = push_leaf_left(trans, root, path, data_size);
|
||||||
if (wret < 0)
|
if (wret < 0)
|
||||||
return wret;
|
return wret;
|
||||||
if (wret) {
|
if (wret) {
|
||||||
wret = push_leaf_right(root, path, data_size);
|
wret = push_leaf_right(trans, root, path, data_size);
|
||||||
if (wret < 0)
|
if (wret < 0)
|
||||||
return wret;
|
return wret;
|
||||||
}
|
}
|
||||||
@ -1055,14 +1060,14 @@ static int split_leaf(struct btrfs_root *root, struct btrfs_path *path,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!path->nodes[1]) {
|
if (!path->nodes[1]) {
|
||||||
ret = insert_new_root(root, path, 1);
|
ret = insert_new_root(trans, root, path, 1);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
slot = path->slots[0];
|
slot = path->slots[0];
|
||||||
nritems = btrfs_header_nritems(&l->header);
|
nritems = btrfs_header_nritems(&l->header);
|
||||||
mid = (nritems + 1)/ 2;
|
mid = (nritems + 1)/ 2;
|
||||||
right_buffer = btrfs_alloc_free_block(root);
|
right_buffer = btrfs_alloc_free_block(trans, root);
|
||||||
BUG_ON(!right_buffer);
|
BUG_ON(!right_buffer);
|
||||||
BUG_ON(mid == nritems);
|
BUG_ON(mid == nritems);
|
||||||
right = &right_buffer->leaf;
|
right = &right_buffer->leaf;
|
||||||
@ -1100,7 +1105,7 @@ static int split_leaf(struct btrfs_root *root, struct btrfs_path *path,
|
|||||||
|
|
||||||
btrfs_set_header_nritems(&l->header, mid);
|
btrfs_set_header_nritems(&l->header, mid);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
wret = insert_ptr(root, path, &right->items[0].key,
|
wret = insert_ptr(trans, root, path, &right->items[0].key,
|
||||||
right_buffer->blocknr, path->slots[1] + 1, 1);
|
right_buffer->blocknr, path->slots[1] + 1, 1);
|
||||||
if (wret)
|
if (wret)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
@ -1122,8 +1127,9 @@ static int split_leaf(struct btrfs_root *root, struct btrfs_path *path,
|
|||||||
* Given a key and some data, insert an item into the tree.
|
* Given a key and some data, insert an item into the tree.
|
||||||
* This does all the path init required, making room in the tree if needed.
|
* This does all the path init required, making room in the tree if needed.
|
||||||
*/
|
*/
|
||||||
int btrfs_insert_empty_item(struct btrfs_root *root, struct btrfs_path *path,
|
int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
struct btrfs_key *cpu_key, u32 data_size)
|
*root, struct btrfs_path *path, struct btrfs_key
|
||||||
|
*cpu_key, u32 data_size)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int slot;
|
int slot;
|
||||||
@ -1139,7 +1145,7 @@ int btrfs_insert_empty_item(struct btrfs_root *root, struct btrfs_path *path,
|
|||||||
/* create a root if there isn't one */
|
/* create a root if there isn't one */
|
||||||
if (!root->node)
|
if (!root->node)
|
||||||
BUG();
|
BUG();
|
||||||
ret = btrfs_search_slot(root, cpu_key, path, data_size, 1);
|
ret = btrfs_search_slot(trans, root, cpu_key, path, data_size, 1);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
btrfs_release_path(root, path);
|
btrfs_release_path(root, path);
|
||||||
return -EEXIST;
|
return -EEXIST;
|
||||||
@ -1193,7 +1199,7 @@ int btrfs_insert_empty_item(struct btrfs_root *root, struct btrfs_path *path,
|
|||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
if (slot == 0)
|
if (slot == 0)
|
||||||
ret = fixup_low_keys(root, path, &disk_key, 1);
|
ret = fixup_low_keys(trans, root, path, &disk_key, 1);
|
||||||
|
|
||||||
BUG_ON(list_empty(&leaf_buf->dirty));
|
BUG_ON(list_empty(&leaf_buf->dirty));
|
||||||
if (btrfs_leaf_free_space(root, leaf) < 0)
|
if (btrfs_leaf_free_space(root, leaf) < 0)
|
||||||
@ -1207,15 +1213,16 @@ int btrfs_insert_empty_item(struct btrfs_root *root, struct btrfs_path *path,
|
|||||||
* Given a key and some data, insert an item into the tree.
|
* Given a key and some data, insert an item into the tree.
|
||||||
* This does all the path init required, making room in the tree if needed.
|
* This does all the path init required, making room in the tree if needed.
|
||||||
*/
|
*/
|
||||||
int btrfs_insert_item(struct btrfs_root *root, struct btrfs_key *cpu_key,
|
int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
void *data, u32 data_size)
|
*root, struct btrfs_key *cpu_key, void *data, u32
|
||||||
|
data_size)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct btrfs_path path;
|
struct btrfs_path path;
|
||||||
u8 *ptr;
|
u8 *ptr;
|
||||||
|
|
||||||
btrfs_init_path(&path);
|
btrfs_init_path(&path);
|
||||||
ret = btrfs_insert_empty_item(root, &path, cpu_key, data_size);
|
ret = btrfs_insert_empty_item(trans, root, &path, cpu_key, data_size);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
ptr = btrfs_item_ptr(&path.nodes[0]->leaf, path.slots[0], u8);
|
ptr = btrfs_item_ptr(&path.nodes[0]->leaf, path.slots[0], u8);
|
||||||
memcpy(ptr, data, data_size);
|
memcpy(ptr, data, data_size);
|
||||||
@ -1231,8 +1238,8 @@ int btrfs_insert_item(struct btrfs_root *root, struct btrfs_key *cpu_key,
|
|||||||
* continuing all the way the root if required. The root is converted into
|
* continuing all the way the root if required. The root is converted into
|
||||||
* a leaf if all the nodes are emptied.
|
* a leaf if all the nodes are emptied.
|
||||||
*/
|
*/
|
||||||
static int del_ptr(struct btrfs_root *root, struct btrfs_path *path, int level,
|
static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
int slot)
|
struct btrfs_path *path, int level, int slot)
|
||||||
{
|
{
|
||||||
struct btrfs_node *node;
|
struct btrfs_node *node;
|
||||||
struct btrfs_buffer *parent = path->nodes[level];
|
struct btrfs_buffer *parent = path->nodes[level];
|
||||||
@ -1253,7 +1260,7 @@ static int del_ptr(struct btrfs_root *root, struct btrfs_path *path, int level,
|
|||||||
/* just turn the root into a leaf and break */
|
/* just turn the root into a leaf and break */
|
||||||
btrfs_set_header_level(&root->node->node.header, 0);
|
btrfs_set_header_level(&root->node->node.header, 0);
|
||||||
} else if (slot == 0) {
|
} else if (slot == 0) {
|
||||||
wret = fixup_low_keys(root, path, &node->ptrs[0].key,
|
wret = fixup_low_keys(trans, root, path, &node->ptrs[0].key,
|
||||||
level + 1);
|
level + 1);
|
||||||
if (wret)
|
if (wret)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
@ -1266,7 +1273,8 @@ static int del_ptr(struct btrfs_root *root, struct btrfs_path *path, int level,
|
|||||||
* delete the item at the leaf level in path. If that empties
|
* delete the item at the leaf level in path. If that empties
|
||||||
* the leaf, remove it from the tree
|
* the leaf, remove it from the tree
|
||||||
*/
|
*/
|
||||||
int btrfs_del_item(struct btrfs_root *root, struct btrfs_path *path)
|
int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
|
struct btrfs_path *path)
|
||||||
{
|
{
|
||||||
int slot;
|
int slot;
|
||||||
struct btrfs_leaf *leaf;
|
struct btrfs_leaf *leaf;
|
||||||
@ -1306,19 +1314,20 @@ int btrfs_del_item(struct btrfs_root *root, struct btrfs_path *path)
|
|||||||
btrfs_set_header_level(&leaf->header, 0);
|
btrfs_set_header_level(&leaf->header, 0);
|
||||||
BUG_ON(list_empty(&leaf_buf->dirty));
|
BUG_ON(list_empty(&leaf_buf->dirty));
|
||||||
} else {
|
} else {
|
||||||
clean_tree_block(root, leaf_buf);
|
clean_tree_block(trans, root, leaf_buf);
|
||||||
wret = del_ptr(root, path, 1, path->slots[1]);
|
wret = del_ptr(trans, root, path, 1, path->slots[1]);
|
||||||
if (wret)
|
if (wret)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
wret = btrfs_free_extent(root, leaf_buf->blocknr, 1, 1);
|
wret = btrfs_free_extent(trans, root,
|
||||||
|
leaf_buf->blocknr, 1, 1);
|
||||||
if (wret)
|
if (wret)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int used = leaf_space_used(leaf, 0, nritems);
|
int used = leaf_space_used(leaf, 0, nritems);
|
||||||
if (slot == 0) {
|
if (slot == 0) {
|
||||||
wret = fixup_low_keys(root, path,
|
wret = fixup_low_keys(trans, root, path,
|
||||||
&leaf->items[0].key, 1);
|
&leaf->items[0].key, 1);
|
||||||
if (wret)
|
if (wret)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
}
|
}
|
||||||
@ -1332,23 +1341,24 @@ int btrfs_del_item(struct btrfs_root *root, struct btrfs_path *path)
|
|||||||
*/
|
*/
|
||||||
slot = path->slots[1];
|
slot = path->slots[1];
|
||||||
leaf_buf->count++;
|
leaf_buf->count++;
|
||||||
wret = push_leaf_left(root, path, 1);
|
wret = push_leaf_left(trans, root, path, 1);
|
||||||
if (wret < 0)
|
if (wret < 0)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
if (path->nodes[0] == leaf_buf &&
|
if (path->nodes[0] == leaf_buf &&
|
||||||
btrfs_header_nritems(&leaf->header)) {
|
btrfs_header_nritems(&leaf->header)) {
|
||||||
wret = push_leaf_right(root, path, 1);
|
wret = push_leaf_right(trans, root, path, 1);
|
||||||
if (wret < 0)
|
if (wret < 0)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
}
|
}
|
||||||
if (btrfs_header_nritems(&leaf->header) == 0) {
|
if (btrfs_header_nritems(&leaf->header) == 0) {
|
||||||
u64 blocknr = leaf_buf->blocknr;
|
u64 blocknr = leaf_buf->blocknr;
|
||||||
clean_tree_block(root, leaf_buf);
|
clean_tree_block(trans, root, leaf_buf);
|
||||||
wret = del_ptr(root, path, 1, slot);
|
wret = del_ptr(trans, root, path, 1, slot);
|
||||||
if (wret)
|
if (wret)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
btrfs_block_release(root, leaf_buf);
|
btrfs_block_release(root, leaf_buf);
|
||||||
wret = btrfs_free_extent(root, blocknr, 1, 1);
|
wret = btrfs_free_extent(trans, root, blocknr,
|
||||||
|
1, 1);
|
||||||
if (wret)
|
if (wret)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
} else {
|
} else {
|
||||||
@ -1401,5 +1411,3 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "kerncompat.h"
|
#include "kerncompat.h"
|
||||||
|
|
||||||
|
struct btrfs_trans_handle;
|
||||||
|
|
||||||
#define BTRFS_MAGIC "_BtRfS_M"
|
#define BTRFS_MAGIC "_BtRfS_M"
|
||||||
|
|
||||||
#define BTRFS_ROOT_TREE_OBJECTID 1
|
#define BTRFS_ROOT_TREE_OBJECTID 1
|
||||||
@ -200,6 +202,7 @@ struct btrfs_root {
|
|||||||
struct btrfs_root_item root_item;
|
struct btrfs_root_item root_item;
|
||||||
struct btrfs_key root_key;
|
struct btrfs_key root_key;
|
||||||
u32 blocksize;
|
u32 blocksize;
|
||||||
|
struct btrfs_trans_handle *running_transaction;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* the lower bits in the key flags defines the item type */
|
/* the lower bits in the key flags defines the item type */
|
||||||
@ -656,34 +659,46 @@ static inline u8 *btrfs_leaf_data(struct btrfs_leaf *l)
|
|||||||
((type *)(btrfs_leaf_data(leaf) + \
|
((type *)(btrfs_leaf_data(leaf) + \
|
||||||
btrfs_item_offset((leaf)->items + (slot))))
|
btrfs_item_offset((leaf)->items + (slot))))
|
||||||
|
|
||||||
struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_root *root);
|
struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
|
||||||
int btrfs_inc_ref(struct btrfs_root *root, struct btrfs_buffer *buf);
|
struct btrfs_root *root);
|
||||||
int btrfs_free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks,
|
int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
int pin);
|
struct btrfs_buffer *buf);
|
||||||
int btrfs_search_slot(struct btrfs_root *root, struct btrfs_key *key,
|
int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
struct btrfs_path *p, int ins_len, int cow);
|
*root, u64 blocknr, u64 num_blocks, int pin);
|
||||||
|
int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
|
*root, struct btrfs_key *key, struct btrfs_path *p, int
|
||||||
|
ins_len, int cow);
|
||||||
void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p);
|
void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p);
|
||||||
void btrfs_init_path(struct btrfs_path *p);
|
void btrfs_init_path(struct btrfs_path *p);
|
||||||
int btrfs_del_item(struct btrfs_root *root, struct btrfs_path *path);
|
int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
int btrfs_insert_item(struct btrfs_root *root, struct btrfs_key *key,
|
struct btrfs_path *path);
|
||||||
void *data, u32 data_size);
|
int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
int btrfs_insert_empty_item(struct btrfs_root *root, struct btrfs_path *path,
|
*root, struct btrfs_key *key, void *data, u32 data_size);
|
||||||
struct btrfs_key *cpu_key, u32 data_size);
|
int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
|
*root, struct btrfs_path *path, struct btrfs_key
|
||||||
|
*cpu_key, u32 data_size);
|
||||||
int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path);
|
int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path);
|
||||||
int btrfs_leaf_free_space(struct btrfs_root *root, struct btrfs_leaf *leaf);
|
int btrfs_leaf_free_space(struct btrfs_root *root, struct btrfs_leaf *leaf);
|
||||||
int btrfs_drop_snapshot(struct btrfs_root *root, struct btrfs_buffer *snap);
|
int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
int btrfs_finish_extent_commit(struct btrfs_root *root);
|
*root, struct btrfs_buffer *snap);
|
||||||
int btrfs_del_root(struct btrfs_root *root, struct btrfs_key *key);
|
int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
|
||||||
int btrfs_insert_root(struct btrfs_root *root, struct btrfs_key *key,
|
btrfs_root *root);
|
||||||
struct btrfs_root_item *item);
|
int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
int btrfs_update_root(struct btrfs_root *root, struct btrfs_key *key,
|
struct btrfs_key *key);
|
||||||
struct btrfs_root_item *item);
|
int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
int btrfs_find_last_root(struct btrfs_root *root, u64 objectid,
|
*root, struct btrfs_key *key, struct btrfs_root_item
|
||||||
struct btrfs_root_item *item, struct btrfs_key *key);
|
*item);
|
||||||
int btrfs_insert_dir_item(struct btrfs_root *root, char *name, int name_len,
|
int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
u64 dir, u64 objectid, u8 type);
|
*root, struct btrfs_key *key, struct btrfs_root_item
|
||||||
int btrfs_lookup_dir_item(struct btrfs_root *root, struct btrfs_path *path,
|
*item);
|
||||||
u64 dir, char *name, int name_len, int mod);
|
int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct
|
||||||
|
btrfs_root_item *item, struct btrfs_key *key);
|
||||||
|
int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
|
*root, char *name, int name_len, u64 dir, u64
|
||||||
|
objectid, u8 type);
|
||||||
|
int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
|
*root, struct btrfs_path *path, u64 dir, char *name,
|
||||||
|
int name_len, int mod);
|
||||||
int btrfs_match_dir_item_name(struct btrfs_root *root, struct btrfs_path *path,
|
int btrfs_match_dir_item_name(struct btrfs_root *root, struct btrfs_path *path,
|
||||||
char *name, int name_len);
|
char *name, int name_len);
|
||||||
#endif
|
#endif
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "ctree.h"
|
#include "ctree.h"
|
||||||
#include "disk-io.h"
|
#include "disk-io.h"
|
||||||
#include "print-tree.h"
|
#include "print-tree.h"
|
||||||
|
#include "transaction.h"
|
||||||
|
|
||||||
int main(int ac, char **av) {
|
int main(int ac, char **av) {
|
||||||
struct btrfs_super_block super;
|
struct btrfs_super_block super;
|
||||||
|
@ -5,9 +5,11 @@
|
|||||||
#include "ctree.h"
|
#include "ctree.h"
|
||||||
#include "disk-io.h"
|
#include "disk-io.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
|
#include "transaction.h"
|
||||||
|
|
||||||
int btrfs_insert_dir_item(struct btrfs_root *root, char *name, int name_len,
|
int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
u64 dir, u64 objectid, u8 type)
|
*root, char *name, int name_len, u64 dir, u64
|
||||||
|
objectid, u8 type)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct btrfs_path path;
|
struct btrfs_path path;
|
||||||
@ -23,7 +25,7 @@ int btrfs_insert_dir_item(struct btrfs_root *root, char *name, int name_len,
|
|||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
btrfs_init_path(&path);
|
btrfs_init_path(&path);
|
||||||
data_size = sizeof(*dir_item) + name_len;
|
data_size = sizeof(*dir_item) + name_len;
|
||||||
ret = btrfs_insert_empty_item(root, &path, &key, data_size);
|
ret = btrfs_insert_empty_item(trans, root, &path, &key, data_size);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -40,8 +42,9 @@ int btrfs_insert_dir_item(struct btrfs_root *root, char *name, int name_len,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int btrfs_lookup_dir_item(struct btrfs_root *root, struct btrfs_path *path,
|
int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
u64 dir, char *name, int name_len, int mod)
|
*root, struct btrfs_path *path, u64 dir, char *name,
|
||||||
|
int name_len, int mod)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct btrfs_key key;
|
struct btrfs_key key;
|
||||||
@ -53,12 +56,13 @@ int btrfs_lookup_dir_item(struct btrfs_root *root, struct btrfs_path *path,
|
|||||||
btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY);
|
btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY);
|
||||||
ret = btrfs_name_hash(name, name_len, &key.offset);
|
ret = btrfs_name_hash(name, name_len, &key.offset);
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
ret = btrfs_search_slot(root, &key, path, ins_len, cow);
|
ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int btrfs_match_dir_item_name(struct btrfs_root *root, struct btrfs_path *path,
|
int btrfs_match_dir_item_name(struct btrfs_root *root,
|
||||||
char *name, int name_len)
|
struct btrfs_path *path, char
|
||||||
|
*name, int name_len)
|
||||||
{
|
{
|
||||||
struct btrfs_dir_item *dir_item;
|
struct btrfs_dir_item *dir_item;
|
||||||
char *name_ptr;
|
char *name_ptr;
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "disk-io.h"
|
#include "disk-io.h"
|
||||||
#include "print-tree.h"
|
#include "print-tree.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
|
#include "transaction.h"
|
||||||
|
|
||||||
int keep_running = 1;
|
int keep_running = 1;
|
||||||
struct btrfs_super_block super;
|
struct btrfs_super_block super;
|
||||||
@ -38,7 +39,8 @@ static int find_num(struct radix_tree_root *root, unsigned long *num_ret,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ins_one(struct btrfs_root *root, struct radix_tree_root *radix)
|
static int ins_one(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
|
struct radix_tree_root *radix)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
char buf[128];
|
char buf[128];
|
||||||
@ -48,8 +50,8 @@ static int ins_one(struct btrfs_root *root, struct radix_tree_root *radix)
|
|||||||
find_num(radix, &oid, 0);
|
find_num(radix, &oid, 0);
|
||||||
sprintf(buf, "str-%lu", oid);
|
sprintf(buf, "str-%lu", oid);
|
||||||
|
|
||||||
ret = btrfs_insert_dir_item(root, buf, strlen(buf), dir_oid, file_oid,
|
ret = btrfs_insert_dir_item(trans, root, buf, strlen(buf), dir_oid,
|
||||||
1);
|
file_oid, 1);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -68,7 +70,8 @@ static int ins_one(struct btrfs_root *root, struct radix_tree_root *radix)
|
|||||||
* check
|
* check
|
||||||
*/
|
*/
|
||||||
btrfs_init_path(&path);
|
btrfs_init_path(&path);
|
||||||
ret = btrfs_lookup_dir_item(root, &path, dir_oid, buf, strlen(buf), 0);
|
ret = btrfs_lookup_dir_item(trans, root, &path, dir_oid, buf,
|
||||||
|
strlen(buf), 0);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto fatal_release;
|
goto fatal_release;
|
||||||
if (!btrfs_match_dir_item_name(root, &path, buf, strlen(buf))) {
|
if (!btrfs_match_dir_item_name(root, &path, buf, strlen(buf))) {
|
||||||
@ -96,7 +99,8 @@ static int ins_one(struct btrfs_root *root, struct radix_tree_root *radix)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int insert_dup(struct btrfs_root *root, struct radix_tree_root *radix)
|
static int insert_dup(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
|
*root, struct radix_tree_root *radix)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
char buf[128];
|
char buf[128];
|
||||||
@ -107,8 +111,8 @@ static int insert_dup(struct btrfs_root *root, struct radix_tree_root *radix)
|
|||||||
return 0;
|
return 0;
|
||||||
sprintf(buf, "str-%lu", oid);
|
sprintf(buf, "str-%lu", oid);
|
||||||
|
|
||||||
ret = btrfs_insert_dir_item(root, buf, strlen(buf), dir_oid, file_oid,
|
ret = btrfs_insert_dir_item(trans, root, buf, strlen(buf), dir_oid,
|
||||||
1);
|
file_oid, 1);
|
||||||
if (ret != -EEXIST) {
|
if (ret != -EEXIST) {
|
||||||
printf("insert on %s gave us %d\n", buf, ret);
|
printf("insert on %s gave us %d\n", buf, ret);
|
||||||
return 1;
|
return 1;
|
||||||
@ -116,7 +120,8 @@ static int insert_dup(struct btrfs_root *root, struct radix_tree_root *radix)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int del_one(struct btrfs_root *root, struct radix_tree_root *radix)
|
static int del_one(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
|
struct radix_tree_root *radix)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
char buf[128];
|
char buf[128];
|
||||||
@ -129,10 +134,11 @@ static int del_one(struct btrfs_root *root, struct radix_tree_root *radix)
|
|||||||
return 0;
|
return 0;
|
||||||
sprintf(buf, "str-%lu", oid);
|
sprintf(buf, "str-%lu", oid);
|
||||||
btrfs_init_path(&path);
|
btrfs_init_path(&path);
|
||||||
ret = btrfs_lookup_dir_item(root, &path, dir_oid, buf, strlen(buf), -1);
|
ret = btrfs_lookup_dir_item(trans, root, &path, dir_oid, buf,
|
||||||
|
strlen(buf), -1);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_release;
|
goto out_release;
|
||||||
ret = btrfs_del_item(root, &path);
|
ret = btrfs_del_item(trans, root, &path);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_release;
|
goto out_release;
|
||||||
btrfs_release_path(root, &path);
|
btrfs_release_path(root, &path);
|
||||||
@ -149,7 +155,8 @@ static int del_one(struct btrfs_root *root, struct radix_tree_root *radix)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lookup_item(struct btrfs_root *root, struct radix_tree_root *radix)
|
static int lookup_item(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
|
*root, struct radix_tree_root *radix)
|
||||||
{
|
{
|
||||||
struct btrfs_path path;
|
struct btrfs_path path;
|
||||||
char buf[128];
|
char buf[128];
|
||||||
@ -161,7 +168,8 @@ static int lookup_item(struct btrfs_root *root, struct radix_tree_root *radix)
|
|||||||
return 0;
|
return 0;
|
||||||
sprintf(buf, "str-%lu", oid);
|
sprintf(buf, "str-%lu", oid);
|
||||||
btrfs_init_path(&path);
|
btrfs_init_path(&path);
|
||||||
ret = btrfs_lookup_dir_item(root, &path, dir_oid, buf, strlen(buf), 0);
|
ret = btrfs_lookup_dir_item(trans, root, &path, dir_oid, buf,
|
||||||
|
strlen(buf), 0);
|
||||||
btrfs_release_path(root, &path);
|
btrfs_release_path(root, &path);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printf("unable to find key %lu\n", oid);
|
printf("unable to find key %lu\n", oid);
|
||||||
@ -170,7 +178,8 @@ static int lookup_item(struct btrfs_root *root, struct radix_tree_root *radix)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lookup_enoent(struct btrfs_root *root, struct radix_tree_root *radix)
|
static int lookup_enoent(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
|
*root, struct radix_tree_root *radix)
|
||||||
{
|
{
|
||||||
struct btrfs_path path;
|
struct btrfs_path path;
|
||||||
char buf[128];
|
char buf[128];
|
||||||
@ -182,7 +191,8 @@ static int lookup_enoent(struct btrfs_root *root, struct radix_tree_root *radix)
|
|||||||
return 0;
|
return 0;
|
||||||
sprintf(buf, "str-%lu", oid);
|
sprintf(buf, "str-%lu", oid);
|
||||||
btrfs_init_path(&path);
|
btrfs_init_path(&path);
|
||||||
ret = btrfs_lookup_dir_item(root, &path, dir_oid, buf, strlen(buf), 0);
|
ret = btrfs_lookup_dir_item(trans, root, &path, dir_oid, buf,
|
||||||
|
strlen(buf), 0);
|
||||||
btrfs_release_path(root, &path);
|
btrfs_release_path(root, &path);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
printf("able to find key that should not exist %lu\n", oid);
|
printf("able to find key that should not exist %lu\n", oid);
|
||||||
@ -191,8 +201,8 @@ static int lookup_enoent(struct btrfs_root *root, struct radix_tree_root *radix)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int empty_tree(struct btrfs_root *root, struct radix_tree_root *radix,
|
static int empty_tree(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
int nr)
|
*root, struct radix_tree_root *radix, int nr)
|
||||||
{
|
{
|
||||||
struct btrfs_path path;
|
struct btrfs_path path;
|
||||||
struct btrfs_key key;
|
struct btrfs_key key;
|
||||||
@ -211,7 +221,7 @@ static int empty_tree(struct btrfs_root *root, struct radix_tree_root *radix,
|
|||||||
key.objectid = dir_oid;
|
key.objectid = dir_oid;
|
||||||
while(nr-- >= 0) {
|
while(nr-- >= 0) {
|
||||||
btrfs_init_path(&path);
|
btrfs_init_path(&path);
|
||||||
ret = btrfs_search_slot(root, &key, &path, -1, 1);
|
ret = btrfs_search_slot(trans, root, &key, &path, -1, 1);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
btrfs_release_path(root, &path);
|
btrfs_release_path(root, &path);
|
||||||
return ret;
|
return ret;
|
||||||
@ -231,7 +241,7 @@ static int empty_tree(struct btrfs_root *root, struct radix_tree_root *radix,
|
|||||||
BUG_ON(found_len > 128);
|
BUG_ON(found_len > 128);
|
||||||
buf[found_len] = '\0';
|
buf[found_len] = '\0';
|
||||||
found = atoi(buf + 4);
|
found = atoi(buf + 4);
|
||||||
ret = btrfs_del_item(root, &path);
|
ret = btrfs_del_item(trans, root, &path);
|
||||||
count++;
|
count++;
|
||||||
if (ret) {
|
if (ret) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@ -252,19 +262,19 @@ static int empty_tree(struct btrfs_root *root, struct radix_tree_root *radix,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fill_tree(struct btrfs_root *root, struct radix_tree_root *radix,
|
static int fill_tree(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
int count)
|
struct radix_tree_root *radix, int count)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
ret = ins_one(root, radix);
|
ret = ins_one(trans, root, radix);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
fprintf(stderr, "fill failed\n");
|
fprintf(stderr, "fill failed\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (i % 1000 == 0) {
|
if (i % 1000 == 0) {
|
||||||
ret = btrfs_commit_transaction(root, &super);
|
ret = btrfs_commit_transaction(trans, root, &super);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
fprintf(stderr, "fill commit failed\n");
|
fprintf(stderr, "fill commit failed\n");
|
||||||
return ret;
|
return ret;
|
||||||
@ -280,7 +290,8 @@ static int fill_tree(struct btrfs_root *root, struct radix_tree_root *radix,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bulk_op(struct btrfs_root *root, struct radix_tree_root *radix)
|
static int bulk_op(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
|
struct radix_tree_root *radix)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
int nr = rand() % 5000;
|
int nr = rand() % 5000;
|
||||||
@ -289,17 +300,18 @@ static int bulk_op(struct btrfs_root *root, struct radix_tree_root *radix)
|
|||||||
/* do the bulk op much less frequently */
|
/* do the bulk op much less frequently */
|
||||||
if (run_nr++ % 100)
|
if (run_nr++ % 100)
|
||||||
return 0;
|
return 0;
|
||||||
ret = empty_tree(root, radix, nr);
|
ret = empty_tree(trans, root, radix, nr);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
ret = fill_tree(root, radix, nr);
|
ret = fill_tree(trans, root, radix, nr);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int (*ops[])(struct btrfs_root *root, struct radix_tree_root *radix) =
|
int (*ops[])(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct
|
||||||
|
radix_tree_root *radix) =
|
||||||
{ ins_one, insert_dup, del_one, lookup_item,
|
{ ins_one, insert_dup, del_one, lookup_item,
|
||||||
lookup_enoent, bulk_op };
|
lookup_enoent, bulk_op };
|
||||||
|
|
||||||
@ -330,11 +342,13 @@ int main(int ac, char **av)
|
|||||||
int init_fill_count = 800000;
|
int init_fill_count = 800000;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
int initial_only = 0;
|
int initial_only = 0;
|
||||||
|
struct btrfs_trans_handle *trans;
|
||||||
radix_tree_init();
|
radix_tree_init();
|
||||||
|
|
||||||
printf("removing old tree\n");
|
printf("removing old tree\n");
|
||||||
unlink("dbfile");
|
unlink("dbfile");
|
||||||
root = open_ctree("dbfile", &super);
|
root = open_ctree("dbfile", &super);
|
||||||
|
trans = btrfs_start_transaction(root, 1);
|
||||||
|
|
||||||
signal(SIGTERM, sigstopper);
|
signal(SIGTERM, sigstopper);
|
||||||
signal(SIGINT, sigstopper);
|
signal(SIGINT, sigstopper);
|
||||||
@ -353,7 +367,7 @@ int main(int ac, char **av)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("initial fill\n");
|
printf("initial fill\n");
|
||||||
ret = fill_tree(root, &radix, init_fill_count);
|
ret = fill_tree(trans, root, &radix, init_fill_count);
|
||||||
printf("starting run\n");
|
printf("starting run\n");
|
||||||
if (ret) {
|
if (ret) {
|
||||||
err = ret;
|
err = ret;
|
||||||
@ -377,7 +391,7 @@ int main(int ac, char **av)
|
|||||||
root = open_ctree("dbfile", &super);
|
root = open_ctree("dbfile", &super);
|
||||||
}
|
}
|
||||||
while(count--) {
|
while(count--) {
|
||||||
ret = ops[op](root, &radix);
|
ret = ops[op](trans, root, &radix);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
fprintf(stderr, "op %d failed %d:%d\n",
|
fprintf(stderr, "op %d failed %d:%d\n",
|
||||||
op, i, iterations);
|
op, i, iterations);
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "radix-tree.h"
|
#include "radix-tree.h"
|
||||||
#include "ctree.h"
|
#include "ctree.h"
|
||||||
#include "disk-io.h"
|
#include "disk-io.h"
|
||||||
|
#include "transaction.h"
|
||||||
|
|
||||||
static int allocated_blocks = 0;
|
static int allocated_blocks = 0;
|
||||||
int cache_max = 10000;
|
int cache_max = 10000;
|
||||||
@ -107,7 +108,8 @@ struct btrfs_buffer *read_tree_block(struct btrfs_root *root, u64 blocknr)
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dirty_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf)
|
int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
|
struct btrfs_buffer *buf)
|
||||||
{
|
{
|
||||||
if (!list_empty(&buf->dirty))
|
if (!list_empty(&buf->dirty))
|
||||||
return 0;
|
return 0;
|
||||||
@ -116,7 +118,8 @@ int dirty_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int clean_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf)
|
int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
|
struct btrfs_buffer *buf)
|
||||||
{
|
{
|
||||||
if (!list_empty(&buf->dirty)) {
|
if (!list_empty(&buf->dirty)) {
|
||||||
list_del_init(&buf->dirty);
|
list_del_init(&buf->dirty);
|
||||||
@ -125,7 +128,8 @@ int clean_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int write_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf)
|
int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
|
struct btrfs_buffer *buf)
|
||||||
{
|
{
|
||||||
u64 blocknr = buf->blocknr;
|
u64 blocknr = buf->blocknr;
|
||||||
loff_t offset = blocknr * root->blocksize;
|
loff_t offset = blocknr * root->blocksize;
|
||||||
@ -139,7 +143,8 @@ int write_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __commit_transaction(struct btrfs_root *root)
|
static int __commit_transaction(struct btrfs_trans_handle *trans, struct
|
||||||
|
btrfs_root *root)
|
||||||
{
|
{
|
||||||
struct btrfs_buffer *b;
|
struct btrfs_buffer *b;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@ -147,7 +152,7 @@ static int __commit_transaction(struct btrfs_root *root)
|
|||||||
while(!list_empty(&root->trans)) {
|
while(!list_empty(&root->trans)) {
|
||||||
b = list_entry(root->trans.next, struct btrfs_buffer, dirty);
|
b = list_entry(root->trans.next, struct btrfs_buffer, dirty);
|
||||||
list_del_init(&b->dirty);
|
list_del_init(&b->dirty);
|
||||||
wret = write_tree_block(root, b);
|
wret = write_tree_block(trans, root, b);
|
||||||
if (wret)
|
if (wret)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
btrfs_block_release(root, b);
|
btrfs_block_release(root, b);
|
||||||
@ -155,8 +160,9 @@ static int __commit_transaction(struct btrfs_root *root)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int commit_extent_and_tree_roots(struct btrfs_root *tree_root,
|
static int commit_extent_and_tree_roots(struct btrfs_trans_handle *trans,
|
||||||
struct btrfs_root *extent_root)
|
struct btrfs_root *tree_root, struct
|
||||||
|
btrfs_root *extent_root)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
u64 old_extent_block;
|
u64 old_extent_block;
|
||||||
@ -167,24 +173,24 @@ static int commit_extent_and_tree_roots(struct btrfs_root *tree_root,
|
|||||||
break;
|
break;
|
||||||
btrfs_set_root_blocknr(&extent_root->root_item,
|
btrfs_set_root_blocknr(&extent_root->root_item,
|
||||||
extent_root->node->blocknr);
|
extent_root->node->blocknr);
|
||||||
ret = btrfs_update_root(tree_root,
|
ret = btrfs_update_root(trans, tree_root,
|
||||||
&extent_root->root_key,
|
&extent_root->root_key,
|
||||||
&extent_root->root_item);
|
&extent_root->root_item);
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
}
|
}
|
||||||
__commit_transaction(extent_root);
|
__commit_transaction(trans, extent_root);
|
||||||
__commit_transaction(tree_root);
|
__commit_transaction(trans, tree_root);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int btrfs_commit_transaction(struct btrfs_root *root,
|
int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct
|
||||||
struct btrfs_super_block *s)
|
btrfs_root *root, struct btrfs_super_block *s)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct btrfs_buffer *snap = root->commit_root;
|
struct btrfs_buffer *snap = root->commit_root;
|
||||||
struct btrfs_key snap_key;
|
struct btrfs_key snap_key;
|
||||||
|
|
||||||
ret = __commit_transaction(root);
|
ret = __commit_transaction(trans, root);
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
|
|
||||||
if (root->commit_root == root->node)
|
if (root->commit_root == root->node)
|
||||||
@ -194,23 +200,24 @@ int btrfs_commit_transaction(struct btrfs_root *root,
|
|||||||
root->root_key.offset++;
|
root->root_key.offset++;
|
||||||
|
|
||||||
btrfs_set_root_blocknr(&root->root_item, root->node->blocknr);
|
btrfs_set_root_blocknr(&root->root_item, root->node->blocknr);
|
||||||
ret = btrfs_insert_root(root->tree_root, &root->root_key,
|
ret = btrfs_insert_root(trans, root->tree_root, &root->root_key,
|
||||||
&root->root_item);
|
&root->root_item);
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
|
|
||||||
ret = commit_extent_and_tree_roots(root->tree_root, root->extent_root);
|
ret = commit_extent_and_tree_roots(trans, root->tree_root,
|
||||||
|
root->extent_root);
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
|
|
||||||
write_ctree_super(root, s);
|
write_ctree_super(trans, root, s);
|
||||||
btrfs_finish_extent_commit(root->extent_root);
|
btrfs_finish_extent_commit(trans, root->extent_root);
|
||||||
btrfs_finish_extent_commit(root->tree_root);
|
btrfs_finish_extent_commit(trans, root->tree_root);
|
||||||
|
|
||||||
root->commit_root = root->node;
|
root->commit_root = root->node;
|
||||||
root->node->count++;
|
root->node->count++;
|
||||||
ret = btrfs_drop_snapshot(root, snap);
|
ret = btrfs_drop_snapshot(trans, root, snap);
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
|
|
||||||
ret = btrfs_del_root(root->tree_root, &snap_key);
|
ret = btrfs_del_root(trans, root->tree_root, &snap_key);
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -312,7 +319,8 @@ struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *super)
|
|||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
int write_ctree_super(struct btrfs_root *root, struct btrfs_super_block *s)
|
int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
|
*root, struct btrfs_super_block *s)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
btrfs_set_super_root(s, root->tree_root->node->blocknr);
|
btrfs_set_super_root(s, root->tree_root->node->blocknr);
|
||||||
@ -338,10 +346,14 @@ static int drop_cache(struct btrfs_root *root)
|
|||||||
int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s)
|
int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
btrfs_commit_transaction(root, s);
|
struct btrfs_trans_handle *trans;
|
||||||
ret = commit_extent_and_tree_roots(root->tree_root, root->extent_root);
|
|
||||||
|
trans = root->running_transaction;
|
||||||
|
btrfs_commit_transaction(trans, root, s);
|
||||||
|
ret = commit_extent_and_tree_roots(trans, root->tree_root,
|
||||||
|
root->extent_root);
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
write_ctree_super(root, s);
|
write_ctree_super(trans, root, s);
|
||||||
drop_cache(root->extent_root);
|
drop_cache(root->extent_root);
|
||||||
drop_cache(root->tree_root);
|
drop_cache(root->tree_root);
|
||||||
drop_cache(root);
|
drop_cache(root);
|
||||||
|
@ -15,15 +15,19 @@ struct btrfs_buffer {
|
|||||||
|
|
||||||
struct btrfs_buffer *read_tree_block(struct btrfs_root *root, u64 blocknr);
|
struct btrfs_buffer *read_tree_block(struct btrfs_root *root, u64 blocknr);
|
||||||
struct btrfs_buffer *find_tree_block(struct btrfs_root *root, u64 blocknr);
|
struct btrfs_buffer *find_tree_block(struct btrfs_root *root, u64 blocknr);
|
||||||
int write_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf);
|
int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
int dirty_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf);
|
struct btrfs_buffer *buf);
|
||||||
int clean_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf);
|
int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
int btrfs_commit_transaction(struct btrfs_root *root,
|
struct btrfs_buffer *buf);
|
||||||
struct btrfs_super_block *s);
|
int clean_tree_block(struct btrfs_trans_handle *trans,
|
||||||
|
struct btrfs_root *root, struct btrfs_buffer *buf);
|
||||||
|
int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
|
*root, struct btrfs_super_block *s);
|
||||||
struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *s);
|
struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *s);
|
||||||
int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s);
|
int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s);
|
||||||
void btrfs_block_release(struct btrfs_root *root, struct btrfs_buffer *buf);
|
void btrfs_block_release(struct btrfs_root *root, struct btrfs_buffer *buf);
|
||||||
int write_ctree_super(struct btrfs_root *root, struct btrfs_super_block *s);
|
int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
|
struct btrfs_super_block *s);
|
||||||
int mkfs(int fd, u64 num_blocks, u32 blocksize);
|
int mkfs(int fd, u64 num_blocks, u32 blocksize);
|
||||||
|
|
||||||
#define BTRFS_SUPER_INFO_OFFSET (16 * 1024)
|
#define BTRFS_SUPER_INFO_OFFSET (16 * 1024)
|
||||||
|
@ -5,12 +5,15 @@
|
|||||||
#include "ctree.h"
|
#include "ctree.h"
|
||||||
#include "disk-io.h"
|
#include "disk-io.h"
|
||||||
#include "print-tree.h"
|
#include "print-tree.h"
|
||||||
|
#include "transaction.h"
|
||||||
|
|
||||||
static int find_free_extent(struct btrfs_root *orig_root, u64 num_blocks,
|
static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
u64 search_start, u64 search_end,
|
*orig_root, u64 num_blocks, u64 search_start, u64
|
||||||
struct btrfs_key *ins);
|
search_end, struct btrfs_key *ins);
|
||||||
static int finish_current_insert(struct btrfs_root *extent_root);
|
static int finish_current_insert(struct btrfs_trans_handle *trans, struct
|
||||||
static int run_pending(struct btrfs_root *extent_root);
|
btrfs_root *extent_root);
|
||||||
|
static int run_pending(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
|
*extent_root);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* pending extents are blocks that we're trying to allocate in the extent
|
* pending extents are blocks that we're trying to allocate in the extent
|
||||||
@ -21,7 +24,8 @@ static int run_pending(struct btrfs_root *extent_root);
|
|||||||
*/
|
*/
|
||||||
#define CTREE_EXTENT_PENDING_DEL 0
|
#define CTREE_EXTENT_PENDING_DEL 0
|
||||||
|
|
||||||
static int inc_block_ref(struct btrfs_root *root, u64 blocknr)
|
static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
|
*root, u64 blocknr)
|
||||||
{
|
{
|
||||||
struct btrfs_path path;
|
struct btrfs_path path;
|
||||||
int ret;
|
int ret;
|
||||||
@ -31,13 +35,13 @@ static int inc_block_ref(struct btrfs_root *root, u64 blocknr)
|
|||||||
struct btrfs_key ins;
|
struct btrfs_key ins;
|
||||||
u32 refs;
|
u32 refs;
|
||||||
|
|
||||||
find_free_extent(root->extent_root, 0, 0, (u64)-1, &ins);
|
find_free_extent(trans, root->extent_root, 0, 0, (u64)-1, &ins);
|
||||||
btrfs_init_path(&path);
|
btrfs_init_path(&path);
|
||||||
key.objectid = blocknr;
|
key.objectid = blocknr;
|
||||||
key.flags = 0;
|
key.flags = 0;
|
||||||
btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
|
btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
|
||||||
key.offset = 1;
|
key.offset = 1;
|
||||||
ret = btrfs_search_slot(root->extent_root, &key, &path, 0, 1);
|
ret = btrfs_search_slot(trans, root->extent_root, &key, &path, 0, 1);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
BUG();
|
BUG();
|
||||||
BUG_ON(ret != 0);
|
BUG_ON(ret != 0);
|
||||||
@ -48,12 +52,13 @@ static int inc_block_ref(struct btrfs_root *root, u64 blocknr)
|
|||||||
|
|
||||||
BUG_ON(list_empty(&path.nodes[0]->dirty));
|
BUG_ON(list_empty(&path.nodes[0]->dirty));
|
||||||
btrfs_release_path(root->extent_root, &path);
|
btrfs_release_path(root->extent_root, &path);
|
||||||
finish_current_insert(root->extent_root);
|
finish_current_insert(trans, root->extent_root);
|
||||||
run_pending(root->extent_root);
|
run_pending(trans, root->extent_root);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lookup_block_ref(struct btrfs_root *root, u64 blocknr, u32 *refs)
|
static int lookup_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
|
*root, u64 blocknr, u32 *refs)
|
||||||
{
|
{
|
||||||
struct btrfs_path path;
|
struct btrfs_path path;
|
||||||
int ret;
|
int ret;
|
||||||
@ -65,7 +70,7 @@ static int lookup_block_ref(struct btrfs_root *root, u64 blocknr, u32 *refs)
|
|||||||
key.offset = 1;
|
key.offset = 1;
|
||||||
key.flags = 0;
|
key.flags = 0;
|
||||||
btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
|
btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
|
||||||
ret = btrfs_search_slot(root->extent_root, &key, &path, 0, 0);
|
ret = btrfs_search_slot(trans, root->extent_root, &key, &path, 0, 0);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
BUG();
|
BUG();
|
||||||
l = &path.nodes[0]->leaf;
|
l = &path.nodes[0]->leaf;
|
||||||
@ -75,7 +80,8 @@ static int lookup_block_ref(struct btrfs_root *root, u64 blocknr, u32 *refs)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int btrfs_inc_ref(struct btrfs_root *root, struct btrfs_buffer *buf)
|
int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
|
struct btrfs_buffer *buf)
|
||||||
{
|
{
|
||||||
u64 blocknr;
|
u64 blocknr;
|
||||||
int i;
|
int i;
|
||||||
@ -87,12 +93,13 @@ int btrfs_inc_ref(struct btrfs_root *root, struct btrfs_buffer *buf)
|
|||||||
|
|
||||||
for (i = 0; i < btrfs_header_nritems(&buf->node.header); i++) {
|
for (i = 0; i < btrfs_header_nritems(&buf->node.header); i++) {
|
||||||
blocknr = btrfs_node_blockptr(&buf->node, i);
|
blocknr = btrfs_node_blockptr(&buf->node, i);
|
||||||
inc_block_ref(root, blocknr);
|
inc_block_ref(trans, root, blocknr);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int btrfs_finish_extent_commit(struct btrfs_root *root)
|
int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
|
||||||
|
btrfs_root *root)
|
||||||
{
|
{
|
||||||
unsigned long gang[8];
|
unsigned long gang[8];
|
||||||
u64 first = 0;
|
u64 first = 0;
|
||||||
@ -116,7 +123,8 @@ int btrfs_finish_extent_commit(struct btrfs_root *root)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int finish_current_insert(struct btrfs_root *extent_root)
|
static int finish_current_insert(struct btrfs_trans_handle *trans, struct
|
||||||
|
btrfs_root *extent_root)
|
||||||
{
|
{
|
||||||
struct btrfs_key ins;
|
struct btrfs_key ins;
|
||||||
struct btrfs_extent_item extent_item;
|
struct btrfs_extent_item extent_item;
|
||||||
@ -132,8 +140,8 @@ static int finish_current_insert(struct btrfs_root *extent_root)
|
|||||||
|
|
||||||
for (i = 0; i < extent_root->current_insert.flags; i++) {
|
for (i = 0; i < extent_root->current_insert.flags; i++) {
|
||||||
ins.objectid = extent_root->current_insert.objectid + i;
|
ins.objectid = extent_root->current_insert.objectid + i;
|
||||||
ret = btrfs_insert_item(extent_root, &ins, &extent_item,
|
ret = btrfs_insert_item(trans, extent_root, &ins, &extent_item,
|
||||||
sizeof(extent_item));
|
sizeof(extent_item));
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
}
|
}
|
||||||
extent_root->current_insert.offset = 0;
|
extent_root->current_insert.offset = 0;
|
||||||
@ -143,8 +151,8 @@ static int finish_current_insert(struct btrfs_root *extent_root)
|
|||||||
/*
|
/*
|
||||||
* remove an extent from the root, returns 0 on success
|
* remove an extent from the root, returns 0 on success
|
||||||
*/
|
*/
|
||||||
static int __free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks,
|
static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
int pin)
|
*root, u64 blocknr, u64 num_blocks, int pin)
|
||||||
{
|
{
|
||||||
struct btrfs_path path;
|
struct btrfs_path path;
|
||||||
struct btrfs_key key;
|
struct btrfs_key key;
|
||||||
@ -160,9 +168,9 @@ static int __free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks,
|
|||||||
btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
|
btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
|
||||||
key.offset = num_blocks;
|
key.offset = num_blocks;
|
||||||
|
|
||||||
find_free_extent(root, 0, 0, (u64)-1, &ins);
|
find_free_extent(trans, root, 0, 0, (u64)-1, &ins);
|
||||||
btrfs_init_path(&path);
|
btrfs_init_path(&path);
|
||||||
ret = btrfs_search_slot(extent_root, &key, &path, -1, 1);
|
ret = btrfs_search_slot(trans, extent_root, &key, &path, -1, 1);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printf("failed to find %Lu\n", key.objectid);
|
printf("failed to find %Lu\n", key.objectid);
|
||||||
btrfs_print_tree(extent_root, extent_root->node);
|
btrfs_print_tree(extent_root, extent_root->node);
|
||||||
@ -183,14 +191,14 @@ static int __free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks,
|
|||||||
BUG_ON(err);
|
BUG_ON(err);
|
||||||
radix_tree_preload_end();
|
radix_tree_preload_end();
|
||||||
}
|
}
|
||||||
ret = btrfs_del_item(extent_root, &path);
|
ret = btrfs_del_item(trans, extent_root, &path);
|
||||||
if (!pin && extent_root->last_insert.objectid > blocknr)
|
if (!pin && extent_root->last_insert.objectid > blocknr)
|
||||||
extent_root->last_insert.objectid = blocknr;
|
extent_root->last_insert.objectid = blocknr;
|
||||||
if (ret)
|
if (ret)
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
btrfs_release_path(extent_root, &path);
|
btrfs_release_path(extent_root, &path);
|
||||||
finish_current_insert(extent_root);
|
finish_current_insert(trans, extent_root);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,7 +206,8 @@ static int __free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks,
|
|||||||
* find all the blocks marked as pending in the radix tree and remove
|
* find all the blocks marked as pending in the radix tree and remove
|
||||||
* them from the extent map
|
* them from the extent map
|
||||||
*/
|
*/
|
||||||
static int del_pending_extents(struct btrfs_root *extent_root)
|
static int del_pending_extents(struct btrfs_trans_handle *trans, struct
|
||||||
|
btrfs_root *extent_root)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct btrfs_buffer *gang[4];
|
struct btrfs_buffer *gang[4];
|
||||||
@ -212,7 +221,7 @@ static int del_pending_extents(struct btrfs_root *extent_root)
|
|||||||
if (!ret)
|
if (!ret)
|
||||||
break;
|
break;
|
||||||
for (i = 0; i < ret; i++) {
|
for (i = 0; i < ret; i++) {
|
||||||
ret = __free_extent(extent_root,
|
ret = __free_extent(trans, extent_root,
|
||||||
gang[i]->blocknr, 1, 1);
|
gang[i]->blocknr, 1, 1);
|
||||||
radix_tree_tag_clear(&extent_root->cache_radix,
|
radix_tree_tag_clear(&extent_root->cache_radix,
|
||||||
gang[i]->blocknr,
|
gang[i]->blocknr,
|
||||||
@ -223,11 +232,12 @@ static int del_pending_extents(struct btrfs_root *extent_root)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int run_pending(struct btrfs_root *extent_root)
|
static int run_pending(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
|
*extent_root)
|
||||||
{
|
{
|
||||||
while(radix_tree_tagged(&extent_root->cache_radix,
|
while(radix_tree_tagged(&extent_root->cache_radix,
|
||||||
CTREE_EXTENT_PENDING_DEL))
|
CTREE_EXTENT_PENDING_DEL))
|
||||||
del_pending_extents(extent_root);
|
del_pending_extents(trans, extent_root);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,8 +245,8 @@ static int run_pending(struct btrfs_root *extent_root)
|
|||||||
/*
|
/*
|
||||||
* remove an extent from the root, returns 0 on success
|
* remove an extent from the root, returns 0 on success
|
||||||
*/
|
*/
|
||||||
int btrfs_free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks,
|
int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
int pin)
|
*root, u64 blocknr, u64 num_blocks, int pin)
|
||||||
{
|
{
|
||||||
struct btrfs_root *extent_root = root->extent_root;
|
struct btrfs_root *extent_root = root->extent_root;
|
||||||
struct btrfs_buffer *t;
|
struct btrfs_buffer *t;
|
||||||
@ -249,8 +259,8 @@ int btrfs_free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks,
|
|||||||
CTREE_EXTENT_PENDING_DEL);
|
CTREE_EXTENT_PENDING_DEL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ret = __free_extent(root, blocknr, num_blocks, pin);
|
ret = __free_extent(trans, root, blocknr, num_blocks, pin);
|
||||||
pending_ret = run_pending(root->extent_root);
|
pending_ret = run_pending(trans, root->extent_root);
|
||||||
return ret ? ret : pending_ret;
|
return ret ? ret : pending_ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,9 +272,9 @@ int btrfs_free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks,
|
|||||||
* ins->offset == number of blocks
|
* ins->offset == number of blocks
|
||||||
* Any available blocks before search_start are skipped.
|
* Any available blocks before search_start are skipped.
|
||||||
*/
|
*/
|
||||||
static int find_free_extent(struct btrfs_root *orig_root, u64 num_blocks,
|
static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
u64 search_start, u64 search_end,
|
*orig_root, u64 num_blocks, u64 search_start, u64
|
||||||
struct btrfs_key *ins)
|
search_end, struct btrfs_key *ins)
|
||||||
{
|
{
|
||||||
struct btrfs_path path;
|
struct btrfs_path path;
|
||||||
struct btrfs_key key;
|
struct btrfs_key key;
|
||||||
@ -290,7 +300,7 @@ static int find_free_extent(struct btrfs_root *orig_root, u64 num_blocks,
|
|||||||
ins->objectid = search_start;
|
ins->objectid = search_start;
|
||||||
ins->offset = 0;
|
ins->offset = 0;
|
||||||
start_found = 0;
|
start_found = 0;
|
||||||
ret = btrfs_search_slot(root, ins, &path, 0, 0);
|
ret = btrfs_search_slot(trans, root, ins, &path, 0, 0);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -367,9 +377,9 @@ static int find_free_extent(struct btrfs_root *orig_root, u64 num_blocks,
|
|||||||
*
|
*
|
||||||
* returns 0 if everything worked, non-zero otherwise.
|
* returns 0 if everything worked, non-zero otherwise.
|
||||||
*/
|
*/
|
||||||
static int alloc_extent(struct btrfs_root *root, u64 num_blocks,
|
static int alloc_extent(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
u64 search_start, u64 search_end, u64 owner,
|
*root, u64 num_blocks, u64 search_start, u64
|
||||||
struct btrfs_key *ins)
|
search_end, u64 owner, struct btrfs_key *ins)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
int pending_ret;
|
int pending_ret;
|
||||||
@ -389,16 +399,16 @@ static int alloc_extent(struct btrfs_root *root, u64 num_blocks,
|
|||||||
extent_root->current_insert.flags++;
|
extent_root->current_insert.flags++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ret = find_free_extent(root, num_blocks, search_start,
|
ret = find_free_extent(trans, root, num_blocks, search_start,
|
||||||
search_end, ins);
|
search_end, ins);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = btrfs_insert_item(extent_root, ins, &extent_item,
|
ret = btrfs_insert_item(trans, extent_root, ins, &extent_item,
|
||||||
sizeof(extent_item));
|
sizeof(extent_item));
|
||||||
|
|
||||||
finish_current_insert(extent_root);
|
finish_current_insert(trans, extent_root);
|
||||||
pending_ret = run_pending(extent_root);
|
pending_ret = run_pending(trans, extent_root);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
if (pending_ret)
|
if (pending_ret)
|
||||||
@ -410,13 +420,14 @@ static int alloc_extent(struct btrfs_root *root, u64 num_blocks,
|
|||||||
* helper function to allocate a block for a given tree
|
* helper function to allocate a block for a given tree
|
||||||
* returns the tree buffer or NULL.
|
* returns the tree buffer or NULL.
|
||||||
*/
|
*/
|
||||||
struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_root *root)
|
struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
|
||||||
|
struct btrfs_root *root)
|
||||||
{
|
{
|
||||||
struct btrfs_key ins;
|
struct btrfs_key ins;
|
||||||
int ret;
|
int ret;
|
||||||
struct btrfs_buffer *buf;
|
struct btrfs_buffer *buf;
|
||||||
|
|
||||||
ret = alloc_extent(root, 1, 0, (unsigned long)-1,
|
ret = alloc_extent(trans, root, 1, 0, (unsigned long)-1,
|
||||||
btrfs_header_parentid(&root->node->node.header),
|
btrfs_header_parentid(&root->node->node.header),
|
||||||
&ins);
|
&ins);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@ -424,7 +435,7 @@ struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_root *root)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
buf = find_tree_block(root, ins.objectid);
|
buf = find_tree_block(root, ins.objectid);
|
||||||
dirty_tree_block(root, buf);
|
dirty_tree_block(trans, root, buf);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -432,8 +443,8 @@ struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_root *root)
|
|||||||
* helper function for drop_snapshot, this walks down the tree dropping ref
|
* helper function for drop_snapshot, this walks down the tree dropping ref
|
||||||
* counts as it goes.
|
* counts as it goes.
|
||||||
*/
|
*/
|
||||||
static int walk_down_tree(struct btrfs_root *root,
|
static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
struct btrfs_path *path, int *level)
|
*root, struct btrfs_path *path, int *level)
|
||||||
{
|
{
|
||||||
struct btrfs_buffer *next;
|
struct btrfs_buffer *next;
|
||||||
struct btrfs_buffer *cur;
|
struct btrfs_buffer *cur;
|
||||||
@ -441,7 +452,8 @@ static int walk_down_tree(struct btrfs_root *root,
|
|||||||
int ret;
|
int ret;
|
||||||
u32 refs;
|
u32 refs;
|
||||||
|
|
||||||
ret = lookup_block_ref(root, path->nodes[*level]->blocknr, &refs);
|
ret = lookup_block_ref(trans, root, path->nodes[*level]->blocknr,
|
||||||
|
&refs);
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
if (refs > 1)
|
if (refs > 1)
|
||||||
goto out;
|
goto out;
|
||||||
@ -454,10 +466,10 @@ static int walk_down_tree(struct btrfs_root *root,
|
|||||||
btrfs_header_nritems(&cur->node.header))
|
btrfs_header_nritems(&cur->node.header))
|
||||||
break;
|
break;
|
||||||
blocknr = btrfs_node_blockptr(&cur->node, path->slots[*level]);
|
blocknr = btrfs_node_blockptr(&cur->node, path->slots[*level]);
|
||||||
ret = lookup_block_ref(root, blocknr, &refs);
|
ret = lookup_block_ref(trans, root, blocknr, &refs);
|
||||||
if (refs != 1 || *level == 1) {
|
if (refs != 1 || *level == 1) {
|
||||||
path->slots[*level]++;
|
path->slots[*level]++;
|
||||||
ret = btrfs_free_extent(root, blocknr, 1, 1);
|
ret = btrfs_free_extent(trans, root, blocknr, 1, 1);
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -470,7 +482,8 @@ static int walk_down_tree(struct btrfs_root *root,
|
|||||||
path->slots[*level] = 0;
|
path->slots[*level] = 0;
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
ret = btrfs_free_extent(root, path->nodes[*level]->blocknr, 1, 1);
|
ret = btrfs_free_extent(trans, root, path->nodes[*level]->blocknr, 1,
|
||||||
|
1);
|
||||||
btrfs_block_release(root, path->nodes[*level]);
|
btrfs_block_release(root, path->nodes[*level]);
|
||||||
path->nodes[*level] = NULL;
|
path->nodes[*level] = NULL;
|
||||||
*level += 1;
|
*level += 1;
|
||||||
@ -483,8 +496,8 @@ static int walk_down_tree(struct btrfs_root *root,
|
|||||||
* to find the first node higher up where we haven't yet gone through
|
* to find the first node higher up where we haven't yet gone through
|
||||||
* all the slots
|
* all the slots
|
||||||
*/
|
*/
|
||||||
static int walk_up_tree(struct btrfs_root *root, struct btrfs_path *path,
|
static int walk_up_tree(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
int *level)
|
*root, struct btrfs_path *path, int *level)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int slot;
|
int slot;
|
||||||
@ -497,8 +510,9 @@ static int walk_up_tree(struct btrfs_root *root, struct btrfs_path *path,
|
|||||||
*level = i;
|
*level = i;
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
ret = btrfs_free_extent(root,
|
ret = btrfs_free_extent(trans, root,
|
||||||
path->nodes[*level]->blocknr, 1, 1);
|
path->nodes[*level]->blocknr,
|
||||||
|
1, 1);
|
||||||
btrfs_block_release(root, path->nodes[*level]);
|
btrfs_block_release(root, path->nodes[*level]);
|
||||||
path->nodes[*level] = NULL;
|
path->nodes[*level] = NULL;
|
||||||
*level = i + 1;
|
*level = i + 1;
|
||||||
@ -513,7 +527,8 @@ static int walk_up_tree(struct btrfs_root *root, struct btrfs_path *path,
|
|||||||
* the tree freeing any blocks that have a ref count of zero after being
|
* the tree freeing any blocks that have a ref count of zero after being
|
||||||
* decremented.
|
* decremented.
|
||||||
*/
|
*/
|
||||||
int btrfs_drop_snapshot(struct btrfs_root *root, struct btrfs_buffer *snap)
|
int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
|
*root, struct btrfs_buffer *snap)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int wret;
|
int wret;
|
||||||
@ -529,13 +544,13 @@ int btrfs_drop_snapshot(struct btrfs_root *root, struct btrfs_buffer *snap)
|
|||||||
path.nodes[level] = snap;
|
path.nodes[level] = snap;
|
||||||
path.slots[level] = 0;
|
path.slots[level] = 0;
|
||||||
while(1) {
|
while(1) {
|
||||||
wret = walk_down_tree(root, &path, &level);
|
wret = walk_down_tree(trans, root, &path, &level);
|
||||||
if (wret > 0)
|
if (wret > 0)
|
||||||
break;
|
break;
|
||||||
if (wret < 0)
|
if (wret < 0)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
|
|
||||||
wret = walk_up_tree(root, &path, &level);
|
wret = walk_up_tree(trans, root, &path, &level);
|
||||||
if (wret > 0)
|
if (wret > 0)
|
||||||
break;
|
break;
|
||||||
if (wret < 0)
|
if (wret < 0)
|
||||||
|
@ -4,9 +4,11 @@
|
|||||||
#include "radix-tree.h"
|
#include "radix-tree.h"
|
||||||
#include "ctree.h"
|
#include "ctree.h"
|
||||||
#include "disk-io.h"
|
#include "disk-io.h"
|
||||||
|
#include "transaction.h"
|
||||||
|
|
||||||
int btrfs_insert_inode(struct btrfs_root *root, u64 objectid,
|
int btrfs_insert_inode(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
struct btrfs_inode_item *inode_item)
|
*root, u64 objectid, struct btrfs_inode_item
|
||||||
|
*inode_item)
|
||||||
{
|
{
|
||||||
struct btrfs_path path;
|
struct btrfs_path path;
|
||||||
struct btrfs_key key;
|
struct btrfs_key key;
|
||||||
@ -17,13 +19,14 @@ int btrfs_insert_inode(struct btrfs_root *root, u64 objectid,
|
|||||||
key.offset = 0;
|
key.offset = 0;
|
||||||
|
|
||||||
btrfs_init_path(&path);
|
btrfs_init_path(&path);
|
||||||
ret = btrfs_insert_item(root, &key, inode_item, sizeof(*inode_item));
|
ret = btrfs_insert_item(trans, root, &key, inode_item,
|
||||||
|
sizeof(*inode_item));
|
||||||
btrfs_release_path(root, &path);
|
btrfs_release_path(root, &path);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int btrfs_lookup_inode(struct btrfs_root *root, struct btrfs_path *path,
|
int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
u64 objectid, int mod)
|
*root, struct btrfs_path *path, u64 objectid, int mod)
|
||||||
{
|
{
|
||||||
struct btrfs_key key;
|
struct btrfs_key key;
|
||||||
int ins_len = mod < 0 ? -1 : 0;
|
int ins_len = mod < 0 ? -1 : 0;
|
||||||
@ -33,5 +36,5 @@ int btrfs_lookup_inode(struct btrfs_root *root, struct btrfs_path *path,
|
|||||||
key.flags = 0;
|
key.flags = 0;
|
||||||
btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY);
|
btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY);
|
||||||
key.offset = 0;
|
key.offset = 0;
|
||||||
return btrfs_search_slot(root, &key, path, ins_len, cow);
|
return btrfs_search_slot(trans, root, &key, path, ins_len, cow);
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#ifndef __PRINT_TREE_
|
||||||
|
#define __PRINT_TREE_
|
||||||
void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l);
|
void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l);
|
||||||
void btrfs_print_tree(struct btrfs_root *root, struct btrfs_buffer *t);
|
void btrfs_print_tree(struct btrfs_root *root, struct btrfs_buffer *t);
|
||||||
|
#endif
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "ctree.h"
|
#include "ctree.h"
|
||||||
#include "disk-io.h"
|
#include "disk-io.h"
|
||||||
#include "print-tree.h"
|
#include "print-tree.h"
|
||||||
|
#include "transaction.h"
|
||||||
|
|
||||||
/* for testing only */
|
/* for testing only */
|
||||||
int next_key(int i, int max_key) {
|
int next_key(int i, int max_key) {
|
||||||
@ -25,10 +26,12 @@ int main(int ac, char **av) {
|
|||||||
struct btrfs_path path;
|
struct btrfs_path path;
|
||||||
struct btrfs_super_block super;
|
struct btrfs_super_block super;
|
||||||
struct btrfs_root *root;
|
struct btrfs_root *root;
|
||||||
|
struct btrfs_trans_handle *trans;
|
||||||
|
|
||||||
radix_tree_init();
|
radix_tree_init();
|
||||||
|
|
||||||
root = open_ctree("dbfile", &super);
|
root = open_ctree("dbfile", &super);
|
||||||
|
trans = btrfs_start_transaction(root, 1);
|
||||||
srand(55);
|
srand(55);
|
||||||
ins.flags = 0;
|
ins.flags = 0;
|
||||||
btrfs_set_key_type(&ins, BTRFS_STRING_ITEM_KEY);
|
btrfs_set_key_type(&ins, BTRFS_STRING_ITEM_KEY);
|
||||||
@ -41,12 +44,12 @@ int main(int ac, char **av) {
|
|||||||
fprintf(stderr, "insert %d:%d\n", num, i);
|
fprintf(stderr, "insert %d:%d\n", num, i);
|
||||||
ins.objectid = num;
|
ins.objectid = num;
|
||||||
ins.offset = 0;
|
ins.offset = 0;
|
||||||
ret = btrfs_insert_item(root, &ins, buf, strlen(buf));
|
ret = btrfs_insert_item(trans, root, &ins, buf, strlen(buf));
|
||||||
if (!ret)
|
if (!ret)
|
||||||
tree_size++;
|
tree_size++;
|
||||||
free(buf);
|
free(buf);
|
||||||
if (i == run_size - 5) {
|
if (i == run_size - 5) {
|
||||||
btrfs_commit_transaction(root, &super);
|
btrfs_commit_transaction(trans, root, &super);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -61,7 +64,7 @@ int main(int ac, char **av) {
|
|||||||
btrfs_init_path(&path);
|
btrfs_init_path(&path);
|
||||||
if (i % 10000 == 0)
|
if (i % 10000 == 0)
|
||||||
fprintf(stderr, "search %d:%d\n", num, i);
|
fprintf(stderr, "search %d:%d\n", num, i);
|
||||||
ret = btrfs_search_slot(root, &ins, &path, 0, 0);
|
ret = btrfs_search_slot(trans, root, &ins, &path, 0, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
btrfs_print_tree(root, root->node);
|
btrfs_print_tree(root, root->node);
|
||||||
printf("unable to find %d\n", num);
|
printf("unable to find %d\n", num);
|
||||||
@ -83,11 +86,11 @@ int main(int ac, char **av) {
|
|||||||
num = next_key(i, max_key);
|
num = next_key(i, max_key);
|
||||||
ins.objectid = num;
|
ins.objectid = num;
|
||||||
btrfs_init_path(&path);
|
btrfs_init_path(&path);
|
||||||
ret = btrfs_search_slot(root, &ins, &path, -1, 1);
|
ret = btrfs_search_slot(trans, root, &ins, &path, -1, 1);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
if (i % 10000 == 0)
|
if (i % 10000 == 0)
|
||||||
fprintf(stderr, "del %d:%d\n", num, i);
|
fprintf(stderr, "del %d:%d\n", num, i);
|
||||||
ret = btrfs_del_item(root, &path);
|
ret = btrfs_del_item(trans, root, &path);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
BUG();
|
BUG();
|
||||||
tree_size--;
|
tree_size--;
|
||||||
@ -104,7 +107,7 @@ int main(int ac, char **av) {
|
|||||||
ins.objectid = num;
|
ins.objectid = num;
|
||||||
if (i % 10000 == 0)
|
if (i % 10000 == 0)
|
||||||
fprintf(stderr, "insert %d:%d\n", num, i);
|
fprintf(stderr, "insert %d:%d\n", num, i);
|
||||||
ret = btrfs_insert_item(root, &ins, buf, strlen(buf));
|
ret = btrfs_insert_item(trans, root, &ins, buf, strlen(buf));
|
||||||
if (!ret)
|
if (!ret)
|
||||||
tree_size++;
|
tree_size++;
|
||||||
free(buf);
|
free(buf);
|
||||||
@ -119,7 +122,7 @@ int main(int ac, char **av) {
|
|||||||
btrfs_init_path(&path);
|
btrfs_init_path(&path);
|
||||||
if (i % 10000 == 0)
|
if (i % 10000 == 0)
|
||||||
fprintf(stderr, "search %d:%d\n", num, i);
|
fprintf(stderr, "search %d:%d\n", num, i);
|
||||||
ret = btrfs_search_slot(root, &ins, &path, 0, 0);
|
ret = btrfs_search_slot(trans, root, &ins, &path, 0, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
btrfs_print_tree(root, root->node);
|
btrfs_print_tree(root, root->node);
|
||||||
printf("unable to find %d\n", num);
|
printf("unable to find %d\n", num);
|
||||||
@ -134,7 +137,7 @@ int main(int ac, char **av) {
|
|||||||
int slot;
|
int slot;
|
||||||
ins.objectid = (u64)-1;
|
ins.objectid = (u64)-1;
|
||||||
btrfs_init_path(&path);
|
btrfs_init_path(&path);
|
||||||
ret = btrfs_search_slot(root, &ins, &path, -1, 1);
|
ret = btrfs_search_slot(trans, root, &ins, &path, -1, 1);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
BUG();
|
BUG();
|
||||||
|
|
||||||
@ -150,7 +153,7 @@ int main(int ac, char **av) {
|
|||||||
btrfs_disk_key_to_cpu(&last, &leaf->items[slot].key);
|
btrfs_disk_key_to_cpu(&last, &leaf->items[slot].key);
|
||||||
if (tree_size % 10000 == 0)
|
if (tree_size % 10000 == 0)
|
||||||
printf("big del %d:%d\n", tree_size, i);
|
printf("big del %d:%d\n", tree_size, i);
|
||||||
ret = btrfs_del_item(root, &path);
|
ret = btrfs_del_item(trans, root, &path);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
printf("del_item returned %d\n", ret);
|
printf("del_item returned %d\n", ret);
|
||||||
BUG();
|
BUG();
|
||||||
@ -165,7 +168,7 @@ int main(int ac, char **av) {
|
|||||||
printf("map before commit\n");
|
printf("map before commit\n");
|
||||||
btrfs_print_tree(root->extent_root, root->extent_root->node);
|
btrfs_print_tree(root->extent_root, root->extent_root->node);
|
||||||
*/
|
*/
|
||||||
btrfs_commit_transaction(root, &super);
|
btrfs_commit_transaction(trans, root, &super);
|
||||||
printf("tree size is now %d\n", tree_size);
|
printf("tree size is now %d\n", tree_size);
|
||||||
printf("root %p commit root %p\n", root->node, root->commit_root);
|
printf("root %p commit root %p\n", root->node, root->commit_root);
|
||||||
printf("map tree\n");
|
printf("map tree\n");
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "ctree.h"
|
#include "ctree.h"
|
||||||
#include "disk-io.h"
|
#include "disk-io.h"
|
||||||
#include "print-tree.h"
|
#include "print-tree.h"
|
||||||
|
#include "transaction.h"
|
||||||
|
|
||||||
int keep_running = 1;
|
int keep_running = 1;
|
||||||
struct btrfs_super_block super;
|
struct btrfs_super_block super;
|
||||||
@ -37,7 +38,8 @@ static int setup_key(struct radix_tree_root *root, struct btrfs_key *key,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ins_one(struct btrfs_root *root, struct radix_tree_root *radix)
|
static int ins_one(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
|
struct radix_tree_root *radix)
|
||||||
{
|
{
|
||||||
struct btrfs_path path;
|
struct btrfs_path path;
|
||||||
struct btrfs_key key;
|
struct btrfs_key key;
|
||||||
@ -47,7 +49,7 @@ static int ins_one(struct btrfs_root *root, struct radix_tree_root *radix)
|
|||||||
btrfs_init_path(&path);
|
btrfs_init_path(&path);
|
||||||
ret = setup_key(radix, &key, 0);
|
ret = setup_key(radix, &key, 0);
|
||||||
sprintf(buf, "str-%Lu\n", key.objectid);
|
sprintf(buf, "str-%Lu\n", key.objectid);
|
||||||
ret = btrfs_insert_item(root, &key, buf, strlen(buf));
|
ret = btrfs_insert_item(trans, root, &key, buf, strlen(buf));
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
oid = (unsigned long)key.objectid;
|
oid = (unsigned long)key.objectid;
|
||||||
@ -62,7 +64,8 @@ static int ins_one(struct btrfs_root *root, struct radix_tree_root *radix)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int insert_dup(struct btrfs_root *root, struct radix_tree_root *radix)
|
static int insert_dup(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
|
*root, struct radix_tree_root *radix)
|
||||||
{
|
{
|
||||||
struct btrfs_path path;
|
struct btrfs_path path;
|
||||||
struct btrfs_key key;
|
struct btrfs_key key;
|
||||||
@ -73,7 +76,7 @@ static int insert_dup(struct btrfs_root *root, struct radix_tree_root *radix)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return 0;
|
return 0;
|
||||||
sprintf(buf, "str-%Lu\n", key.objectid);
|
sprintf(buf, "str-%Lu\n", key.objectid);
|
||||||
ret = btrfs_insert_item(root, &key, buf, strlen(buf));
|
ret = btrfs_insert_item(trans, root, &key, buf, strlen(buf));
|
||||||
if (ret != -EEXIST) {
|
if (ret != -EEXIST) {
|
||||||
printf("insert on %Lu gave us %d\n", key.objectid, ret);
|
printf("insert on %Lu gave us %d\n", key.objectid, ret);
|
||||||
return 1;
|
return 1;
|
||||||
@ -81,7 +84,8 @@ static int insert_dup(struct btrfs_root *root, struct radix_tree_root *radix)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int del_one(struct btrfs_root *root, struct radix_tree_root *radix)
|
static int del_one(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
|
struct radix_tree_root *radix)
|
||||||
{
|
{
|
||||||
struct btrfs_path path;
|
struct btrfs_path path;
|
||||||
struct btrfs_key key;
|
struct btrfs_key key;
|
||||||
@ -91,10 +95,10 @@ static int del_one(struct btrfs_root *root, struct radix_tree_root *radix)
|
|||||||
ret = setup_key(radix, &key, 1);
|
ret = setup_key(radix, &key, 1);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return 0;
|
return 0;
|
||||||
ret = btrfs_search_slot(root, &key, &path, -1, 1);
|
ret = btrfs_search_slot(trans, root, &key, &path, -1, 1);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
ret = btrfs_del_item(root, &path);
|
ret = btrfs_del_item(trans, root, &path);
|
||||||
btrfs_release_path(root, &path);
|
btrfs_release_path(root, &path);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
goto error;
|
goto error;
|
||||||
@ -107,7 +111,8 @@ static int del_one(struct btrfs_root *root, struct radix_tree_root *radix)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lookup_item(struct btrfs_root *root, struct radix_tree_root *radix)
|
static int lookup_item(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
|
*root, struct radix_tree_root *radix)
|
||||||
{
|
{
|
||||||
struct btrfs_path path;
|
struct btrfs_path path;
|
||||||
struct btrfs_key key;
|
struct btrfs_key key;
|
||||||
@ -116,7 +121,7 @@ static int lookup_item(struct btrfs_root *root, struct radix_tree_root *radix)
|
|||||||
ret = setup_key(radix, &key, 1);
|
ret = setup_key(radix, &key, 1);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return 0;
|
return 0;
|
||||||
ret = btrfs_search_slot(root, &key, &path, 0, 1);
|
ret = btrfs_search_slot(trans, root, &key, &path, 0, 1);
|
||||||
btrfs_release_path(root, &path);
|
btrfs_release_path(root, &path);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
@ -126,7 +131,8 @@ static int lookup_item(struct btrfs_root *root, struct radix_tree_root *radix)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lookup_enoent(struct btrfs_root *root, struct radix_tree_root *radix)
|
static int lookup_enoent(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
|
*root, struct radix_tree_root *radix)
|
||||||
{
|
{
|
||||||
struct btrfs_path path;
|
struct btrfs_path path;
|
||||||
struct btrfs_key key;
|
struct btrfs_key key;
|
||||||
@ -135,7 +141,7 @@ static int lookup_enoent(struct btrfs_root *root, struct radix_tree_root *radix)
|
|||||||
ret = setup_key(radix, &key, 0);
|
ret = setup_key(radix, &key, 0);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
ret = btrfs_search_slot(root, &key, &path, 0, 0);
|
ret = btrfs_search_slot(trans, root, &key, &path, 0, 0);
|
||||||
btrfs_release_path(root, &path);
|
btrfs_release_path(root, &path);
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
goto error;
|
goto error;
|
||||||
@ -145,8 +151,8 @@ static int lookup_enoent(struct btrfs_root *root, struct radix_tree_root *radix)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int empty_tree(struct btrfs_root *root, struct radix_tree_root *radix,
|
static int empty_tree(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
int nr)
|
*root, struct radix_tree_root *radix, int nr)
|
||||||
{
|
{
|
||||||
struct btrfs_path path;
|
struct btrfs_path path;
|
||||||
struct btrfs_key key;
|
struct btrfs_key key;
|
||||||
@ -162,7 +168,7 @@ static int empty_tree(struct btrfs_root *root, struct radix_tree_root *radix,
|
|||||||
key.objectid = (unsigned long)-1;
|
key.objectid = (unsigned long)-1;
|
||||||
while(nr-- >= 0) {
|
while(nr-- >= 0) {
|
||||||
btrfs_init_path(&path);
|
btrfs_init_path(&path);
|
||||||
ret = btrfs_search_slot(root, &key, &path, -1, 1);
|
ret = btrfs_search_slot(trans, root, &key, &path, -1, 1);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
btrfs_release_path(root, &path);
|
btrfs_release_path(root, &path);
|
||||||
return ret;
|
return ret;
|
||||||
@ -177,7 +183,7 @@ static int empty_tree(struct btrfs_root *root, struct radix_tree_root *radix,
|
|||||||
slot = path.slots[0];
|
slot = path.slots[0];
|
||||||
found = btrfs_disk_key_objectid(
|
found = btrfs_disk_key_objectid(
|
||||||
&path.nodes[0]->leaf.items[slot].key);
|
&path.nodes[0]->leaf.items[slot].key);
|
||||||
ret = btrfs_del_item(root, &path);
|
ret = btrfs_del_item(trans, root, &path);
|
||||||
count++;
|
count++;
|
||||||
if (ret) {
|
if (ret) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@ -198,19 +204,19 @@ static int empty_tree(struct btrfs_root *root, struct radix_tree_root *radix,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fill_tree(struct btrfs_root *root, struct radix_tree_root *radix,
|
static int fill_tree(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
int count)
|
struct radix_tree_root *radix, int count)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
ret = ins_one(root, radix);
|
ret = ins_one(trans, root, radix);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
fprintf(stderr, "fill failed\n");
|
fprintf(stderr, "fill failed\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (i % 1000 == 0) {
|
if (i % 1000 == 0) {
|
||||||
ret = btrfs_commit_transaction(root, &super);
|
ret = btrfs_commit_transaction(trans, root, &super);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
fprintf(stderr, "fill commit failed\n");
|
fprintf(stderr, "fill commit failed\n");
|
||||||
return ret;
|
return ret;
|
||||||
@ -226,7 +232,8 @@ static int fill_tree(struct btrfs_root *root, struct radix_tree_root *radix,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bulk_op(struct btrfs_root *root, struct radix_tree_root *radix)
|
static int bulk_op(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
|
struct radix_tree_root *radix)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
int nr = rand() % 5000;
|
int nr = rand() % 5000;
|
||||||
@ -235,17 +242,18 @@ static int bulk_op(struct btrfs_root *root, struct radix_tree_root *radix)
|
|||||||
/* do the bulk op much less frequently */
|
/* do the bulk op much less frequently */
|
||||||
if (run_nr++ % 100)
|
if (run_nr++ % 100)
|
||||||
return 0;
|
return 0;
|
||||||
ret = empty_tree(root, radix, nr);
|
ret = empty_tree(trans, root, radix, nr);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
ret = fill_tree(root, radix, nr);
|
ret = fill_tree(trans, root, radix, nr);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int (*ops[])(struct btrfs_root *root, struct radix_tree_root *radix) =
|
int (*ops[])(struct btrfs_trans_handle *,
|
||||||
|
struct btrfs_root *root, struct radix_tree_root *radix) =
|
||||||
{ ins_one, insert_dup, del_one, lookup_item,
|
{ ins_one, insert_dup, del_one, lookup_item,
|
||||||
lookup_enoent, bulk_op };
|
lookup_enoent, bulk_op };
|
||||||
|
|
||||||
@ -264,7 +272,7 @@ static int fill_radix(struct btrfs_root *root, struct radix_tree_root *radix)
|
|||||||
key.objectid = (unsigned long)-1;
|
key.objectid = (unsigned long)-1;
|
||||||
while(1) {
|
while(1) {
|
||||||
btrfs_init_path(&path);
|
btrfs_init_path(&path);
|
||||||
ret = btrfs_search_slot(root, &key, &path, 0, 0);
|
ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
btrfs_release_path(root, &path);
|
btrfs_release_path(root, &path);
|
||||||
return ret;
|
return ret;
|
||||||
@ -325,6 +333,7 @@ int main(int ac, char **av)
|
|||||||
int init_fill_count = 800000;
|
int init_fill_count = 800000;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
int initial_only = 0;
|
int initial_only = 0;
|
||||||
|
struct btrfs_trans_handle *trans;
|
||||||
radix_tree_init();
|
radix_tree_init();
|
||||||
root = open_ctree("dbfile", &super);
|
root = open_ctree("dbfile", &super);
|
||||||
fill_radix(root, &radix);
|
fill_radix(root, &radix);
|
||||||
@ -346,7 +355,8 @@ int main(int ac, char **av)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("initial fill\n");
|
printf("initial fill\n");
|
||||||
ret = fill_tree(root, &radix, init_fill_count);
|
trans = btrfs_start_transaction(root, 1);
|
||||||
|
ret = fill_tree(trans, root, &radix, init_fill_count);
|
||||||
printf("starting run\n");
|
printf("starting run\n");
|
||||||
if (ret) {
|
if (ret) {
|
||||||
err = ret;
|
err = ret;
|
||||||
@ -370,7 +380,7 @@ int main(int ac, char **av)
|
|||||||
root = open_ctree("dbfile", &super);
|
root = open_ctree("dbfile", &super);
|
||||||
}
|
}
|
||||||
while(count--) {
|
while(count--) {
|
||||||
ret = ops[op](root, &radix);
|
ret = ops[op](trans, root, &radix);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
fprintf(stderr, "op %d failed %d:%d\n",
|
fprintf(stderr, "op %d failed %d:%d\n",
|
||||||
op, i, iterations);
|
op, i, iterations);
|
||||||
|
@ -20,7 +20,7 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid,
|
|||||||
search_key.offset = (u32)-1;
|
search_key.offset = (u32)-1;
|
||||||
|
|
||||||
btrfs_init_path(&path);
|
btrfs_init_path(&path);
|
||||||
ret = btrfs_search_slot(root, &search_key, &path, 0, 0);
|
ret = btrfs_search_slot(NULL, root, &search_key, &path, 0, 0);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
BUG_ON(ret == 0);
|
BUG_ON(ret == 0);
|
||||||
@ -40,8 +40,9 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int btrfs_update_root(struct btrfs_root *root, struct btrfs_key *key,
|
int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
struct btrfs_root_item *item)
|
*root, struct btrfs_key *key, struct btrfs_root_item
|
||||||
|
*item)
|
||||||
{
|
{
|
||||||
struct btrfs_path path;
|
struct btrfs_path path;
|
||||||
struct btrfs_leaf *l;
|
struct btrfs_leaf *l;
|
||||||
@ -49,7 +50,7 @@ int btrfs_update_root(struct btrfs_root *root, struct btrfs_key *key,
|
|||||||
int slot;
|
int slot;
|
||||||
|
|
||||||
btrfs_init_path(&path);
|
btrfs_init_path(&path);
|
||||||
ret = btrfs_search_slot(root, key, &path, 0, 1);
|
ret = btrfs_search_slot(trans, root, key, &path, 0, 1);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
BUG_ON(ret != 0);
|
BUG_ON(ret != 0);
|
||||||
@ -62,26 +63,28 @@ int btrfs_update_root(struct btrfs_root *root, struct btrfs_key *key,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int btrfs_insert_root(struct btrfs_root *root, struct btrfs_key *key,
|
int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
struct btrfs_root_item *item)
|
*root, struct btrfs_key *key, struct btrfs_root_item
|
||||||
|
*item)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
ret = btrfs_insert_item(root, key, item, sizeof(*item));
|
ret = btrfs_insert_item(trans, root, key, item, sizeof(*item));
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int btrfs_del_root(struct btrfs_root *root, struct btrfs_key *key)
|
int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
|
struct btrfs_key *key)
|
||||||
{
|
{
|
||||||
struct btrfs_path path;
|
struct btrfs_path path;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
btrfs_init_path(&path);
|
btrfs_init_path(&path);
|
||||||
ret = btrfs_search_slot(root, key, &path, -1, 1);
|
ret = btrfs_search_slot(trans, root, key, &path, -1, 1);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
BUG_ON(ret != 0);
|
BUG_ON(ret != 0);
|
||||||
ret = btrfs_del_item(root, &path);
|
ret = btrfs_del_item(trans, root, &path);
|
||||||
out:
|
out:
|
||||||
btrfs_release_path(root, &path);
|
btrfs_release_path(root, &path);
|
||||||
return ret;
|
return ret;
|
||||||
|
27
fs/btrfs/transaction.h
Normal file
27
fs/btrfs/transaction.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#ifndef __TRANSACTION__
|
||||||
|
#define __TRANSACTION__
|
||||||
|
|
||||||
|
struct btrfs_trans_handle {
|
||||||
|
u64 transid;
|
||||||
|
unsigned long blocks_reserved;
|
||||||
|
unsigned long blocks_used;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct btrfs_trans_handle *
|
||||||
|
btrfs_start_transaction(struct btrfs_root *root, int num_blocks)
|
||||||
|
{
|
||||||
|
struct btrfs_trans_handle *h = malloc(sizeof(*h));
|
||||||
|
h->transid = root->root_key.offset;
|
||||||
|
h->blocks_reserved = num_blocks;
|
||||||
|
h->blocks_used = 0;
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void btrfs_free_transaction(struct btrfs_root *root,
|
||||||
|
struct btrfs_trans_handle *handle)
|
||||||
|
{
|
||||||
|
memset(handle, 0, sizeof(*handle));
|
||||||
|
free(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user