ctree.c (bb8039515d7c1b521ea22f095b43618ccc771885) ctree.c (79f95c82dca7665f32bafd68b7cdf4a01fab0840)
1#include <stdio.h>
2#include <stdlib.h>
3#include "kerncompat.h"
4#include "radix-tree.h"
5#include "ctree.h"
6#include "disk-io.h"
7#include "print-tree.h"
8
9static int split_node(struct ctree_root *root, struct ctree_path *path,
10 int level);
11static int split_leaf(struct ctree_root *root, struct ctree_path *path,
12 int data_size);
13static int push_node_left(struct ctree_root *root, struct tree_buffer *dst,
14 struct tree_buffer *src);
1#include <stdio.h>
2#include <stdlib.h>
3#include "kerncompat.h"
4#include "radix-tree.h"
5#include "ctree.h"
6#include "disk-io.h"
7#include "print-tree.h"
8
9static int split_node(struct ctree_root *root, struct ctree_path *path,
10 int level);
11static int split_leaf(struct ctree_root *root, struct ctree_path *path,
12 int data_size);
13static int push_node_left(struct ctree_root *root, struct tree_buffer *dst,
14 struct tree_buffer *src);
15static int balance_node_right(struct ctree_root *root,
16 struct tree_buffer *dst_buf,
17 struct tree_buffer *src_buf);
15static int del_ptr(struct ctree_root *root, struct ctree_path *path, int level,
16 int slot);
17
18inline void init_path(struct ctree_path *p)
19{
20 memset(p, 0, sizeof(*p));
21}
22

--- 189 unchanged lines hidden (view full) ---

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;
18static int del_ptr(struct ctree_root *root, struct ctree_path *path, int level,
19 int slot);
20
21inline void init_path(struct ctree_path *p)
22{
23 memset(p, 0, sizeof(*p));
24}
25

--- 189 unchanged lines hidden (view full) ---

215 struct tree_buffer *parent_buf = NULL;
216 struct node *right = NULL;
217 struct node *mid;
218 struct node *left = NULL;
219 struct node *parent = NULL;
220 int ret = 0;
221 int wret;
222 int pslot;
220 int used = 0;
221 int count;
222 int orig_slot = path->slots[level];
223 int orig_slot = path->slots[level];
224 u64 orig_ptr;
223
224 if (level == 0)
225 return 0;
226
227 mid_buf = path->nodes[level];
228 mid = &mid_buf->node;
225
226 if (level == 0)
227 return 0;
228
229 mid_buf = path->nodes[level];
230 mid = &mid_buf->node;
231 orig_ptr = mid->blockptrs[orig_slot];
232
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

--- 11 unchanged lines hidden (view full) ---

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
233 if (level < MAX_LEVEL - 1)
234 parent_buf = path->nodes[level + 1];
235 pslot = path->slots[level + 1];
236
237 if (!parent_buf) {
238 struct tree_buffer *child;
239 u64 blocknr = mid_buf->blocknr;
240

--- 11 unchanged lines hidden (view full) ---

252 tree_block_release(root, mid_buf);
253 return free_extent(root, blocknr, 1);
254 }
255 parent = &parent_buf->node;
256
257 if (mid->header.nritems > NODEPTRS_PER_BLOCK / 4)
258 return 0;
259
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);
260 left_buf = read_node_slot(root, parent_buf, pslot - 1);
261 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 }
262
263 /* first, try to make some room in the middle buffer */
264 if (left_buf) {
265 left = &left_buf->node;
264 if (left_buf) {
265 left = &left_buf->node;
266 used += left->header.nritems;
267 orig_slot += left->header.nritems;
266 orig_slot += left->header.nritems;
268 count++;
267 wret = push_node_left(root, left_buf, mid_buf);
268 if (wret < 0)
269 ret = wret;
269 }
270 }
270 if (left_buf)
271 push_node_left(root, left_buf, mid_buf);
271
272 /*
273 * then try to empty the right most buffer into the middle
274 */
272 if (right_buf) {
275 if (right_buf) {
273 push_node_left(root, mid_buf, right_buf);
276 right = &right_buf->node;
277 wret = push_node_left(root, mid_buf, right_buf);
278 if (wret < 0)
279 ret = wret;
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));
280 if (right->header.nritems == 0) {
281 u64 blocknr = right_buf->blocknr;
282 tree_block_release(root, right_buf);
283 right_buf = NULL;
284 right = NULL;
285 wret = del_ptr(root, path, level + 1, pslot + 1);
286 if (wret)
287 ret = wret;
288 wret = free_extent(root, blocknr, 1);
289 if (wret)
290 ret = wret;
291 } else {
292 memcpy(parent->keys + pslot + 1, right->keys,
293 sizeof(struct key));
294 wret = write_tree_block(root, parent_buf);
295 if (wret)
296 ret = wret;
288 }
289 }
297 }
298 }
299 if (mid->header.nritems == 1) {
300 /*
301 * we're not allowed to leave a node with one item in the
302 * tree during a delete. A deletion from lower in the tree
303 * could try to delete the only pointer in this node.
304 * So, pull some keys from the left.
305 * There has to be a left pointer at this point because
306 * otherwise we would have pulled some pointers from the
307 * right
308 */
309 BUG_ON(!left_buf);
310 wret = balance_node_right(root, mid_buf, left_buf);
311 if (wret < 0)
312 ret = wret;
313 BUG_ON(wret == 1);
314 }
290 if (mid->header.nritems == 0) {
315 if (mid->header.nritems == 0) {
316 /* we've managed to empty the middle node, drop it */
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;
317 u64 blocknr = mid_buf->blocknr;
318 tree_block_release(root, mid_buf);
319 mid_buf = NULL;
320 mid = NULL;
321 wret = del_ptr(root, path, level + 1, pslot);
322 if (wret)
323 ret = wret;
324 wret = free_extent(root, blocknr, 1);
325 if (wret)
326 ret = wret;
301 } else
327 } else {
328 /* update the parent key to reflect our changes */
302 memcpy(parent->keys + pslot, mid->keys, sizeof(struct key));
329 memcpy(parent->keys + pslot, mid->keys, sizeof(struct key));
330 wret = write_tree_block(root, parent_buf);
331 if (wret)
332 ret = wret;
333 }
303
334
335 /* update the path */
304 if (left_buf) {
336 if (left_buf) {
305 if (left->header.nritems >= orig_slot) {
337 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 }
338 left_buf->count++; // released below
339 path->nodes[level] = left_buf;
340 path->slots[level + 1] -= 1;
341 path->slots[level] = orig_slot;
342 if (mid_buf)
343 tree_block_release(root, mid_buf);
344 } else {
345 orig_slot -= left->header.nritems;
346 path->slots[level] = orig_slot;
347 }
348 }
349 /* double check we haven't messed things up */
350 check_block(path, level);
351 if (orig_ptr != path->nodes[level]->node.blockptrs[path->slots[level]])
352 BUG();
317
318 if (right_buf)
319 tree_block_release(root, right_buf);
320 if (left_buf)
321 tree_block_release(root, left_buf);
353
354 if (right_buf)
355 tree_block_release(root, right_buf);
356 if (left_buf)
357 tree_block_release(root, left_buf);
322
323 return ret;
324}
325
326/*
327 * look for key in the tree. path is filled in with nodes along the way
328 * if key is found, we return zero and you can find the item in the leaf
329 * level of the path (level 0)
330 *

--- 42 unchanged lines hidden (view full) ---

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];
358 return ret;
359}
360
361/*
362 * look for key in the tree. path is filled in with nodes along the way
363 * if key is found, we return zero and you can find the item in the leaf
364 * level of the path (level 0)
365 *

--- 42 unchanged lines hidden (view full) ---

408 int sret = balance_level(root, p, level);
409 if (sret)
410 return sret;
411 b = p->nodes[level];
412 if (!b)
413 goto again;
414 c = &b->node;
415 slot = p->slots[level];
416 BUG_ON(c->header.nritems == 1);
381 }
382 b = read_tree_block(root, c->blockptrs[slot]);
383 } else {
384 struct leaf *l = (struct leaf *)c;
385 p->slots[level] = slot;
386 if (ins_len > 0 && leaf_free_space(l) <
387 sizeof(struct item) + ins_len) {
388 int sret = split_leaf(root, p, ins_len);

--- 39 unchanged lines hidden (view full) ---

428 if (tslot != 0)
429 break;
430 }
431 return ret;
432}
433
434/*
435 * try to push data from one node into the next node left in the
417 }
418 b = read_tree_block(root, c->blockptrs[slot]);
419 } else {
420 struct leaf *l = (struct leaf *)c;
421 p->slots[level] = slot;
422 if (ins_len > 0 && leaf_free_space(l) <
423 sizeof(struct item) + ins_len) {
424 int sret = split_leaf(root, p, ins_len);

--- 39 unchanged lines hidden (view full) ---

464 if (tslot != 0)
465 break;
466 }
467 return ret;
468}
469
470/*
471 * try to push data from one node into the next node left in the
436 * tree. The src node is found at specified level in the path.
437 * If some bytes were pushed, return 0, otherwise return 1.
472 * tree.
438 *
473 *
439 * Lower nodes/leaves in the path are not touched, higher nodes may
440 * be modified to reflect the push.
441 *
442 * The path is altered to reflect the push.
443 *
444 * returns 0 if some ptrs were pushed left, < 0 if there was some horrible
445 * error, and > 0 if there was no room in the left hand block.
446 */
447static int push_node_left(struct ctree_root *root, struct tree_buffer *dst_buf,
448 struct tree_buffer *src_buf)
449{
450 struct node *src = &src_buf->node;
451 struct node *dst = &dst_buf->node;

--- 6 unchanged lines hidden (view full) ---

458 src_nritems = src->header.nritems;
459 dst_nritems = dst->header.nritems;
460 push_items = NODEPTRS_PER_BLOCK - dst_nritems;
461 if (push_items <= 0) {
462 return 1;
463 }
464
465 if (src_nritems < push_items)
474 * returns 0 if some ptrs were pushed left, < 0 if there was some horrible
475 * error, and > 0 if there was no room in the left hand block.
476 */
477static int push_node_left(struct ctree_root *root, struct tree_buffer *dst_buf,
478 struct tree_buffer *src_buf)
479{
480 struct node *src = &src_buf->node;
481 struct node *dst = &dst_buf->node;

--- 6 unchanged lines hidden (view full) ---

488 src_nritems = src->header.nritems;
489 dst_nritems = dst->header.nritems;
490 push_items = NODEPTRS_PER_BLOCK - dst_nritems;
491 if (push_items <= 0) {
492 return 1;
493 }
494
495 if (src_nritems < push_items)
466 push_items =src_nritems;
496 push_items = src_nritems;
497
467 memcpy(dst->keys + dst_nritems, src->keys,
468 push_items * sizeof(struct key));
469 memcpy(dst->blockptrs + dst_nritems, src->blockptrs,
470 push_items * sizeof(u64));
471 if (push_items < src_nritems) {
472 memmove(src->keys, src->keys + push_items,
473 (src_nritems - push_items) * sizeof(struct key));
474 memmove(src->blockptrs, src->blockptrs + push_items,

--- 8 unchanged lines hidden (view full) ---

483
484 wret = write_tree_block(root, dst_buf);
485 if (wret < 0)
486 ret = wret;
487 return ret;
488}
489
490/*
498 memcpy(dst->keys + dst_nritems, src->keys,
499 push_items * sizeof(struct key));
500 memcpy(dst->blockptrs + dst_nritems, src->blockptrs,
501 push_items * sizeof(u64));
502 if (push_items < src_nritems) {
503 memmove(src->keys, src->keys + push_items,
504 (src_nritems - push_items) * sizeof(struct key));
505 memmove(src->blockptrs, src->blockptrs + push_items,

--- 8 unchanged lines hidden (view full) ---

514
515 wret = write_tree_block(root, dst_buf);
516 if (wret < 0)
517 ret = wret;
518 return ret;
519}
520
521/*
522 * try to push data from one node into the next node right in the
523 * tree.
524 *
525 * returns 0 if some ptrs were pushed, < 0 if there was some horrible
526 * error, and > 0 if there was no room in the right hand block.
527 *
528 * this will only push up to 1/2 the contents of the left node over
529 */
530static int balance_node_right(struct ctree_root *root,
531 struct tree_buffer *dst_buf,
532 struct tree_buffer *src_buf)
533{
534 struct node *src = &src_buf->node;
535 struct node *dst = &dst_buf->node;
536 int push_items = 0;
537 int max_push;
538 int src_nritems;
539 int dst_nritems;
540 int ret = 0;
541 int wret;
542
543 src_nritems = src->header.nritems;
544 dst_nritems = dst->header.nritems;
545 push_items = NODEPTRS_PER_BLOCK - dst_nritems;
546 if (push_items <= 0) {
547 return 1;
548 }
549
550 max_push = src_nritems / 2 + 1;
551 /* don't try to empty the node */
552 if (max_push > src_nritems)
553 return 1;
554 if (max_push < push_items)
555 push_items = max_push;
556
557 memmove(dst->keys + push_items, dst->keys,
558 dst_nritems * sizeof(struct key));
559 memmove(dst->blockptrs + push_items, dst->blockptrs,
560 dst_nritems * sizeof(u64));
561 memcpy(dst->keys, src->keys + src_nritems - push_items,
562 push_items * sizeof(struct key));
563 memcpy(dst->blockptrs, src->blockptrs + src_nritems - push_items,
564 push_items * sizeof(u64));
565
566 src->header.nritems -= push_items;
567 dst->header.nritems += push_items;
568
569 wret = write_tree_block(root, src_buf);
570 if (wret < 0)
571 ret = wret;
572
573 wret = write_tree_block(root, dst_buf);
574 if (wret < 0)
575 ret = wret;
576 return ret;
577}
578
579/*
491 * helper function to insert a new root level in the tree.
492 * A new node is allocated, and a single item is inserted to
493 * point to the existing root
494 *
495 * returns zero on success or < 0 on failure.
496 */
497static int insert_new_root(struct ctree_root *root,
498 struct ctree_path *path, int level)

--- 714 unchanged lines hidden ---
580 * helper function to insert a new root level in the tree.
581 * A new node is allocated, and a single item is inserted to
582 * point to the existing root
583 *
584 * returns zero on success or < 0 on failure.
585 */
586static int insert_new_root(struct ctree_root *root,
587 struct ctree_path *path, int level)

--- 714 unchanged lines hidden ---