diff options
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r-- | fs/btrfs/ctree.c | 148 |
1 files changed, 4 insertions, 144 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 6d183f60d63a..b33436211000 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -4402,149 +4402,6 @@ void btrfs_extend_item(struct btrfs_trans_handle *trans, | |||
4402 | } | 4402 | } |
4403 | 4403 | ||
4404 | /* | 4404 | /* |
4405 | * Given a key and some data, insert items into the tree. | ||
4406 | * This does all the path init required, making room in the tree if needed. | ||
4407 | * Returns the number of keys that were inserted. | ||
4408 | */ | ||
4409 | int btrfs_insert_some_items(struct btrfs_trans_handle *trans, | ||
4410 | struct btrfs_root *root, | ||
4411 | struct btrfs_path *path, | ||
4412 | struct btrfs_key *cpu_key, u32 *data_size, | ||
4413 | int nr) | ||
4414 | { | ||
4415 | struct extent_buffer *leaf; | ||
4416 | struct btrfs_item *item; | ||
4417 | int ret = 0; | ||
4418 | int slot; | ||
4419 | int i; | ||
4420 | u32 nritems; | ||
4421 | u32 total_data = 0; | ||
4422 | u32 total_size = 0; | ||
4423 | unsigned int data_end; | ||
4424 | struct btrfs_disk_key disk_key; | ||
4425 | struct btrfs_key found_key; | ||
4426 | struct btrfs_map_token token; | ||
4427 | |||
4428 | btrfs_init_map_token(&token); | ||
4429 | |||
4430 | for (i = 0; i < nr; i++) { | ||
4431 | if (total_size + data_size[i] + sizeof(struct btrfs_item) > | ||
4432 | BTRFS_LEAF_DATA_SIZE(root)) { | ||
4433 | break; | ||
4434 | nr = i; | ||
4435 | } | ||
4436 | total_data += data_size[i]; | ||
4437 | total_size += data_size[i] + sizeof(struct btrfs_item); | ||
4438 | } | ||
4439 | BUG_ON(nr == 0); | ||
4440 | |||
4441 | ret = btrfs_search_slot(trans, root, cpu_key, path, total_size, 1); | ||
4442 | if (ret == 0) | ||
4443 | return -EEXIST; | ||
4444 | if (ret < 0) | ||
4445 | goto out; | ||
4446 | |||
4447 | leaf = path->nodes[0]; | ||
4448 | |||
4449 | nritems = btrfs_header_nritems(leaf); | ||
4450 | data_end = leaf_data_end(root, leaf); | ||
4451 | |||
4452 | if (btrfs_leaf_free_space(root, leaf) < total_size) { | ||
4453 | for (i = nr; i >= 0; i--) { | ||
4454 | total_data -= data_size[i]; | ||
4455 | total_size -= data_size[i] + sizeof(struct btrfs_item); | ||
4456 | if (total_size < btrfs_leaf_free_space(root, leaf)) | ||
4457 | break; | ||
4458 | } | ||
4459 | nr = i; | ||
4460 | } | ||
4461 | |||
4462 | slot = path->slots[0]; | ||
4463 | BUG_ON(slot < 0); | ||
4464 | |||
4465 | if (slot != nritems) { | ||
4466 | unsigned int old_data = btrfs_item_end_nr(leaf, slot); | ||
4467 | |||
4468 | item = btrfs_item_nr(leaf, slot); | ||
4469 | btrfs_item_key_to_cpu(leaf, &found_key, slot); | ||
4470 | |||
4471 | /* figure out how many keys we can insert in here */ | ||
4472 | total_data = data_size[0]; | ||
4473 | for (i = 1; i < nr; i++) { | ||
4474 | if (btrfs_comp_cpu_keys(&found_key, cpu_key + i) <= 0) | ||
4475 | break; | ||
4476 | total_data += data_size[i]; | ||
4477 | } | ||
4478 | nr = i; | ||
4479 | |||
4480 | if (old_data < data_end) { | ||
4481 | btrfs_print_leaf(root, leaf); | ||
4482 | printk(KERN_CRIT "slot %d old_data %d data_end %d\n", | ||
4483 | slot, old_data, data_end); | ||
4484 | BUG_ON(1); | ||
4485 | } | ||
4486 | /* | ||
4487 | * item0..itemN ... dataN.offset..dataN.size .. data0.size | ||
4488 | */ | ||
4489 | /* first correct the data pointers */ | ||
4490 | for (i = slot; i < nritems; i++) { | ||
4491 | u32 ioff; | ||
4492 | |||
4493 | item = btrfs_item_nr(leaf, i); | ||
4494 | ioff = btrfs_token_item_offset(leaf, item, &token); | ||
4495 | btrfs_set_token_item_offset(leaf, item, | ||
4496 | ioff - total_data, &token); | ||
4497 | } | ||
4498 | /* shift the items */ | ||
4499 | memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot + nr), | ||
4500 | btrfs_item_nr_offset(slot), | ||
4501 | (nritems - slot) * sizeof(struct btrfs_item)); | ||
4502 | |||
4503 | /* shift the data */ | ||
4504 | memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) + | ||
4505 | data_end - total_data, btrfs_leaf_data(leaf) + | ||
4506 | data_end, old_data - data_end); | ||
4507 | data_end = old_data; | ||
4508 | } else { | ||
4509 | /* | ||
4510 | * this sucks but it has to be done, if we are inserting at | ||
4511 | * the end of the leaf only insert 1 of the items, since we | ||
4512 | * have no way of knowing whats on the next leaf and we'd have | ||
4513 | * to drop our current locks to figure it out | ||
4514 | */ | ||
4515 | nr = 1; | ||
4516 | } | ||
4517 | |||
4518 | /* setup the item for the new data */ | ||
4519 | for (i = 0; i < nr; i++) { | ||
4520 | btrfs_cpu_key_to_disk(&disk_key, cpu_key + i); | ||
4521 | btrfs_set_item_key(leaf, &disk_key, slot + i); | ||
4522 | item = btrfs_item_nr(leaf, slot + i); | ||
4523 | btrfs_set_token_item_offset(leaf, item, | ||
4524 | data_end - data_size[i], &token); | ||
4525 | data_end -= data_size[i]; | ||
4526 | btrfs_set_token_item_size(leaf, item, data_size[i], &token); | ||
4527 | } | ||
4528 | btrfs_set_header_nritems(leaf, nritems + nr); | ||
4529 | btrfs_mark_buffer_dirty(leaf); | ||
4530 | |||
4531 | ret = 0; | ||
4532 | if (slot == 0) { | ||
4533 | btrfs_cpu_key_to_disk(&disk_key, cpu_key); | ||
4534 | fixup_low_keys(trans, root, path, &disk_key, 1); | ||
4535 | } | ||
4536 | |||
4537 | if (btrfs_leaf_free_space(root, leaf) < 0) { | ||
4538 | btrfs_print_leaf(root, leaf); | ||
4539 | BUG(); | ||
4540 | } | ||
4541 | out: | ||
4542 | if (!ret) | ||
4543 | ret = nr; | ||
4544 | return ret; | ||
4545 | } | ||
4546 | |||
4547 | /* | ||
4548 | * this is a helper for btrfs_insert_empty_items, the main goal here is | 4405 | * this is a helper for btrfs_insert_empty_items, the main goal here is |
4549 | * to save stack depth by doing the bulk of the work in a function | 4406 | * to save stack depth by doing the bulk of the work in a function |
4550 | * that doesn't call btrfs_search_slot | 4407 | * that doesn't call btrfs_search_slot |
@@ -5073,6 +4930,7 @@ static void tree_move_down(struct btrfs_root *root, | |||
5073 | struct btrfs_path *path, | 4930 | struct btrfs_path *path, |
5074 | int *level, int root_level) | 4931 | int *level, int root_level) |
5075 | { | 4932 | { |
4933 | BUG_ON(*level == 0); | ||
5076 | path->nodes[*level - 1] = read_node_slot(root, path->nodes[*level], | 4934 | path->nodes[*level - 1] = read_node_slot(root, path->nodes[*level], |
5077 | path->slots[*level]); | 4935 | path->slots[*level]); |
5078 | path->slots[*level - 1] = 0; | 4936 | path->slots[*level - 1] = 0; |
@@ -5089,7 +4947,7 @@ static int tree_move_next_or_upnext(struct btrfs_root *root, | |||
5089 | 4947 | ||
5090 | path->slots[*level]++; | 4948 | path->slots[*level]++; |
5091 | 4949 | ||
5092 | while (path->slots[*level] == nritems) { | 4950 | while (path->slots[*level] >= nritems) { |
5093 | if (*level == root_level) | 4951 | if (*level == root_level) |
5094 | return -1; | 4952 | return -1; |
5095 | 4953 | ||
@@ -5433,9 +5291,11 @@ int btrfs_compare_trees(struct btrfs_root *left_root, | |||
5433 | goto out; | 5291 | goto out; |
5434 | advance_right = ADVANCE; | 5292 | advance_right = ADVANCE; |
5435 | } else { | 5293 | } else { |
5294 | WARN_ON(!extent_buffer_uptodate(left_path->nodes[0])); | ||
5436 | ret = tree_compare_item(left_root, left_path, | 5295 | ret = tree_compare_item(left_root, left_path, |
5437 | right_path, tmp_buf); | 5296 | right_path, tmp_buf); |
5438 | if (ret) { | 5297 | if (ret) { |
5298 | WARN_ON(!extent_buffer_uptodate(left_path->nodes[0])); | ||
5439 | ret = changed_cb(left_root, right_root, | 5299 | ret = changed_cb(left_root, right_root, |
5440 | left_path, right_path, | 5300 | left_path, right_path, |
5441 | &left_key, | 5301 | &left_key, |