diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-03-01 12:04:21 -0500 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-03-01 12:04:21 -0500 |
commit | bb8039515d7c1b521ea22f095b43618ccc771885 (patch) | |
tree | ad217372c4d6f8cf49ceb465b928907b9d94da89 /fs/btrfs | |
parent | 0f70abe2b39d19171d4133d2ffdf77fb9113106a (diff) |
Btrfs: merge on the way down during deletes
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/ctree.c | 420 |
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); |
11 | static int split_leaf(struct ctree_root *root, struct ctree_path *path, | 11 | static int split_leaf(struct ctree_root *root, struct ctree_path *path, |
12 | int data_size); | 12 | int data_size); |
13 | static int push_node_left(struct ctree_root *root, struct ctree_path *path, | 13 | static int push_node_left(struct ctree_root *root, struct tree_buffer *dst, |
14 | int level); | 14 | struct tree_buffer *src); |
15 | static int push_node_right(struct ctree_root *root, | 15 | static int del_ptr(struct ctree_root *root, struct ctree_path *path, int level, |
16 | struct ctree_path *path, int level); | 16 | int slot); |
17 | static int del_ptr(struct ctree_root *root, struct ctree_path *path, int level); | ||
18 | 17 | ||
19 | inline void init_path(struct ctree_path *p) | 18 | inline 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 | ||
194 | struct 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 | |||
206 | static 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) | |||
208 | int search_slot(struct ctree_root *root, struct key *key, | 339 | int 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 | ||
348 | again: | ||
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 | */ |
304 | static int push_node_left(struct ctree_root *root, struct ctree_path *path, | 447 | static 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 | */ | ||
389 | static 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 | */ |
1025 | static int del_ptr(struct ctree_root *root, struct ctree_path *path, int level) | 1045 | static 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); |