Loading fs/btrfs/ctree.c +198 −47 Original line number Original line Diff line number Diff line Loading @@ -8,9 +8,12 @@ #define SEARCH_READ 0 #define SEARCH_READ 0 #define SEARCH_WRITE 1 #define SEARCH_WRITE 1 static int refill_alloc_extent(struct ctree_root *root); #define CTREE_EXTENT_PENDING 0 int split_node(struct ctree_root *root, struct ctree_path *path, int level); int split_node(struct ctree_root *root, struct ctree_path *path, int level); int split_leaf(struct ctree_root *root, struct ctree_path *path, int data_size); int split_leaf(struct ctree_root *root, struct ctree_path *path, int data_size); struct tree_buffer *alloc_free_block(struct ctree_root *root); int free_extent(struct ctree_root *root, u64 blocknr, u64 num_blocks); static inline void init_path(struct ctree_path *p) static inline void init_path(struct ctree_path *p) { { Loading Loading @@ -682,8 +685,6 @@ int insert_item(struct ctree_root *root, struct key *key, unsigned int data_end; unsigned int data_end; struct ctree_path path; struct ctree_path path; refill_alloc_extent(root); /* create a root if there isn't one */ /* create a root if there isn't one */ if (!root->node) if (!root->node) BUG(); BUG(); Loading Loading @@ -756,6 +757,7 @@ int del_ptr(struct ctree_root *root, struct ctree_path *path, int level) struct tree_buffer *t; struct tree_buffer *t; struct node *node; struct node *node; int nritems; int nritems; u64 blocknr; while(1) { while(1) { t = path->nodes[level]; t = path->nodes[level]; Loading @@ -774,6 +776,7 @@ int del_ptr(struct ctree_root *root, struct ctree_path *path, int level) } } node->header.nritems--; node->header.nritems--; write_tree_block(root, t); write_tree_block(root, t); blocknr = t->blocknr; if (node->header.nritems != 0) { if (node->header.nritems != 0) { int tslot; int tslot; if (slot == 0) if (slot == 0) Loading @@ -799,6 +802,7 @@ int del_ptr(struct ctree_root *root, struct ctree_path *path, int level) break; break; } } level++; level++; free_extent(root, blocknr, 1); if (!path->nodes[level]) if (!path->nodes[level]) BUG(); BUG(); } } Loading Loading @@ -841,8 +845,10 @@ int del_item(struct ctree_root *root, struct ctree_path *path) if (leaf_buf == root->node) { if (leaf_buf == root->node) { leaf->header.flags = node_level(0); leaf->header.flags = node_level(0); write_tree_block(root, leaf_buf); write_tree_block(root, leaf_buf); } else } else { del_ptr(root, path, 1); del_ptr(root, path, 1); free_extent(root, leaf_buf->blocknr, 1); } } else { } else { if (slot == 0) if (slot == 0) fixup_low_keys(root, path, &leaf->items[0].key, 1); fixup_low_keys(root, path, &leaf->items[0].key, 1); Loading @@ -867,6 +873,72 @@ int del_item(struct ctree_root *root, struct ctree_path *path) return 0; return 0; } } static int del_pending_extents(struct ctree_root *extent_root) { int ret; struct key key; struct tree_buffer *gang[4]; int i; struct ctree_path path; while(1) { ret = radix_tree_gang_lookup_tag(&extent_root->cache_radix, (void **)gang, 0, ARRAY_SIZE(gang), CTREE_EXTENT_PENDING); if (!ret) break; for (i = 0; i < ret; i++) { key.objectid = gang[i]->blocknr; key.flags = 0; key.offset = 1; init_path(&path); ret = search_slot(extent_root, &key, &path, 0); if (ret) { BUG(); // FIXME undo it and return sane return ret; } ret = del_item(extent_root, &path); if (ret) { BUG(); return ret; } release_path(extent_root, &path); radix_tree_tag_clear(&extent_root->cache_radix, gang[i]->blocknr, CTREE_EXTENT_PENDING); tree_block_release(extent_root, gang[i]); } } return 0; } int free_extent(struct ctree_root *root, u64 blocknr, u64 num_blocks) { struct ctree_path path; struct key key; struct ctree_root *extent_root = root->extent_root; struct tree_buffer *t; int pending_ret; int ret; key.objectid = blocknr; key.flags = 0; key.offset = num_blocks; if (root == extent_root) { t = read_tree_block(root, key.objectid); radix_tree_tag_set(&root->cache_radix, key.objectid, CTREE_EXTENT_PENDING); return 0; } init_path(&path); ret = search_slot(extent_root, &key, &path, 0); if (ret) BUG(); ret = del_item(extent_root, &path); release_path(extent_root, &path); pending_ret = del_pending_extents(root->extent_root); return ret ? ret : pending_ret; } int next_leaf(struct ctree_root *root, struct ctree_path *path) int next_leaf(struct ctree_root *root, struct ctree_path *path) { { int slot; int slot; Loading Loading @@ -904,8 +976,8 @@ int next_leaf(struct ctree_root *root, struct ctree_path *path) return 0; return 0; } } int alloc_extent(struct ctree_root *orig_root, u64 num_blocks, u64 search_start, int find_free_extent(struct ctree_root *orig_root, u64 num_blocks, u64 search_start, u64 search_end, u64 owner, struct key *ins) u64 search_end, struct key *ins) { { struct ctree_path path; struct ctree_path path; struct key *key; struct key *key; Loading @@ -915,15 +987,13 @@ int alloc_extent(struct ctree_root *orig_root, u64 num_blocks, u64 search_start, u64 last_block; u64 last_block; int start_found = 0; int start_found = 0; struct leaf *l; struct leaf *l; struct extent_item extent_item; struct ctree_root * root = orig_root->extent_root; struct ctree_root * root = orig_root->extent_root; init_path(&path); init_path(&path); ins->objectid = search_start; ins->objectid = search_start; ins->offset = 0; ins->offset = 0; ins->flags = 0; ins->flags = 0; ret = search_slot(root, ins, &path, 0); ret = search_slot(root, ins, &path, sizeof(struct extent_item)); while (1) { while (1) { l = &path.nodes[0]->leaf; l = &path.nodes[0]->leaf; slot = path.slots[0]; slot = path.slots[0]; Loading @@ -938,6 +1008,7 @@ int alloc_extent(struct ctree_root *orig_root, u64 num_blocks, u64 search_start, ins->objectid = search_start; ins->objectid = search_start; ins->offset = num_blocks; ins->offset = num_blocks; hole_size = search_end - search_start; hole_size = search_end - search_start; start_found = 1; goto insert; goto insert; } } ins->objectid = last_block; ins->objectid = last_block; Loading @@ -956,51 +1027,119 @@ int alloc_extent(struct ctree_root *orig_root, u64 num_blocks, u64 search_start, } else } else start_found = 1; start_found = 1; last_block = key->objectid + key->offset; last_block = key->objectid + key->offset; insert_failed: path.slots[0]++; path.slots[0]++; } } // FIXME -ENOSPC // FIXME -ENOSPC insert: insert: if (orig_root->extent_root == orig_root) { BUG_ON(num_blocks != 1); if ((root->current_insert.objectid <= ins->objectid && root->current_insert.objectid + root->current_insert.offset > ins->objectid) || (root->current_insert.objectid > ins->objectid && root->current_insert.objectid <= ins->objectid + ins->offset) || radix_tree_tag_get(&root->cache_radix, ins->objectid, CTREE_EXTENT_PENDING)) { last_block = ins->objectid + 1; search_start = last_block; goto insert_failed; } } release_path(root, &path); release_path(root, &path); extent_item.refs = 1; if (ins->offset != 1) extent_item.owner = owner; BUG(); if (root == orig_root && root->reserve_extent->num_blocks == 0) { return 0; root->reserve_extent->blocknr = ins->objectid; root->reserve_extent->num_blocks = ins->offset; root->reserve_extent->num_used = 0; } } ret = insert_item(root->extent_root, ins, &extent_item, sizeof(extent_item)); static int insert_pending_extents(struct ctree_root *extent_root) { int ret; struct key key; struct extent_item item; struct tree_buffer *gang[4]; int i; // FIXME -ENOSPC item.refs = 1; item.owner = extent_root->node->node.header.parentid; while(1) { ret = radix_tree_gang_lookup_tag(&extent_root->cache_radix, (void **)gang, 0, ARRAY_SIZE(gang), CTREE_EXTENT_PENDING); if (!ret) break; for (i = 0; i < ret; i++) { key.objectid = gang[i]->blocknr; key.flags = 0; key.offset = 1; ret = insert_item(extent_root, &key, &item, sizeof(item)); if (ret) { BUG(); // FIXME undo it and return sane return ret; return ret; } } radix_tree_tag_clear(&extent_root->cache_radix, gang[i]->blocknr, CTREE_EXTENT_PENDING); tree_block_release(extent_root, gang[i]); } } return 0; } static int refill_alloc_extent(struct ctree_root *root) int alloc_extent(struct ctree_root *root, u64 num_blocks, u64 search_start, u64 search_end, u64 owner, struct key *ins, struct tree_buffer **buf) { { struct alloc_extent *ae = root->alloc_extent; struct key key; int ret; int ret; int min_blocks = MAX_LEVEL * 2; int pending_ret; struct extent_item extent_item; if (ae->num_blocks > ae->num_used && ae->num_blocks - ae->num_used > extent_item.refs = 1; min_blocks) extent_item.owner = owner; ret = find_free_extent(root, num_blocks, search_start, search_end, ins); if (ret) return ret; if (root != root->extent_root) { memcpy(&root->extent_root->current_insert, ins, sizeof(*ins)); ret = insert_item(root->extent_root, ins, &extent_item, sizeof(extent_item)); memset(&root->extent_root->current_insert, 0, sizeof(struct key)); pending_ret = insert_pending_extents(root->extent_root); if (ret) return ret; if (pending_ret) return pending_ret; *buf = find_tree_block(root, ins->objectid); return 0; return 0; ae = root->reserve_extent; if (ae->num_blocks > ae->num_used) { if (root->alloc_extent->num_blocks == 0) { /* we should swap reserve/alloc_extent when alloc * fills up */ BUG(); } } if (ae->num_blocks - ae->num_used < min_blocks) /* we're allocating an extent for the extent tree, don't recurse */ BUG(); BUG_ON(ins->offset != 1); *buf = find_tree_block(root, ins->objectid); BUG_ON(!*buf); radix_tree_tag_set(&root->cache_radix, ins->objectid, CTREE_EXTENT_PENDING); (*buf)->count++; return 0; return 0; } } ret = alloc_extent(root, min_blocks * 2, 0, (unsigned long)-1, struct tree_buffer *alloc_free_block(struct ctree_root *root) root->node->node.header.parentid, &key); { ae->blocknr = key.objectid; struct key ins; ae->num_blocks = key.offset; int ret; ae->num_used = 0; struct tree_buffer *buf = NULL; return ret; ret = alloc_extent(root, 1, 0, (unsigned long)-1, root->node->node.header.parentid, &ins, &buf); if (ret) { BUG(); return NULL; } if (root != root->extent_root) BUG_ON(radix_tree_tag_get(&root->extent_root->cache_radix, buf->blocknr, CTREE_EXTENT_PENDING)); return buf; } } void print_leaf(struct leaf *l) void print_leaf(struct leaf *l) Loading Loading @@ -1096,6 +1235,7 @@ int main() { print_tree(root, root->node); print_tree(root, root->node); printf("map tree\n"); printf("map tree\n"); print_tree(root->extent_root, root->extent_root->node); print_tree(root->extent_root, root->extent_root->node); fflush(stdout); srand(55); srand(55); for (i = 0; i < run_size; i++) { for (i = 0; i < run_size; i++) { Loading @@ -1111,12 +1251,6 @@ int main() { if (!ret) if (!ret) tree_size++; tree_size++; } } printf("root used: %lu\n", root->alloc_extent->num_used); printf("root tree\n"); // print_tree(root, root->node); printf("map tree\n"); printf("map used: %lu\n", root->extent_root->alloc_extent->num_used); // print_tree(root->extent_root, root->extent_root->node); write_ctree_super(root, &super); write_ctree_super(root, &super); close_ctree(root); close_ctree(root); Loading Loading @@ -1167,12 +1301,27 @@ int main() { ret = insert_item(root, &ins, buf, strlen(buf)); ret = insert_item(root, &ins, buf, strlen(buf)); if (!ret) if (!ret) tree_size++; tree_size++; if (i >= 5) { struct key ugh; ugh.objectid = 5; ugh.flags = 0; ugh.offset = 0; init_path(&path); ret = search_slot(root, &ugh, &path, 0); if (ret) { print_tree(root, root->node); printf("unable to find 5 %d\n", num); exit(1); } release_path(root, &path); } } } write_ctree_super(root, &super); write_ctree_super(root, &super); close_ctree(root); close_ctree(root); root = open_ctree("dbfile", &super); root = open_ctree("dbfile", &super); printf("starting search2\n"); srand(128); srand(128); printf("starting search2\n"); for (i = 0; i < run_size; i++) { for (i = 0; i < run_size; i++) { num = next_key(i, max_key); num = next_key(i, max_key); ins.objectid = num; ins.objectid = num; Loading Loading @@ -1219,5 +1368,7 @@ int main() { write_ctree_super(root, &super); write_ctree_super(root, &super); close_ctree(root); close_ctree(root); printf("tree size is now %d\n", tree_size); printf("tree size is now %d\n", tree_size); printf("map tree\n"); print_tree(root->extent_root, root->extent_root->node); return 0; return 0; } } fs/btrfs/ctree.h +1 −12 Original line number Original line Diff line number Diff line Loading @@ -28,21 +28,12 @@ struct header { struct tree_buffer; struct tree_buffer; struct alloc_extent { u64 blocknr; u64 num_blocks; u64 num_used; } __attribute__ ((__packed__)); struct ctree_root { struct ctree_root { struct tree_buffer *node; struct tree_buffer *node; struct ctree_root *extent_root; struct ctree_root *extent_root; struct alloc_extent *alloc_extent; struct key current_insert; struct alloc_extent *reserve_extent; int fp; int fp; struct radix_tree_root cache_radix; struct radix_tree_root cache_radix; struct alloc_extent ai1; struct alloc_extent ai2; }; }; struct ctree_root_info { struct ctree_root_info { Loading @@ -52,8 +43,6 @@ struct ctree_root_info { u64 tree_root; /* the tree root */ u64 tree_root; /* the tree root */ u32 csum; u32 csum; u32 ham; u32 ham; struct alloc_extent alloc_extent; struct alloc_extent reserve_extent; u64 snapuuid[2]; /* root specific uuid */ u64 snapuuid[2]; /* root specific uuid */ } __attribute__ ((__packed__)); } __attribute__ ((__packed__)); Loading fs/btrfs/disk-io.c +31 −59 Original line number Original line Diff line number Diff line Loading @@ -12,33 +12,13 @@ static int allocated_blocks = 0; static int allocated_blocks = 0; static int get_free_block(struct ctree_root *root, u64 *block) static int check_tree_block(struct ctree_root *root, struct tree_buffer *buf) { { struct stat st; if (buf->blocknr != buf->node.header.blocknr) int ret = 0; BUG(); if (root->node && buf->node.header.parentid != root->node->node.header.parentid) if (root->alloc_extent->num_used >= root->alloc_extent->num_blocks) BUG(); return -1; return 0; *block = root->alloc_extent->blocknr + root->alloc_extent->num_used; root->alloc_extent->num_used += 1; if (root->alloc_extent->num_used >= root->alloc_extent->num_blocks) { struct alloc_extent *ae = root->alloc_extent; root->alloc_extent = root->reserve_extent; root->reserve_extent = ae; ae->num_blocks = 0; } st.st_size = 0; ret = fstat(root->fp, &st); if (st.st_size < (*block + 1) * CTREE_BLOCKSIZE) { ret = ftruncate(root->fp, (*block + 1) * CTREE_BLOCKSIZE); if (ret) { perror("ftruncate"); exit(1); } } return ret; } } struct tree_buffer *alloc_tree_block(struct ctree_root *root, u64 blocknr) struct tree_buffer *alloc_tree_block(struct ctree_root *root, u64 blocknr) Loading @@ -61,22 +41,23 @@ struct tree_buffer *alloc_tree_block(struct ctree_root *root, u64 blocknr) return buf; return buf; } } struct tree_buffer *alloc_free_block(struct ctree_root *root) struct tree_buffer *find_tree_block(struct ctree_root *root, u64 blocknr) { { u64 free_block; int ret; struct tree_buffer *buf; struct tree_buffer *buf; ret = get_free_block(root, &free_block); buf = radix_tree_lookup(&root->cache_radix, blocknr); if (ret) { if (buf) { buf->count++; } else { buf = alloc_tree_block(root, blocknr); if (!buf) { BUG(); BUG(); return NULL; return NULL; } } buf = alloc_tree_block(root, free_block); } if (!buf) BUG(); return buf; return buf; } } struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr) struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr) { { loff_t offset = blocknr * CTREE_BLOCKSIZE; loff_t offset = blocknr * CTREE_BLOCKSIZE; Loading @@ -86,8 +67,7 @@ struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr) buf = radix_tree_lookup(&root->cache_radix, blocknr); buf = radix_tree_lookup(&root->cache_radix, blocknr); if (buf) { if (buf) { buf->count++; buf->count++; goto test; } else { } buf = alloc_tree_block(root, blocknr); buf = alloc_tree_block(root, blocknr); if (!buf) if (!buf) return NULL; return NULL; Loading @@ -96,10 +76,8 @@ struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr) free(buf); free(buf); return NULL; return NULL; } } test: } if (buf->blocknr != buf->node.header.blocknr) if (check_tree_block(root, buf)) BUG(); if (root->node && buf->node.header.parentid != root->node->node.header.parentid) BUG(); BUG(); return buf; return buf; } } Loading @@ -121,17 +99,10 @@ int write_tree_block(struct ctree_root *root, struct tree_buffer *buf) static int __setup_root(struct ctree_root *root, struct ctree_root *extent_root, static int __setup_root(struct ctree_root *root, struct ctree_root *extent_root, struct ctree_root_info *info, int fp) struct ctree_root_info *info, int fp) { { INIT_RADIX_TREE(&root->cache_radix, GFP_KERNEL); root->fp = fp; root->fp = fp; root->node = NULL; root->node = NULL; root->node = read_tree_block(root, info->tree_root); root->node = read_tree_block(root, info->tree_root); root->extent_root = extent_root; root->extent_root = extent_root; memcpy(&root->ai1, &info->alloc_extent, sizeof(info->alloc_extent)); memcpy(&root->ai2, &info->reserve_extent, sizeof(info->reserve_extent)); root->alloc_extent = &root->ai1; root->reserve_extent = &root->ai2; printf("setup done reading root %p, used %lu available %lu\n", root, root->alloc_extent->num_used, root->alloc_extent->num_blocks); printf("setup done reading root %p, reserve used %lu available %lu\n", root, root->reserve_extent->num_used, root->reserve_extent->num_blocks); return 0; return 0; } } Loading @@ -147,6 +118,8 @@ struct ctree_root *open_ctree(char *filename, struct ctree_super_block *super) free(root); free(root); return NULL; return NULL; } } INIT_RADIX_TREE(&root->cache_radix, GFP_KERNEL); INIT_RADIX_TREE(&extent_root->cache_radix, GFP_KERNEL); ret = pread(fp, super, sizeof(struct ctree_super_block), ret = pread(fp, super, sizeof(struct ctree_super_block), CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE)); CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE)); if (ret == 0 || super->root_info.tree_root == 0) { if (ret == 0 || super->root_info.tree_root == 0) { Loading @@ -168,8 +141,6 @@ struct ctree_root *open_ctree(char *filename, struct ctree_super_block *super) static int __update_root(struct ctree_root *root, struct ctree_root_info *info) static int __update_root(struct ctree_root *root, struct ctree_root_info *info) { { info->tree_root = root->node->blocknr; info->tree_root = root->node->blocknr; memcpy(&info->alloc_extent, root->alloc_extent, sizeof(struct alloc_extent)); memcpy(&info->reserve_extent, root->reserve_extent, sizeof(struct alloc_extent)); return 0; return 0; } } Loading Loading @@ -201,6 +172,7 @@ int close_ctree(struct ctree_root *root) void tree_block_release(struct ctree_root *root, struct tree_buffer *buf) void tree_block_release(struct ctree_root *root, struct tree_buffer *buf) { { buf->count--; buf->count--; write_tree_block(root, buf); if (buf->count < 0) if (buf->count < 0) BUG(); BUG(); if (buf->count == 0) { if (buf->count == 0) { Loading fs/btrfs/disk-io.h +1 −1 Original line number Original line Diff line number Diff line Loading @@ -11,11 +11,11 @@ struct tree_buffer { }; }; struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr); struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr); struct tree_buffer *find_tree_block(struct ctree_root *root, u64 blocknr); int write_tree_block(struct ctree_root *root, struct tree_buffer *buf); int write_tree_block(struct ctree_root *root, struct tree_buffer *buf); struct ctree_root *open_ctree(char *filename, struct ctree_super_block *s); struct ctree_root *open_ctree(char *filename, struct ctree_super_block *s); int close_ctree(struct ctree_root *root); int close_ctree(struct ctree_root *root); void tree_block_release(struct ctree_root *root, struct tree_buffer *buf); void tree_block_release(struct ctree_root *root, struct tree_buffer *buf); struct tree_buffer *alloc_free_block(struct ctree_root *root); int write_ctree_super(struct ctree_root *root, struct ctree_super_block *s); int write_ctree_super(struct ctree_root *root, struct ctree_super_block *s); int mkfs(int fd); int mkfs(int fd); Loading fs/btrfs/mkfs.c +21 −16 Original line number Original line Diff line number Diff line Loading @@ -23,17 +23,10 @@ int mkfs(int fd) info[0].blocknr = 16; info[0].blocknr = 16; info[0].objectid = 1; info[0].objectid = 1; info[0].tree_root = 17; info[0].tree_root = 17; info[0].alloc_extent.blocknr = 0; info[0].alloc_extent.num_blocks = 64; /* 0-17 are used (inclusive) */ info[0].alloc_extent.num_used = 18; info[1].blocknr = 16; info[1].blocknr = 16; info[1].objectid = 2; info[1].objectid = 2; info[1].tree_root = 64; info[1].tree_root = 18; info[1].alloc_extent.blocknr = 64; info[1].alloc_extent.num_blocks = 64; info[1].alloc_extent.num_used = 1; ret = pwrite(fd, info, sizeof(info), ret = pwrite(fd, info, sizeof(info), CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE)); CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE)); if (ret != sizeof(info)) if (ret != sizeof(info)) Loading @@ -48,24 +41,36 @@ int mkfs(int fd) return -1; return -1; empty_leaf.header.parentid = 2; empty_leaf.header.parentid = 2; empty_leaf.header.blocknr = 64; empty_leaf.header.blocknr = 18; empty_leaf.header.nritems = 2; empty_leaf.header.nritems = 3; /* item1, reserve blocks 0-16 */ item.key.objectid = 0; item.key.objectid = 0; item.key.offset = 64; item.key.offset = 17; item.key.flags = 0; item.key.flags = 0; item.offset = LEAF_DATA_SIZE - sizeof(struct extent_item); item.offset = LEAF_DATA_SIZE - sizeof(struct extent_item); item.size = sizeof(struct extent_item); item.size = sizeof(struct extent_item); extent_item.refs = 1; extent_item.refs = 1; extent_item.owner = 1; extent_item.owner = 0; memcpy(empty_leaf.items, &item, sizeof(item)); memcpy(empty_leaf.items, &item, sizeof(item)); memcpy(empty_leaf.data + item.offset, &extent_item, item.size); memcpy(empty_leaf.data + item.offset, &extent_item, item.size); item.key.objectid = 64; item.key.offset = 64; /* item2, give block 17 to the root */ item.key.objectid = 17; item.key.offset = 1; item.offset = LEAF_DATA_SIZE - sizeof(struct extent_item) * 2; item.offset = LEAF_DATA_SIZE - sizeof(struct extent_item) * 2; extent_item.owner = 2; extent_item.owner = 1; memcpy(empty_leaf.items + 1, &item, sizeof(item)); memcpy(empty_leaf.items + 1, &item, sizeof(item)); memcpy(empty_leaf.data + item.offset, &extent_item, item.size); memcpy(empty_leaf.data + item.offset, &extent_item, item.size); ret = pwrite(fd, &empty_leaf, sizeof(empty_leaf), 64 * CTREE_BLOCKSIZE); /* item3, give block 18 for the extent root */ item.key.objectid = 18; item.key.offset = 1; item.offset = LEAF_DATA_SIZE - sizeof(struct extent_item) * 3; extent_item.owner = 2; memcpy(empty_leaf.items + 2, &item, sizeof(item)); memcpy(empty_leaf.data + item.offset, &extent_item, item.size); ret = pwrite(fd, &empty_leaf, sizeof(empty_leaf), 18 * CTREE_BLOCKSIZE); if (ret != sizeof(empty_leaf)) if (ret != sizeof(empty_leaf)) return -1; return -1; return 0; return 0; Loading Loading
fs/btrfs/ctree.c +198 −47 Original line number Original line Diff line number Diff line Loading @@ -8,9 +8,12 @@ #define SEARCH_READ 0 #define SEARCH_READ 0 #define SEARCH_WRITE 1 #define SEARCH_WRITE 1 static int refill_alloc_extent(struct ctree_root *root); #define CTREE_EXTENT_PENDING 0 int split_node(struct ctree_root *root, struct ctree_path *path, int level); int split_node(struct ctree_root *root, struct ctree_path *path, int level); int split_leaf(struct ctree_root *root, struct ctree_path *path, int data_size); int split_leaf(struct ctree_root *root, struct ctree_path *path, int data_size); struct tree_buffer *alloc_free_block(struct ctree_root *root); int free_extent(struct ctree_root *root, u64 blocknr, u64 num_blocks); static inline void init_path(struct ctree_path *p) static inline void init_path(struct ctree_path *p) { { Loading Loading @@ -682,8 +685,6 @@ int insert_item(struct ctree_root *root, struct key *key, unsigned int data_end; unsigned int data_end; struct ctree_path path; struct ctree_path path; refill_alloc_extent(root); /* create a root if there isn't one */ /* create a root if there isn't one */ if (!root->node) if (!root->node) BUG(); BUG(); Loading Loading @@ -756,6 +757,7 @@ int del_ptr(struct ctree_root *root, struct ctree_path *path, int level) struct tree_buffer *t; struct tree_buffer *t; struct node *node; struct node *node; int nritems; int nritems; u64 blocknr; while(1) { while(1) { t = path->nodes[level]; t = path->nodes[level]; Loading @@ -774,6 +776,7 @@ int del_ptr(struct ctree_root *root, struct ctree_path *path, int level) } } node->header.nritems--; node->header.nritems--; write_tree_block(root, t); write_tree_block(root, t); blocknr = t->blocknr; if (node->header.nritems != 0) { if (node->header.nritems != 0) { int tslot; int tslot; if (slot == 0) if (slot == 0) Loading @@ -799,6 +802,7 @@ int del_ptr(struct ctree_root *root, struct ctree_path *path, int level) break; break; } } level++; level++; free_extent(root, blocknr, 1); if (!path->nodes[level]) if (!path->nodes[level]) BUG(); BUG(); } } Loading Loading @@ -841,8 +845,10 @@ int del_item(struct ctree_root *root, struct ctree_path *path) if (leaf_buf == root->node) { if (leaf_buf == root->node) { leaf->header.flags = node_level(0); leaf->header.flags = node_level(0); write_tree_block(root, leaf_buf); write_tree_block(root, leaf_buf); } else } else { del_ptr(root, path, 1); del_ptr(root, path, 1); free_extent(root, leaf_buf->blocknr, 1); } } else { } else { if (slot == 0) if (slot == 0) fixup_low_keys(root, path, &leaf->items[0].key, 1); fixup_low_keys(root, path, &leaf->items[0].key, 1); Loading @@ -867,6 +873,72 @@ int del_item(struct ctree_root *root, struct ctree_path *path) return 0; return 0; } } static int del_pending_extents(struct ctree_root *extent_root) { int ret; struct key key; struct tree_buffer *gang[4]; int i; struct ctree_path path; while(1) { ret = radix_tree_gang_lookup_tag(&extent_root->cache_radix, (void **)gang, 0, ARRAY_SIZE(gang), CTREE_EXTENT_PENDING); if (!ret) break; for (i = 0; i < ret; i++) { key.objectid = gang[i]->blocknr; key.flags = 0; key.offset = 1; init_path(&path); ret = search_slot(extent_root, &key, &path, 0); if (ret) { BUG(); // FIXME undo it and return sane return ret; } ret = del_item(extent_root, &path); if (ret) { BUG(); return ret; } release_path(extent_root, &path); radix_tree_tag_clear(&extent_root->cache_radix, gang[i]->blocknr, CTREE_EXTENT_PENDING); tree_block_release(extent_root, gang[i]); } } return 0; } int free_extent(struct ctree_root *root, u64 blocknr, u64 num_blocks) { struct ctree_path path; struct key key; struct ctree_root *extent_root = root->extent_root; struct tree_buffer *t; int pending_ret; int ret; key.objectid = blocknr; key.flags = 0; key.offset = num_blocks; if (root == extent_root) { t = read_tree_block(root, key.objectid); radix_tree_tag_set(&root->cache_radix, key.objectid, CTREE_EXTENT_PENDING); return 0; } init_path(&path); ret = search_slot(extent_root, &key, &path, 0); if (ret) BUG(); ret = del_item(extent_root, &path); release_path(extent_root, &path); pending_ret = del_pending_extents(root->extent_root); return ret ? ret : pending_ret; } int next_leaf(struct ctree_root *root, struct ctree_path *path) int next_leaf(struct ctree_root *root, struct ctree_path *path) { { int slot; int slot; Loading Loading @@ -904,8 +976,8 @@ int next_leaf(struct ctree_root *root, struct ctree_path *path) return 0; return 0; } } int alloc_extent(struct ctree_root *orig_root, u64 num_blocks, u64 search_start, int find_free_extent(struct ctree_root *orig_root, u64 num_blocks, u64 search_start, u64 search_end, u64 owner, struct key *ins) u64 search_end, struct key *ins) { { struct ctree_path path; struct ctree_path path; struct key *key; struct key *key; Loading @@ -915,15 +987,13 @@ int alloc_extent(struct ctree_root *orig_root, u64 num_blocks, u64 search_start, u64 last_block; u64 last_block; int start_found = 0; int start_found = 0; struct leaf *l; struct leaf *l; struct extent_item extent_item; struct ctree_root * root = orig_root->extent_root; struct ctree_root * root = orig_root->extent_root; init_path(&path); init_path(&path); ins->objectid = search_start; ins->objectid = search_start; ins->offset = 0; ins->offset = 0; ins->flags = 0; ins->flags = 0; ret = search_slot(root, ins, &path, 0); ret = search_slot(root, ins, &path, sizeof(struct extent_item)); while (1) { while (1) { l = &path.nodes[0]->leaf; l = &path.nodes[0]->leaf; slot = path.slots[0]; slot = path.slots[0]; Loading @@ -938,6 +1008,7 @@ int alloc_extent(struct ctree_root *orig_root, u64 num_blocks, u64 search_start, ins->objectid = search_start; ins->objectid = search_start; ins->offset = num_blocks; ins->offset = num_blocks; hole_size = search_end - search_start; hole_size = search_end - search_start; start_found = 1; goto insert; goto insert; } } ins->objectid = last_block; ins->objectid = last_block; Loading @@ -956,51 +1027,119 @@ int alloc_extent(struct ctree_root *orig_root, u64 num_blocks, u64 search_start, } else } else start_found = 1; start_found = 1; last_block = key->objectid + key->offset; last_block = key->objectid + key->offset; insert_failed: path.slots[0]++; path.slots[0]++; } } // FIXME -ENOSPC // FIXME -ENOSPC insert: insert: if (orig_root->extent_root == orig_root) { BUG_ON(num_blocks != 1); if ((root->current_insert.objectid <= ins->objectid && root->current_insert.objectid + root->current_insert.offset > ins->objectid) || (root->current_insert.objectid > ins->objectid && root->current_insert.objectid <= ins->objectid + ins->offset) || radix_tree_tag_get(&root->cache_radix, ins->objectid, CTREE_EXTENT_PENDING)) { last_block = ins->objectid + 1; search_start = last_block; goto insert_failed; } } release_path(root, &path); release_path(root, &path); extent_item.refs = 1; if (ins->offset != 1) extent_item.owner = owner; BUG(); if (root == orig_root && root->reserve_extent->num_blocks == 0) { return 0; root->reserve_extent->blocknr = ins->objectid; root->reserve_extent->num_blocks = ins->offset; root->reserve_extent->num_used = 0; } } ret = insert_item(root->extent_root, ins, &extent_item, sizeof(extent_item)); static int insert_pending_extents(struct ctree_root *extent_root) { int ret; struct key key; struct extent_item item; struct tree_buffer *gang[4]; int i; // FIXME -ENOSPC item.refs = 1; item.owner = extent_root->node->node.header.parentid; while(1) { ret = radix_tree_gang_lookup_tag(&extent_root->cache_radix, (void **)gang, 0, ARRAY_SIZE(gang), CTREE_EXTENT_PENDING); if (!ret) break; for (i = 0; i < ret; i++) { key.objectid = gang[i]->blocknr; key.flags = 0; key.offset = 1; ret = insert_item(extent_root, &key, &item, sizeof(item)); if (ret) { BUG(); // FIXME undo it and return sane return ret; return ret; } } radix_tree_tag_clear(&extent_root->cache_radix, gang[i]->blocknr, CTREE_EXTENT_PENDING); tree_block_release(extent_root, gang[i]); } } return 0; } static int refill_alloc_extent(struct ctree_root *root) int alloc_extent(struct ctree_root *root, u64 num_blocks, u64 search_start, u64 search_end, u64 owner, struct key *ins, struct tree_buffer **buf) { { struct alloc_extent *ae = root->alloc_extent; struct key key; int ret; int ret; int min_blocks = MAX_LEVEL * 2; int pending_ret; struct extent_item extent_item; if (ae->num_blocks > ae->num_used && ae->num_blocks - ae->num_used > extent_item.refs = 1; min_blocks) extent_item.owner = owner; ret = find_free_extent(root, num_blocks, search_start, search_end, ins); if (ret) return ret; if (root != root->extent_root) { memcpy(&root->extent_root->current_insert, ins, sizeof(*ins)); ret = insert_item(root->extent_root, ins, &extent_item, sizeof(extent_item)); memset(&root->extent_root->current_insert, 0, sizeof(struct key)); pending_ret = insert_pending_extents(root->extent_root); if (ret) return ret; if (pending_ret) return pending_ret; *buf = find_tree_block(root, ins->objectid); return 0; return 0; ae = root->reserve_extent; if (ae->num_blocks > ae->num_used) { if (root->alloc_extent->num_blocks == 0) { /* we should swap reserve/alloc_extent when alloc * fills up */ BUG(); } } if (ae->num_blocks - ae->num_used < min_blocks) /* we're allocating an extent for the extent tree, don't recurse */ BUG(); BUG_ON(ins->offset != 1); *buf = find_tree_block(root, ins->objectid); BUG_ON(!*buf); radix_tree_tag_set(&root->cache_radix, ins->objectid, CTREE_EXTENT_PENDING); (*buf)->count++; return 0; return 0; } } ret = alloc_extent(root, min_blocks * 2, 0, (unsigned long)-1, struct tree_buffer *alloc_free_block(struct ctree_root *root) root->node->node.header.parentid, &key); { ae->blocknr = key.objectid; struct key ins; ae->num_blocks = key.offset; int ret; ae->num_used = 0; struct tree_buffer *buf = NULL; return ret; ret = alloc_extent(root, 1, 0, (unsigned long)-1, root->node->node.header.parentid, &ins, &buf); if (ret) { BUG(); return NULL; } if (root != root->extent_root) BUG_ON(radix_tree_tag_get(&root->extent_root->cache_radix, buf->blocknr, CTREE_EXTENT_PENDING)); return buf; } } void print_leaf(struct leaf *l) void print_leaf(struct leaf *l) Loading Loading @@ -1096,6 +1235,7 @@ int main() { print_tree(root, root->node); print_tree(root, root->node); printf("map tree\n"); printf("map tree\n"); print_tree(root->extent_root, root->extent_root->node); print_tree(root->extent_root, root->extent_root->node); fflush(stdout); srand(55); srand(55); for (i = 0; i < run_size; i++) { for (i = 0; i < run_size; i++) { Loading @@ -1111,12 +1251,6 @@ int main() { if (!ret) if (!ret) tree_size++; tree_size++; } } printf("root used: %lu\n", root->alloc_extent->num_used); printf("root tree\n"); // print_tree(root, root->node); printf("map tree\n"); printf("map used: %lu\n", root->extent_root->alloc_extent->num_used); // print_tree(root->extent_root, root->extent_root->node); write_ctree_super(root, &super); write_ctree_super(root, &super); close_ctree(root); close_ctree(root); Loading Loading @@ -1167,12 +1301,27 @@ int main() { ret = insert_item(root, &ins, buf, strlen(buf)); ret = insert_item(root, &ins, buf, strlen(buf)); if (!ret) if (!ret) tree_size++; tree_size++; if (i >= 5) { struct key ugh; ugh.objectid = 5; ugh.flags = 0; ugh.offset = 0; init_path(&path); ret = search_slot(root, &ugh, &path, 0); if (ret) { print_tree(root, root->node); printf("unable to find 5 %d\n", num); exit(1); } release_path(root, &path); } } } write_ctree_super(root, &super); write_ctree_super(root, &super); close_ctree(root); close_ctree(root); root = open_ctree("dbfile", &super); root = open_ctree("dbfile", &super); printf("starting search2\n"); srand(128); srand(128); printf("starting search2\n"); for (i = 0; i < run_size; i++) { for (i = 0; i < run_size; i++) { num = next_key(i, max_key); num = next_key(i, max_key); ins.objectid = num; ins.objectid = num; Loading Loading @@ -1219,5 +1368,7 @@ int main() { write_ctree_super(root, &super); write_ctree_super(root, &super); close_ctree(root); close_ctree(root); printf("tree size is now %d\n", tree_size); printf("tree size is now %d\n", tree_size); printf("map tree\n"); print_tree(root->extent_root, root->extent_root->node); return 0; return 0; } }
fs/btrfs/ctree.h +1 −12 Original line number Original line Diff line number Diff line Loading @@ -28,21 +28,12 @@ struct header { struct tree_buffer; struct tree_buffer; struct alloc_extent { u64 blocknr; u64 num_blocks; u64 num_used; } __attribute__ ((__packed__)); struct ctree_root { struct ctree_root { struct tree_buffer *node; struct tree_buffer *node; struct ctree_root *extent_root; struct ctree_root *extent_root; struct alloc_extent *alloc_extent; struct key current_insert; struct alloc_extent *reserve_extent; int fp; int fp; struct radix_tree_root cache_radix; struct radix_tree_root cache_radix; struct alloc_extent ai1; struct alloc_extent ai2; }; }; struct ctree_root_info { struct ctree_root_info { Loading @@ -52,8 +43,6 @@ struct ctree_root_info { u64 tree_root; /* the tree root */ u64 tree_root; /* the tree root */ u32 csum; u32 csum; u32 ham; u32 ham; struct alloc_extent alloc_extent; struct alloc_extent reserve_extent; u64 snapuuid[2]; /* root specific uuid */ u64 snapuuid[2]; /* root specific uuid */ } __attribute__ ((__packed__)); } __attribute__ ((__packed__)); Loading
fs/btrfs/disk-io.c +31 −59 Original line number Original line Diff line number Diff line Loading @@ -12,33 +12,13 @@ static int allocated_blocks = 0; static int allocated_blocks = 0; static int get_free_block(struct ctree_root *root, u64 *block) static int check_tree_block(struct ctree_root *root, struct tree_buffer *buf) { { struct stat st; if (buf->blocknr != buf->node.header.blocknr) int ret = 0; BUG(); if (root->node && buf->node.header.parentid != root->node->node.header.parentid) if (root->alloc_extent->num_used >= root->alloc_extent->num_blocks) BUG(); return -1; return 0; *block = root->alloc_extent->blocknr + root->alloc_extent->num_used; root->alloc_extent->num_used += 1; if (root->alloc_extent->num_used >= root->alloc_extent->num_blocks) { struct alloc_extent *ae = root->alloc_extent; root->alloc_extent = root->reserve_extent; root->reserve_extent = ae; ae->num_blocks = 0; } st.st_size = 0; ret = fstat(root->fp, &st); if (st.st_size < (*block + 1) * CTREE_BLOCKSIZE) { ret = ftruncate(root->fp, (*block + 1) * CTREE_BLOCKSIZE); if (ret) { perror("ftruncate"); exit(1); } } return ret; } } struct tree_buffer *alloc_tree_block(struct ctree_root *root, u64 blocknr) struct tree_buffer *alloc_tree_block(struct ctree_root *root, u64 blocknr) Loading @@ -61,22 +41,23 @@ struct tree_buffer *alloc_tree_block(struct ctree_root *root, u64 blocknr) return buf; return buf; } } struct tree_buffer *alloc_free_block(struct ctree_root *root) struct tree_buffer *find_tree_block(struct ctree_root *root, u64 blocknr) { { u64 free_block; int ret; struct tree_buffer *buf; struct tree_buffer *buf; ret = get_free_block(root, &free_block); buf = radix_tree_lookup(&root->cache_radix, blocknr); if (ret) { if (buf) { buf->count++; } else { buf = alloc_tree_block(root, blocknr); if (!buf) { BUG(); BUG(); return NULL; return NULL; } } buf = alloc_tree_block(root, free_block); } if (!buf) BUG(); return buf; return buf; } } struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr) struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr) { { loff_t offset = blocknr * CTREE_BLOCKSIZE; loff_t offset = blocknr * CTREE_BLOCKSIZE; Loading @@ -86,8 +67,7 @@ struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr) buf = radix_tree_lookup(&root->cache_radix, blocknr); buf = radix_tree_lookup(&root->cache_radix, blocknr); if (buf) { if (buf) { buf->count++; buf->count++; goto test; } else { } buf = alloc_tree_block(root, blocknr); buf = alloc_tree_block(root, blocknr); if (!buf) if (!buf) return NULL; return NULL; Loading @@ -96,10 +76,8 @@ struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr) free(buf); free(buf); return NULL; return NULL; } } test: } if (buf->blocknr != buf->node.header.blocknr) if (check_tree_block(root, buf)) BUG(); if (root->node && buf->node.header.parentid != root->node->node.header.parentid) BUG(); BUG(); return buf; return buf; } } Loading @@ -121,17 +99,10 @@ int write_tree_block(struct ctree_root *root, struct tree_buffer *buf) static int __setup_root(struct ctree_root *root, struct ctree_root *extent_root, static int __setup_root(struct ctree_root *root, struct ctree_root *extent_root, struct ctree_root_info *info, int fp) struct ctree_root_info *info, int fp) { { INIT_RADIX_TREE(&root->cache_radix, GFP_KERNEL); root->fp = fp; root->fp = fp; root->node = NULL; root->node = NULL; root->node = read_tree_block(root, info->tree_root); root->node = read_tree_block(root, info->tree_root); root->extent_root = extent_root; root->extent_root = extent_root; memcpy(&root->ai1, &info->alloc_extent, sizeof(info->alloc_extent)); memcpy(&root->ai2, &info->reserve_extent, sizeof(info->reserve_extent)); root->alloc_extent = &root->ai1; root->reserve_extent = &root->ai2; printf("setup done reading root %p, used %lu available %lu\n", root, root->alloc_extent->num_used, root->alloc_extent->num_blocks); printf("setup done reading root %p, reserve used %lu available %lu\n", root, root->reserve_extent->num_used, root->reserve_extent->num_blocks); return 0; return 0; } } Loading @@ -147,6 +118,8 @@ struct ctree_root *open_ctree(char *filename, struct ctree_super_block *super) free(root); free(root); return NULL; return NULL; } } INIT_RADIX_TREE(&root->cache_radix, GFP_KERNEL); INIT_RADIX_TREE(&extent_root->cache_radix, GFP_KERNEL); ret = pread(fp, super, sizeof(struct ctree_super_block), ret = pread(fp, super, sizeof(struct ctree_super_block), CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE)); CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE)); if (ret == 0 || super->root_info.tree_root == 0) { if (ret == 0 || super->root_info.tree_root == 0) { Loading @@ -168,8 +141,6 @@ struct ctree_root *open_ctree(char *filename, struct ctree_super_block *super) static int __update_root(struct ctree_root *root, struct ctree_root_info *info) static int __update_root(struct ctree_root *root, struct ctree_root_info *info) { { info->tree_root = root->node->blocknr; info->tree_root = root->node->blocknr; memcpy(&info->alloc_extent, root->alloc_extent, sizeof(struct alloc_extent)); memcpy(&info->reserve_extent, root->reserve_extent, sizeof(struct alloc_extent)); return 0; return 0; } } Loading Loading @@ -201,6 +172,7 @@ int close_ctree(struct ctree_root *root) void tree_block_release(struct ctree_root *root, struct tree_buffer *buf) void tree_block_release(struct ctree_root *root, struct tree_buffer *buf) { { buf->count--; buf->count--; write_tree_block(root, buf); if (buf->count < 0) if (buf->count < 0) BUG(); BUG(); if (buf->count == 0) { if (buf->count == 0) { Loading
fs/btrfs/disk-io.h +1 −1 Original line number Original line Diff line number Diff line Loading @@ -11,11 +11,11 @@ struct tree_buffer { }; }; struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr); struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr); struct tree_buffer *find_tree_block(struct ctree_root *root, u64 blocknr); int write_tree_block(struct ctree_root *root, struct tree_buffer *buf); int write_tree_block(struct ctree_root *root, struct tree_buffer *buf); struct ctree_root *open_ctree(char *filename, struct ctree_super_block *s); struct ctree_root *open_ctree(char *filename, struct ctree_super_block *s); int close_ctree(struct ctree_root *root); int close_ctree(struct ctree_root *root); void tree_block_release(struct ctree_root *root, struct tree_buffer *buf); void tree_block_release(struct ctree_root *root, struct tree_buffer *buf); struct tree_buffer *alloc_free_block(struct ctree_root *root); int write_ctree_super(struct ctree_root *root, struct ctree_super_block *s); int write_ctree_super(struct ctree_root *root, struct ctree_super_block *s); int mkfs(int fd); int mkfs(int fd); Loading
fs/btrfs/mkfs.c +21 −16 Original line number Original line Diff line number Diff line Loading @@ -23,17 +23,10 @@ int mkfs(int fd) info[0].blocknr = 16; info[0].blocknr = 16; info[0].objectid = 1; info[0].objectid = 1; info[0].tree_root = 17; info[0].tree_root = 17; info[0].alloc_extent.blocknr = 0; info[0].alloc_extent.num_blocks = 64; /* 0-17 are used (inclusive) */ info[0].alloc_extent.num_used = 18; info[1].blocknr = 16; info[1].blocknr = 16; info[1].objectid = 2; info[1].objectid = 2; info[1].tree_root = 64; info[1].tree_root = 18; info[1].alloc_extent.blocknr = 64; info[1].alloc_extent.num_blocks = 64; info[1].alloc_extent.num_used = 1; ret = pwrite(fd, info, sizeof(info), ret = pwrite(fd, info, sizeof(info), CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE)); CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE)); if (ret != sizeof(info)) if (ret != sizeof(info)) Loading @@ -48,24 +41,36 @@ int mkfs(int fd) return -1; return -1; empty_leaf.header.parentid = 2; empty_leaf.header.parentid = 2; empty_leaf.header.blocknr = 64; empty_leaf.header.blocknr = 18; empty_leaf.header.nritems = 2; empty_leaf.header.nritems = 3; /* item1, reserve blocks 0-16 */ item.key.objectid = 0; item.key.objectid = 0; item.key.offset = 64; item.key.offset = 17; item.key.flags = 0; item.key.flags = 0; item.offset = LEAF_DATA_SIZE - sizeof(struct extent_item); item.offset = LEAF_DATA_SIZE - sizeof(struct extent_item); item.size = sizeof(struct extent_item); item.size = sizeof(struct extent_item); extent_item.refs = 1; extent_item.refs = 1; extent_item.owner = 1; extent_item.owner = 0; memcpy(empty_leaf.items, &item, sizeof(item)); memcpy(empty_leaf.items, &item, sizeof(item)); memcpy(empty_leaf.data + item.offset, &extent_item, item.size); memcpy(empty_leaf.data + item.offset, &extent_item, item.size); item.key.objectid = 64; item.key.offset = 64; /* item2, give block 17 to the root */ item.key.objectid = 17; item.key.offset = 1; item.offset = LEAF_DATA_SIZE - sizeof(struct extent_item) * 2; item.offset = LEAF_DATA_SIZE - sizeof(struct extent_item) * 2; extent_item.owner = 2; extent_item.owner = 1; memcpy(empty_leaf.items + 1, &item, sizeof(item)); memcpy(empty_leaf.items + 1, &item, sizeof(item)); memcpy(empty_leaf.data + item.offset, &extent_item, item.size); memcpy(empty_leaf.data + item.offset, &extent_item, item.size); ret = pwrite(fd, &empty_leaf, sizeof(empty_leaf), 64 * CTREE_BLOCKSIZE); /* item3, give block 18 for the extent root */ item.key.objectid = 18; item.key.offset = 1; item.offset = LEAF_DATA_SIZE - sizeof(struct extent_item) * 3; extent_item.owner = 2; memcpy(empty_leaf.items + 2, &item, sizeof(item)); memcpy(empty_leaf.data + item.offset, &extent_item, item.size); ret = pwrite(fd, &empty_leaf, sizeof(empty_leaf), 18 * CTREE_BLOCKSIZE); if (ret != sizeof(empty_leaf)) if (ret != sizeof(empty_leaf)) return -1; return -1; return 0; return 0; Loading