status_t DirEntryTree::_InsertEntryIncrementDepth(LevelInfo* infos, Transaction& transaction) { FUNCTION("depth: %u -> %u\n", _Depth(), _Depth() + 1); if (_Depth() >= kCheckSumFSMaxDirEntryTreeDepth) RETURN_ERROR(B_DEVICE_FULL); // allocate a new block AllocatedBlock allocatedBlock( fDirectory->GetVolume()->GetBlockAllocator(), transaction); status_t error = allocatedBlock.Allocate(fDirectory->BlockIndex()); if (error != B_OK) RETURN_ERROR(error); fDirectory->SetSize(fDirectory->Size() + B_PAGE_SIZE); LevelInfo& newInfo = infos[1]; if (!newInfo.block.GetZero(fDirectory->GetVolume(), allocatedBlock.Index(), transaction)) { RETURN_ERROR(B_ERROR); } allocatedBlock.Detach(); newInfo.entryBlock.SetTo( (checksumfs_dir_entry_block*)newInfo.block.Data(), B_PAGE_SIZE); ASSERT(newInfo.entryBlock.Check()); // move the old root block contents to the new block LevelInfo& rootInfo = infos[0]; rootInfo.entryBlock.SplitBlock(0, newInfo.entryBlock); // add an entry for the new block to the root block size_t nameLength; const char* name = newInfo.entryBlock.NameAt(0, nameLength); rootInfo.entryBlock.InsertEntry(0, name, nameLength, newInfo.block.Index()); PRINT(" -> new block: %" B_PRIu64 "\n", newInfo.block.Index()); newInfo.index = rootInfo.index; rootInfo.index = 0; fTree->depth++; return B_OK; }
/** * deletes the passed node and all decedents if available */ void erase_node(Node *n) noexcept { if (n == nullptr) { return; } if (n->next.load()) { // delete all possible next Nodes in the list erase_node(n->next.load()); n->next = nullptr; } // Create a temporary node on the stack Node stackNode; // Move the allocator to the temporary node stackNode = std::move(*n); block allocatedBlock(n, stackNode.allocatedThisSize); stackNode.allocator.deallocate(allocatedBlock); }
status_t Volume::CreateDirectory(mode_t mode, Directory*& _directory) { // allocate a free block AllocatedBlock allocatedBlock(fBlockAllocator); status_t error = allocatedBlock.Allocate(); if (error != B_OK) return error; // create the directory Directory* directory = new(std::nothrow) Directory(this, allocatedBlock.Index(), (mode & ~(mode_t)S_IFMT) | S_IFDIR); if (directory == NULL) return B_NO_MEMORY; allocatedBlock.Detach(); _directory = directory; return B_OK; }
status_t DirEntryTree::_InsertEntrySplitBlock(int32 level, LevelInfo& info, size_t needed, Transaction& transaction, Block& newBlock, int32& _splitIndex) { int32 splitIndex = info.entryBlock.FindSplitIndex(info.index, needed); FUNCTION("level: %" B_PRId32 ", size needed: %" B_PRIuSIZE ", split index: " "%" B_PRId32 "/%" B_PRId32 "\n", level, needed, splitIndex, info.entryBlock.EntryCount()); // allocate a new block AllocatedBlock allocatedBlock( fDirectory->GetVolume()->GetBlockAllocator(), transaction); status_t error = allocatedBlock.Allocate(fDirectory->BlockIndex()); if (error != B_OK) RETURN_ERROR(error); fDirectory->SetSize(fDirectory->Size() + B_PAGE_SIZE); if (!newBlock.GetZero(fDirectory->GetVolume(), allocatedBlock.Index(), transaction)) { RETURN_ERROR(B_ERROR); } allocatedBlock.Detach(); // split the old block DirEntryBlock newEntryBlock( (checksumfs_dir_entry_block*)newBlock.Data(), B_PAGE_SIZE); ASSERT(newEntryBlock.Check()); info.entryBlock.SplitBlock(splitIndex, newEntryBlock); PRINT(" -> new block: %" B_PRIu64 "\n", newBlock.Index()); _splitIndex = splitIndex; return B_OK; }