From 694224971cf28a3295d889b02e04be2971782516 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Mon, 9 Nov 2020 12:06:12 +0100 Subject: [PATCH 1/5] rbtree: Replace spaces with tabs Signed-off-by: Robert Baldyga --- src/utils/utils_rbtree.c | 50 ++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/utils/utils_rbtree.c b/src/utils/utils_rbtree.c index ae551cc..85fbbb3 100644 --- a/src/utils/utils_rbtree.c +++ b/src/utils/utils_rbtree.c @@ -359,38 +359,38 @@ bool ocf_rb_tree_can_update(struct ocf_rb_tree *tree, struct ocf_rb_node *node, struct ocf_rb_node *new_node) { struct ocf_rb_node *iter = tree->root; - int cmp = 0; + int cmp = 0; - while (iter) { - if (iter == node) - break; + while (iter) { + if (iter == node) + break; - cmp = tree->cmp(new_node, iter); - iter = (cmp < 0) ? iter->left : iter->right; - } + cmp = tree->cmp(new_node, iter); + iter = (cmp < 0) ? iter->left : iter->right; + } - if (!iter) - return false; + if (!iter) + return false; - cmp = tree->cmp(new_node, iter); + cmp = tree->cmp(new_node, iter); - if (cmp < 0) { - iter = ocf_rb_tree_predecessor(iter); - if (!iter) - return true; - cmp = tree->cmp(new_node, iter); - return (cmp > 0); - } + if (cmp < 0) { + iter = ocf_rb_tree_predecessor(iter); + if (!iter) + return true; + cmp = tree->cmp(new_node, iter); + return (cmp > 0); + } - if (cmp > 0) { - iter = ocf_rb_tree_successor(iter); - if (!iter) - return true; - cmp = tree->cmp(new_node, iter); - return (cmp < 0); - } + if (cmp > 0) { + iter = ocf_rb_tree_successor(iter); + if (!iter) + return true; + cmp = tree->cmp(new_node, iter); + return (cmp < 0); + } - return true; + return true; } struct ocf_rb_node *ocf_rb_tree_find(struct ocf_rb_tree *tree, From 50c4de0495ba5c790276bddd1f27b4212775341b Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Mon, 9 Nov 2020 17:28:27 +0100 Subject: [PATCH 2/5] rbtree: Make swap resistant to nodes outside the tree Signed-off-by: Robert Baldyga --- src/utils/utils_rbtree.c | 88 +++++++++++++++++++++++----------------- 1 file changed, 51 insertions(+), 37 deletions(-) diff --git a/src/utils/utils_rbtree.c b/src/utils/utils_rbtree.c index 85fbbb3..61195a7 100644 --- a/src/utils/utils_rbtree.c +++ b/src/utils/utils_rbtree.c @@ -12,24 +12,19 @@ void ocf_rb_tree_init(struct ocf_rb_tree *tree, ocf_rb_tree_node_cmp_cb cmp) } static void ocf_rb_tree_update_parent(struct ocf_rb_tree *tree, - struct ocf_rb_node *node, struct ocf_rb_node *old_node, + struct ocf_rb_node *parent, struct ocf_rb_node *old_node, struct ocf_rb_node *new_node) { - if (!node->parent) - tree->root = new_node; - else if (old_node == node->parent->left) - node->parent->left = new_node; - else if (old_node == node->parent->right) - node->parent->right = new_node; -} + if (!parent) { + if (tree->root == old_node) + tree->root = new_node; + return; + } -static void ocf_rb_tree_update_children(struct ocf_rb_node *node) -{ - if (node->left) - node->left->parent = node; - - if (node->right) - node->right->parent = node; + if (parent->left == old_node) + parent->left = new_node; + else if (parent->right == old_node) + parent->right = new_node; } static void ocf_rb_tree_rotate_left(struct ocf_rb_tree *tree, @@ -44,7 +39,7 @@ static void ocf_rb_tree_rotate_left(struct ocf_rb_tree *tree, right->parent = node->parent; - ocf_rb_tree_update_parent(tree, node, node, right); + ocf_rb_tree_update_parent(tree, node->parent, node, right); right->left = node; node->parent = right; @@ -62,7 +57,7 @@ static void ocf_rb_tree_rotate_right(struct ocf_rb_tree *tree, left->parent = node->parent; - ocf_rb_tree_update_parent(tree, node, node, left); + ocf_rb_tree_update_parent(tree, node->parent, node, left); left->right = node; node->parent = left; @@ -165,34 +160,51 @@ void ocf_rb_tree_insert(struct ocf_rb_tree *tree, struct ocf_rb_node *node) ocf_rb_tree_fix_violation(tree, node); } +static void ocf_rb_copy_node(struct ocf_rb_node *dst, struct ocf_rb_node *src) +{ + dst->red = src->red; + dst->left = src->left; + dst->right = src->right; + dst->parent = src->parent; +} + +static void ocf_rb_tree_update_children(struct ocf_rb_node *node) +{ + if (node->left) + node->left->parent = node; + + if (node->right) + node->right->parent = node; +} + static void ocf_rb_tree_swap(struct ocf_rb_tree *tree, struct ocf_rb_node *node1, struct ocf_rb_node *node2) { struct ocf_rb_node tmp; - if (node1->left == node2) - node1->left = node1; - else if (node1->right == node2) - node1->right = node1; - else if (node1->parent == node2) - node1->parent = node1; + ocf_rb_copy_node(&tmp, node1); + ocf_rb_copy_node(node1, node2); + ocf_rb_copy_node(node2, &tmp); - if (node2->left == node1) - node2->left = node2; - else if (node2->right == node1) - node2->right = node2; - else if (node2->parent == node1) - node2->parent = node2; + if (node1->parent == node1) + node1->parent = node2; + else if (node1->left == node1) + node1->left = node2; + else if (node1->right == node1) + node1->right = node2; - tmp = *node1; - *node1 = *node2; - *node2 = tmp; - - ocf_rb_tree_update_parent(tree, node1, node2, node1); - ocf_rb_tree_update_parent(tree, node2, node1, node2); + if (node2->parent == node2) + node2->parent = node1; + else if (node2->left == node2) + node2->left = node1; + else if (node2->right == node2) + node2->right = node1; ocf_rb_tree_update_children(node1); ocf_rb_tree_update_children(node2); + + ocf_rb_tree_update_parent(tree, node2->parent, node1, node2); + ocf_rb_tree_update_parent(tree, node1->parent, node2, node1); } static struct ocf_rb_node *ocf_rb_tree_successor(struct ocf_rb_node *node) @@ -334,7 +346,8 @@ void ocf_rb_tree_remove(struct ocf_rb_tree *tree, struct ocf_rb_node *node) else if (sibling) sibling->red = true; - ocf_rb_tree_update_parent(tree, node, node, NULL); + ocf_rb_tree_update_parent(tree, node->parent, + node, NULL); } break; } @@ -346,7 +359,8 @@ void ocf_rb_tree_remove(struct ocf_rb_tree *tree, struct ocf_rb_node *node) if (!node->red) ocf_rb_tree_fix_double_black(tree, node); - ocf_rb_tree_update_parent(tree, node, node, NULL); + ocf_rb_tree_update_parent(tree, node->parent, + node, NULL); break; } From 0ae4f4b5b23900f36c5ff56b63267ad7a8ac749b Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Mon, 9 Nov 2020 12:07:26 +0100 Subject: [PATCH 3/5] rbtree: Add equal nodes to linked list Signed-off-by: Robert Baldyga --- src/utils/utils_rbtree.c | 30 +++++++++++++++++++++++++++++- src/utils/utils_rbtree.h | 1 + 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/utils/utils_rbtree.c b/src/utils/utils_rbtree.c index 61195a7..727811a 100644 --- a/src/utils/utils_rbtree.c +++ b/src/utils/utils_rbtree.c @@ -134,8 +134,11 @@ void ocf_rb_tree_insert(struct ocf_rb_tree *tree, struct ocf_rb_node *node) struct ocf_rb_node *iter, *new_iter; int cmp; + INIT_LIST_HEAD(&node->list); + node->left = NULL; node->right = NULL; + node->parent = NULL; if (!tree->root) { node->red = false; @@ -147,9 +150,16 @@ void ocf_rb_tree_insert(struct ocf_rb_tree *tree, struct ocf_rb_node *node) for (new_iter = tree->root; new_iter;) { iter = new_iter; cmp = tree->cmp(node, iter); + if (cmp == 0) + break; new_iter = (cmp < 0) ? iter->left : iter->right; } + if (cmp == 0) { + list_add_tail(&node->list, &iter->list); + return; + } + node->red = true; node->parent = iter; if (cmp < 0) @@ -330,7 +340,22 @@ void ocf_rb_tree_fix_double_black(struct ocf_rb_tree *tree, void ocf_rb_tree_remove(struct ocf_rb_tree *tree, struct ocf_rb_node *node) { - struct ocf_rb_node *sibling, *rep; + struct ocf_rb_node *sibling, *rep, *next; + + if (!list_empty(&node->list)) { + /* Node list is not empty */ + if (!node->parent && node != tree->root) { + /* Node is in the middle of the list -> just remove */ + list_del(&node->list); + return; + } + + /* Node is at head of the list -> need to make new head */ + next = list_first_entry(&node->list, struct ocf_rb_node, list); + ocf_rb_tree_swap(tree, node, next); + list_del(&node->list); + return; + } while (true) { sibling = ocf_rb_tree_sibling(node); @@ -375,6 +400,9 @@ bool ocf_rb_tree_can_update(struct ocf_rb_tree *tree, struct ocf_rb_node *iter = tree->root; int cmp = 0; + if (!list_empty(&node->list)) + return false; + while (iter) { if (iter == node) break; diff --git a/src/utils/utils_rbtree.h b/src/utils/utils_rbtree.h index 8ad7a0f..04a99d0 100644 --- a/src/utils/utils_rbtree.h +++ b/src/utils/utils_rbtree.h @@ -13,6 +13,7 @@ struct ocf_rb_node { struct ocf_rb_node *left; struct ocf_rb_node *right; struct ocf_rb_node *parent; + struct list_head list; }; typedef int (*ocf_rb_tree_node_cmp_cb)(struct ocf_rb_node *n1, From 8b03271626b286867777164dff1f15d9f53bf513 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Mon, 9 Nov 2020 14:36:39 +0100 Subject: [PATCH 4/5] rbtree: Introduce list find callback Signed-off-by: Robert Baldyga --- src/ocf_seq_cutoff.c | 2 +- src/utils/utils_rbtree.c | 25 ++++++++++++++++++- src/utils/utils_rbtree.h | 14 ++++++++++- .../tests/utils/utils_rbtree.c/utils_rbtree.c | 2 +- 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/ocf_seq_cutoff.c b/src/ocf_seq_cutoff.c index 55c4999..c34bb6d 100644 --- a/src/ocf_seq_cutoff.c +++ b/src/ocf_seq_cutoff.c @@ -52,7 +52,7 @@ void ocf_core_seq_cutoff_init(ocf_core_t core) ocf_core_log(core, log_info, "Seqential cutoff init\n"); env_rwlock_init(&core->seq_cutoff.lock); - ocf_rb_tree_init(&core->seq_cutoff.tree, ocf_seq_cutoff_stream_cmp); + ocf_rb_tree_init(&core->seq_cutoff.tree, ocf_seq_cutoff_stream_cmp, NULL); INIT_LIST_HEAD(&core->seq_cutoff.lru); for (i = 0; i < OCF_SEQ_CUTOFF_MAX_STREAMS; i++) { diff --git a/src/utils/utils_rbtree.c b/src/utils/utils_rbtree.c index 727811a..e4ce67f 100644 --- a/src/utils/utils_rbtree.c +++ b/src/utils/utils_rbtree.c @@ -5,10 +5,15 @@ #include "utils_rbtree.h" -void ocf_rb_tree_init(struct ocf_rb_tree *tree, ocf_rb_tree_node_cmp_cb cmp) +static struct ocf_rb_node *ocf_rb_tree_list_find_first( + struct ocf_rb_node_list *node_list); + +void ocf_rb_tree_init(struct ocf_rb_tree *tree, ocf_rb_tree_node_cmp_cb cmp, + ocf_rb_tree_list_find_cb find) { tree->root = NULL; tree->cmp = cmp; + tree->find = find ?: ocf_rb_tree_list_find_first; } static void ocf_rb_tree_update_parent(struct ocf_rb_tree *tree, @@ -435,10 +440,22 @@ bool ocf_rb_tree_can_update(struct ocf_rb_tree *tree, return true; } +static struct ocf_rb_node *ocf_rb_tree_list_find_first( + struct ocf_rb_node_list *node_list) +{ + struct ocf_rb_node *node; + + ocf_rb_list_for_each_node(node_list, node) + return node; + + return NULL; +} + struct ocf_rb_node *ocf_rb_tree_find(struct ocf_rb_tree *tree, struct ocf_rb_node *node) { struct ocf_rb_node *iter = tree->root; + struct ocf_rb_node_list node_list; int cmp = 0; while (iter) { @@ -449,5 +466,11 @@ struct ocf_rb_node *ocf_rb_tree_find(struct ocf_rb_tree *tree, iter = (cmp < 0) ? iter->left : iter->right; } + if (!iter || list_empty(&iter->list)) + return iter; + + list_add_tail(&node_list.list, &iter->list); + iter = tree->find(&node_list); + list_del(&node_list.list); return iter; } diff --git a/src/utils/utils_rbtree.h b/src/utils/utils_rbtree.h index 04a99d0..61fcb34 100644 --- a/src/utils/utils_rbtree.h +++ b/src/utils/utils_rbtree.h @@ -16,15 +16,27 @@ struct ocf_rb_node { struct list_head list; }; +struct ocf_rb_node_list { + struct list_head list; +}; + +#define ocf_rb_list_for_each_node(node_list, node) \ + list_for_each_entry(node, &node_list->list, list) + typedef int (*ocf_rb_tree_node_cmp_cb)(struct ocf_rb_node *n1, struct ocf_rb_node *n2); +typedef struct ocf_rb_node *(*ocf_rb_tree_list_find_cb)( + struct ocf_rb_node_list *node_list); + struct ocf_rb_tree { struct ocf_rb_node *root; ocf_rb_tree_node_cmp_cb cmp; + ocf_rb_tree_list_find_cb find; }; -void ocf_rb_tree_init(struct ocf_rb_tree *tree, ocf_rb_tree_node_cmp_cb cmp); +void ocf_rb_tree_init(struct ocf_rb_tree *tree, ocf_rb_tree_node_cmp_cb cmp, + ocf_rb_tree_list_find_cb find); void ocf_rb_tree_insert(struct ocf_rb_tree *tree, struct ocf_rb_node *node); diff --git a/tests/unit/tests/utils/utils_rbtree.c/utils_rbtree.c b/tests/unit/tests/utils/utils_rbtree.c/utils_rbtree.c index dae23fe..8abeebe 100644 --- a/tests/unit/tests/utils/utils_rbtree.c/utils_rbtree.c +++ b/tests/unit/tests/utils/utils_rbtree.c/utils_rbtree.c @@ -77,7 +77,7 @@ void prepare(struct ocf_rb_tree *tree) { int i; - ocf_rb_tree_init(tree, test_cmp); + ocf_rb_tree_init(tree, test_cmp, NULL); for (i = 0; i < nodes_number; i++) ocf_rb_tree_insert(tree, &nodes[i].tree); From a54d4461f09457f57e124b641d1375fc2ac0ffdf Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Mon, 9 Nov 2020 18:07:02 +0100 Subject: [PATCH 5/5] seq_cutoff: Always continue the biggest stream Signed-off-by: Robert Baldyga --- src/ocf_seq_cutoff.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/ocf_seq_cutoff.c b/src/ocf_seq_cutoff.c index c34bb6d..236a2c9 100644 --- a/src/ocf_seq_cutoff.c +++ b/src/ocf_seq_cutoff.c @@ -45,6 +45,21 @@ static int ocf_seq_cutoff_stream_cmp(struct ocf_rb_node *n1, return 0; } +static struct ocf_rb_node *ocf_seq_cutoff_stream_list_find( + struct ocf_rb_node_list *node_list) +{ + struct ocf_seq_cutoff_stream *stream, *max_stream = NULL; + struct ocf_rb_node *node; + + ocf_rb_list_for_each_node(node_list, node) { + stream = container_of(node, struct ocf_seq_cutoff_stream, node); + if (!max_stream || stream->bytes > max_stream->bytes) + max_stream = stream; + } + + return &max_stream->node; +} + void ocf_core_seq_cutoff_init(ocf_core_t core) { struct ocf_seq_cutoff_stream *stream; @@ -52,7 +67,8 @@ void ocf_core_seq_cutoff_init(ocf_core_t core) ocf_core_log(core, log_info, "Seqential cutoff init\n"); env_rwlock_init(&core->seq_cutoff.lock); - ocf_rb_tree_init(&core->seq_cutoff.tree, ocf_seq_cutoff_stream_cmp, NULL); + ocf_rb_tree_init(&core->seq_cutoff.tree, ocf_seq_cutoff_stream_cmp, + ocf_seq_cutoff_stream_list_find); INIT_LIST_HEAD(&core->seq_cutoff.lru); for (i = 0; i < OCF_SEQ_CUTOFF_MAX_STREAMS; i++) {