diff options
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r-- | fs/btrfs/ctree.c | 92 |
1 files changed, 54 insertions, 38 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index e43c827e0dfd..489019ac04b8 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -95,19 +95,23 @@ int leaf_free_space(struct leaf *leaf) | |||
95 | /* | 95 | /* |
96 | * compare two keys in a memcmp fashion | 96 | * compare two keys in a memcmp fashion |
97 | */ | 97 | */ |
98 | int comp_keys(struct key *k1, struct key *k2) | 98 | int comp_keys(struct btrfs_disk_key *disk, struct btrfs_key *k2) |
99 | { | 99 | { |
100 | if (k1->objectid > k2->objectid) | 100 | struct btrfs_key k1; |
101 | |||
102 | btrfs_disk_key_to_cpu(&k1, disk); | ||
103 | |||
104 | if (k1.objectid > k2->objectid) | ||
101 | return 1; | 105 | return 1; |
102 | if (k1->objectid < k2->objectid) | 106 | if (k1.objectid < k2->objectid) |
103 | return -1; | 107 | return -1; |
104 | if (k1->flags > k2->flags) | 108 | if (k1.flags > k2->flags) |
105 | return 1; | 109 | return 1; |
106 | if (k1->flags < k2->flags) | 110 | if (k1.flags < k2->flags) |
107 | return -1; | 111 | return -1; |
108 | if (k1->offset > k2->offset) | 112 | if (k1.offset > k2->offset) |
109 | return 1; | 113 | return 1; |
110 | if (k1->offset < k2->offset) | 114 | if (k1.offset < k2->offset) |
111 | return -1; | 115 | return -1; |
112 | return 0; | 116 | return 0; |
113 | } | 117 | } |
@@ -125,15 +129,18 @@ int check_node(struct ctree_path *path, int level) | |||
125 | parent_slot = path->slots[level + 1]; | 129 | parent_slot = path->slots[level + 1]; |
126 | BUG_ON(nritems == 0); | 130 | BUG_ON(nritems == 0); |
127 | if (parent) { | 131 | if (parent) { |
128 | struct key *parent_key; | 132 | struct btrfs_disk_key *parent_key; |
129 | parent_key = &parent->keys[parent_slot]; | 133 | parent_key = &parent->keys[parent_slot]; |
130 | BUG_ON(memcmp(parent_key, node->keys, sizeof(struct key))); | 134 | BUG_ON(memcmp(parent_key, node->keys, |
135 | sizeof(struct btrfs_disk_key))); | ||
131 | BUG_ON(parent->blockptrs[parent_slot] != | 136 | BUG_ON(parent->blockptrs[parent_slot] != |
132 | btrfs_header_blocknr(&node->header)); | 137 | btrfs_header_blocknr(&node->header)); |
133 | } | 138 | } |
134 | BUG_ON(nritems > NODEPTRS_PER_BLOCK); | 139 | BUG_ON(nritems > NODEPTRS_PER_BLOCK); |
135 | for (i = 0; nritems > 1 && i < nritems - 2; i++) { | 140 | for (i = 0; nritems > 1 && i < nritems - 2; i++) { |
136 | BUG_ON(comp_keys(&node->keys[i], &node->keys[i+1]) >= 0); | 141 | struct btrfs_key cpukey; |
142 | btrfs_disk_key_to_cpu(&cpukey, &node->keys[i + 1]); | ||
143 | BUG_ON(comp_keys(&node->keys[i], &cpukey) >= 0); | ||
137 | } | 144 | } |
138 | return 0; | 145 | return 0; |
139 | } | 146 | } |
@@ -155,16 +162,18 @@ int check_leaf(struct ctree_path *path, int level) | |||
155 | return 0; | 162 | return 0; |
156 | 163 | ||
157 | if (parent) { | 164 | if (parent) { |
158 | struct key *parent_key; | 165 | struct btrfs_disk_key *parent_key; |
159 | parent_key = &parent->keys[parent_slot]; | 166 | parent_key = &parent->keys[parent_slot]; |
160 | BUG_ON(memcmp(parent_key, &leaf->items[0].key, | 167 | BUG_ON(memcmp(parent_key, &leaf->items[0].key, |
161 | sizeof(struct key))); | 168 | sizeof(struct btrfs_disk_key))); |
162 | BUG_ON(parent->blockptrs[parent_slot] != | 169 | BUG_ON(parent->blockptrs[parent_slot] != |
163 | btrfs_header_blocknr(&leaf->header)); | 170 | btrfs_header_blocknr(&leaf->header)); |
164 | } | 171 | } |
165 | for (i = 0; nritems > 1 && i < nritems - 2; i++) { | 172 | for (i = 0; nritems > 1 && i < nritems - 2; i++) { |
173 | struct btrfs_key cpukey; | ||
174 | btrfs_disk_key_to_cpu(&cpukey, &leaf->items[i + 1].key); | ||
166 | BUG_ON(comp_keys(&leaf->items[i].key, | 175 | BUG_ON(comp_keys(&leaf->items[i].key, |
167 | &leaf->items[i+1].key) >= 0); | 176 | &cpukey) >= 0); |
168 | BUG_ON(leaf->items[i].offset != leaf->items[i + 1].offset + | 177 | BUG_ON(leaf->items[i].offset != leaf->items[i + 1].offset + |
169 | leaf->items[i + 1].size); | 178 | leaf->items[i + 1].size); |
170 | if (i == 0) { | 179 | if (i == 0) { |
@@ -191,18 +200,18 @@ int check_block(struct ctree_path *path, int level) | |||
191 | * | 200 | * |
192 | * slot may point to max if the key is bigger than all of the keys | 201 | * slot may point to max if the key is bigger than all of the keys |
193 | */ | 202 | */ |
194 | int generic_bin_search(char *p, int item_size, struct key *key, | 203 | int generic_bin_search(char *p, int item_size, struct btrfs_key *key, |
195 | int max, int *slot) | 204 | int max, int *slot) |
196 | { | 205 | { |
197 | int low = 0; | 206 | int low = 0; |
198 | int high = max; | 207 | int high = max; |
199 | int mid; | 208 | int mid; |
200 | int ret; | 209 | int ret; |
201 | struct key *tmp; | 210 | struct btrfs_disk_key *tmp; |
202 | 211 | ||
203 | while(low < high) { | 212 | while(low < high) { |
204 | mid = (low + high) / 2; | 213 | mid = (low + high) / 2; |
205 | tmp = (struct key *)(p + mid * item_size); | 214 | tmp = (struct btrfs_disk_key *)(p + mid * item_size); |
206 | ret = comp_keys(tmp, key); | 215 | ret = comp_keys(tmp, key); |
207 | 216 | ||
208 | if (ret < 0) | 217 | if (ret < 0) |
@@ -222,7 +231,7 @@ int generic_bin_search(char *p, int item_size, struct key *key, | |||
222 | * simple bin_search frontend that does the right thing for | 231 | * simple bin_search frontend that does the right thing for |
223 | * leaves vs nodes | 232 | * leaves vs nodes |
224 | */ | 233 | */ |
225 | int bin_search(struct node *c, struct key *key, int *slot) | 234 | int bin_search(struct node *c, struct btrfs_key *key, int *slot) |
226 | { | 235 | { |
227 | if (btrfs_is_leaf(c)) { | 236 | if (btrfs_is_leaf(c)) { |
228 | struct leaf *l = (struct leaf *)c; | 237 | struct leaf *l = (struct leaf *)c; |
@@ -230,7 +239,8 @@ int bin_search(struct node *c, struct key *key, int *slot) | |||
230 | key, btrfs_header_nritems(&c->header), | 239 | key, btrfs_header_nritems(&c->header), |
231 | slot); | 240 | slot); |
232 | } else { | 241 | } else { |
233 | return generic_bin_search((void *)c->keys, sizeof(struct key), | 242 | return generic_bin_search((void *)c->keys, |
243 | sizeof(struct btrfs_disk_key), | ||
234 | key, btrfs_header_nritems(&c->header), | 244 | key, btrfs_header_nritems(&c->header), |
235 | slot); | 245 | slot); |
236 | } | 246 | } |
@@ -339,7 +349,7 @@ static int balance_level(struct ctree_root *root, struct ctree_path *path, | |||
339 | ret = wret; | 349 | ret = wret; |
340 | } else { | 350 | } else { |
341 | memcpy(parent->keys + pslot + 1, right->keys, | 351 | memcpy(parent->keys + pslot + 1, right->keys, |
342 | sizeof(struct key)); | 352 | sizeof(struct btrfs_disk_key)); |
343 | BUG_ON(list_empty(&parent_buf->dirty)); | 353 | BUG_ON(list_empty(&parent_buf->dirty)); |
344 | } | 354 | } |
345 | } | 355 | } |
@@ -374,7 +384,8 @@ static int balance_level(struct ctree_root *root, struct ctree_path *path, | |||
374 | ret = wret; | 384 | ret = wret; |
375 | } else { | 385 | } else { |
376 | /* update the parent key to reflect our changes */ | 386 | /* update the parent key to reflect our changes */ |
377 | memcpy(parent->keys + pslot, mid->keys, sizeof(struct key)); | 387 | memcpy(parent->keys + pslot, mid->keys, |
388 | sizeof(struct btrfs_disk_key)); | ||
378 | BUG_ON(list_empty(&parent_buf->dirty)); | 389 | BUG_ON(list_empty(&parent_buf->dirty)); |
379 | } | 390 | } |
380 | 391 | ||
@@ -417,7 +428,7 @@ static int balance_level(struct ctree_root *root, struct ctree_path *path, | |||
417 | * tree. if ins_len < 0, nodes will be merged as we walk down the tree (if | 428 | * tree. if ins_len < 0, nodes will be merged as we walk down the tree (if |
418 | * possible) | 429 | * possible) |
419 | */ | 430 | */ |
420 | int search_slot(struct ctree_root *root, struct key *key, | 431 | int search_slot(struct ctree_root *root, struct btrfs_key *key, |
421 | struct ctree_path *p, int ins_len, int cow) | 432 | struct ctree_path *p, int ins_len, int cow) |
422 | { | 433 | { |
423 | struct tree_buffer *b; | 434 | struct tree_buffer *b; |
@@ -499,7 +510,7 @@ again: | |||
499 | * fixing up the blocks in ram so the tree is consistent. | 510 | * fixing up the blocks in ram so the tree is consistent. |
500 | */ | 511 | */ |
501 | static int fixup_low_keys(struct ctree_root *root, | 512 | static int fixup_low_keys(struct ctree_root *root, |
502 | struct ctree_path *path, struct key *key, | 513 | struct ctree_path *path, struct btrfs_disk_key *key, |
503 | int level) | 514 | int level) |
504 | { | 515 | { |
505 | int i; | 516 | int i; |
@@ -546,12 +557,13 @@ static int push_node_left(struct ctree_root *root, struct tree_buffer *dst_buf, | |||
546 | push_items = src_nritems; | 557 | push_items = src_nritems; |
547 | 558 | ||
548 | memcpy(dst->keys + dst_nritems, src->keys, | 559 | memcpy(dst->keys + dst_nritems, src->keys, |
549 | push_items * sizeof(struct key)); | 560 | push_items * sizeof(struct btrfs_disk_key)); |
550 | memcpy(dst->blockptrs + dst_nritems, src->blockptrs, | 561 | memcpy(dst->blockptrs + dst_nritems, src->blockptrs, |
551 | push_items * sizeof(u64)); | 562 | push_items * sizeof(u64)); |
552 | if (push_items < src_nritems) { | 563 | if (push_items < src_nritems) { |
553 | memmove(src->keys, src->keys + push_items, | 564 | memmove(src->keys, src->keys + push_items, |
554 | (src_nritems - push_items) * sizeof(struct key)); | 565 | (src_nritems - push_items) * |
566 | sizeof(struct btrfs_disk_key)); | ||
555 | memmove(src->blockptrs, src->blockptrs + push_items, | 567 | memmove(src->blockptrs, src->blockptrs + push_items, |
556 | (src_nritems - push_items) * sizeof(u64)); | 568 | (src_nritems - push_items) * sizeof(u64)); |
557 | } | 569 | } |
@@ -598,11 +610,11 @@ static int balance_node_right(struct ctree_root *root, | |||
598 | push_items = max_push; | 610 | push_items = max_push; |
599 | 611 | ||
600 | memmove(dst->keys + push_items, dst->keys, | 612 | memmove(dst->keys + push_items, dst->keys, |
601 | dst_nritems * sizeof(struct key)); | 613 | dst_nritems * sizeof(struct btrfs_disk_key)); |
602 | memmove(dst->blockptrs + push_items, dst->blockptrs, | 614 | memmove(dst->blockptrs + push_items, dst->blockptrs, |
603 | dst_nritems * sizeof(u64)); | 615 | dst_nritems * sizeof(u64)); |
604 | memcpy(dst->keys, src->keys + src_nritems - push_items, | 616 | memcpy(dst->keys, src->keys + src_nritems - push_items, |
605 | push_items * sizeof(struct key)); | 617 | push_items * sizeof(struct btrfs_disk_key)); |
606 | memcpy(dst->blockptrs, src->blockptrs + src_nritems - push_items, | 618 | memcpy(dst->blockptrs, src->blockptrs + src_nritems - push_items, |
607 | push_items * sizeof(u64)); | 619 | push_items * sizeof(u64)); |
608 | 620 | ||
@@ -627,7 +639,7 @@ static int insert_new_root(struct ctree_root *root, | |||
627 | struct tree_buffer *t; | 639 | struct tree_buffer *t; |
628 | struct node *lower; | 640 | struct node *lower; |
629 | struct node *c; | 641 | struct node *c; |
630 | struct key *lower_key; | 642 | struct btrfs_disk_key *lower_key; |
631 | 643 | ||
632 | BUG_ON(path->nodes[level]); | 644 | BUG_ON(path->nodes[level]); |
633 | BUG_ON(path->nodes[level-1] != root->node); | 645 | BUG_ON(path->nodes[level-1] != root->node); |
@@ -645,7 +657,7 @@ static int insert_new_root(struct ctree_root *root, | |||
645 | lower_key = &((struct leaf *)lower)->items[0].key; | 657 | lower_key = &((struct leaf *)lower)->items[0].key; |
646 | else | 658 | else |
647 | lower_key = lower->keys; | 659 | lower_key = lower->keys; |
648 | memcpy(c->keys, lower_key, sizeof(struct key)); | 660 | memcpy(c->keys, lower_key, sizeof(struct btrfs_disk_key)); |
649 | c->blockptrs[0] = path->nodes[level-1]->blocknr; | 661 | c->blockptrs[0] = path->nodes[level-1]->blocknr; |
650 | /* the super has an extra ref to root->node */ | 662 | /* the super has an extra ref to root->node */ |
651 | tree_block_release(root, root->node); | 663 | tree_block_release(root, root->node); |
@@ -666,7 +678,7 @@ static int insert_new_root(struct ctree_root *root, | |||
666 | * returns zero on success and < 0 on any error | 678 | * returns zero on success and < 0 on any error |
667 | */ | 679 | */ |
668 | static int insert_ptr(struct ctree_root *root, | 680 | static int insert_ptr(struct ctree_root *root, |
669 | struct ctree_path *path, struct key *key, | 681 | struct ctree_path *path, struct btrfs_disk_key *key, |
670 | u64 blocknr, int slot, int level) | 682 | u64 blocknr, int slot, int level) |
671 | { | 683 | { |
672 | struct node *lower; | 684 | struct node *lower; |
@@ -681,11 +693,11 @@ static int insert_ptr(struct ctree_root *root, | |||
681 | BUG(); | 693 | BUG(); |
682 | if (slot != nritems) { | 694 | if (slot != nritems) { |
683 | memmove(lower->keys + slot + 1, lower->keys + slot, | 695 | memmove(lower->keys + slot + 1, lower->keys + slot, |
684 | (nritems - slot) * sizeof(struct key)); | 696 | (nritems - slot) * sizeof(struct btrfs_disk_key)); |
685 | memmove(lower->blockptrs + slot + 1, lower->blockptrs + slot, | 697 | memmove(lower->blockptrs + slot + 1, lower->blockptrs + slot, |
686 | (nritems - slot) * sizeof(u64)); | 698 | (nritems - slot) * sizeof(u64)); |
687 | } | 699 | } |
688 | memcpy(lower->keys + slot, key, sizeof(struct key)); | 700 | memcpy(lower->keys + slot, key, sizeof(struct btrfs_disk_key)); |
689 | lower->blockptrs[slot] = blocknr; | 701 | lower->blockptrs[slot] = blocknr; |
690 | btrfs_set_header_nritems(&lower->header, nritems + 1); | 702 | btrfs_set_header_nritems(&lower->header, nritems + 1); |
691 | if (lower->keys[1].objectid == 0) | 703 | if (lower->keys[1].objectid == 0) |
@@ -732,7 +744,7 @@ static int split_node(struct ctree_root *root, struct ctree_path *path, | |||
732 | btrfs_header_parentid(&root->node->node.header)); | 744 | btrfs_header_parentid(&root->node->node.header)); |
733 | mid = (c_nritems + 1) / 2; | 745 | mid = (c_nritems + 1) / 2; |
734 | memcpy(split->keys, c->keys + mid, | 746 | memcpy(split->keys, c->keys + mid, |
735 | (c_nritems - mid) * sizeof(struct key)); | 747 | (c_nritems - mid) * sizeof(struct btrfs_disk_key)); |
736 | memcpy(split->blockptrs, c->blockptrs + mid, | 748 | memcpy(split->blockptrs, c->blockptrs + mid, |
737 | (c_nritems - mid) * sizeof(u64)); | 749 | (c_nritems - mid) * sizeof(u64)); |
738 | btrfs_set_header_nritems(&split->header, c_nritems - mid); | 750 | btrfs_set_header_nritems(&split->header, c_nritems - mid); |
@@ -869,7 +881,7 @@ static int push_leaf_right(struct ctree_root *root, struct ctree_path *path, | |||
869 | BUG_ON(list_empty(&left_buf->dirty)); | 881 | BUG_ON(list_empty(&left_buf->dirty)); |
870 | BUG_ON(list_empty(&right_buf->dirty)); | 882 | BUG_ON(list_empty(&right_buf->dirty)); |
871 | memcpy(upper->node.keys + slot + 1, | 883 | memcpy(upper->node.keys + slot + 1, |
872 | &right->items[0].key, sizeof(struct key)); | 884 | &right->items[0].key, sizeof(struct btrfs_disk_key)); |
873 | BUG_ON(list_empty(&upper->dirty)); | 885 | BUG_ON(list_empty(&upper->dirty)); |
874 | 886 | ||
875 | /* then fixup the leaf pointer in the path */ | 887 | /* then fixup the leaf pointer in the path */ |
@@ -1090,7 +1102,7 @@ static int split_leaf(struct ctree_root *root, struct ctree_path *path, | |||
1090 | * Given a key and some data, insert an item into the tree. | 1102 | * Given a key and some data, insert an item into the tree. |
1091 | * This does all the path init required, making room in the tree if needed. | 1103 | * This does all the path init required, making room in the tree if needed. |
1092 | */ | 1104 | */ |
1093 | int insert_item(struct ctree_root *root, struct key *key, | 1105 | int insert_item(struct ctree_root *root, struct btrfs_key *cpu_key, |
1094 | void *data, int data_size) | 1106 | void *data, int data_size) |
1095 | { | 1107 | { |
1096 | int ret = 0; | 1108 | int ret = 0; |
@@ -1101,12 +1113,15 @@ int insert_item(struct ctree_root *root, struct key *key, | |||
1101 | u32 nritems; | 1113 | u32 nritems; |
1102 | unsigned int data_end; | 1114 | unsigned int data_end; |
1103 | struct ctree_path path; | 1115 | struct ctree_path path; |
1116 | struct btrfs_disk_key disk_key; | ||
1117 | |||
1118 | btrfs_cpu_key_to_disk(&disk_key, cpu_key); | ||
1104 | 1119 | ||
1105 | /* create a root if there isn't one */ | 1120 | /* create a root if there isn't one */ |
1106 | if (!root->node) | 1121 | if (!root->node) |
1107 | BUG(); | 1122 | BUG(); |
1108 | init_path(&path); | 1123 | init_path(&path); |
1109 | ret = search_slot(root, key, &path, data_size, 1); | 1124 | ret = search_slot(root, cpu_key, &path, data_size, 1); |
1110 | if (ret == 0) { | 1125 | if (ret == 0) { |
1111 | release_path(root, &path); | 1126 | release_path(root, &path); |
1112 | return -EEXIST; | 1127 | return -EEXIST; |
@@ -1148,7 +1163,8 @@ int insert_item(struct ctree_root *root, struct key *key, | |||
1148 | data_end = old_data; | 1163 | data_end = old_data; |
1149 | } | 1164 | } |
1150 | /* copy the new data in */ | 1165 | /* copy the new data in */ |
1151 | memcpy(&leaf->items[slot].key, key, sizeof(struct key)); | 1166 | memcpy(&leaf->items[slot].key, &disk_key, |
1167 | sizeof(struct btrfs_disk_key)); | ||
1152 | leaf->items[slot].offset = data_end - data_size; | 1168 | leaf->items[slot].offset = data_end - data_size; |
1153 | leaf->items[slot].size = data_size; | 1169 | leaf->items[slot].size = data_size; |
1154 | memcpy(leaf->data + data_end - data_size, data, data_size); | 1170 | memcpy(leaf->data + data_end - data_size, data, data_size); |
@@ -1156,7 +1172,7 @@ int insert_item(struct ctree_root *root, struct key *key, | |||
1156 | 1172 | ||
1157 | ret = 0; | 1173 | ret = 0; |
1158 | if (slot == 0) | 1174 | if (slot == 0) |
1159 | ret = fixup_low_keys(root, &path, key, 1); | 1175 | ret = fixup_low_keys(root, &path, &disk_key, 1); |
1160 | 1176 | ||
1161 | BUG_ON(list_empty(&leaf_buf->dirty)); | 1177 | BUG_ON(list_empty(&leaf_buf->dirty)); |
1162 | if (leaf_free_space(leaf) < 0) | 1178 | if (leaf_free_space(leaf) < 0) |
@@ -1187,7 +1203,7 @@ static int del_ptr(struct ctree_root *root, struct ctree_path *path, int level, | |||
1187 | nritems = btrfs_header_nritems(&node->header); | 1203 | nritems = btrfs_header_nritems(&node->header); |
1188 | if (slot != nritems -1) { | 1204 | if (slot != nritems -1) { |
1189 | memmove(node->keys + slot, node->keys + slot + 1, | 1205 | memmove(node->keys + slot, node->keys + slot + 1, |
1190 | sizeof(struct key) * (nritems - slot - 1)); | 1206 | sizeof(struct btrfs_disk_key) * (nritems - slot - 1)); |
1191 | memmove(node->blockptrs + slot, | 1207 | memmove(node->blockptrs + slot, |
1192 | node->blockptrs + slot + 1, | 1208 | node->blockptrs + slot + 1, |
1193 | sizeof(u64) * (nritems - slot - 1)); | 1209 | sizeof(u64) * (nritems - slot - 1)); |