xref: /spdk/lib/blobfs/tree.c (revision d182ee1d5acd5f3a3af9daab34edebdacb0e03be)
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