Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2017 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "spdk/stdinc.h"
7 : :
8 : : #include "spdk/blobfs.h"
9 : : #include "cache_tree.h"
10 : :
11 : : #include "spdk/queue.h"
12 : : #include "spdk/assert.h"
13 : : #include "spdk/env.h"
14 : : #include "spdk/log.h"
15 : :
16 : : struct cache_buffer *
17 : 71566037 : tree_find_buffer(struct cache_tree *tree, uint64_t offset)
18 : : {
19 : 46 : uint64_t index;
20 : :
21 [ + + ]: 142847066 : while (tree != NULL) {
22 [ + + + + : 138677387 : index = offset / CACHE_TREE_LEVEL_SIZE(tree->level);
+ - + - +
- + - ]
23 [ + + + - ]: 138677387 : if (index >= CACHE_TREE_WIDTH) {
24 : 18628 : return NULL;
25 : : }
26 [ + + + - : 138658759 : if (tree->level == 0) {
+ + ]
27 [ - + - + : 67377730 : return tree->u.buffer[index];
- + - + -
+ ]
28 : : } else {
29 [ + + + - : 71281029 : offset &= CACHE_TREE_LEVEL_MASK(tree->level);
+ - + - +
- ]
30 [ + - + - : 71281029 : tree = tree->u.tree[index];
+ - + - ]
31 : : }
32 : : }
33 : :
34 : 4169679 : return NULL;
35 : 46 : }
36 : :
37 : : struct cache_buffer *
38 : 26844067 : tree_find_filled_buffer(struct cache_tree *tree, uint64_t offset)
39 : : {
40 : 3 : struct cache_buffer *buf;
41 : :
42 : 26844067 : buf = tree_find_buffer(tree, offset);
43 [ + + + + : 26844067 : if (buf != NULL && buf->bytes_filled > 0) {
+ - + + ]
44 : 22401639 : return buf;
45 : : } else {
46 : 4442428 : return NULL;
47 : : }
48 : 3 : }
49 : :
50 : : struct cache_tree *
51 : 1052164 : tree_insert_buffer(struct cache_tree *root, struct cache_buffer *buffer)
52 : : {
53 : 16 : struct cache_tree *tree;
54 : 16 : uint64_t index, offset;
55 : :
56 [ + - + - ]: 1052164 : offset = buffer->offset;
57 [ + + + + : 1057635 : while (offset >= CACHE_TREE_LEVEL_SIZE(root->level + 1)) {
+ - + - +
- + - +
+ ]
58 [ + + + - : 5471 : if (root->present_mask != 0) {
+ - ]
59 : 2443 : tree = calloc(1, sizeof(*tree));
60 [ + + # # ]: 2443 : assert(tree != NULL);
61 [ + - + - : 2443 : tree->level = root->level + 1;
+ - + - +
- ]
62 [ + - + - : 2443 : tree->u.tree[0] = root;
+ - + - ]
63 : 2443 : root = tree;
64 [ + - + - ]: 2443 : root->present_mask = 0x1ULL;
65 : 3 : } else {
66 [ # # ]: 3028 : root->level++;
67 : : }
68 : : }
69 : :
70 : 1052164 : tree = root;
71 [ + + + - : 1949280 : while (tree->level > 0) {
+ + ]
72 [ + + + + : 897116 : index = offset / CACHE_TREE_LEVEL_SIZE(tree->level);
+ - + - +
- + - ]
73 [ + + + - : 897116 : assert(index < CACHE_TREE_WIDTH);
# # ]
74 [ + + + - : 897116 : offset &= CACHE_TREE_LEVEL_MASK(tree->level);
+ - + - +
- ]
75 [ + + + - : 897116 : if (tree->u.tree[index] == NULL) {
+ - + - -
+ ]
76 [ + - + - : 20618 : tree->u.tree[index] = calloc(1, sizeof(*tree));
+ - + - ]
77 [ + + + - : 20618 : assert(tree->u.tree[index] != NULL);
+ - + - +
- # # ]
78 [ + - + - : 20618 : tree->u.tree[index]->level = tree->level - 1;
+ - + - +
- + - + -
+ - + - ]
79 [ + + + - : 20618 : tree->present_mask |= (1ULL << index);
+ - ]
80 : 5 : }
81 [ + - + - : 897116 : tree = tree->u.tree[index];
+ - + - ]
82 : : }
83 : :
84 [ + - + - ]: 1052164 : index = offset / CACHE_BUFFER_SIZE;
85 [ + + + - : 1052164 : assert(index < CACHE_TREE_WIDTH);
# # ]
86 [ + + + - : 1052164 : assert(tree->u.buffer[index] == NULL);
+ - + - +
- + - #
# ]
87 [ + - + - : 1052164 : tree->u.buffer[index] = buffer;
+ - + - +
- ]
88 [ + + + - : 1052164 : tree->present_mask |= (1ULL << index);
+ - ]
89 : 1052180 : return root;
90 : 16 : }
91 : :
92 : : void
93 : 698926 : tree_remove_buffer(struct cache_tree *tree, struct cache_buffer *buffer)
94 : : {
95 : 6 : struct cache_tree *child;
96 : 6 : uint64_t index;
97 : :
98 [ + + + - : 698926 : index = CACHE_TREE_INDEX(tree->level, buffer->offset);
+ - + - +
- + - + -
+ - ]
99 : :
100 [ + + + - : 698926 : if (tree->level == 0) {
+ + ]
101 [ + + + - : 349091 : assert(tree->u.buffer[index] != NULL);
+ - + - +
- + - #
# ]
102 [ + + + - : 349091 : assert(buffer == tree->u.buffer[index]);
+ - + - +
- + - #
# ]
103 [ + + + - : 349091 : tree->present_mask &= ~(1ULL << index);
+ - ]
104 [ + - + - : 349091 : tree->u.buffer[index] = NULL;
+ - + - +
- ]
105 : 349091 : cache_buffer_free(buffer);
106 : 349091 : return;
107 : : }
108 : :
109 [ + - + - : 349835 : child = tree->u.tree[index];
+ - + - ]
110 [ + + # # ]: 349835 : assert(child != NULL);
111 : 349835 : tree_remove_buffer(child, buffer);
112 [ + + + - : 349835 : if (child->present_mask == 0) {
+ + ]
113 [ + + + - : 4801 : tree->present_mask &= ~(1ULL << index);
+ - ]
114 [ + - + - : 4801 : tree->u.tree[index] = NULL;
+ - + - ]
115 : 4801 : free(child);
116 : 1 : }
117 [ - + ]: 6 : }
118 : :
119 : : void
120 : 27295 : tree_free_buffers(struct cache_tree *tree)
121 : : {
122 : 16 : struct cache_buffer *buffer;
123 : 16 : struct cache_tree *child;
124 : 16 : uint32_t i;
125 : :
126 [ + + + - : 27295 : if (tree->present_mask == 0) {
+ - ]
127 : 0 : return;
128 : : }
129 : :
130 [ + + + - : 27295 : if (tree->level == 0) {
+ + ]
131 [ + + + + ]: 1201915 : for (i = 0; i < CACHE_TREE_WIDTH; i++) {
132 [ + - + - : 1183424 : buffer = tree->u.buffer[i];
+ - + - +
- ]
133 [ + + + + : 1183440 : if (buffer != NULL && buffer->in_progress == false &&
+ + + - +
- - + ]
134 [ + - + - : 703085 : buffer->bytes_filled == buffer->bytes_flushed) {
+ - + - ]
135 : 703085 : cache_buffer_free(buffer);
136 [ + - + - : 703085 : tree->u.buffer[i] = NULL;
+ - + - +
- ]
137 [ + + + - : 703085 : tree->present_mask &= ~(1ULL << i);
+ - ]
138 : 16 : }
139 : 640 : }
140 : 10 : } else {
141 [ + + + + ]: 572260 : for (i = 0; i < CACHE_TREE_WIDTH; i++) {
142 [ + - + - : 563456 : child = tree->u.tree[i];
+ - + - ]
143 [ + + ]: 563456 : if (child != NULL) {
144 : 18307 : tree_free_buffers(child);
145 [ + + + - : 18307 : if (child->present_mask == 0) {
- + ]
146 : 18272 : free(child);
147 [ + - + - : 18272 : tree->u.tree[i] = NULL;
+ - + - ]
148 [ + + + - : 18272 : tree->present_mask &= ~(1ULL << i);
+ - ]
149 : 9 : }
150 : 9 : }
151 : 384 : }
152 : : }
153 [ - + ]: 16 : }
|