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 46 : tree_find_buffer(struct cache_tree *tree, uint64_t offset) 18 : { 19 : uint64_t index; 20 : 21 62 : while (tree != NULL) { 22 57 : index = offset / CACHE_TREE_LEVEL_SIZE(tree->level); 23 57 : if (index >= CACHE_TREE_WIDTH) { 24 0 : return NULL; 25 : } 26 57 : if (tree->level == 0) { 27 41 : return tree->u.buffer[index]; 28 : } else { 29 16 : offset &= CACHE_TREE_LEVEL_MASK(tree->level); 30 16 : tree = tree->u.tree[index]; 31 : } 32 : } 33 : 34 5 : return NULL; 35 : } 36 : 37 : struct cache_buffer * 38 3 : tree_find_filled_buffer(struct cache_tree *tree, uint64_t offset) 39 : { 40 : struct cache_buffer *buf; 41 : 42 3 : buf = tree_find_buffer(tree, offset); 43 3 : if (buf != NULL && buf->bytes_filled > 0) { 44 2 : return buf; 45 : } else { 46 1 : return NULL; 47 : } 48 : } 49 : 50 : struct cache_tree * 51 16 : tree_insert_buffer(struct cache_tree *root, struct cache_buffer *buffer) 52 : { 53 : struct cache_tree *tree; 54 : uint64_t index, offset; 55 : 56 16 : offset = buffer->offset; 57 19 : while (offset >= CACHE_TREE_LEVEL_SIZE(root->level + 1)) { 58 3 : if (root->present_mask != 0) { 59 3 : tree = calloc(1, sizeof(*tree)); 60 3 : assert(tree != NULL); 61 3 : tree->level = root->level + 1; 62 3 : tree->u.tree[0] = root; 63 3 : root = tree; 64 3 : root->present_mask = 0x1ULL; 65 : } else { 66 0 : root->level++; 67 : } 68 : } 69 : 70 16 : tree = root; 71 21 : while (tree->level > 0) { 72 5 : index = offset / CACHE_TREE_LEVEL_SIZE(tree->level); 73 5 : assert(index < CACHE_TREE_WIDTH); 74 5 : offset &= CACHE_TREE_LEVEL_MASK(tree->level); 75 5 : if (tree->u.tree[index] == NULL) { 76 5 : tree->u.tree[index] = calloc(1, sizeof(*tree)); 77 5 : assert(tree->u.tree[index] != NULL); 78 5 : tree->u.tree[index]->level = tree->level - 1; 79 5 : tree->present_mask |= (1ULL << index); 80 : } 81 5 : tree = tree->u.tree[index]; 82 : } 83 : 84 16 : index = offset / CACHE_BUFFER_SIZE; 85 16 : assert(index < CACHE_TREE_WIDTH); 86 16 : assert(tree->u.buffer[index] == NULL); 87 16 : tree->u.buffer[index] = buffer; 88 16 : tree->present_mask |= (1ULL << index); 89 16 : return root; 90 : } 91 : 92 : void 93 6 : tree_remove_buffer(struct cache_tree *tree, struct cache_buffer *buffer) 94 : { 95 : struct cache_tree *child; 96 : uint64_t index; 97 : 98 6 : index = CACHE_TREE_INDEX(tree->level, buffer->offset); 99 : 100 6 : if (tree->level == 0) { 101 2 : assert(tree->u.buffer[index] != NULL); 102 2 : assert(buffer == tree->u.buffer[index]); 103 2 : tree->present_mask &= ~(1ULL << index); 104 2 : tree->u.buffer[index] = NULL; 105 2 : cache_buffer_free(buffer); 106 2 : return; 107 : } 108 : 109 4 : child = tree->u.tree[index]; 110 4 : assert(child != NULL); 111 4 : tree_remove_buffer(child, buffer); 112 4 : if (child->present_mask == 0) { 113 1 : tree->present_mask &= ~(1ULL << index); 114 1 : tree->u.tree[index] = NULL; 115 1 : free(child); 116 : } 117 : } 118 : 119 : void 120 16 : tree_free_buffers(struct cache_tree *tree) 121 : { 122 : struct cache_buffer *buffer; 123 : struct cache_tree *child; 124 : uint32_t i; 125 : 126 16 : if (tree->present_mask == 0) { 127 0 : return; 128 : } 129 : 130 16 : if (tree->level == 0) { 131 650 : for (i = 0; i < CACHE_TREE_WIDTH; i++) { 132 640 : buffer = tree->u.buffer[i]; 133 640 : if (buffer != NULL && buffer->in_progress == false && 134 16 : buffer->bytes_filled == buffer->bytes_flushed) { 135 16 : cache_buffer_free(buffer); 136 16 : tree->u.buffer[i] = NULL; 137 16 : tree->present_mask &= ~(1ULL << i); 138 : } 139 : } 140 : } else { 141 390 : for (i = 0; i < CACHE_TREE_WIDTH; i++) { 142 384 : child = tree->u.tree[i]; 143 384 : if (child != NULL) { 144 9 : tree_free_buffers(child); 145 9 : if (child->present_mask == 0) { 146 9 : free(child); 147 9 : tree->u.tree[i] = NULL; 148 9 : tree->present_mask &= ~(1ULL << i); 149 : } 150 : } 151 : } 152 : } 153 : }