mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-09-22 12:44:11 +08:00
Btrfs: push_leaf_right
Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
parent
5de08d7d50
commit
00ec4c5161
109
fs/btrfs/ctree.c
109
fs/btrfs/ctree.c
@ -517,6 +517,97 @@ int leaf_space_used(struct leaf *l, int start, int nr)
|
|||||||
return data_len;
|
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
|
* push some data in the path leaf to the left, trying to free up at
|
||||||
* least data_size bytes. returns zero if the push worked, nonzero otherwise
|
* least data_size bytes. returns zero if the push worked, nonzero otherwise
|
||||||
@ -631,7 +722,8 @@ int split_leaf(struct ctree_root *root, struct ctree_path *path, int data_size)
|
|||||||
int i;
|
int i;
|
||||||
int ret;
|
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_buf = path->nodes[0];
|
||||||
l = &l_buf->leaf;
|
l = &l_buf->leaf;
|
||||||
if (leaf_free_space(l) >= sizeof(struct item) + data_size)
|
if (leaf_free_space(l) >= sizeof(struct item) + data_size)
|
||||||
@ -875,6 +967,8 @@ int del_item(struct ctree_root *root, struct ctree_path *path)
|
|||||||
slot = path->slots[1];
|
slot = path->slots[1];
|
||||||
leaf_buf->count++;
|
leaf_buf->count++;
|
||||||
push_leaf_left(root, path, 1);
|
push_leaf_left(root, path, 1);
|
||||||
|
if (leaf->header.nritems)
|
||||||
|
push_leaf_right(root, path, 1);
|
||||||
if (leaf->header.nritems == 0) {
|
if (leaf->header.nritems == 0) {
|
||||||
u64 blocknr = leaf_buf->blocknr;
|
u64 blocknr = leaf_buf->blocknr;
|
||||||
path->slots[1] = slot;
|
path->slots[1] = slot;
|
||||||
@ -929,7 +1023,7 @@ int next_leaf(struct ctree_root *root, struct ctree_path *path)
|
|||||||
/* for testing only */
|
/* for testing only */
|
||||||
int next_key(int i, int max_key) {
|
int next_key(int i, int max_key) {
|
||||||
return rand() % max_key;
|
return rand() % max_key;
|
||||||
// return i;
|
//return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
@ -958,7 +1052,7 @@ int main() {
|
|||||||
// num = i;
|
// num = i;
|
||||||
sprintf(buf, "string-%d", num);
|
sprintf(buf, "string-%d", num);
|
||||||
if (i % 10000 == 0)
|
if (i % 10000 == 0)
|
||||||
printf("insert %d:%d\n", num, i);
|
fprintf(stderr, "insert %d:%d\n", num, i);
|
||||||
ins.objectid = num;
|
ins.objectid = num;
|
||||||
ins.offset = 0;
|
ins.offset = 0;
|
||||||
ins.flags = 0;
|
ins.flags = 0;
|
||||||
@ -978,7 +1072,7 @@ int main() {
|
|||||||
ins.objectid = num;
|
ins.objectid = num;
|
||||||
init_path(&path);
|
init_path(&path);
|
||||||
if (i % 10000 == 0)
|
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);
|
ret = search_slot(root, &ins, &path, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
print_tree(root, root->node);
|
print_tree(root, root->node);
|
||||||
@ -1004,7 +1098,7 @@ int main() {
|
|||||||
ret = search_slot(root, &ins, &path, -1);
|
ret = search_slot(root, &ins, &path, -1);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
if (i % 10000 == 0)
|
if (i % 10000 == 0)
|
||||||
printf("del %d:%d\n", num, i);
|
fprintf(stderr, "del %d:%d\n", num, i);
|
||||||
ret = del_item(root, &path);
|
ret = del_item(root, &path);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
BUG();
|
BUG();
|
||||||
@ -1022,7 +1116,7 @@ int main() {
|
|||||||
sprintf(buf, "string-%d", num);
|
sprintf(buf, "string-%d", num);
|
||||||
ins.objectid = num;
|
ins.objectid = num;
|
||||||
if (i % 10000 == 0)
|
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));
|
ret = insert_item(root, &ins, buf, strlen(buf));
|
||||||
if (!ret)
|
if (!ret)
|
||||||
tree_size++;
|
tree_size++;
|
||||||
@ -1038,7 +1132,7 @@ int main() {
|
|||||||
ins.objectid = num;
|
ins.objectid = num;
|
||||||
init_path(&path);
|
init_path(&path);
|
||||||
if (i % 10000 == 0)
|
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);
|
ret = search_slot(root, &ins, &path, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
print_tree(root, root->node);
|
print_tree(root, root->node);
|
||||||
@ -1082,6 +1176,7 @@ int main() {
|
|||||||
}
|
}
|
||||||
printf("tree size is now %d\n", tree_size);
|
printf("tree size is now %d\n", tree_size);
|
||||||
printf("map tree\n");
|
printf("map tree\n");
|
||||||
|
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);
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user