aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ctree.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-03-01 12:04:21 -0500
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-03-01 12:04:21 -0500
commitbb8039515d7c1b521ea22f095b43618ccc771885 (patch)
treead217372c4d6f8cf49ceb465b928907b9d94da89 /fs/btrfs/ctree.c
parent0f70abe2b39d19171d4133d2ffdf77fb9113106a (diff)
Btrfs: merge on the way down during deletes
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r--fs/btrfs/ctree.c420
1 files changed, 200 insertions, 220 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 273239932255..df4a19d65206 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -10,11 +10,10 @@ static int split_node(struct ctree_root *root, struct ctree_path *path,
10 int level); 10 int level);
11static int split_leaf(struct ctree_root *root, struct ctree_path *path, 11static int split_leaf(struct ctree_root *root, struct ctree_path *path,
12 int data_size); 12 int data_size);
13static int push_node_left(struct ctree_root *root, struct ctree_path *path, 13static int push_node_left(struct ctree_root *root, struct tree_buffer *dst,
14 int level); 14 struct tree_buffer *src);
15static int push_node_right(struct ctree_root *root, 15static int del_ptr(struct ctree_root *root, struct ctree_path *path, int level,
16 struct ctree_path *path, int level); 16 int slot);
17static int del_ptr(struct ctree_root *root, struct ctree_path *path, int level);
18 17
19inline void init_path(struct ctree_path *p) 18inline void init_path(struct ctree_path *p)
20{ 19{
@@ -192,6 +191,138 @@ int bin_search(struct node *c, struct key *key, int *slot)
192 return -1; 191 return -1;
193} 192}
194 193
194struct tree_buffer *read_node_slot(struct ctree_root *root,
195 struct tree_buffer *parent_buf,
196 int slot)
197{
198 struct node *node = &parent_buf->node;
199 if (slot < 0)
200 return NULL;
201 if (slot >= node->header.nritems)
202 return NULL;
203 return read_tree_block(root, node->blockptrs[slot]);
204}
205
206static int balance_level(struct ctree_root *root, struct ctree_path *path,
207 int level)
208{
209 struct tree_buffer *right_buf;
210 struct tree_buffer *mid_buf;
211 struct tree_buffer *left_buf;
212 struct tree_buffer *parent_buf = NULL;
213 struct node *right = NULL;
214 struct node *mid;
215 struct node *left = NULL;
216 struct node *parent = NULL;
217 int ret = 0;
218 int wret;
219 int pslot;
220 int used = 0;
221 int count;
222 int orig_slot = path->slots[level];
223
224 if (level == 0)
225 return 0;
226
227 mid_buf = path->nodes[level];
228 mid = &mid_buf->node;
229 if (level < MAX_LEVEL - 1)
230 parent_buf = path->nodes[level + 1];
231 pslot = path->slots[level + 1];
232
233 if (!parent_buf) {
234 struct tree_buffer *child;
235 u64 blocknr = mid_buf->blocknr;
236
237 if (mid->header.nritems != 1)
238 return 0;
239
240 /* promote the child to a root */
241 child = read_node_slot(root, mid_buf, 0);
242 BUG_ON(!child);
243 root->node = child;
244 path->nodes[level] = NULL;
245 /* once for the path */
246 tree_block_release(root, mid_buf);
247 /* once for the root ptr */
248 tree_block_release(root, mid_buf);
249 return free_extent(root, blocknr, 1);
250 }
251 parent = &parent_buf->node;
252
253 if (mid->header.nritems > NODEPTRS_PER_BLOCK / 4)
254 return 0;
255
256 // print_tree(root, root->node);
257 left_buf = read_node_slot(root, parent_buf, pslot - 1);
258 right_buf = read_node_slot(root, parent_buf, pslot + 1);
259 if (right_buf) {
260 right = &right_buf->node;
261 used = right->header.nritems;
262 count = 1;
263 }
264 if (left_buf) {
265 left = &left_buf->node;
266 used += left->header.nritems;
267 orig_slot += left->header.nritems;
268 count++;
269 }
270 if (left_buf)
271 push_node_left(root, left_buf, mid_buf);
272 if (right_buf) {
273 push_node_left(root, mid_buf, right_buf);
274 if (right->header.nritems == 0) {
275 u64 blocknr = right_buf->blocknr;
276 tree_block_release(root, right_buf);
277 right_buf = NULL;
278 right = NULL;
279 wret = del_ptr(root, path, level + 1, pslot + 1);
280 if (wret)
281 ret = wret;
282 wret = free_extent(root, blocknr, 1);
283 if (wret)
284 ret = wret;
285 } else {
286 memcpy(parent->keys + pslot + 1, right->keys,
287 sizeof(struct key));
288 }
289 }
290 if (mid->header.nritems == 0) {
291 u64 blocknr = mid_buf->blocknr;
292 tree_block_release(root, mid_buf);
293 mid_buf = NULL;
294 mid = NULL;
295 wret = del_ptr(root, path, level + 1, pslot);
296 if (wret)
297 ret = wret;
298 wret = free_extent(root, blocknr, 1);
299 if (wret)
300 ret = wret;
301 } else
302 memcpy(parent->keys + pslot, mid->keys, sizeof(struct key));
303
304 if (left_buf) {
305 if (left->header.nritems >= orig_slot) {
306 left_buf->count++; // released below
307 path->nodes[level] = left_buf;
308 path->slots[level + 1] -= 1;
309 path->slots[level] = orig_slot;
310 if (mid_buf)
311 tree_block_release(root, mid_buf);
312 } else {
313 orig_slot -= left->header.nritems;
314 path->slots[level] = orig_slot;
315 }
316 }
317
318 if (right_buf)
319 tree_block_release(root, right_buf);
320 if (left_buf)
321 tree_block_release(root, left_buf);
322
323 return ret;
324}
325
195/* 326/*
196 * look for key in the tree. path is filled in with nodes along the way 327 * look for key in the tree. path is filled in with nodes along the way
197 * if key is found, we return zero and you can find the item in the leaf 328 * if key is found, we return zero and you can find the item in the leaf
@@ -208,12 +339,14 @@ int bin_search(struct node *c, struct key *key, int *slot)
208int search_slot(struct ctree_root *root, struct key *key, 339int search_slot(struct ctree_root *root, struct key *key,
209 struct ctree_path *p, int ins_len) 340 struct ctree_path *p, int ins_len)
210{ 341{
211 struct tree_buffer *b = root->node; 342 struct tree_buffer *b;
212 struct node *c; 343 struct node *c;
213 int slot; 344 int slot;
214 int ret; 345 int ret;
215 int level; 346 int level;
216 347
348again:
349 b = root->node;
217 b->count++; 350 b->count++;
218 while (b) { 351 while (b) {
219 c = &b->node; 352 c = &b->node;
@@ -236,9 +369,17 @@ int search_slot(struct ctree_root *root, struct key *key,
236 b = p->nodes[level]; 369 b = p->nodes[level];
237 c = &b->node; 370 c = &b->node;
238 slot = p->slots[level]; 371 slot = p->slots[level];
372 } else if (ins_len < 0) {
373 int sret = balance_level(root, p, level);
374 if (sret)
375 return sret;
376 b = p->nodes[level];
377 if (!b)
378 goto again;
379 c = &b->node;
380 slot = p->slots[level];
239 } 381 }
240 b = read_tree_block(root, c->blockptrs[slot]); 382 b = read_tree_block(root, c->blockptrs[slot]);
241 continue;
242 } else { 383 } else {
243 struct leaf *l = (struct leaf *)c; 384 struct leaf *l = (struct leaf *)c;
244 p->slots[level] = slot; 385 p->slots[level] = slot;
@@ -249,9 +390,11 @@ int search_slot(struct ctree_root *root, struct key *key,
249 if (sret) 390 if (sret)
250 return sret; 391 return sret;
251 } 392 }
393 BUG_ON(root->node->count == 1);
252 return ret; 394 return ret;
253 } 395 }
254 } 396 }
397 BUG_ON(root->node->count == 1);
255 return 1; 398 return 1;
256} 399}
257 400
@@ -301,164 +444,50 @@ static int fixup_low_keys(struct ctree_root *root,
301 * returns 0 if some ptrs were pushed left, < 0 if there was some horrible 444 * returns 0 if some ptrs were pushed left, < 0 if there was some horrible
302 * error, and > 0 if there was no room in the left hand block. 445 * error, and > 0 if there was no room in the left hand block.
303 */ 446 */
304static int push_node_left(struct ctree_root *root, struct ctree_path *path, 447static int push_node_left(struct ctree_root *root, struct tree_buffer *dst_buf,
305 int level) 448 struct tree_buffer *src_buf)
306{ 449{
307 int slot; 450 struct node *src = &src_buf->node;
308 struct node *left; 451 struct node *dst = &dst_buf->node;
309 struct node *right;
310 int push_items = 0; 452 int push_items = 0;
311 int left_nritems; 453 int src_nritems;
312 int right_nritems; 454 int dst_nritems;
313 struct tree_buffer *t;
314 struct tree_buffer *right_buf;
315 int ret = 0; 455 int ret = 0;
316 int wret; 456 int wret;
317 457
318 if (level == MAX_LEVEL - 1 || path->nodes[level + 1] == 0) 458 src_nritems = src->header.nritems;
319 return 1; 459 dst_nritems = dst->header.nritems;
320 slot = path->slots[level + 1]; 460 push_items = NODEPTRS_PER_BLOCK - dst_nritems;
321 if (slot == 0)
322 return 1;
323
324 t = read_tree_block(root,
325 path->nodes[level + 1]->node.blockptrs[slot - 1]);
326 left = &t->node;
327 right_buf = path->nodes[level];
328 right = &right_buf->node;
329 left_nritems = left->header.nritems;
330 right_nritems = right->header.nritems;
331 push_items = NODEPTRS_PER_BLOCK - (left_nritems + 1);
332 if (push_items <= 0) { 461 if (push_items <= 0) {
333 tree_block_release(root, t);
334 return 1; 462 return 1;
335 } 463 }
336 464
337 if (right_nritems < push_items) 465 if (src_nritems < push_items)
338 push_items = right_nritems; 466 push_items =src_nritems;
339 memcpy(left->keys + left_nritems, right->keys, 467 memcpy(dst->keys + dst_nritems, src->keys,
340 push_items * sizeof(struct key)); 468 push_items * sizeof(struct key));
341 memcpy(left->blockptrs + left_nritems, right->blockptrs, 469 memcpy(dst->blockptrs + dst_nritems, src->blockptrs,
342 push_items * sizeof(u64)); 470 push_items * sizeof(u64));
343 memmove(right->keys, right->keys + push_items, 471 if (push_items < src_nritems) {
344 (right_nritems - push_items) * sizeof(struct key)); 472 memmove(src->keys, src->keys + push_items,
345 memmove(right->blockptrs, right->blockptrs + push_items, 473 (src_nritems - push_items) * sizeof(struct key));
346 (right_nritems - push_items) * sizeof(u64)); 474 memmove(src->blockptrs, src->blockptrs + push_items,
347 right->header.nritems -= push_items; 475 (src_nritems - push_items) * sizeof(u64));
348 left->header.nritems += push_items; 476 }
349 477 src->header.nritems -= push_items;
350 /* adjust the pointers going up the tree */ 478 dst->header.nritems += push_items;
351 wret = fixup_low_keys(root, path, right->keys, level + 1);
352 if (wret < 0)
353 ret = wret;
354 479
355 wret = write_tree_block(root, t); 480 wret = write_tree_block(root, src_buf);
356 if (wret < 0) 481 if (wret < 0)
357 ret = wret; 482 ret = wret;
358 483
359 wret = write_tree_block(root, right_buf); 484 wret = write_tree_block(root, dst_buf);
360 if (wret < 0) 485 if (wret < 0)
361 ret = wret; 486 ret = wret;
362
363 /* then fixup the leaf pointer in the path */
364 if (path->slots[level] < push_items) {
365 path->slots[level] += left_nritems;
366 tree_block_release(root, path->nodes[level]);
367 path->nodes[level] = t;
368 path->slots[level + 1] -= 1;
369 } else {
370 path->slots[level] -= push_items;
371 tree_block_release(root, t);
372 }
373 return ret; 487 return ret;
374} 488}
375 489
376/* 490/*
377 * try to push data from one node into the next node right in the
378 * tree. The src node is found at specified level in the path.
379 * If some bytes were pushed, return 0, otherwise return 1.
380 *
381 * Lower nodes/leaves in the path are not touched, higher nodes may
382 * be modified to reflect the push.
383 *
384 * The path is altered to reflect the push.
385 *
386 * returns 0 if some ptrs were pushed, < 0 if there was some horrible
387 * error, and > 0 if there was no room in the right hand block.
388 */
389static int push_node_right(struct ctree_root *root, struct ctree_path *path,
390 int level)
391{
392 int slot;
393 struct tree_buffer *t;
394 struct tree_buffer *src_buffer;
395 struct node *dst;
396 struct node *src;
397 int push_items = 0;
398 int dst_nritems;
399 int src_nritems;
400
401 /* can't push from the root */
402 if (level == MAX_LEVEL - 1 || path->nodes[level + 1] == 0)
403 return 1;
404
405 /* only try to push inside the node higher up */
406 slot = path->slots[level + 1];
407 if (slot == NODEPTRS_PER_BLOCK - 1)
408 return 1;
409
410 if (slot >= path->nodes[level + 1]->node.header.nritems -1)
411 return 1;
412
413 t = read_tree_block(root,
414 path->nodes[level + 1]->node.blockptrs[slot + 1]);
415 dst = &t->node;
416 src_buffer = path->nodes[level];
417 src = &src_buffer->node;
418 dst_nritems = dst->header.nritems;
419 src_nritems = src->header.nritems;
420 push_items = NODEPTRS_PER_BLOCK - (dst_nritems + 1);
421 if (push_items <= 0) {
422 tree_block_release(root, t);
423 return 1;
424 }
425
426 if (src_nritems < push_items)
427 push_items = src_nritems;
428 memmove(dst->keys + push_items, dst->keys,
429 dst_nritems * sizeof(struct key));
430 memcpy(dst->keys, src->keys + src_nritems - push_items,
431 push_items * sizeof(struct key));
432
433 memmove(dst->blockptrs + push_items, dst->blockptrs,
434 dst_nritems * sizeof(u64));
435 memcpy(dst->blockptrs, src->blockptrs + src_nritems - push_items,
436 push_items * sizeof(u64));
437
438 src->header.nritems -= push_items;
439 dst->header.nritems += push_items;
440
441 /* adjust the pointers going up the tree */
442 memcpy(path->nodes[level + 1]->node.keys + path->slots[level + 1] + 1,
443 dst->keys, sizeof(struct key));
444
445 write_tree_block(root, path->nodes[level + 1]);
446 write_tree_block(root, t);
447 write_tree_block(root, src_buffer);
448
449 /* then fixup the pointers in the path */
450 if (path->slots[level] >= src->header.nritems) {
451 path->slots[level] -= src->header.nritems;
452 tree_block_release(root, path->nodes[level]);
453 path->nodes[level] = t;
454 path->slots[level + 1] += 1;
455 } else {
456 tree_block_release(root, t);
457 }
458 return 0;
459}
460
461/*
462 * helper function to insert a new root level in the tree. 491 * helper function to insert a new root level in the tree.
463 * A new node is allocated, and a single item is inserted to 492 * A new node is allocated, and a single item is inserted to
464 * point to the existing root 493 * point to the existing root
@@ -558,16 +587,6 @@ static int split_node(struct ctree_root *root, struct ctree_path *path,
558 int ret; 587 int ret;
559 int wret; 588 int wret;
560 589
561 ret = push_node_left(root, path, level);
562 if (!ret)
563 return 0;
564 if (ret < 0)
565 return ret;
566 ret = push_node_right(root, path, level);
567 if (!ret)
568 return 0;
569 if (ret < 0)
570 return ret;
571 t = path->nodes[level]; 590 t = path->nodes[level];
572 c = &t->node; 591 c = &t->node;
573 if (t == root->node) { 592 if (t == root->node) {
@@ -1011,6 +1030,7 @@ int insert_item(struct ctree_root *root, struct key *key,
1011 1030
1012 if (leaf_free_space(leaf) < 0) 1031 if (leaf_free_space(leaf) < 0)
1013 BUG(); 1032 BUG();
1033 check_leaf(&path, 0);
1014 release_path(root, &path); 1034 release_path(root, &path);
1015 return ret; 1035 return ret;
1016} 1036}
@@ -1022,77 +1042,38 @@ int insert_item(struct ctree_root *root, struct key *key,
1022 * continuing all the way the root if required. The root is converted into 1042 * continuing all the way the root if required. The root is converted into
1023 * a leaf if all the nodes are emptied. 1043 * a leaf if all the nodes are emptied.
1024 */ 1044 */
1025static int del_ptr(struct ctree_root *root, struct ctree_path *path, int level) 1045static int del_ptr(struct ctree_root *root, struct ctree_path *path, int level,
1046 int slot)
1026{ 1047{
1027 int slot;
1028 struct tree_buffer *t;
1029 struct node *node; 1048 struct node *node;
1049 struct tree_buffer *parent = path->nodes[level];
1030 int nritems; 1050 int nritems;
1031 u64 blocknr;
1032 int wret;
1033 int ret = 0; 1051 int ret = 0;
1052 int wret;
1034 1053
1035 while(1) { 1054 node = &parent->node;
1036 t = path->nodes[level]; 1055 nritems = node->header.nritems;
1037 if (!t) 1056
1038 break; 1057 if (slot != nritems -1) {
1039 node = &t->node; 1058 memmove(node->keys + slot, node->keys + slot + 1,
1040 slot = path->slots[level]; 1059 sizeof(struct key) * (nritems - slot - 1));
1041 nritems = node->header.nritems; 1060 memmove(node->blockptrs + slot,
1042 1061 node->blockptrs + slot + 1,
1043 if (slot != nritems -1) { 1062 sizeof(u64) * (nritems - slot - 1));
1044 memmove(node->keys + slot, node->keys + slot + 1, 1063 }
1045 sizeof(struct key) * (nritems - slot - 1)); 1064 node->header.nritems--;
1046 memmove(node->blockptrs + slot, 1065 if (node->header.nritems == 0 && parent == root->node) {
1047 node->blockptrs + slot + 1, 1066 BUG_ON(node_level(root->node->node.header.flags) != 1);
1048 sizeof(u64) * (nritems - slot - 1)); 1067 /* just turn the root into a leaf and break */
1049 } 1068 root->node->node.header.flags = node_level(0);
1050 node->header.nritems--; 1069 } else if (slot == 0) {
1051 blocknr = t->blocknr; 1070 wret = fixup_low_keys(root, path, node->keys, level + 1);
1052 write_tree_block(root, t);
1053 if (node->header.nritems != 0) {
1054 int tslot;
1055 if (slot == 0) {
1056 wret = fixup_low_keys(root, path,
1057 node->keys,
1058 level + 1);
1059 if (wret)
1060 ret = wret;
1061 }
1062 tslot = path->slots[level + 1];
1063 t->count++;
1064 wret = push_node_left(root, path, level);
1065 if (wret < 0) {
1066 ret = wret;
1067 break;
1068 }
1069 if (node->header.nritems != 0) {
1070 wret = push_node_right(root, path, level);
1071 if (wret < 0) {
1072 ret = wret;
1073 break;
1074 }
1075 }
1076 path->slots[level + 1] = tslot;
1077 if (node->header.nritems != 0) {
1078 tree_block_release(root, t);
1079 break;
1080 }
1081 tree_block_release(root, t);
1082 }
1083 if (t == root->node) {
1084 /* just turn the root into a leaf and break */
1085 root->node->node.header.flags = node_level(0);
1086 write_tree_block(root, t);
1087 break;
1088 }
1089 level++;
1090 wret = free_extent(root, blocknr, 1);
1091 if (wret) 1071 if (wret)
1092 ret = wret; 1072 ret = wret;
1093 if (!path->nodes[level])
1094 BUG();
1095 } 1073 }
1074 wret = write_tree_block(root, parent);
1075 if (wret)
1076 ret = wret;
1096 return ret; 1077 return ret;
1097} 1078}
1098 1079
@@ -1135,7 +1116,7 @@ int del_item(struct ctree_root *root, struct ctree_path *path)
1135 leaf->header.flags = node_level(0); 1116 leaf->header.flags = node_level(0);
1136 write_tree_block(root, leaf_buf); 1117 write_tree_block(root, leaf_buf);
1137 } else { 1118 } else {
1138 wret = del_ptr(root, path, 1); 1119 wret = del_ptr(root, path, 1, path->slots[1]);
1139 if (wret) 1120 if (wret)
1140 ret = wret; 1121 ret = wret;
1141 wret = free_extent(root, leaf_buf->blocknr, 1); 1122 wret = free_extent(root, leaf_buf->blocknr, 1);
@@ -1172,8 +1153,7 @@ int del_item(struct ctree_root *root, struct ctree_path *path)
1172 } 1153 }
1173 if (leaf->header.nritems == 0) { 1154 if (leaf->header.nritems == 0) {
1174 u64 blocknr = leaf_buf->blocknr; 1155 u64 blocknr = leaf_buf->blocknr;
1175 path->slots[1] = slot; 1156 wret = del_ptr(root, path, 1, slot);
1176 wret = del_ptr(root, path, 1);
1177 if (wret) 1157 if (wret)
1178 ret = wret; 1158 ret = wret;
1179 tree_block_release(root, leaf_buf); 1159 tree_block_release(root, leaf_buf);