diff --git a/src/add-ons/kernel/file_systems/ramfs/DataContainer.cpp b/src/add-ons/kernel/file_systems/ramfs/DataContainer.cpp index ad025941c9..4779d2e6a8 100644 --- a/src/add-ons/kernel/file_systems/ramfs/DataContainer.cpp +++ b/src/add-ons/kernel/file_systems/ramfs/DataContainer.cpp @@ -1,420 +1,359 @@ /* * Copyright 2007, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2019, Haiku, Inc. * All rights reserved. Distributed under the terms of the MIT license. */ +#include "DataContainer.h" + +#include +#include + +#include +#include #include "AllocationInfo.h" -#include "Attribute.h" // for debugging only -#include "Block.h" -#include "DataContainer.h" #include "DebugSupport.h" #include "Misc.h" -#include "Node.h" // for debugging only #include "Volume.h" // constructor DataContainer::DataContainer(Volume *volume) : fVolume(volume), - fSize(0) + fSize(0), + fCache(NULL) { } // destructor DataContainer::~DataContainer() { - Resize(0); + if (fCache != NULL) { + fCache->Lock(); + fCache->ReleaseRefAndUnlock(); + fCache = NULL; + } } // InitCheck status_t DataContainer::InitCheck() const { - return (fVolume ? B_OK : B_ERROR); + return (fVolume != NULL ? B_OK : B_ERROR); } // Resize status_t DataContainer::Resize(off_t newSize) { +// PRINT("DataContainer::Resize(%Ld), fSize: %Ld\n", newSize, fSize); + status_t error = B_OK; - if (newSize < 0) - newSize = 0; - if (newSize != fSize) { - // Shrinking should never fail. Growing can fail, if we run out of - // memory. Then we try to shrink back to the original size. - off_t oldSize = fSize; - error = _Resize(newSize); - if (error == B_NO_MEMORY && newSize > fSize) - _Resize(oldSize); + if (newSize < fSize) { + // shrink + if (_IsCacheMode()) { + // resize the VMCache, which will automatically free pages + AutoLocker _(fCache); + error = fCache->Resize(newSize, VM_PRIORITY_SYSTEM); + if (error != B_OK) + return error; + } else { + // small buffer mode: just set the new size (done below) + } + } else if (newSize > fSize) { + // grow + if (_RequiresCacheMode(newSize)) { + if (!_IsCacheMode()) + error = _SwitchToCacheMode(fSize); + if (error != B_OK) + return error; + + AutoLocker _(fCache); + fCache->Resize(newSize, VM_PRIORITY_SYSTEM); + + // pages will be added as they are written to; so nothing else + // needs to be done here. + } else { + // no need to switch to cache mode: just set the new size + // (done below) + } } + + fSize = newSize; + +// PRINT("DataContainer::Resize() done: %lx, fSize: %Ld\n", error, fSize); return error; } // ReadAt status_t DataContainer::ReadAt(off_t offset, void *_buffer, size_t size, - size_t *bytesRead) + size_t *bytesRead) { uint8 *buffer = (uint8*)_buffer; - status_t error = (buffer && offset >= 0 && bytesRead ? B_OK : B_BAD_VALUE); - if (error == B_OK) { - // read not more than we have to offer - offset = min(offset, fSize); - size = min(size, size_t(fSize - offset)); - // iterate through the blocks, reading as long as there's something - // left to read - size_t blockSize = fVolume->GetBlockSize(); - *bytesRead = 0; - while (size > 0) { - size_t inBlockOffset = offset % blockSize; - size_t toRead = min(size, size_t(blockSize - inBlockOffset)); - void *blockData = _GetBlockDataAt(offset / blockSize, - inBlockOffset, toRead); -D( -if (!blockData) { - Node *node = NULL; - if (Attribute *attribute = dynamic_cast(this)) { - FATAL("attribute `%s' of\n", attribute->GetName()); - node = attribute->GetNode(); - } else { - node = dynamic_cast(this); - } - if (node) -// FATAL(("node `%s'\n", node->GetName())); - FATAL("container size: %Ld, offset: %Ld, buffer size: %lu\n", - fSize, offset, size); - return B_ERROR; -} -); - memcpy(buffer, blockData, toRead); - buffer += toRead; - size -= toRead; - offset += toRead; - *bytesRead += toRead; - } + status_t error = (buffer && offset >= 0 && + bytesRead ? B_OK : B_BAD_VALUE); + if (error != B_OK) + return error; + + // read not more than we have to offer + offset = min(offset, fSize); + size = min(size, size_t(fSize - offset)); + + if (!_IsCacheMode()) { + // in non-cache mode, we just copy the data directly + memcpy(buffer, fSmallBuffer + offset, size); + if (bytesRead != NULL) + *bytesRead = size; + return B_OK; } + + // cache mode + error = _DoCacheIO(offset, buffer, size, bytesRead, false); + return error; } // WriteAt status_t DataContainer::WriteAt(off_t offset, const void *_buffer, size_t size, - size_t *bytesWritten) + size_t *bytesWritten) { -//PRINT(("DataContainer::WriteAt(%Ld, %p, %lu, %p), fSize: %Ld\n", offset, _buffer, size, bytesWritten, fSize)); + PRINT("DataContainer::WriteAt(%Ld, %p, %lu, %p), fSize: %Ld\n", offset, _buffer, size, bytesWritten, fSize); + const uint8 *buffer = (const uint8*)_buffer; status_t error = (buffer && offset >= 0 && bytesWritten - ? B_OK : B_BAD_VALUE); - // resize the container, if necessary - if (error == B_OK) { - off_t newSize = offset + size; - off_t oldSize = fSize; - if (newSize > fSize) { - error = Resize(newSize); - // pad with zero, if necessary - if (error == B_OK && offset > oldSize) - _ClearArea(offset, oldSize - offset); - } - } - if (error == B_OK) { - // iterate through the blocks, writing as long as there's something - // left to write - size_t blockSize = fVolume->GetBlockSize(); - *bytesWritten = 0; - while (size > 0) { - size_t inBlockOffset = offset % blockSize; - size_t toWrite = min(size, size_t(blockSize - inBlockOffset)); - void *blockData = _GetBlockDataAt(offset / blockSize, - inBlockOffset, toWrite); -D(if (!blockData) return B_ERROR;); - memcpy(blockData, buffer, toWrite); - buffer += toWrite; - size -= toWrite; - offset += toWrite; - *bytesWritten += toWrite; - } - } -//PRINT(("DataContainer::WriteAt() done: %lx, fSize: %Ld\n", error, fSize)); - return error; -} + ? B_OK : B_BAD_VALUE); + if (error != B_OK) + return error; -// GetFirstDataBlock -void -DataContainer::GetFirstDataBlock(const uint8 **data, size_t *length) -{ - if (data && length) { - if (_IsBlockMode()) { - BlockReference *block = _GetBlockList()->ItemAt(0); - *data = (const uint8*)block->GetData(); - *length = min(fSize, fVolume->GetBlockSize()); - } else { - *data = fSmallBuffer; - *length = fSize; - } + // resize the container, if necessary + if ((offset + size) > fSize) + error = Resize(offset + size); + if (error != B_OK) + return error; + + if (!_IsCacheMode()) { + // in non-cache mode, we just copy the data directly + memcpy(fSmallBuffer + offset, buffer, size); + if (bytesWritten != NULL) + *bytesWritten = size; + return B_OK; } + + // cache mode + error = _DoCacheIO(offset, (uint8*)buffer, size, bytesWritten, true); + + PRINT("DataContainer::WriteAt() done: %lx, fSize: %Ld\n", error, fSize); + return error; } // GetAllocationInfo void DataContainer::GetAllocationInfo(AllocationInfo &info) { - if (_IsBlockMode()) { - BlockList *blocks = _GetBlockList(); - info.AddListAllocation(blocks->GetCapacity(), sizeof(BlockReference*)); - int32 blockCount = blocks->CountItems(); - for (int32 i = 0; i < blockCount; i++) - info.AddBlockAllocation(blocks->ItemAt(i)->GetBlock()->GetSize()); + if (_IsCacheMode()) { + info.AddAreaAllocation(fCache->committed_size); } else { // ... } } -// _RequiresBlockMode -inline -bool -DataContainer::_RequiresBlockMode(size_t size) +// _RequiresCacheMode +inline bool +DataContainer::_RequiresCacheMode(size_t size) { - return (size > kSmallDataContainerSize); + // we cannot back out of cache mode after entering it, + // as there may be other consumers of our VMCache + return _IsCacheMode() || (size > kSmallDataContainerSize); } -// _IsBlockMode -inline -bool -DataContainer::_IsBlockMode() const +// _IsCacheMode +inline bool +DataContainer::_IsCacheMode() const { - return (fSize > kSmallDataContainerSize); -} - -// _Resize -status_t -DataContainer::_Resize(off_t newSize) -{ -//PRINT(("DataContainer::_Resize(%Ld), fSize: %Ld\n", newSize, fSize)); - status_t error = B_OK; - if (newSize != fSize) { - size_t blockSize = fVolume->GetBlockSize(); - int32 blockCount = _CountBlocks(); - int32 newBlockCount = (newSize + blockSize - 1) / blockSize; - if (newBlockCount == blockCount) { - // only the last block needs to be resized - if (_IsBlockMode() && _RequiresBlockMode(newSize)) { - // keep block mode - error = _ResizeLastBlock((newSize - 1) % blockSize + 1); - } else if (!_IsBlockMode() && !_RequiresBlockMode(newSize)) { - // keep small buffer mode - fSize = newSize; - } else if (fSize < newSize) { - // switch to block mode - _SwitchToBlockMode(newSize); - } else { - // switch to small buffer mode - _SwitchToSmallBufferMode(newSize); - } - } else if (newBlockCount < blockCount) { - // shrink - if (_IsBlockMode()) { - // remove the last blocks - BlockList *blocks = _GetBlockList(); - for (int32 i = blockCount - 1; i >= newBlockCount; i--) { - BlockReference *block = blocks->ItemAt(i); - blocks->RemoveItem(i); - fVolume->FreeBlock(block); - fSize = (fSize - 1) / blockSize * blockSize; - } - // resize the last block to the correct size, respectively - // switch to small buffer mode - if (_RequiresBlockMode(newSize)) - error = _ResizeLastBlock((newSize - 1) % blockSize + 1); - else - _SwitchToSmallBufferMode(newSize); - } else { - // small buffer mode: just set the new size - fSize = newSize; - } - } else { - // grow - if (_RequiresBlockMode(newSize)) { - // resize the first block to the correct size, respectively - // switch to block mode - if (_IsBlockMode()) - error = _ResizeLastBlock(blockSize); - else { - error = _SwitchToBlockMode(min((size_t)newSize, - blockSize)); - } - // add new blocks - BlockList *blocks = _GetBlockList(); - while (error == B_OK && fSize < newSize) { - size_t newBlockSize = min(size_t(newSize - fSize), - blockSize); - BlockReference *block = NULL; - error = fVolume->AllocateBlock(newBlockSize, &block); - if (error == B_OK) { - if (blocks->AddItem(block)) - fSize += newBlockSize; - else { - SET_ERROR(error, B_NO_MEMORY); - fVolume->FreeBlock(block); - } - } - } - } else { - // no need to switch to block mode: just set the new size - fSize = newSize; - } - } - } -//PRINT(("DataContainer::_Resize() done: %lx, fSize: %Ld\n", error, fSize)); - return error; -} - -// _GetBlockList -inline -DataContainer::BlockList * -DataContainer::_GetBlockList() -{ - return (BlockList*)fBlocks; -} - -// _GetBlockList -inline -const DataContainer::BlockList * -DataContainer::_GetBlockList() const -{ - return (BlockList*)fBlocks; + return fCache != NULL; } // _CountBlocks -inline -int32 +inline int32 DataContainer::_CountBlocks() const { - if (_IsBlockMode()) - return _GetBlockList()->CountItems(); + if (_IsCacheMode()) + return fCache->page_count; else if (fSize == 0) // small buffer mode, empty buffer return 0; return 1; // small buffer mode, non-empty buffer } -// _GetBlockDataAt -inline -void * -DataContainer::_GetBlockDataAt(int32 index, size_t offset, size_t DARG(size)) -{ - if (_IsBlockMode()) { - BlockReference *block = _GetBlockList()->ItemAt(index); -D(if (!fVolume->CheckBlock(block, offset + size)) return NULL;); - return block->GetDataAt(offset); - } else { -D( -if (offset + size > kSmallDataContainerSize) { - FATAL("DataContainer: Data access exceeds small buffer.\n"); - PANIC("DataContainer: Data access exceeds small buffer."); - return NULL; -} -); - return fSmallBuffer + offset; - } -} - -// _ClearArea -void -DataContainer::_ClearArea(off_t offset, off_t size) -{ - // constrain the area to the data area - offset = min(offset, fSize); - size = min(size, fSize - offset); - // iterate through the blocks, clearing as long as there's something - // left to clear - size_t blockSize = fVolume->GetBlockSize(); - while (size > 0) { - size_t inBlockOffset = offset % blockSize; - size_t toClear = min(size_t(size), blockSize - inBlockOffset); - void *blockData = _GetBlockDataAt(offset / blockSize, inBlockOffset, - toClear); -D(if (!blockData) return;); - memset(blockData, 0, toClear); - size -= toClear; - offset += toClear; - } -} - -// _ResizeLastBlock +// _SwitchToCacheMode status_t -DataContainer::_ResizeLastBlock(size_t newSize) +DataContainer::_SwitchToCacheMode(size_t newBlockSize) { -//PRINT(("DataContainer::_ResizeLastBlock(%lu), fSize: %Ld\n", newSize, fSize)); - int32 blockCount = _CountBlocks(); - status_t error = (fSize > 0 && blockCount > 0 && newSize > 0 - ? B_OK : B_BAD_VALUE); -D( -if (!_IsBlockMode()) { - FATAL("Call of _ResizeLastBlock() in small buffer mode.\n"); - PANIC("Call of _ResizeLastBlock() in small buffer mode."); - return B_ERROR; -} -); - if (error == B_OK) { - size_t blockSize = fVolume->GetBlockSize(); - size_t oldSize = (fSize - 1) % blockSize + 1; - if (newSize != oldSize) { - BlockList *blocks = _GetBlockList(); - BlockReference *block = blocks->ItemAt(blockCount - 1); - BlockReference *newBlock = fVolume->ResizeBlock(block, newSize); - if (newBlock) { - if (newBlock != block) - blocks->ReplaceItem(blockCount - 1, newBlock); - fSize += off_t(newSize) - oldSize; - } else - SET_ERROR(error, B_NO_MEMORY); - } - } -//PRINT(("DataContainer::_ResizeLastBlock() done: %lx, fSize: %Ld\n", error, fSize)); + status_t error = VMCacheFactory::CreateAnonymousCache(fCache, false, 0, + 0, false, VM_PRIORITY_SYSTEM); + if (error != B_OK) + return error; + + fCache->temporary = 1; + fCache->virtual_end = newBlockSize; + + error = fCache->Commit(newBlockSize, VM_PRIORITY_SYSTEM); + if (error != B_OK) + return error; + + if (fSize != 0) + error = _DoCacheIO(0, fSmallBuffer, fSize, NULL, true); + return error; } -// _SwitchToBlockMode +// _DoCacheIO status_t -DataContainer::_SwitchToBlockMode(size_t newBlockSize) +DataContainer::_DoCacheIO(const off_t offset, uint8* buffer, ssize_t length, + size_t* bytesProcessed, bool isWrite) { - // allocate a new block - BlockReference *block = NULL; - status_t error = fVolume->AllocateBlock(newBlockSize, &block); - if (error == B_OK) { - // copy the data from the small buffer into the block - if (fSize > 0) - memcpy(block->GetData(), fSmallBuffer, fSize); - // construct the block list and add the block - new (fBlocks) BlockList(10); - BlockList *blocks = _GetBlockList(); - if (blocks->AddItem(block)) { - fSize = newBlockSize; + const size_t originalLength = length; + const bool user = IS_USER_ADDRESS(buffer); + + const off_t rounded_offset = ROUNDDOWN(offset, B_PAGE_SIZE); + const size_t rounded_len = ROUNDUP((length) + (offset - rounded_offset), + B_PAGE_SIZE); + vm_page** pages = new(std::nothrow) vm_page*[rounded_len / B_PAGE_SIZE]; + if (pages == NULL) + return B_NO_MEMORY; + ArrayDeleter pagesDeleter(pages); + + _GetPages(rounded_offset, rounded_len, isWrite, pages); + + status_t error = B_OK; + size_t index = 0; + + while (length > 0) { + vm_page* page = pages[index]; + phys_addr_t at = (page->physical_page_number * B_PAGE_SIZE); + ssize_t bytes = B_PAGE_SIZE; + if (index == 0) { + const uint32 pageoffset = (offset % B_PAGE_SIZE); + at += pageoffset; + bytes -= pageoffset; + } + bytes = min(length, bytes); + + if (isWrite) { + page->modified = true; + error = vm_memcpy_to_physical(at, buffer, bytes, user); } else { - // error: destroy the block list and free the block - SET_ERROR(error, B_NO_MEMORY); - blocks->~BlockList(); - if (fSize > 0) - memcpy(fSmallBuffer, block->GetData(), fSize); - fVolume->FreeBlock(block); + if (page != NULL) { + error = vm_memcpy_from_physical(buffer, at, bytes, user); + } else { + if (user) { + error = user_memset(buffer, 0, bytes); + } else { + memset(buffer, 0, bytes); + } + } } + if (error != B_OK) + break; + + buffer += bytes; + length -= bytes; + index++; } + + _PutPages(rounded_offset, rounded_len, pages, error == B_OK); + + if (bytesProcessed != NULL) + *bytesProcessed = length > 0 ? originalLength - length : originalLength; + return error; } -// _SwitchToSmallBufferMode +// _GetPages void -DataContainer::_SwitchToSmallBufferMode(size_t newSize) +DataContainer::_GetPages(off_t offset, off_t length, bool isWrite, + vm_page** pages) { - // remove the first (and only) block - BlockList *blocks = _GetBlockList(); - BlockReference *block = blocks->ItemAt(0); - blocks->RemoveItem((int32)0L); - // destroy the block list and copy the data into the small buffer - blocks->~BlockList(); - if (newSize > 0) - memcpy(fSmallBuffer, block->GetData(), newSize); - // free the block and set the new size - fVolume->FreeBlock(block); - fSize = newSize; + // TODO: This method is duplicated in the ram_disk. Perhaps it + // should be put into a common location? + + // get the pages, we already have + AutoLocker locker(fCache); + + size_t pageCount = length / B_PAGE_SIZE; + size_t index = 0; + size_t missingPages = 0; + + while (length > 0) { + vm_page* page = fCache->LookupPage(offset); + if (page != NULL) { + if (page->busy) { + fCache->WaitForPageEvents(page, PAGE_EVENT_NOT_BUSY, true); + continue; + } + + DEBUG_PAGE_ACCESS_START(page); + page->busy = true; + } else + missingPages++; + + pages[index++] = page; + offset += B_PAGE_SIZE; + length -= B_PAGE_SIZE; + } + + locker.Unlock(); + + // For a write we need to reserve the missing pages. + if (isWrite && missingPages > 0) { + vm_page_reservation reservation; + vm_page_reserve_pages(&reservation, missingPages, + VM_PRIORITY_SYSTEM); + + for (size_t i = 0; i < pageCount; i++) { + if (pages[i] != NULL) + continue; + + pages[i] = vm_page_allocate_page(&reservation, + PAGE_STATE_WIRED | VM_PAGE_ALLOC_BUSY); + + if (--missingPages == 0) + break; + } + + vm_page_unreserve_pages(&reservation); + } } +void +DataContainer::_PutPages(off_t offset, off_t length, vm_page** pages, + bool success) +{ + // TODO: This method is duplicated in the ram_disk. Perhaps it + // should be put into a common location? + + AutoLocker locker(fCache); + + // Mark all pages unbusy. On error free the newly allocated pages. + size_t index = 0; + + while (length > 0) { + vm_page* page = pages[index++]; + if (page != NULL) { + if (page->CacheRef() == NULL) { + if (success) { + fCache->InsertPage(page, offset); + fCache->MarkPageUnbusy(page); + DEBUG_PAGE_ACCESS_END(page); + } else + vm_page_free(NULL, page); + } else { + fCache->MarkPageUnbusy(page); + DEBUG_PAGE_ACCESS_END(page); + } + } + + offset += B_PAGE_SIZE; + length -= B_PAGE_SIZE; + } +} diff --git a/src/add-ons/kernel/file_systems/ramfs/DataContainer.h b/src/add-ons/kernel/file_systems/ramfs/DataContainer.h index d51e640ae2..7c2fe5a45d 100644 --- a/src/add-ons/kernel/file_systems/ramfs/DataContainer.h +++ b/src/add-ons/kernel/file_systems/ramfs/DataContainer.h @@ -1,14 +1,16 @@ /* * Copyright 2007, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2019, Haiku, Inc. * All rights reserved. Distributed under the terms of the MIT license. */ #ifndef DATA_CONTAINER_H #define DATA_CONTAINER_H -#include "List.h" +#include +struct vm_page; +class VMCache; class AllocationInfo; -class BlockReference; class Volume; // Size of the DataContainer's small buffer. If it contains data up to this @@ -49,38 +51,25 @@ public: virtual status_t WriteAt(off_t offset, const void *buffer, size_t size, size_t *bytesWritten); - void GetFirstDataBlock(const uint8 **data, size_t *length); - // debugging void GetAllocationInfo(AllocationInfo &info); private: - typedef List BlockList; + inline bool _RequiresCacheMode(size_t size); + inline bool _IsCacheMode() const; + status_t _SwitchToCacheMode(size_t newBlockSize); + void _GetPages(off_t offset, off_t length, bool isWrite, vm_page** pages); + void _PutPages(off_t offset, off_t length, vm_page** pages, bool success); + status_t _DoCacheIO(const off_t offset, uint8* buffer, ssize_t length, + size_t* bytesProcessed, bool isWrite); -private: - static inline bool _RequiresBlockMode(size_t size); - inline bool _IsBlockMode() const; - - inline BlockList *_GetBlockList(); - inline const BlockList *_GetBlockList() const; inline int32 _CountBlocks() const; - inline void *_GetBlockDataAt(int32 index, size_t offset, size_t size); - - void _ClearArea(off_t offset, off_t size); - - status_t _Resize(off_t newSize); - status_t _ResizeLastBlock(size_t newSize); - - status_t _SwitchToBlockMode(size_t newBlockSize); - void _SwitchToSmallBufferMode(size_t newSize); private: - Volume *fVolume; - off_t fSize; - union { - uint8 fBlocks[sizeof(BlockList)]; - uint8 fSmallBuffer[kSmallDataContainerSize]; - }; + Volume *fVolume; + off_t fSize; + VMCache* fCache; + uint8 fSmallBuffer[kSmallDataContainerSize]; }; #endif // DATA_CONTAINER_H diff --git a/src/add-ons/kernel/file_systems/ramfs/Jamfile b/src/add-ons/kernel/file_systems/ramfs/Jamfile index c5920f53c8..446c9ba17a 100644 --- a/src/add-ons/kernel/file_systems/ramfs/Jamfile +++ b/src/add-ons/kernel/file_systems/ramfs/Jamfile @@ -12,10 +12,6 @@ KernelAddon ramfs AttributeIndex.cpp AttributeIndexImpl.cpp AttributeIterator.cpp - BlockAllocator.cpp - BlockAllocatorArea.cpp - BlockAllocatorAreaBucket.cpp - BlockReferenceManager.cpp DataContainer.cpp DebugSupport.cpp Directory.cpp diff --git a/src/add-ons/kernel/file_systems/ramfs/Volume.cpp b/src/add-ons/kernel/file_systems/ramfs/Volume.cpp index 002b51cbb9..1f46f543dd 100644 --- a/src/add-ons/kernel/file_systems/ramfs/Volume.cpp +++ b/src/add-ons/kernel/file_systems/ramfs/Volume.cpp @@ -26,8 +26,8 @@ #include #include -#include "Block.h" -#include "BlockAllocator.h" +#include + #include "DebugSupport.h" #include "Directory.h" #include "DirectoryEntryTable.h" @@ -43,11 +43,6 @@ #include "TwoKeyAVLTree.h" #include "Volume.h" -// default block size -static const off_t kDefaultBlockSize = 4096; - -static const size_t kDefaultAreaSize = kDefaultBlockSize * 128; - // default volume name static const char *kDefaultVolumeName = "RAM FS"; @@ -143,9 +138,6 @@ Volume::Volume(fs_volume* volume) fAnyNodeListeners(), fEntryListeners(NULL), fAnyEntryListeners(), - fBlockAllocator(NULL), - fBlockSize(kDefaultBlockSize), - fAllocatedBlocks(0), fAccessTime(0), fMounted(false) { @@ -173,14 +165,6 @@ Volume::Mount(uint32 flags) Unmount(); status_t error = B_OK; - // create a block allocator - if (error == B_OK) { - fBlockAllocator = new(nothrow) BlockAllocator(kDefaultAreaSize); - if (fBlockAllocator) - error = fBlockAllocator->InitCheck(); - else - SET_ERROR(error, B_NO_MEMORY); - } // create the listener trees if (error == B_OK) { fNodeListeners = new(nothrow) NodeListenerTree; @@ -267,41 +251,22 @@ Volume::Unmount() delete fNodeTable; fNodeTable = NULL; } - // delete the block allocator - if (fBlockAllocator) { - delete fBlockAllocator; - fBlockAllocator = NULL; - } return B_OK; } -// GetBlockSize -off_t -Volume::GetBlockSize() const -{ - return fBlockSize; -} - // CountBlocks off_t Volume::CountBlocks() const { - size_t bytes = 0; - system_info sysInfo; - if (get_system_info(&sysInfo) == B_OK) { - int32 freePages = sysInfo.max_pages - sysInfo.used_pages; - bytes = (uint32)freePages * B_PAGE_SIZE - + fBlockAllocator->GetAvailableBytes(); - } - return bytes / kDefaultBlockSize; + // TODO: Compute how many pages we are using across all DataContainers. + return 0; } // CountFreeBlocks off_t Volume::CountFreeBlocks() const { - // TODO:... - return CountBlocks() - fBlockAllocator->GetUsedBytes() / kDefaultBlockSize; + return vm_page_num_available_pages(); } // SetName @@ -752,54 +717,6 @@ Volume::UpdateLiveQueries(Entry *entry, Node* node, const char *attribute, } } -// AllocateBlock -status_t -Volume::AllocateBlock(size_t size, BlockReference **block) -{ - status_t error = (size > 0 && size <= fBlockSize && block - ? B_OK : B_BAD_VALUE); - if (error == B_OK) { - *block = fBlockAllocator->AllocateBlock(size); - if (*block) - fAllocatedBlocks++; - else - SET_ERROR(error, B_NO_MEMORY); - } - return error; -} - -// FreeBlock -void -Volume::FreeBlock(BlockReference *block) -{ - if (block) { - fBlockAllocator->FreeBlock(block); - fAllocatedBlocks--; - } -} - -// ResizeBlock -BlockReference * -Volume::ResizeBlock(BlockReference *block, size_t size) -{ - BlockReference *newBlock = NULL; - if (size <= fBlockSize && block) { - if (size == 0) { - fBlockAllocator->FreeBlock(block); - fAllocatedBlocks--; - } else - newBlock = fBlockAllocator->ResizeBlock(block, size); - } - return newBlock; -} - -// CheckBlock -bool -Volume::CheckBlock(BlockReference *block, size_t size) -{ - return fBlockAllocator->CheckBlock(block, size); -} - // GetAllocationInfo void Volume::GetAllocationInfo(AllocationInfo &info) @@ -813,9 +730,6 @@ Volume::GetAllocationInfo(AllocationInfo &info) fRootDirectory->GetAllocationInfo(info); // name info.AddStringAllocation(fName.GetLength()); - // block allocator - info.AddOtherAllocation(sizeof(BlockAllocator)); - fBlockAllocator->GetAllocationInfo(info); } // ReadLock diff --git a/src/add-ons/kernel/file_systems/ramfs/Volume.h b/src/add-ons/kernel/file_systems/ramfs/Volume.h index ea103123ba..f3425918b6 100644 --- a/src/add-ons/kernel/file_systems/ramfs/Volume.h +++ b/src/add-ons/kernel/file_systems/ramfs/Volume.h @@ -34,9 +34,8 @@ #include "String.h" class AllocationInfo; -class Block; -class BlockAllocator; -class BlockReference; +class Attribute; +class AttributeIndex; class Directory; class DirectoryEntryTable; class Entry; @@ -101,7 +100,6 @@ public: dev_t GetID() const { return fVolume != NULL ? fVolume->id : -1; } fs_volume* FSVolume() const { return fVolume; } - off_t GetBlockSize() const; off_t CountBlocks() const; off_t CountFreeBlocks() const; @@ -156,11 +154,6 @@ public: ino_t NextNodeID() { return fNextNodeID++; } - status_t AllocateBlock(size_t size, BlockReference **block); - void FreeBlock(BlockReference *block); - BlockReference *ResizeBlock(BlockReference *block, size_t size); - // debugging only - bool CheckBlock(BlockReference *block, size_t size = 0); void GetAllocationInfo(AllocationInfo &info); bigtime_t GetAccessTime() const { return fAccessTime; } @@ -194,9 +187,6 @@ private: EntryListenerTree *fEntryListeners; EntryListenerList fAnyEntryListeners; QueryList fQueries; - BlockAllocator *fBlockAllocator; - off_t fBlockSize; - off_t fAllocatedBlocks; bigtime_t fAccessTime; bool fMounted; }; diff --git a/src/add-ons/kernel/file_systems/ramfs/kernel_interface.cpp b/src/add-ons/kernel/file_systems/ramfs/kernel_interface.cpp index 6f8d803689..42d0bff234 100644 --- a/src/add-ons/kernel/file_systems/ramfs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/ramfs/kernel_interface.cpp @@ -137,7 +137,7 @@ ramfs_read_fs_info(fs_volume* _volume, struct fs_info *info) if (VolumeReadLocker locker = volume) { info->flags = B_FS_IS_PERSISTENT | B_FS_HAS_ATTR | B_FS_HAS_MIME | B_FS_HAS_QUERY; - info->block_size = volume->GetBlockSize(); + info->block_size = B_PAGE_SIZE; info->io_size = kOptimalIOSize; info->total_blocks = volume->CountBlocks(); info->free_blocks = volume->CountFreeBlocks();