1488570ebSJim Harris /* SPDX-License-Identifier: BSD-3-Clause 2*a6dbe372Spaul luse * Copyright (C) 2017 Intel Corporation. 31edd9bf3SJim Harris * All rights reserved. 41edd9bf3SJim Harris */ 51edd9bf3SJim Harris 6b961d9ccSBen Walker #include "spdk/stdinc.h" 71edd9bf3SJim Harris 8e70dc52fSJim Harris #include "cache_tree.h" 91edd9bf3SJim Harris 101edd9bf3SJim Harris #include "spdk/assert.h" 111edd9bf3SJim Harris 121edd9bf3SJim Harris struct cache_buffer * 13bc0180f6SSeth Howell tree_find_buffer(struct cache_tree *tree, uint64_t offset) 141edd9bf3SJim Harris { 151edd9bf3SJim Harris uint64_t index; 161edd9bf3SJim Harris 171edd9bf3SJim Harris while (tree != NULL) { 181edd9bf3SJim Harris index = offset / CACHE_TREE_LEVEL_SIZE(tree->level); 191edd9bf3SJim Harris if (index >= CACHE_TREE_WIDTH) { 201edd9bf3SJim Harris return NULL; 211edd9bf3SJim Harris } 221edd9bf3SJim Harris if (tree->level == 0) { 231edd9bf3SJim Harris return tree->u.buffer[index]; 241edd9bf3SJim Harris } else { 251edd9bf3SJim Harris offset &= CACHE_TREE_LEVEL_MASK(tree->level); 261edd9bf3SJim Harris tree = tree->u.tree[index]; 271edd9bf3SJim Harris } 281edd9bf3SJim Harris } 291edd9bf3SJim Harris 301edd9bf3SJim Harris return NULL; 311edd9bf3SJim Harris } 321edd9bf3SJim Harris 331edd9bf3SJim Harris struct cache_buffer * 34bc0180f6SSeth Howell tree_find_filled_buffer(struct cache_tree *tree, uint64_t offset) 351edd9bf3SJim Harris { 361edd9bf3SJim Harris struct cache_buffer *buf; 371edd9bf3SJim Harris 38bc0180f6SSeth Howell buf = tree_find_buffer(tree, offset); 391edd9bf3SJim Harris if (buf != NULL && buf->bytes_filled > 0) { 401edd9bf3SJim Harris return buf; 411edd9bf3SJim Harris } else { 421edd9bf3SJim Harris return NULL; 431edd9bf3SJim Harris } 441edd9bf3SJim Harris } 451edd9bf3SJim Harris 461edd9bf3SJim Harris struct cache_tree * 47bc0180f6SSeth Howell tree_insert_buffer(struct cache_tree *root, struct cache_buffer *buffer) 481edd9bf3SJim Harris { 491edd9bf3SJim Harris struct cache_tree *tree; 501edd9bf3SJim Harris uint64_t index, offset; 511edd9bf3SJim Harris 521edd9bf3SJim Harris offset = buffer->offset; 539ea96234SZiye Yang while (offset >= CACHE_TREE_LEVEL_SIZE(root->level + 1)) { 541edd9bf3SJim Harris if (root->present_mask != 0) { 551edd9bf3SJim Harris tree = calloc(1, sizeof(*tree)); 564803dc36SGangCao assert(tree != NULL); 571edd9bf3SJim Harris tree->level = root->level + 1; 581edd9bf3SJim Harris tree->u.tree[0] = root; 591edd9bf3SJim Harris root = tree; 601edd9bf3SJim Harris root->present_mask = 0x1ULL; 611edd9bf3SJim Harris } else { 621edd9bf3SJim Harris root->level++; 631edd9bf3SJim Harris } 641edd9bf3SJim Harris } 651edd9bf3SJim Harris 661edd9bf3SJim Harris tree = root; 671edd9bf3SJim Harris while (tree->level > 0) { 681edd9bf3SJim Harris index = offset / CACHE_TREE_LEVEL_SIZE(tree->level); 698037bc0dSDaniel Verkamp assert(index < CACHE_TREE_WIDTH); 701edd9bf3SJim Harris offset &= CACHE_TREE_LEVEL_MASK(tree->level); 711edd9bf3SJim Harris if (tree->u.tree[index] == NULL) { 721edd9bf3SJim Harris tree->u.tree[index] = calloc(1, sizeof(*tree)); 734803dc36SGangCao assert(tree->u.tree[index] != NULL); 741edd9bf3SJim Harris tree->u.tree[index]->level = tree->level - 1; 751edd9bf3SJim Harris tree->present_mask |= (1ULL << index); 761edd9bf3SJim Harris } 771edd9bf3SJim Harris tree = tree->u.tree[index]; 781edd9bf3SJim Harris } 791edd9bf3SJim Harris 801edd9bf3SJim Harris index = offset / CACHE_BUFFER_SIZE; 818037bc0dSDaniel Verkamp assert(index < CACHE_TREE_WIDTH); 821edd9bf3SJim Harris assert(tree->u.buffer[index] == NULL); 831edd9bf3SJim Harris tree->u.buffer[index] = buffer; 841edd9bf3SJim Harris tree->present_mask |= (1ULL << index); 851edd9bf3SJim Harris return root; 861edd9bf3SJim Harris } 871edd9bf3SJim Harris 881edd9bf3SJim Harris void 89bc0180f6SSeth Howell tree_remove_buffer(struct cache_tree *tree, struct cache_buffer *buffer) 901edd9bf3SJim Harris { 911edd9bf3SJim Harris struct cache_tree *child; 921edd9bf3SJim Harris uint64_t index; 931edd9bf3SJim Harris 941edd9bf3SJim Harris index = CACHE_TREE_INDEX(tree->level, buffer->offset); 951edd9bf3SJim Harris 961edd9bf3SJim Harris if (tree->level == 0) { 971edd9bf3SJim Harris assert(tree->u.buffer[index] != NULL); 981edd9bf3SJim Harris assert(buffer == tree->u.buffer[index]); 991edd9bf3SJim Harris tree->present_mask &= ~(1ULL << index); 1001edd9bf3SJim Harris tree->u.buffer[index] = NULL; 101bc0180f6SSeth Howell cache_buffer_free(buffer); 1021edd9bf3SJim Harris return; 1031edd9bf3SJim Harris } 1041edd9bf3SJim Harris 1051edd9bf3SJim Harris child = tree->u.tree[index]; 1061edd9bf3SJim Harris assert(child != NULL); 107bc0180f6SSeth Howell tree_remove_buffer(child, buffer); 1081edd9bf3SJim Harris if (child->present_mask == 0) { 1091edd9bf3SJim Harris tree->present_mask &= ~(1ULL << index); 1101edd9bf3SJim Harris tree->u.tree[index] = NULL; 1111edd9bf3SJim Harris free(child); 1121edd9bf3SJim Harris } 1131edd9bf3SJim Harris } 1141edd9bf3SJim Harris 1151edd9bf3SJim Harris void 116bc0180f6SSeth Howell tree_free_buffers(struct cache_tree *tree) 1171edd9bf3SJim Harris { 1181edd9bf3SJim Harris struct cache_buffer *buffer; 1191edd9bf3SJim Harris struct cache_tree *child; 1201edd9bf3SJim Harris uint32_t i; 1211edd9bf3SJim Harris 1221edd9bf3SJim Harris if (tree->present_mask == 0) { 1231edd9bf3SJim Harris return; 1241edd9bf3SJim Harris } 1251edd9bf3SJim Harris 1261edd9bf3SJim Harris if (tree->level == 0) { 1271edd9bf3SJim Harris for (i = 0; i < CACHE_TREE_WIDTH; i++) { 1281edd9bf3SJim Harris buffer = tree->u.buffer[i]; 1291edd9bf3SJim Harris if (buffer != NULL && buffer->in_progress == false && 1301edd9bf3SJim Harris buffer->bytes_filled == buffer->bytes_flushed) { 131bc0180f6SSeth Howell cache_buffer_free(buffer); 1321edd9bf3SJim Harris tree->u.buffer[i] = NULL; 1331edd9bf3SJim Harris tree->present_mask &= ~(1ULL << i); 1341edd9bf3SJim Harris } 1351edd9bf3SJim Harris } 1361edd9bf3SJim Harris } else { 1371edd9bf3SJim Harris for (i = 0; i < CACHE_TREE_WIDTH; i++) { 1381edd9bf3SJim Harris child = tree->u.tree[i]; 1391edd9bf3SJim Harris if (child != NULL) { 140bc0180f6SSeth Howell tree_free_buffers(child); 1411edd9bf3SJim Harris if (child->present_mask == 0) { 1421edd9bf3SJim Harris free(child); 1431edd9bf3SJim Harris tree->u.tree[i] = NULL; 1441edd9bf3SJim Harris tree->present_mask &= ~(1ULL << i); 1451edd9bf3SJim Harris } 1461edd9bf3SJim Harris } 1471edd9bf3SJim Harris } 1481edd9bf3SJim Harris } 1491edd9bf3SJim Harris } 150