void* tommy_tree_remove_existing(tommy_tree* tree, tommy_tree_node* node) { void* data = tommy_tree_remove(tree, node->data); assert(data != 0); return data; }
void fs_deallocate(struct snapraid_disk* disk, block_off_t parity_pos) { struct snapraid_chunk* chunk; struct snapraid_chunk* second_chunk; struct snapraid_chunk* parity_chunk; struct snapraid_chunk* file_chunk; block_off_t first_count, second_count; chunk = fs_par2chunk_get_ts(disk, &disk->fs_last, parity_pos); if (!chunk) { /* LCOV_EXCL_START */ log_fatal("Internal inconsistency when deallocating parity position '%u' for not existing chunk in disk '%s'\n", parity_pos, disk->name); exit(EXIT_FAILURE); /* LCOV_EXCL_STOP */ } /* if it's the only block of the chunk, delete it */ if (chunk->count == 1) { /* remove from the trees */ tommy_tree_remove(&disk->fs_parity, chunk); tommy_tree_remove(&disk->fs_file, chunk); /* deallocate */ chunk_free(chunk); /* clear the last accessed chunk */ disk->fs_last = 0; return; } /* if it's at the start of the chunk, shrink the chunk */ if (parity_pos == chunk->parity_pos) { ++chunk->parity_pos; ++chunk->file_pos; --chunk->count; return; } /* if it's at the end of the chunk, shrink the chunk */ if (parity_pos == chunk->parity_pos + chunk->count - 1) { --chunk->count; return; } /* otherwise it's in the middle */ first_count = parity_pos - chunk->parity_pos; second_count = chunk->count - first_count - 1; /* adjust the first chunk */ chunk->count = first_count; /* allocate the second chunk */ second_chunk = chunk_alloc(chunk->parity_pos + first_count + 1, chunk->file, chunk->file_pos + first_count + 1, second_count); /* insert the chunk in the trees */ parity_chunk = tommy_tree_insert(&disk->fs_parity, &second_chunk->parity_node, second_chunk); file_chunk = tommy_tree_insert(&disk->fs_file, &second_chunk->file_node, second_chunk); if (parity_chunk != second_chunk || file_chunk != second_chunk) { /* LCOV_EXCL_START */ log_fatal("Internal inconsistency when deallocating parity position '%u' for splitting chunk '%u:%u' in disk '%s'\n", parity_pos, second_chunk->file_pos, second_chunk->count, disk->name); exit(EXIT_FAILURE); /* LCOV_EXCL_STOP */ } /* store the last accessed chunk */ disk->fs_last = second_chunk; }