Loading fs/btrfs/ctree.c +102 −7 Original line number Diff line number Diff line Loading @@ -517,6 +517,97 @@ int leaf_space_used(struct leaf *l, int start, int nr) return data_len; } /* * push some data in the path leaf to the right, trying to free up at * least data_size bytes. returns zero if the push worked, nonzero otherwise */ int push_leaf_right(struct ctree_root *root, struct ctree_path *path, int data_size) { struct tree_buffer *left_buf = path->nodes[0]; struct leaf *left = &left_buf->leaf; struct leaf *right; struct tree_buffer *right_buf; struct tree_buffer *upper; int slot; int i; int free_space; int push_space = 0; int push_items = 0; struct item *item; slot = path->slots[1]; if (!path->nodes[1]) { return 1; } upper = path->nodes[1]; if (slot >= upper->node.header.nritems - 1) { return 1; } right_buf = read_tree_block(root, upper->node.blockptrs[slot + 1]); right = &right_buf->leaf; free_space = leaf_free_space(right); if (free_space < data_size + sizeof(struct item)) { tree_block_release(root, right_buf); return 1; } for (i = left->header.nritems - 1; i >= 0; i--) { item = left->items + i; if (path->slots[0] == i) push_space += data_size + sizeof(*item); if (item->size + sizeof(*item) + push_space > free_space) break; push_items++; push_space += item->size + sizeof(*item); } if (push_items == 0) { tree_block_release(root, right_buf); return 1; } /* push left to right */ push_space = left->items[left->header.nritems - push_items].offset + left->items[left->header.nritems - push_items].size; push_space -= leaf_data_end(left); /* make room in the right data area */ memmove(right->data + leaf_data_end(right) - push_space, right->data + leaf_data_end(right), LEAF_DATA_SIZE - leaf_data_end(right)); /* copy from the left data area */ memcpy(right->data + LEAF_DATA_SIZE - push_space, left->data + leaf_data_end(left), push_space); memmove(right->items + push_items, right->items, right->header.nritems * sizeof(struct item)); /* copy the items from left to right */ memcpy(right->items, left->items + left->header.nritems - push_items, push_items * sizeof(struct item)); /* update the item pointers */ right->header.nritems += push_items; push_space = LEAF_DATA_SIZE; for (i = 0; i < right->header.nritems; i++) { right->items[i].offset = push_space - right->items[i].size; push_space = right->items[i].offset; } left->header.nritems -= push_items; write_tree_block(root, left_buf); write_tree_block(root, right_buf); memcpy(upper->node.keys + slot + 1, &right->items[0].key, sizeof(struct key)); write_tree_block(root, upper); /* then fixup the leaf pointer in the path */ // FIXME use nritems in here somehow if (path->slots[0] >= left->header.nritems) { path->slots[0] -= left->header.nritems; tree_block_release(root, path->nodes[0]); path->nodes[0] = right_buf; path->slots[1] += 1; } else { tree_block_release(root, right_buf); } return 0; } /* * push some data in the path leaf to the left, trying to free up at * least data_size bytes. returns zero if the push worked, nonzero otherwise Loading Loading @@ -631,7 +722,8 @@ int split_leaf(struct ctree_root *root, struct ctree_path *path, int data_size) int i; int ret; if (push_leaf_left(root, path, data_size) == 0) { if (push_leaf_left(root, path, data_size) == 0 || push_leaf_right(root, path, data_size) == 0) { l_buf = path->nodes[0]; l = &l_buf->leaf; if (leaf_free_space(l) >= sizeof(struct item) + data_size) Loading Loading @@ -875,6 +967,8 @@ int del_item(struct ctree_root *root, struct ctree_path *path) slot = path->slots[1]; leaf_buf->count++; push_leaf_left(root, path, 1); if (leaf->header.nritems) push_leaf_right(root, path, 1); if (leaf->header.nritems == 0) { u64 blocknr = leaf_buf->blocknr; path->slots[1] = slot; Loading Loading @@ -958,7 +1052,7 @@ int main() { // num = i; sprintf(buf, "string-%d", num); if (i % 10000 == 0) printf("insert %d:%d\n", num, i); fprintf(stderr, "insert %d:%d\n", num, i); ins.objectid = num; ins.offset = 0; ins.flags = 0; Loading @@ -978,7 +1072,7 @@ int main() { ins.objectid = num; init_path(&path); if (i % 10000 == 0) printf("search %d:%d\n", num, i); fprintf(stderr, "search %d:%d\n", num, i); ret = search_slot(root, &ins, &path, 0); if (ret) { print_tree(root, root->node); Loading @@ -1004,7 +1098,7 @@ int main() { ret = search_slot(root, &ins, &path, -1); if (!ret) { if (i % 10000 == 0) printf("del %d:%d\n", num, i); fprintf(stderr, "del %d:%d\n", num, i); ret = del_item(root, &path); if (ret != 0) BUG(); Loading @@ -1022,7 +1116,7 @@ int main() { sprintf(buf, "string-%d", num); ins.objectid = num; if (i % 10000 == 0) printf("insert %d:%d\n", num, i); fprintf(stderr, "insert %d:%d\n", num, i); ret = insert_item(root, &ins, buf, strlen(buf)); if (!ret) tree_size++; Loading @@ -1038,7 +1132,7 @@ int main() { ins.objectid = num; init_path(&path); if (i % 10000 == 0) printf("search %d:%d\n", num, i); fprintf(stderr, "search %d:%d\n", num, i); ret = search_slot(root, &ins, &path, 0); if (ret) { print_tree(root, root->node); Loading Loading @@ -1082,6 +1176,7 @@ int main() { } printf("tree size is now %d\n", tree_size); printf("map tree\n"); print_tree(root->extent_root, root->extent_root->node); write_ctree_super(root, &super); close_ctree(root); return 0; Loading Loading
fs/btrfs/ctree.c +102 −7 Original line number Diff line number Diff line Loading @@ -517,6 +517,97 @@ int leaf_space_used(struct leaf *l, int start, int nr) return data_len; } /* * push some data in the path leaf to the right, trying to free up at * least data_size bytes. returns zero if the push worked, nonzero otherwise */ int push_leaf_right(struct ctree_root *root, struct ctree_path *path, int data_size) { struct tree_buffer *left_buf = path->nodes[0]; struct leaf *left = &left_buf->leaf; struct leaf *right; struct tree_buffer *right_buf; struct tree_buffer *upper; int slot; int i; int free_space; int push_space = 0; int push_items = 0; struct item *item; slot = path->slots[1]; if (!path->nodes[1]) { return 1; } upper = path->nodes[1]; if (slot >= upper->node.header.nritems - 1) { return 1; } right_buf = read_tree_block(root, upper->node.blockptrs[slot + 1]); right = &right_buf->leaf; free_space = leaf_free_space(right); if (free_space < data_size + sizeof(struct item)) { tree_block_release(root, right_buf); return 1; } for (i = left->header.nritems - 1; i >= 0; i--) { item = left->items + i; if (path->slots[0] == i) push_space += data_size + sizeof(*item); if (item->size + sizeof(*item) + push_space > free_space) break; push_items++; push_space += item->size + sizeof(*item); } if (push_items == 0) { tree_block_release(root, right_buf); return 1; } /* push left to right */ push_space = left->items[left->header.nritems - push_items].offset + left->items[left->header.nritems - push_items].size; push_space -= leaf_data_end(left); /* make room in the right data area */ memmove(right->data + leaf_data_end(right) - push_space, right->data + leaf_data_end(right), LEAF_DATA_SIZE - leaf_data_end(right)); /* copy from the left data area */ memcpy(right->data + LEAF_DATA_SIZE - push_space, left->data + leaf_data_end(left), push_space); memmove(right->items + push_items, right->items, right->header.nritems * sizeof(struct item)); /* copy the items from left to right */ memcpy(right->items, left->items + left->header.nritems - push_items, push_items * sizeof(struct item)); /* update the item pointers */ right->header.nritems += push_items; push_space = LEAF_DATA_SIZE; for (i = 0; i < right->header.nritems; i++) { right->items[i].offset = push_space - right->items[i].size; push_space = right->items[i].offset; } left->header.nritems -= push_items; write_tree_block(root, left_buf); write_tree_block(root, right_buf); memcpy(upper->node.keys + slot + 1, &right->items[0].key, sizeof(struct key)); write_tree_block(root, upper); /* then fixup the leaf pointer in the path */ // FIXME use nritems in here somehow if (path->slots[0] >= left->header.nritems) { path->slots[0] -= left->header.nritems; tree_block_release(root, path->nodes[0]); path->nodes[0] = right_buf; path->slots[1] += 1; } else { tree_block_release(root, right_buf); } return 0; } /* * push some data in the path leaf to the left, trying to free up at * least data_size bytes. returns zero if the push worked, nonzero otherwise Loading Loading @@ -631,7 +722,8 @@ int split_leaf(struct ctree_root *root, struct ctree_path *path, int data_size) int i; int ret; if (push_leaf_left(root, path, data_size) == 0) { if (push_leaf_left(root, path, data_size) == 0 || push_leaf_right(root, path, data_size) == 0) { l_buf = path->nodes[0]; l = &l_buf->leaf; if (leaf_free_space(l) >= sizeof(struct item) + data_size) Loading Loading @@ -875,6 +967,8 @@ int del_item(struct ctree_root *root, struct ctree_path *path) slot = path->slots[1]; leaf_buf->count++; push_leaf_left(root, path, 1); if (leaf->header.nritems) push_leaf_right(root, path, 1); if (leaf->header.nritems == 0) { u64 blocknr = leaf_buf->blocknr; path->slots[1] = slot; Loading Loading @@ -958,7 +1052,7 @@ int main() { // num = i; sprintf(buf, "string-%d", num); if (i % 10000 == 0) printf("insert %d:%d\n", num, i); fprintf(stderr, "insert %d:%d\n", num, i); ins.objectid = num; ins.offset = 0; ins.flags = 0; Loading @@ -978,7 +1072,7 @@ int main() { ins.objectid = num; init_path(&path); if (i % 10000 == 0) printf("search %d:%d\n", num, i); fprintf(stderr, "search %d:%d\n", num, i); ret = search_slot(root, &ins, &path, 0); if (ret) { print_tree(root, root->node); Loading @@ -1004,7 +1098,7 @@ int main() { ret = search_slot(root, &ins, &path, -1); if (!ret) { if (i % 10000 == 0) printf("del %d:%d\n", num, i); fprintf(stderr, "del %d:%d\n", num, i); ret = del_item(root, &path); if (ret != 0) BUG(); Loading @@ -1022,7 +1116,7 @@ int main() { sprintf(buf, "string-%d", num); ins.objectid = num; if (i % 10000 == 0) printf("insert %d:%d\n", num, i); fprintf(stderr, "insert %d:%d\n", num, i); ret = insert_item(root, &ins, buf, strlen(buf)); if (!ret) tree_size++; Loading @@ -1038,7 +1132,7 @@ int main() { ins.objectid = num; init_path(&path); if (i % 10000 == 0) printf("search %d:%d\n", num, i); fprintf(stderr, "search %d:%d\n", num, i); ret = search_slot(root, &ins, &path, 0); if (ret) { print_tree(root, root->node); Loading Loading @@ -1082,6 +1176,7 @@ int main() { } printf("tree size is now %d\n", tree_size); printf("map tree\n"); print_tree(root->extent_root, root->extent_root->node); write_ctree_super(root, &super); close_ctree(root); return 0; Loading