summaryrefslogtreecommitdiff
path: root/disk-io.c
diff options
context:
space:
mode:
authorYan <yanzheng@21cn.com>2008-01-04 10:38:22 -0500
committerDavid Woodhouse <dwmw2@hera.kernel.org>2008-01-04 10:38:22 -0500
commit7777e63b425f1444d2472ea05a6b2b9cf865f35b (patch)
tree257d9645b094cd3bae9051f7bb5b24d862764bf4 /disk-io.c
parent088f78aeaadac6cc877975c6974731968c0093d1 (diff)
Update btrfs-progs to match kernel sources
Diffstat (limited to 'disk-io.c')
-rw-r--r--disk-io.c665
1 files changed, 345 insertions, 320 deletions
diff --git a/disk-io.c b/disk-io.c
index c401e3fb..fad099a3 100644
--- a/disk-io.c
+++ b/disk-io.c
@@ -31,215 +31,130 @@
#include "transaction.h"
#include "crc32c.h"
-static u64 allocated_bytes = 0;
-int cache_max = 10000;
-
-int btrfs_map_bh_to_logical(struct btrfs_root *root, struct btrfs_buffer *bh,
- u64 logical)
+int btrfs_map_bh_to_logical(struct btrfs_root *root, struct extent_buffer *buf,
+ u64 logical)
{
- bh->fd = root->fs_info->fp;
- bh->dev_bytenr = logical;
+ buf->fd = root->fs_info->fp;
+ buf->dev_bytenr = logical;
return 0;
}
-static int check_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf)
+static int check_tree_block(struct btrfs_root *root, struct extent_buffer *buf)
{
- if (buf->bytenr != btrfs_header_bytenr(&buf->node.header))
+ if (buf->start != btrfs_header_bytenr(buf))
BUG();
- if (memcmp(root->fs_info->disk_super->fsid, buf->node.header.fsid,
- sizeof(buf->node.header.fsid)))
+
+ if (memcmp_extent_buffer(buf, root->fs_info->fsid,
+ (unsigned long)btrfs_header_fsid(buf),
+ BTRFS_FSID_SIZE))
BUG();
return 0;
}
-static int free_some_buffers(struct btrfs_root *root)
+u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len)
{
- struct list_head *node, *next;
- struct btrfs_buffer *b;
- if (root->fs_info->cache_size < cache_max)
- return 0;
- list_for_each_safe(node, next, &root->fs_info->cache) {
- b = list_entry(node, struct btrfs_buffer, cache);
- if (b->count == 1) {
- BUG_ON(!list_empty(&b->dirty));
- list_del_init(&b->cache);
- btrfs_block_release(root, b);
- if (root->fs_info->cache_size < cache_max)
- break;
- }
- }
- return 0;
+ return crc32c(seed, data, len);
}
-struct btrfs_buffer *alloc_tree_block(struct btrfs_root *root, u64 bytenr,
- u32 blocksize)
+void btrfs_csum_final(u32 crc, char *result)
{
- struct btrfs_buffer *buf;
- int ret;
-
- buf = malloc(sizeof(struct btrfs_buffer) + blocksize);
- if (!buf)
- return buf;
- allocated_bytes += blocksize;
-
- buf->bytenr = bytenr;
- buf->count = 2;
- buf->size = blocksize;
- buf->cache_node.start = bytenr;
- buf->cache_node.size = blocksize;
-
- INIT_LIST_HEAD(&buf->dirty);
- free_some_buffers(root);
-
- ret = insert_existing_cache_extent(&root->fs_info->extent_cache,
- &buf->cache_node);
-
- list_add_tail(&buf->cache, &root->fs_info->cache);
- root->fs_info->cache_size += blocksize;
- if (ret) {
- free(buf);
- return NULL;
- }
- return buf;
+ *(__le32 *)result = ~cpu_to_le32(crc);
}
-struct btrfs_buffer *find_tree_block(struct btrfs_root *root, u64 bytenr,
- u32 blocksize)
+static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
+ int verify)
{
- struct btrfs_buffer *buf;
- struct cache_extent *cache;
-
- cache = find_cache_extent(&root->fs_info->extent_cache,
- bytenr, blocksize);
- if (cache) {
- buf = container_of(cache, struct btrfs_buffer, cache_node);
- buf->count++;
- } else {
- buf = alloc_tree_block(root, bytenr, blocksize);
- if (!buf) {
- BUG();
- return NULL;
- }
- }
- return buf;
-}
+ char result[BTRFS_CRC32_SIZE];
+ u32 len;
+ u32 crc = ~(u32)0;
-struct btrfs_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
- u32 blocksize)
-{
- struct btrfs_buffer *buf;
- int ret;
- struct cache_extent *cache;
+ len = buf->len - BTRFS_CSUM_SIZE;
+ crc = crc32c(crc, buf->data + BTRFS_CSUM_SIZE, len);
+ btrfs_csum_final(crc, result);
- cache = find_cache_extent(&root->fs_info->extent_cache,
- bytenr, blocksize);
- if (cache) {
- buf = container_of(cache, struct btrfs_buffer, cache_node);
- buf->count++;
- if (check_tree_block(root, buf))
- BUG();
- } else {
- buf = alloc_tree_block(root, bytenr, blocksize);
- if (!buf)
- return NULL;
- btrfs_map_bh_to_logical(root, buf, bytenr);
- ret = pread(buf->fd, &buf->node, blocksize,
- buf->dev_bytenr);
- if (ret != blocksize) {
- free(buf);
- return NULL;
+ if (verify) {
+ if (memcmp_extent_buffer(buf, result, 0, BTRFS_CRC32_SIZE)) {
+ printk("checksum verify failed on %llu\n", buf->start);
+ return 1;
}
- if (check_tree_block(root, buf))
- BUG();
+ } else {
+ write_extent_buffer(buf, result, 0, BTRFS_CRC32_SIZE);
}
- return buf;
+ return 0;
}
-int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
- struct btrfs_buffer *buf)
+struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root,
+ u64 bytenr, u32 blocksize)
{
- if (!list_empty(&buf->dirty))
- return 0;
- list_add_tail(&buf->dirty, &root->fs_info->trans);
- buf->count++;
- if (check_tree_block(root, buf))
- BUG();
- return 0;
+ return find_extent_buffer(&root->fs_info->extent_cache,
+ bytenr, blocksize);
}
-int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
- struct btrfs_buffer *buf)
+struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root,
+ u64 bytenr, u32 blocksize)
{
- if (!list_empty(&buf->dirty)) {
- list_del_init(&buf->dirty);
- btrfs_block_release(root, buf);
- }
- return 0;
+ return alloc_extent_buffer(&root->fs_info->extent_cache, bytenr,
+ blocksize);
}
-int btrfs_csum_node(struct btrfs_root *root, struct btrfs_node *node)
+int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize)
{
- u32 crc = ~(u32)0;
- size_t len = btrfs_level_size(root, btrfs_header_level(&node->header)) -
- BTRFS_CSUM_SIZE;
-
- crc = crc32c(crc, (char *)(node) + BTRFS_CSUM_SIZE, len);
- crc = ~cpu_to_le32(crc);
- memcpy(node->header.csum, &crc, BTRFS_CRC32_SIZE);
return 0;
}
-int btrfs_csum_super(struct btrfs_root *root, struct btrfs_super_block *super)
+struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
+ u32 blocksize)
{
- u32 crc = ~(u32)0;
- char block[512];
- size_t len = 512 - BTRFS_CSUM_SIZE;
-
- memset(block, 0, 512);
- memcpy(block, super, sizeof(*super));
+ int ret;
+ struct extent_buffer *eb;
- crc = crc32c(crc, block + BTRFS_CSUM_SIZE, len);
- crc = ~cpu_to_le32(crc);
- memcpy(super->csum, &crc, BTRFS_CRC32_SIZE);
- return 0;
+ eb = btrfs_find_create_tree_block(root, bytenr, blocksize);
+ if (!eb)
+ return NULL;
+ if (!btrfs_buffer_uptodate(eb)) {
+ btrfs_map_bh_to_logical(root, eb, eb->start);
+ ret = read_extent_from_disk(eb);
+ if (ret) {
+ free_extent_buffer(eb);
+ return NULL;
+ }
+ btrfs_set_buffer_uptodate(eb);
+ }
+ return eb;
}
int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
- struct btrfs_buffer *buf)
+ struct extent_buffer *eb)
{
- int ret;
-
- if (buf->bytenr != btrfs_header_bytenr(&buf->node.header))
+ if (check_tree_block(root, eb))
BUG();
- btrfs_map_bh_to_logical(root, buf, buf->bytenr);
- if (check_tree_block(root, buf))
+ if (!btrfs_buffer_uptodate(eb))
BUG();
-
- btrfs_csum_node(root, &buf->node);
-
- ret = pwrite(buf->fd, &buf->node, buf->size,
- buf->dev_bytenr);
- if (ret != buf->size)
- return ret;
- return 0;
+ btrfs_map_bh_to_logical(root, eb, eb->start);
+ csum_tree_block(root, eb, 0);
+ return write_extent_to_disk(eb);
}
-static int __commit_transaction(struct btrfs_trans_handle *trans, struct
- btrfs_root *root)
+static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
+ u32 stripesize, struct btrfs_root *root,
+ struct btrfs_fs_info *fs_info, u64 objectid)
{
- struct btrfs_buffer *b;
- int ret = 0;
- int wret;
- while(!list_empty(&root->fs_info->trans)) {
- b = list_entry(root->fs_info->trans.next, struct btrfs_buffer,
- dirty);
- list_del_init(&b->dirty);
- wret = write_tree_block(trans, root, b);
- if (wret)
- ret = wret;
- btrfs_block_release(root, b);
- }
- return ret;
+ root->node = NULL;
+ root->commit_root = NULL;
+ root->sectorsize = sectorsize;
+ root->nodesize = nodesize;
+ root->leafsize = leafsize;
+ root->stripesize = stripesize;
+ root->ref_cows = 0;
+ root->fs_info = fs_info;
+ root->objectid = objectid;
+ root->last_trans = 0;
+ root->highest_inode = 0;
+ root->last_inode_alloc = 0;
+ memset(&root->root_key, 0, sizeof(root->root_key));
+ memset(&root->root_item, 0, sizeof(root->root_item));
+ root->root_key.objectid = objectid;
+ return 0;
}
static int commit_tree_roots(struct btrfs_trans_handle *trans,
@@ -253,12 +168,12 @@ static int commit_tree_roots(struct btrfs_trans_handle *trans,
btrfs_write_dirty_block_groups(trans, fs_info->extent_root);
while(1) {
old_extent_bytenr = btrfs_root_bytenr(&extent_root->root_item);
- if (old_extent_bytenr == extent_root->node->bytenr)
+ if (old_extent_bytenr == extent_root->node->start)
break;
btrfs_set_root_bytenr(&extent_root->root_item,
- extent_root->node->bytenr);
+ extent_root->node->start);
extent_root->root_item.level =
- btrfs_header_level(&extent_root->node->node.header);
+ btrfs_header_level(extent_root->node);
ret = btrfs_update_root(trans, tree_root,
&extent_root->root_key,
&extent_root->root_item);
@@ -268,96 +183,187 @@ static int commit_tree_roots(struct btrfs_trans_handle *trans,
return 0;
}
-int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct
- btrfs_root *root, struct btrfs_super_block *s)
+static int __commit_transaction(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root)
+{
+ u64 start;
+ u64 end;
+ struct extent_buffer *eb;
+ struct extent_map_tree *tree = &root->fs_info->extent_cache;
+ int ret;
+
+ while(1) {
+ ret = find_first_extent_bit(tree, 0, &start, &end,
+ EXTENT_DIRTY);
+ if (ret)
+ break;
+ while(start <= end) {
+ eb = find_first_extent_buffer(tree, start);
+ BUG_ON(!eb || eb->start != start);
+ ret = write_tree_block(trans, root, eb);
+ BUG_ON(ret);
+ start += eb->len;
+ clear_extent_buffer_dirty(eb);
+ free_extent_buffer(eb);
+ }
+ }
+ return 0;
+}
+
+int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root)
{
int ret = 0;
- struct btrfs_buffer *snap = root->commit_root;
- struct btrfs_key snap_key;
+ struct btrfs_root *new_root = NULL;
+ struct btrfs_fs_info *fs_info = root->fs_info;
if (root->commit_root == root->node)
- return 0;
+ goto commit_tree;
- memcpy(&snap_key, &root->root_key, sizeof(snap_key));
- root->root_key.offset = trans->transid;
+ new_root = malloc(sizeof(*new_root));
+ if (!new_root)
+ return -ENOMEM;
+ memcpy(new_root, root, sizeof(*new_root));
+ new_root->node = root->commit_root;
+ root->commit_root = NULL;
- btrfs_set_root_bytenr(&root->root_item, root->node->bytenr);
- root->root_item.level =
- btrfs_header_level(&root->node->node.header);
- ret = btrfs_insert_root(trans, root->fs_info->tree_root,
+ root->root_key.offset = trans->transid;
+ btrfs_set_root_bytenr(&root->root_item, root->node->start);
+ root->root_item.level = btrfs_header_level(root->node);
+ ret = btrfs_insert_root(trans, fs_info->tree_root,
&root->root_key, &root->root_item);
BUG_ON(ret);
- ret = commit_tree_roots(trans, root->fs_info);
+ btrfs_set_root_refs(&new_root->root_item, 0);
+ ret = btrfs_update_root(trans, root->fs_info->tree_root,
+ &new_root->root_key, &new_root->root_item);
BUG_ON(ret);
+ ret = commit_tree_roots(trans, fs_info);
+ BUG_ON(ret);
ret = __commit_transaction(trans, root);
BUG_ON(ret);
+ write_ctree_super(trans, root);
+ btrfs_finish_extent_commit(trans, fs_info->extent_root,
+ &fs_info->pinned_extents);
+ btrfs_free_transaction(root, trans);
+ fs_info->running_transaction = NULL;
- write_ctree_super(trans, root, s);
- btrfs_finish_extent_commit(trans, root->fs_info->extent_root);
- btrfs_finish_extent_commit(trans, root->fs_info->tree_root);
-
- root->commit_root = root->node;
- root->node->count++;
- ret = btrfs_drop_snapshot(trans, root, snap);
+ trans = btrfs_start_transaction(root, 1);
+ ret = btrfs_drop_snapshot(trans, new_root);
+ BUG_ON(ret);
+ ret = btrfs_del_root(trans, fs_info->tree_root, &new_root->root_key);
+ BUG_ON(ret);
+commit_tree:
+ ret = commit_tree_roots(trans, fs_info);
BUG_ON(ret);
- ret = btrfs_del_root(trans, root->fs_info->tree_root, &snap_key);
+ ret = __commit_transaction(trans, root);
BUG_ON(ret);
+ write_ctree_super(trans, root);
+ btrfs_finish_extent_commit(trans, fs_info->extent_root,
+ &fs_info->pinned_extents);
btrfs_free_transaction(root, trans);
- return ret;
-}
-
-static int __setup_root(struct btrfs_super_block *super,
- struct btrfs_root *root,
- struct btrfs_fs_info *fs_info,
- u64 objectid, int fp)
-{
- root->node = NULL;
+ free_extent_buffer(root->commit_root);
root->commit_root = NULL;
- root->sectorsize = btrfs_super_sectorsize(super);
- root->nodesize = btrfs_super_nodesize(super);
- root->leafsize = btrfs_super_leafsize(super);
- root->stripesize = btrfs_super_stripesize(super);
- root->ref_cows = 0;
- root->fs_info = fs_info;
- memset(&root->root_key, 0, sizeof(root->root_key));
- memset(&root->root_item, 0, sizeof(root->root_item));
- root->root_key.objectid = objectid;
+ fs_info->running_transaction = NULL;
+ if (new_root) {
+ free_extent_buffer(new_root->node);
+ free(new_root);
+ }
return 0;
}
-struct btrfs_buffer *read_root_block(struct btrfs_root *root, u64 bytenr,
- u8 level)
-{
- struct btrfs_buffer *node;
- u32 size = btrfs_level_size(root, level);
-
- node = read_tree_block(root, bytenr, size);
- BUG_ON(!node);
- return node;
-}
-
-static int find_and_setup_root(struct btrfs_super_block *super,
- struct btrfs_root *tree_root,
+static int find_and_setup_root(struct btrfs_root *tree_root,
struct btrfs_fs_info *fs_info,
- u64 objectid,
- struct btrfs_root *root, int fp)
+ u64 objectid, struct btrfs_root *root)
{
int ret;
+ u32 blocksize;
- __setup_root(super, root, fs_info, objectid, fp);
+ __setup_root(tree_root->nodesize, tree_root->leafsize,
+ tree_root->sectorsize, tree_root->stripesize,
+ root, fs_info, objectid);
ret = btrfs_find_last_root(tree_root, objectid,
&root->root_item, &root->root_key);
BUG_ON(ret);
- root->node = read_root_block(root,
- btrfs_root_bytenr(&root->root_item),
- root->root_item.level);
+
+ blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item));
+ root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item),
+ blocksize);
BUG_ON(!root->node);
return 0;
}
-struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *super)
+int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root)
+{
+ if (root->node)
+ free_extent_buffer(root->node);
+ if (root->commit_root)
+ free_extent_buffer(root->commit_root);
+
+ free(root);
+ return 0;
+}
+
+struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
+ struct btrfs_key *location)
+{
+ struct btrfs_root *root;
+ struct btrfs_root *tree_root = fs_info->tree_root;
+ struct btrfs_path *path;
+ struct extent_buffer *l;
+ u32 blocksize;
+ int ret = 0;
+
+ root = malloc(sizeof(*root));
+ if (!root)
+ return ERR_PTR(-ENOMEM);
+ memset(root, 0, sizeof(*root));
+ if (location->offset == (u64)-1) {
+ ret = find_and_setup_root(tree_root, fs_info,
+ location->objectid, root);
+ if (ret) {
+ free(root);
+ return ERR_PTR(ret);
+ }
+ goto insert;
+ }
+
+ __setup_root(tree_root->nodesize, tree_root->leafsize,
+ tree_root->sectorsize, tree_root->stripesize,
+ root, fs_info, location->objectid);
+
+ path = btrfs_alloc_path();
+ BUG_ON(!path);
+ ret = btrfs_search_slot(NULL, tree_root, location, path, 0, 0);
+ if (ret != 0) {
+ if (ret > 0)
+ ret = -ENOENT;
+ goto out;
+ }
+ l = path->nodes[0];
+ read_extent_buffer(l, &root->root_item,
+ btrfs_item_ptr_offset(l, path->slots[0]),
+ sizeof(root->root_item));
+ memcpy(&root->root_key, location, sizeof(*location));
+ ret = 0;
+out:
+ btrfs_release_path(root, path);
+ btrfs_free_path(path);
+ if (ret) {
+ free(root);
+ return ERR_PTR(ret);
+ }
+ blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item));
+ root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item),
+ blocksize);
+ BUG_ON(!root->node);
+insert:
+ root->ref_cows = 1;
+ return root;
+}
+
+struct btrfs_root *open_ctree(char *filename, u64 sb_bytenr)
{
int fp;
@@ -365,145 +371,164 @@ struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *super)
if (fp < 0) {
return NULL;
}
- return open_ctree_fd(fp, super);
+ return open_ctree_fd(fp, sb_bytenr);
}
-struct btrfs_root *open_ctree_fd(int fp, struct btrfs_super_block *super)
+struct btrfs_root *open_ctree_fd(int fp, u64 sb_bytenr)
{
+ u32 sectorsize;
+ u32 nodesize;
+ u32 leafsize;
+ u32 blocksize;
+ u32 stripesize;
struct btrfs_root *root = malloc(sizeof(struct btrfs_root));
- struct btrfs_root *extent_root = malloc(sizeof(struct btrfs_root));
struct btrfs_root *tree_root = malloc(sizeof(struct btrfs_root));
+ struct btrfs_root *extent_root = malloc(sizeof(struct btrfs_root));
struct btrfs_fs_info *fs_info = malloc(sizeof(*fs_info));
int ret;
+ struct btrfs_super_block *disk_super;
+
+ if (sb_bytenr == 0)
+ sb_bytenr = BTRFS_SUPER_INFO_OFFSET;
- INIT_LIST_HEAD(&fs_info->trans);
- INIT_LIST_HEAD(&fs_info->cache);
- cache_tree_init(&fs_info->extent_cache);
- cache_tree_init(&fs_info->pending_tree);
- cache_tree_init(&fs_info->pinned_tree);
- cache_tree_init(&fs_info->del_pending);
- cache_tree_init(&fs_info->block_group_cache);
- fs_info->cache_size = 0;
fs_info->fp = fp;
fs_info->running_transaction = NULL;
fs_info->fs_root = root;
fs_info->tree_root = tree_root;
fs_info->extent_root = extent_root;
- fs_info->last_inode_alloc = 0;
- fs_info->last_inode_alloc_dirid = 0;
- fs_info->disk_super = super;
- memset(&fs_info->last_insert, 0, sizeof(fs_info->last_insert));
-
- ret = pread(fp, super, sizeof(struct btrfs_super_block),
- BTRFS_SUPER_INFO_OFFSET);
- if (ret == 0 || btrfs_super_root(super) == 0) {
- BUG();
- return NULL;
- }
- BUG_ON(ret < 0);
- __setup_root(super, tree_root, fs_info, BTRFS_ROOT_TREE_OBJECTID, fp);
- tree_root->node = read_root_block(tree_root, btrfs_super_root(super),
- btrfs_super_root_level(super));
+ extent_map_tree_init(&fs_info->extent_cache);
+ extent_map_tree_init(&fs_info->free_space_cache);
+ extent_map_tree_init(&fs_info->pending_tree);
+ extent_map_tree_init(&fs_info->pinned_extents);
+ extent_map_tree_init(&fs_info->del_pending);
+ extent_map_tree_init(&fs_info->block_group_cache);
+
+ mutex_init(&fs_info->fs_mutex);
+
+ __setup_root(512, 512, 512, 512, tree_root,
+ fs_info, BTRFS_ROOT_TREE_OBJECTID);
+
+ fs_info->sb_buffer = read_tree_block(tree_root, sb_bytenr, 512);
+ BUG_ON(!fs_info->sb_buffer);
+ read_extent_buffer(fs_info->sb_buffer, &fs_info->super_copy, 0,
+ sizeof(fs_info->super_copy));
+ read_extent_buffer(fs_info->sb_buffer, fs_info->fsid,
+ (unsigned long)btrfs_super_fsid(fs_info->sb_buffer),
+ BTRFS_FSID_SIZE);
+ disk_super = &fs_info->super_copy;
+
+ nodesize = btrfs_super_nodesize(disk_super);
+ leafsize = btrfs_super_leafsize(disk_super);
+ sectorsize = btrfs_super_sectorsize(disk_super);
+ stripesize = btrfs_super_stripesize(disk_super);
+ tree_root->nodesize = nodesize;
+ tree_root->leafsize = leafsize;
+ tree_root->sectorsize = sectorsize;
+ tree_root->stripesize = stripesize;
+
+ blocksize = btrfs_level_size(tree_root,
+ btrfs_super_root_level(disk_super));
+ tree_root->node = read_tree_block(tree_root,
+ btrfs_super_root(disk_super),
+ blocksize);
BUG_ON(!tree_root->node);
-
- ret = find_and_setup_root(super, tree_root, fs_info,
- BTRFS_EXTENT_TREE_OBJECTID, extent_root, fp);
+ ret = find_and_setup_root(tree_root, fs_info,
+ BTRFS_EXTENT_TREE_OBJECTID, extent_root);
BUG_ON(ret);
-
- ret = find_and_setup_root(super, tree_root, fs_info,
- BTRFS_FS_TREE_OBJECTID, root, fp);
+ ret = find_and_setup_root(tree_root, fs_info,
+ BTRFS_FS_TREE_OBJECTID, root);
BUG_ON(ret);
-
- root->commit_root = root->node;
- root->node->count++;
root->ref_cows = 1;
- root->fs_info->generation = btrfs_super_generation(super) + 1;
+ fs_info->generation = btrfs_super_generation(disk_super) + 1;
btrfs_read_block_groups(root);
return root;
}
-int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root
- *root, struct btrfs_super_block *s)
+int write_ctree_super(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root)
{
int ret;
- btrfs_set_super_root(s, root->fs_info->tree_root->node->bytenr);
- btrfs_set_super_generation(s, trans->transid);
- btrfs_set_super_root_level(s,
- btrfs_header_level(&root->fs_info->tree_root->node->node.header));
- btrfs_csum_super(root, s);
-
- ret = pwrite(root->fs_info->fp, s, sizeof(*s),
- BTRFS_SUPER_INFO_OFFSET);
- if (ret != sizeof(*s)) {
+ struct btrfs_root *tree_root = root->fs_info->tree_root;
+ btrfs_set_super_generation(&root->fs_info->super_copy,
+ trans->transid);
+ btrfs_set_super_root(&root->fs_info->super_copy,
+ tree_root->node->start);
+ btrfs_set_super_root_level(&root->fs_info->super_copy,
+ btrfs_header_level(tree_root->node));
+ write_extent_buffer(root->fs_info->sb_buffer,
+ &root->fs_info->super_copy, 0,
+ sizeof(root->fs_info->super_copy));
+ ret = write_tree_block(trans, root, root->fs_info->sb_buffer);
+ if (ret)
fprintf(stderr, "failed to write new super block err %d\n", ret);
- return ret;
- }
- return 0;
-}
-
-static int drop_cache(struct btrfs_root *root)
-{
- while(!list_empty(&root->fs_info->cache)) {
- struct btrfs_buffer *b = list_entry(root->fs_info->cache.next,
- struct btrfs_buffer,
- cache);
- list_del_init(&b->cache);
- btrfs_block_release(root, b);
- }
- return 0;
+ return ret;
}
-int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s)
+int close_ctree(struct btrfs_root *root)
{
int ret;
struct btrfs_trans_handle *trans;
+ struct btrfs_fs_info *fs_info = root->fs_info;
+
trans = btrfs_start_transaction(root, 1);
- btrfs_commit_transaction(trans, root, s);
+ btrfs_commit_transaction(trans, root);
trans = btrfs_start_transaction(root, 1);
ret = commit_tree_roots(trans, root->fs_info);
BUG_ON(ret);
ret = __commit_transaction(trans, root);
BUG_ON(ret);
- write_ctree_super(trans, root, s);
+ write_ctree_super(trans, root);
btrfs_free_transaction(root, trans);
- drop_cache(root);
- BUG_ON(!list_empty(&root->fs_info->trans));
btrfs_free_block_groups(root->fs_info);
close(root->fs_info->fp);
if (root->node)
- btrfs_block_release(root, root->node);
+ free_extent_buffer(root->node);
if (root->fs_info->extent_root->node)
- btrfs_block_release(root->fs_info->extent_root,
- root->fs_info->extent_root->node);
+ free_extent_buffer(root->fs_info->extent_root->node);
if (root->fs_info->tree_root->node)
- btrfs_block_release(root->fs_info->tree_root,
- root->fs_info->tree_root->node);
- btrfs_block_release(root, root->commit_root);
- free(root);
- printf("on close %llu blocks are allocated\n",
- (unsigned long long)allocated_bytes);
+ free_extent_buffer(root->fs_info->tree_root->node);
+ free_extent_buffer(root->commit_root);
+ free_extent_buffer(root->fs_info->sb_buffer);
+
+ extent_map_tree_cleanup(&fs_info->extent_cache);
+ extent_map_tree_cleanup(&fs_info->free_space_cache);
+ extent_map_tree_cleanup(&fs_info->pending_tree);
+ extent_map_tree_cleanup(&fs_info->pinned_extents);
+ extent_map_tree_cleanup(&fs_info->del_pending);
+ extent_map_tree_cleanup(&fs_info->block_group_cache);
+
+ free(fs_info->tree_root);
+ free(fs_info->extent_root);
+ free(fs_info->fs_root);
+ free(fs_info);
+
return 0;
}
-void btrfs_block_release(struct btrfs_root *root, struct btrfs_buffer *buf)
+int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
+ struct extent_buffer *eb)
{
- buf->count--;
- if (buf->count < 0)
- BUG();
- if (buf->count == 0) {
- BUG_ON(!list_empty(&buf->cache));
- BUG_ON(!list_empty(&buf->dirty));
-
- remove_cache_extent(&root->fs_info->extent_cache,
- &buf->cache_node);
- BUG_ON(allocated_bytes == 0);
- allocated_bytes -= buf->size;
- BUG_ON(root->fs_info->cache_size == 0);
- root->fs_info->cache_size -= buf->size;
-
- memset(buf, 0, sizeof(*buf));
- free(buf);
- }
+ return clear_extent_buffer_dirty(eb);
+}
+
+int wait_on_tree_block_writeback(struct btrfs_root *root,
+ struct extent_buffer *eb)
+{
+ return 0;
+}
+
+void btrfs_mark_buffer_dirty(struct extent_buffer *eb)
+{
+ set_extent_buffer_dirty(eb);
}
+int btrfs_buffer_uptodate(struct extent_buffer *eb)
+{
+ return extent_buffer_uptodate(eb);
+}
+
+int btrfs_set_buffer_uptodate(struct extent_buffer *eb)
+{
+ return set_extent_buffer_uptodate(eb);
+}