Loading fs/btrfs/Makefile +2 −1 Original line number Diff line number Diff line Loading @@ -2,7 +2,8 @@ CC=gcc CFLAGS = -g -Wall 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 # if you don't have sparse installed, use ls instead CHECKFLAGS=-D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ -Wbitwise \ Loading fs/btrfs/TODO +1 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ * make a real mkfs and superblock * Do checksumming * Define FS objects in terms of different item types * add inode tree * Add block mapping tree (simple dm layer) * Add simple tree locking (semaphore per tree) * Make allocator smarter Loading fs/btrfs/ctree.h +107 −16 Original line number Diff line number Diff line Loading @@ -4,8 +4,13 @@ #include "list.h" #include "kerncompat.h" #define BTRFS_MAGIC "_BtRfS_M" #define BTRFS_BLOCKSIZE 1024 #define BTRFS_ROOT_TREE_OBJECTID 1 #define BTRFS_EXTENT_TREE_OBJECTID 2 #define BTRFS_FS_TREE_OBJECTID 3 /* * the key defines the order in the tree, and so it also defines (optimal) * block layout. objectid corresonds to the inode number. The flags Loading Loading @@ -36,7 +41,7 @@ struct btrfs_key { * every tree block (leaf or node) starts with this header. */ struct btrfs_header { __le64 fsid[2]; /* FS specific uuid */ u8 fsid[16]; /* FS specific uuid */ __le64 blocknr; /* which block this node is supposed to live in */ __le64 parentid; /* objectid of the tree root */ __le32 csum; Loading @@ -52,6 +57,14 @@ struct btrfs_header { struct btrfs_buffer; struct btrfs_root_item { __le64 blocknr; __le32 flags; __le64 block_limit; __le64 blocks_used; __le32 refs; }; /* * in ram representation of the tree. extent_root is used for all allocations * and for the extent tree extent_root root. current_insert is used Loading @@ -61,6 +74,7 @@ struct btrfs_root { struct btrfs_buffer *node; struct btrfs_buffer *commit_root; struct btrfs_root *extent_root; struct btrfs_root *tree_root; struct btrfs_key current_insert; struct btrfs_key last_insert; int fp; Loading @@ -69,28 +83,25 @@ struct btrfs_root { struct list_head trans; struct list_head cache; int cache_size; int ref_cows; struct btrfs_root_item root_item; struct btrfs_key root_key; }; /* * describes a tree on disk */ struct btrfs_root_info { u64 fsid[2]; /* FS specific uuid */ u64 blocknr; /* blocknr of this block */ u64 objectid; /* inode number of this root */ u64 tree_root; /* the tree root block */ u32 csum; u32 ham; u64 snapuuid[2]; /* root specific uuid */ } __attribute__ ((__packed__)); /* * the super block basically lists the main trees of the FS * it currently lacks any block count etc etc */ struct btrfs_super_block { struct btrfs_root_info root_info; struct btrfs_root_info extent_info; u8 fsid[16]; /* FS specific uuid */ __le64 blocknr; /* this block number */ __le32 csum; __le64 magic; __le16 blocksize; __le64 generation; __le64 root; __le64 total_blocks; __le64 blocks_used; } __attribute__ ((__packed__)); /* Loading Loading @@ -317,6 +328,79 @@ static inline int btrfs_is_leaf(struct btrfs_node *n) return (btrfs_header_level(&n->header) == 0); } static inline u64 btrfs_root_blocknr(struct btrfs_root_item *item) { return le64_to_cpu(item->blocknr); } static inline void btrfs_set_root_blocknr(struct btrfs_root_item *item, u64 val) { item->blocknr = cpu_to_le64(val); } static inline u32 btrfs_root_refs(struct btrfs_root_item *item) { return le32_to_cpu(item->refs); } static inline void btrfs_set_root_refs(struct btrfs_root_item *item, u32 val) { item->refs = cpu_to_le32(val); } static inline u64 btrfs_super_blocknr(struct btrfs_super_block *s) { return le64_to_cpu(s->blocknr); } static inline void btrfs_set_super_blocknr(struct btrfs_super_block *s, u64 val) { s->blocknr = cpu_to_le64(val); } static inline u64 btrfs_super_root(struct btrfs_super_block *s) { return le64_to_cpu(s->root); } static inline void btrfs_set_super_root(struct btrfs_super_block *s, u64 val) { s->root = cpu_to_le64(val); } static inline u64 btrfs_super_total_blocks(struct btrfs_super_block *s) { return le64_to_cpu(s->total_blocks); } static inline void btrfs_set_super_total_blocks(struct btrfs_super_block *s, u64 val) { s->total_blocks = cpu_to_le64(val); } static inline u64 btrfs_super_blocks_used(struct btrfs_super_block *s) { return le64_to_cpu(s->blocks_used); } static inline void btrfs_set_super_blocks_used(struct btrfs_super_block *s, u64 val) { s->blocks_used = cpu_to_le64(val); } static inline u16 btrfs_super_blocksize(struct btrfs_super_block *s) { return le16_to_cpu(s->blocksize); } static inline void btrfs_set_super_blocksize(struct btrfs_super_block *s, u16 val) { s->blocksize = cpu_to_le16(val); } struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_root *root); int btrfs_inc_ref(struct btrfs_root *root, struct btrfs_buffer *buf); int btrfs_free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks); Loading @@ -331,4 +415,11 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path); int btrfs_leaf_free_space(struct btrfs_leaf *leaf); int btrfs_drop_snapshot(struct btrfs_root *root, struct btrfs_buffer *snap); int btrfs_finish_extent_commit(struct btrfs_root *root); int btrfs_del_root(struct btrfs_root *root, struct btrfs_key *key); int btrfs_insert_root(struct btrfs_root *root, struct btrfs_key *key, struct btrfs_root_item *item); int btrfs_update_root(struct btrfs_root *root, struct btrfs_key *key, struct btrfs_root_item *item); int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct btrfs_root_item *item, struct btrfs_key *key); #endif fs/btrfs/debug-tree.c +3 −1 Original line number Diff line number Diff line Loading @@ -11,9 +11,11 @@ int main(int ac, char **av) { struct btrfs_root *root; radix_tree_init(); root = open_ctree("dbfile", &super); printf("root tree\n"); printf("fs tree\n"); btrfs_print_tree(root, root->node); printf("map tree\n"); btrfs_print_tree(root->extent_root, root->extent_root->node); printf("root tree\n"); btrfs_print_tree(root->tree_root, root->tree_root->node); return 0; } fs/btrfs/disk-io.c +107 −28 Original line number Diff line number Diff line Loading @@ -154,41 +154,96 @@ static int __commit_transaction(struct btrfs_root *root) return ret; } static int commit_extent_and_tree_roots(struct btrfs_root *tree_root, struct btrfs_root *extent_root) { int ret; u64 old_extent_block; while(1) { old_extent_block = btrfs_root_blocknr(&extent_root->root_item); if (old_extent_block == extent_root->node->blocknr) break; btrfs_set_root_blocknr(&extent_root->root_item, extent_root->node->blocknr); ret = btrfs_update_root(tree_root, &extent_root->root_key, &extent_root->root_item); BUG_ON(ret); } __commit_transaction(extent_root); __commit_transaction(tree_root); return 0; } int btrfs_commit_transaction(struct btrfs_root *root, struct btrfs_super_block *s) { int ret = 0; struct btrfs_buffer *snap = root->commit_root; struct btrfs_key snap_key; ret = __commit_transaction(root); if (!ret && root != root->extent_root) ret = __commit_transaction(root->extent_root); BUG_ON(ret); if (root->commit_root != root->node) { struct btrfs_buffer *snap = root->commit_root; if (root->commit_root == root->node) return 0; memcpy(&snap_key, &root->root_key, sizeof(snap_key)); root->root_key.offset++; btrfs_set_root_blocknr(&root->root_item, root->node->blocknr); ret = btrfs_insert_root(root->tree_root, &root->root_key, &root->root_item); BUG_ON(ret); ret = commit_extent_and_tree_roots(root->tree_root, root->extent_root); BUG_ON(ret); write_ctree_super(root, s); btrfs_finish_extent_commit(root->extent_root); btrfs_finish_extent_commit(root->tree_root); root->commit_root = root->node; root->node->count++; ret = btrfs_drop_snapshot(root, snap); BUG_ON(ret); // btrfs_block_release(root, snap); } write_ctree_super(root, s); btrfs_finish_extent_commit(root); ret = btrfs_del_root(root->tree_root, &snap_key); BUG_ON(ret); return ret; } static int __setup_root(struct btrfs_root *root, struct btrfs_root *extent_root, struct btrfs_root_info *info, int fp) static int __setup_root(struct btrfs_root *root, u64 objectid, int fp) { INIT_LIST_HEAD(&root->trans); INIT_LIST_HEAD(&root->cache); root->cache_size = 0; root->fp = fp; root->node = NULL; root->extent_root = extent_root; root->commit_root = NULL; root->node = read_tree_block(root, info->tree_root); memset(&root->current_insert, 0, sizeof(root->current_insert)); memset(&root->last_insert, 0, sizeof(root->last_insert)); memset(&root->root_key, 0, sizeof(root->root_key)); memset(&root->root_item, 0, sizeof(root->root_item)); return 0; } static int find_and_setup_root(struct btrfs_root *tree_root, u64 objectid, struct btrfs_root *root, int fp) { int ret; __setup_root(root, objectid, fp); ret = btrfs_find_last_root(tree_root, objectid, &root->root_item, &root->root_key); BUG_ON(ret); root->node = read_tree_block(root, btrfs_root_blocknr(&root->root_item)); root->ref_cows = 0; BUG_ON(!root->node); return 0; } Loading @@ -196,9 +251,19 @@ struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *super) { 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)); int fp; int ret; root->extent_root = extent_root; root->tree_root = tree_root; extent_root->extent_root = extent_root; extent_root->tree_root = tree_root; tree_root->extent_root = extent_root; tree_root->tree_root = tree_root; fp = open(filename, O_CREAT | O_RDWR, 0600); if (fp < 0) { free(root); Loading @@ -208,11 +273,14 @@ struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *super) INIT_RADIX_TREE(&root->pinned_radix, GFP_KERNEL); INIT_RADIX_TREE(&extent_root->pinned_radix, GFP_KERNEL); INIT_RADIX_TREE(&extent_root->cache_radix, GFP_KERNEL); INIT_RADIX_TREE(&tree_root->pinned_radix, GFP_KERNEL); INIT_RADIX_TREE(&tree_root->cache_radix, GFP_KERNEL); ret = pread(fp, super, sizeof(struct btrfs_super_block), BTRFS_SUPER_INFO_OFFSET(BTRFS_BLOCKSIZE)); if (ret == 0 || super->root_info.tree_root == 0) { if (ret == 0 || btrfs_super_root(super) == 0) { printf("making new FS!\n"); ret = mkfs(fp); ret = mkfs(fp, 0, BTRFS_BLOCKSIZE); if (ret) return NULL; ret = pread(fp, super, sizeof(struct btrfs_super_block), Loading @@ -221,24 +289,29 @@ struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *super) return NULL; } BUG_ON(ret < 0); __setup_root(root, extent_root, &super->root_info, fp); __setup_root(extent_root, extent_root, &super->extent_info, fp); __setup_root(tree_root, BTRFS_ROOT_TREE_OBJECTID, fp); tree_root->node = read_tree_block(tree_root, btrfs_super_root(super)); BUG_ON(!tree_root->node); ret = find_and_setup_root(tree_root, BTRFS_EXTENT_TREE_OBJECTID, extent_root, fp); BUG_ON(ret); ret = find_and_setup_root(tree_root, BTRFS_FS_TREE_OBJECTID, root, fp); BUG_ON(ret); root->commit_root = root->node; root->node->count++; root->ref_cows = 1; return root; } static int __update_root(struct btrfs_root *root, struct btrfs_root_info *info) { info->tree_root = root->node->blocknr; return 0; } int write_ctree_super(struct btrfs_root *root, struct btrfs_super_block *s) { int ret; __update_root(root, &s->root_info); __update_root(root->extent_root, &s->extent_info); btrfs_set_super_root(s, root->tree_root->node->blocknr); ret = pwrite(root->fp, s, sizeof(*s), BTRFS_SUPER_INFO_OFFSET(BTRFS_BLOCKSIZE)); if (ret != sizeof(*s)) { Loading @@ -260,19 +333,25 @@ static int drop_cache(struct btrfs_root *root) } int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s) { int ret; btrfs_commit_transaction(root, s); __commit_transaction(root->extent_root); ret = commit_extent_and_tree_roots(root->tree_root, root->extent_root); BUG_ON(ret); write_ctree_super(root, s); drop_cache(root->extent_root); drop_cache(root->tree_root); drop_cache(root); BUG_ON(!list_empty(&root->trans)); BUG_ON(!list_empty(&root->extent_root->trans)); BUG_ON(!list_empty(&root->tree_root->trans)); close(root->fp); if (root->node) btrfs_block_release(root, root->node); if (root->extent_root->node) btrfs_block_release(root->extent_root, root->extent_root->node); if (root->tree_root->node) btrfs_block_release(root->tree_root, root->tree_root->node); btrfs_block_release(root, root->commit_root); free(root); printf("on close %d blocks are allocated\n", allocated_blocks); Loading Loading
fs/btrfs/Makefile +2 −1 Original line number Diff line number Diff line Loading @@ -2,7 +2,8 @@ CC=gcc CFLAGS = -g -Wall 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 # if you don't have sparse installed, use ls instead CHECKFLAGS=-D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ -Wbitwise \ Loading
fs/btrfs/TODO +1 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ * make a real mkfs and superblock * Do checksumming * Define FS objects in terms of different item types * add inode tree * Add block mapping tree (simple dm layer) * Add simple tree locking (semaphore per tree) * Make allocator smarter Loading
fs/btrfs/ctree.h +107 −16 Original line number Diff line number Diff line Loading @@ -4,8 +4,13 @@ #include "list.h" #include "kerncompat.h" #define BTRFS_MAGIC "_BtRfS_M" #define BTRFS_BLOCKSIZE 1024 #define BTRFS_ROOT_TREE_OBJECTID 1 #define BTRFS_EXTENT_TREE_OBJECTID 2 #define BTRFS_FS_TREE_OBJECTID 3 /* * the key defines the order in the tree, and so it also defines (optimal) * block layout. objectid corresonds to the inode number. The flags Loading Loading @@ -36,7 +41,7 @@ struct btrfs_key { * every tree block (leaf or node) starts with this header. */ struct btrfs_header { __le64 fsid[2]; /* FS specific uuid */ u8 fsid[16]; /* FS specific uuid */ __le64 blocknr; /* which block this node is supposed to live in */ __le64 parentid; /* objectid of the tree root */ __le32 csum; Loading @@ -52,6 +57,14 @@ struct btrfs_header { struct btrfs_buffer; struct btrfs_root_item { __le64 blocknr; __le32 flags; __le64 block_limit; __le64 blocks_used; __le32 refs; }; /* * in ram representation of the tree. extent_root is used for all allocations * and for the extent tree extent_root root. current_insert is used Loading @@ -61,6 +74,7 @@ struct btrfs_root { struct btrfs_buffer *node; struct btrfs_buffer *commit_root; struct btrfs_root *extent_root; struct btrfs_root *tree_root; struct btrfs_key current_insert; struct btrfs_key last_insert; int fp; Loading @@ -69,28 +83,25 @@ struct btrfs_root { struct list_head trans; struct list_head cache; int cache_size; int ref_cows; struct btrfs_root_item root_item; struct btrfs_key root_key; }; /* * describes a tree on disk */ struct btrfs_root_info { u64 fsid[2]; /* FS specific uuid */ u64 blocknr; /* blocknr of this block */ u64 objectid; /* inode number of this root */ u64 tree_root; /* the tree root block */ u32 csum; u32 ham; u64 snapuuid[2]; /* root specific uuid */ } __attribute__ ((__packed__)); /* * the super block basically lists the main trees of the FS * it currently lacks any block count etc etc */ struct btrfs_super_block { struct btrfs_root_info root_info; struct btrfs_root_info extent_info; u8 fsid[16]; /* FS specific uuid */ __le64 blocknr; /* this block number */ __le32 csum; __le64 magic; __le16 blocksize; __le64 generation; __le64 root; __le64 total_blocks; __le64 blocks_used; } __attribute__ ((__packed__)); /* Loading Loading @@ -317,6 +328,79 @@ static inline int btrfs_is_leaf(struct btrfs_node *n) return (btrfs_header_level(&n->header) == 0); } static inline u64 btrfs_root_blocknr(struct btrfs_root_item *item) { return le64_to_cpu(item->blocknr); } static inline void btrfs_set_root_blocknr(struct btrfs_root_item *item, u64 val) { item->blocknr = cpu_to_le64(val); } static inline u32 btrfs_root_refs(struct btrfs_root_item *item) { return le32_to_cpu(item->refs); } static inline void btrfs_set_root_refs(struct btrfs_root_item *item, u32 val) { item->refs = cpu_to_le32(val); } static inline u64 btrfs_super_blocknr(struct btrfs_super_block *s) { return le64_to_cpu(s->blocknr); } static inline void btrfs_set_super_blocknr(struct btrfs_super_block *s, u64 val) { s->blocknr = cpu_to_le64(val); } static inline u64 btrfs_super_root(struct btrfs_super_block *s) { return le64_to_cpu(s->root); } static inline void btrfs_set_super_root(struct btrfs_super_block *s, u64 val) { s->root = cpu_to_le64(val); } static inline u64 btrfs_super_total_blocks(struct btrfs_super_block *s) { return le64_to_cpu(s->total_blocks); } static inline void btrfs_set_super_total_blocks(struct btrfs_super_block *s, u64 val) { s->total_blocks = cpu_to_le64(val); } static inline u64 btrfs_super_blocks_used(struct btrfs_super_block *s) { return le64_to_cpu(s->blocks_used); } static inline void btrfs_set_super_blocks_used(struct btrfs_super_block *s, u64 val) { s->blocks_used = cpu_to_le64(val); } static inline u16 btrfs_super_blocksize(struct btrfs_super_block *s) { return le16_to_cpu(s->blocksize); } static inline void btrfs_set_super_blocksize(struct btrfs_super_block *s, u16 val) { s->blocksize = cpu_to_le16(val); } struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_root *root); int btrfs_inc_ref(struct btrfs_root *root, struct btrfs_buffer *buf); int btrfs_free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks); Loading @@ -331,4 +415,11 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path); int btrfs_leaf_free_space(struct btrfs_leaf *leaf); int btrfs_drop_snapshot(struct btrfs_root *root, struct btrfs_buffer *snap); int btrfs_finish_extent_commit(struct btrfs_root *root); int btrfs_del_root(struct btrfs_root *root, struct btrfs_key *key); int btrfs_insert_root(struct btrfs_root *root, struct btrfs_key *key, struct btrfs_root_item *item); int btrfs_update_root(struct btrfs_root *root, struct btrfs_key *key, struct btrfs_root_item *item); int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct btrfs_root_item *item, struct btrfs_key *key); #endif
fs/btrfs/debug-tree.c +3 −1 Original line number Diff line number Diff line Loading @@ -11,9 +11,11 @@ int main(int ac, char **av) { struct btrfs_root *root; radix_tree_init(); root = open_ctree("dbfile", &super); printf("root tree\n"); printf("fs tree\n"); btrfs_print_tree(root, root->node); printf("map tree\n"); btrfs_print_tree(root->extent_root, root->extent_root->node); printf("root tree\n"); btrfs_print_tree(root->tree_root, root->tree_root->node); return 0; }
fs/btrfs/disk-io.c +107 −28 Original line number Diff line number Diff line Loading @@ -154,41 +154,96 @@ static int __commit_transaction(struct btrfs_root *root) return ret; } static int commit_extent_and_tree_roots(struct btrfs_root *tree_root, struct btrfs_root *extent_root) { int ret; u64 old_extent_block; while(1) { old_extent_block = btrfs_root_blocknr(&extent_root->root_item); if (old_extent_block == extent_root->node->blocknr) break; btrfs_set_root_blocknr(&extent_root->root_item, extent_root->node->blocknr); ret = btrfs_update_root(tree_root, &extent_root->root_key, &extent_root->root_item); BUG_ON(ret); } __commit_transaction(extent_root); __commit_transaction(tree_root); return 0; } int btrfs_commit_transaction(struct btrfs_root *root, struct btrfs_super_block *s) { int ret = 0; struct btrfs_buffer *snap = root->commit_root; struct btrfs_key snap_key; ret = __commit_transaction(root); if (!ret && root != root->extent_root) ret = __commit_transaction(root->extent_root); BUG_ON(ret); if (root->commit_root != root->node) { struct btrfs_buffer *snap = root->commit_root; if (root->commit_root == root->node) return 0; memcpy(&snap_key, &root->root_key, sizeof(snap_key)); root->root_key.offset++; btrfs_set_root_blocknr(&root->root_item, root->node->blocknr); ret = btrfs_insert_root(root->tree_root, &root->root_key, &root->root_item); BUG_ON(ret); ret = commit_extent_and_tree_roots(root->tree_root, root->extent_root); BUG_ON(ret); write_ctree_super(root, s); btrfs_finish_extent_commit(root->extent_root); btrfs_finish_extent_commit(root->tree_root); root->commit_root = root->node; root->node->count++; ret = btrfs_drop_snapshot(root, snap); BUG_ON(ret); // btrfs_block_release(root, snap); } write_ctree_super(root, s); btrfs_finish_extent_commit(root); ret = btrfs_del_root(root->tree_root, &snap_key); BUG_ON(ret); return ret; } static int __setup_root(struct btrfs_root *root, struct btrfs_root *extent_root, struct btrfs_root_info *info, int fp) static int __setup_root(struct btrfs_root *root, u64 objectid, int fp) { INIT_LIST_HEAD(&root->trans); INIT_LIST_HEAD(&root->cache); root->cache_size = 0; root->fp = fp; root->node = NULL; root->extent_root = extent_root; root->commit_root = NULL; root->node = read_tree_block(root, info->tree_root); memset(&root->current_insert, 0, sizeof(root->current_insert)); memset(&root->last_insert, 0, sizeof(root->last_insert)); memset(&root->root_key, 0, sizeof(root->root_key)); memset(&root->root_item, 0, sizeof(root->root_item)); return 0; } static int find_and_setup_root(struct btrfs_root *tree_root, u64 objectid, struct btrfs_root *root, int fp) { int ret; __setup_root(root, objectid, fp); ret = btrfs_find_last_root(tree_root, objectid, &root->root_item, &root->root_key); BUG_ON(ret); root->node = read_tree_block(root, btrfs_root_blocknr(&root->root_item)); root->ref_cows = 0; BUG_ON(!root->node); return 0; } Loading @@ -196,9 +251,19 @@ struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *super) { 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)); int fp; int ret; root->extent_root = extent_root; root->tree_root = tree_root; extent_root->extent_root = extent_root; extent_root->tree_root = tree_root; tree_root->extent_root = extent_root; tree_root->tree_root = tree_root; fp = open(filename, O_CREAT | O_RDWR, 0600); if (fp < 0) { free(root); Loading @@ -208,11 +273,14 @@ struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *super) INIT_RADIX_TREE(&root->pinned_radix, GFP_KERNEL); INIT_RADIX_TREE(&extent_root->pinned_radix, GFP_KERNEL); INIT_RADIX_TREE(&extent_root->cache_radix, GFP_KERNEL); INIT_RADIX_TREE(&tree_root->pinned_radix, GFP_KERNEL); INIT_RADIX_TREE(&tree_root->cache_radix, GFP_KERNEL); ret = pread(fp, super, sizeof(struct btrfs_super_block), BTRFS_SUPER_INFO_OFFSET(BTRFS_BLOCKSIZE)); if (ret == 0 || super->root_info.tree_root == 0) { if (ret == 0 || btrfs_super_root(super) == 0) { printf("making new FS!\n"); ret = mkfs(fp); ret = mkfs(fp, 0, BTRFS_BLOCKSIZE); if (ret) return NULL; ret = pread(fp, super, sizeof(struct btrfs_super_block), Loading @@ -221,24 +289,29 @@ struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *super) return NULL; } BUG_ON(ret < 0); __setup_root(root, extent_root, &super->root_info, fp); __setup_root(extent_root, extent_root, &super->extent_info, fp); __setup_root(tree_root, BTRFS_ROOT_TREE_OBJECTID, fp); tree_root->node = read_tree_block(tree_root, btrfs_super_root(super)); BUG_ON(!tree_root->node); ret = find_and_setup_root(tree_root, BTRFS_EXTENT_TREE_OBJECTID, extent_root, fp); BUG_ON(ret); ret = find_and_setup_root(tree_root, BTRFS_FS_TREE_OBJECTID, root, fp); BUG_ON(ret); root->commit_root = root->node; root->node->count++; root->ref_cows = 1; return root; } static int __update_root(struct btrfs_root *root, struct btrfs_root_info *info) { info->tree_root = root->node->blocknr; return 0; } int write_ctree_super(struct btrfs_root *root, struct btrfs_super_block *s) { int ret; __update_root(root, &s->root_info); __update_root(root->extent_root, &s->extent_info); btrfs_set_super_root(s, root->tree_root->node->blocknr); ret = pwrite(root->fp, s, sizeof(*s), BTRFS_SUPER_INFO_OFFSET(BTRFS_BLOCKSIZE)); if (ret != sizeof(*s)) { Loading @@ -260,19 +333,25 @@ static int drop_cache(struct btrfs_root *root) } int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s) { int ret; btrfs_commit_transaction(root, s); __commit_transaction(root->extent_root); ret = commit_extent_and_tree_roots(root->tree_root, root->extent_root); BUG_ON(ret); write_ctree_super(root, s); drop_cache(root->extent_root); drop_cache(root->tree_root); drop_cache(root); BUG_ON(!list_empty(&root->trans)); BUG_ON(!list_empty(&root->extent_root->trans)); BUG_ON(!list_empty(&root->tree_root->trans)); close(root->fp); if (root->node) btrfs_block_release(root, root->node); if (root->extent_root->node) btrfs_block_release(root->extent_root, root->extent_root->node); if (root->tree_root->node) btrfs_block_release(root->tree_root, root->tree_root->node); btrfs_block_release(root, root->commit_root); free(root); printf("on close %d blocks are allocated\n", allocated_blocks); Loading