added 5 changesets to branch 'refs/remotes/ahenriksson-github/production' old head: 9b8ebc80c746198a0e965a9666f3328bf727139f new head: f96bcb2110c5de77d511e80f54268d8ecde10faf ---------------------------------------------------------------------------- 67c349d: Forgot stats in CheckVisitor 393b3a7: Initial support for moving the Log 3fc608f: Added Reinitialize() to BlockAllocator 1b305da: Added ResizeVisitor to handle the resizing f96bcb2: Added resize code invokation to kernel_interface.cpp [ ahenriksson <sausageboy@xxxxxxxxx> ] ---------------------------------------------------------------------------- 11 files changed, 649 insertions(+), 146 deletions(-) .../kernel/file_systems/bfs/BlockAllocator.cpp | 16 + .../kernel/file_systems/bfs/BlockAllocator.h | 1 + .../kernel/file_systems/bfs/CheckVisitor.cpp | 2 + src/add-ons/kernel/file_systems/bfs/Jamfile | 1 + src/add-ons/kernel/file_systems/bfs/Journal.cpp | 122 +++++ src/add-ons/kernel/file_systems/bfs/Journal.h | 2 + .../kernel/file_systems/bfs/ResizeVisitor.cpp | 406 ++++++++++++++++ .../kernel/file_systems/bfs/ResizeVisitor.h | 58 +++ src/add-ons/kernel/file_systems/bfs/Volume.h | 7 + .../kernel/file_systems/bfs/kernel_interface.cpp | 179 ++----- src/tools/bfs_shell/Jamfile | 1 + ############################################################################ Commit: 67c349d21b2ab91c07a638e4349e2c2c5e660f08 Author: ahenriksson <sausageboy@xxxxxxxxx> Date: Tue Jul 10 19:21:51 2012 UTC Forgot stats in CheckVisitor ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/file_systems/bfs/CheckVisitor.cpp b/src/add-ons/kernel/file_systems/bfs/CheckVisitor.cpp index feb9579..9bc72e9 100644 --- a/src/add-ons/kernel/file_systems/bfs/CheckVisitor.cpp +++ b/src/add-ons/kernel/file_systems/bfs/CheckVisitor.cpp @@ -603,6 +603,8 @@ CheckVisitor::_CheckAllocated(block_run run, const char* type) "not allocated!\n", type, run.AllocationGroup(), run.Start(), run.Length(), firstMissing, afterLastMissing - 1)); + Control().stats.missing += afterLastMissing - firstMissing; + block = afterLastMissing; } ############################################################################ Commit: 393b3a7e4e25ae0c2ede3e953fe3fdebb9b0dd10 Author: ahenriksson <sausageboy@xxxxxxxxx> Date: Wed Jul 4 12:11:09 2012 UTC Initial support for moving the Log ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/file_systems/bfs/Journal.cpp b/src/add-ons/kernel/file_systems/bfs/Journal.cpp index f1a1f74..3284f63 100644 --- a/src/add-ons/kernel/file_systems/bfs/Journal.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Journal.cpp @@ -1073,6 +1073,126 @@ Journal::_TransactionDone(bool success) } +status_t +Journal::MoveLog(block_run newLog) +{ + block_run oldLog = fVolume->Log(); + //block_run log_blocks; + + off_t newEnd = newLog.Start() + newLog.Length(); + off_t oldEnd = oldLog.Start() + oldLog.Length(); + //off_t oldLength = fVolume->Log().Length(); + + // make sure the new log position is ok + if (newLog.AllocationGroup() != 0) + return B_BAD_VALUE; + + if (fVolume->ValidateBlockRun(newLog) != B_OK) + return B_BAD_VALUE; + + if (newLog.Start() < 1 + fVolume->NumBitmapBlocks()) + return B_BAD_VALUE; + + if (newEnd > fVolume->NumBlocks()) + return B_BAD_VALUE; + + status_t status; + block_run allocatedRun = {}; + + BlockAllocator& allocator = fVolume->Allocator(); + + // allocate blocks if necessary + if (newEnd > oldEnd) { + off_t allocationSize = newEnd - oldEnd; + + Transaction transaction(fVolume, 0); + + status = allocator.AllocateBlocks(transaction, 0, oldEnd, + allocationSize, allocationSize, allocatedRun, oldEnd, newEnd); + if (status != B_OK) + return status; + + // these can't fail if AllocateBlocks works correctly, but perhaps + // they ought to be checked in the release build anyways rather than + // risking user data? (since we're not actually using the returned run) + ASSERT(allocatedRun.AllocationGroup() == 0); + ASSERT(allocatedRun.Start() == oldEnd); + ASSERT(allocatedRun.Length() == allocationSize); + + status = transaction.Done(); + if (status != B_OK) + return status; + } + + // lock journal here? + + status = FlushLogAndBlocks(); + if (status != B_OK) + return status; + + status = recursive_lock_lock(&fLock); + if (status != B_OK) + return status; + + // lock volume? + MutexLocker volumeLock(fVolume->Lock()); + + // update references to the log location and size + fVolume->SuperBlock().log_blocks = newLog; + status = fVolume->WriteSuperBlock(); + if (status != B_OK) { + fVolume->SuperBlock().log_blocks = oldLog; + recursive_lock_unlock(&fLock); + + /* + // if we had to allocate some blocks, try to free them + // TODO: does it even make sense to try this after we couldn't write + // the superblock? + if (!allocatedRun.IsZero()) { + Transaction transaction(fVolume, 0); + status_t freeStatus = allocator.Free(transaction, allocatedRun); + if (freeStatus == B_OK) + freeStatus = transaction.Done(); + + // don't really care if we fail + if (freeStatus != B_OK) + REPORT_ERROR(freeStatus); + } + */ + + return status; + } + + fLogSize = newLog.Length(); + fMaxTransactionSize = fLogSize / 2 - 5; + + volumeLock.Unlock(); + recursive_lock_unlock(&fLock); + + // unlock volume, unlock journal + + // at this point, the log is moved and functional in its new location + + // free blocks if necessary + if (newEnd < oldEnd) { + block_run runToFree = block_run::Run(0, newEnd, oldEnd - newEnd); + + Transaction transaction(fVolume, 0); + + status = allocator.Free(transaction, runToFree); + if (status == B_OK) + status = transaction.Done(); + + // we've already moved the log, no sense in failing just because we + // couldn't free a couple of blocks + if (status != B_OK) + REPORT_ERROR(status); + } + + return B_OK; +} + + // #pragma mark - debugger commands diff --git a/src/add-ons/kernel/file_systems/bfs/Journal.h b/src/add-ons/kernel/file_systems/bfs/Journal.h index c128a96..9f3ce48 100644 --- a/src/add-ons/kernel/file_systems/bfs/Journal.h +++ b/src/add-ons/kernel/file_systems/bfs/Journal.h @@ -41,6 +41,8 @@ public: inline uint32 FreeLogBlocks() const; + status_t MoveLog(block_run newLog); + #ifdef BFS_DEBUGGER_COMMANDS void Dump(); #endif ############################################################################ Commit: 3fc608f4888f296f53393a93fbf3150458f97606 Author: ahenriksson <sausageboy@xxxxxxxxx> Date: Tue Jul 10 12:04:44 2012 UTC Added Reinitialize() to BlockAllocator ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp index e0c08b6..fc1f00c 100644 --- a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp +++ b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp @@ -611,6 +611,22 @@ BlockAllocator::InitializeAndClearBitmap(Transaction& transaction) status_t +BlockAllocator::Reinitialize() +{ + RecursiveLocker locker(fLock); + + // need to write back any pending changes to the block bitmap + // TODO: shall we read through the cache in _Initialize instead? + status_t status = fVolume->GetJournal(0)->FlushLogAndBlocks(); + if (status != B_OK) + return status; + + delete[] fGroups; + return Initialize(); +} + + +status_t BlockAllocator::_Initialize(BlockAllocator* allocator) { // The lock must already be held at this point diff --git a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.h b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.h index aa62881..c22707f 100644 --- a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.h +++ b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.h @@ -28,6 +28,7 @@ public: status_t Initialize(bool full = true); status_t InitializeAndClearBitmap(Transaction& transaction); + status_t Reinitialize(); void Uninitialize(); ############################################################################ Commit: 1b305da6c691eba86bb9d6b8539b30b199c4a2ca Author: ahenriksson <sausageboy@xxxxxxxxx> Date: Mon Jul 9 21:06:55 2012 UTC Added ResizeVisitor to handle the resizing ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/file_systems/bfs/Jamfile b/src/add-ons/kernel/file_systems/bfs/Jamfile index c48b36e..81a2a26 100644 --- a/src/add-ons/kernel/file_systems/bfs/Jamfile +++ b/src/add-ons/kernel/file_systems/bfs/Jamfile @@ -41,6 +41,7 @@ KernelAddon bfs : Inode.cpp Journal.cpp Query.cpp + ResizeVisitor.cpp Volume.cpp kernel_interface.cpp diff --git a/src/add-ons/kernel/file_systems/bfs/Journal.cpp b/src/add-ons/kernel/file_systems/bfs/Journal.cpp index 3284f63..4489a80 100644 --- a/src/add-ons/kernel/file_systems/bfs/Journal.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Journal.cpp @@ -1077,7 +1077,9 @@ status_t Journal::MoveLog(block_run newLog) { block_run oldLog = fVolume->Log(); - //block_run log_blocks; + + if (newLog == oldLog) + return B_OK; off_t newEnd = newLog.Start() + newLog.Length(); off_t oldEnd = oldLog.Start() + oldLog.Length(); diff --git a/src/add-ons/kernel/file_systems/bfs/ResizeVisitor.cpp b/src/add-ons/kernel/file_systems/bfs/ResizeVisitor.cpp new file mode 100644 index 0000000..d0a69f6 --- /dev/null +++ b/src/add-ons/kernel/file_systems/bfs/ResizeVisitor.cpp @@ -0,0 +1,406 @@ +#include "ResizeVisitor.h" + +#include "BPlusTree.h" +#include "Index.h" +#include "Inode.h" +#include "Journal.h" + + +status_t +ResizeVisitor::StartResize(off_t newSize) +{ + uint32 blockSize = GetVolume()->BlockSize(); + uint32 blockShift = GetVolume()->BlockShift(); + + // round up to a whole block + off_t newNumBlocks = (newSize + blockSize - 1) >> blockShift; + + off_t diskSize; + status_t status = _TemporaryGetDiskSize(diskSize); + if (status != B_OK) + return status; + + if (diskSize < (newNumBlocks << blockShift)) + return B_BAD_VALUE; + + off_t newLogSize = 2048; + if (newNumBlocks <= 20480) + newLogSize = 512; + if (newSize > 1LL * 1024 * 1024 * 1024) + newLogSize = 4096; + + fBitmapBlocks = (newNumBlocks + blockSize * 8 - 1) / (blockSize * 8); + + // the new size is limited by what we can fit into the first allocation + // group + off_t newReservedLength = 1 + fBitmapBlocks + newLogSize; + if (newReservedLength > (1UL << GetVolume()->AllocationGroupShift())) + return B_BAD_VALUE; + + fNewLog.SetTo(0, 1 + fBitmapBlocks, newLogSize); + + fBeginBlock = newReservedLength; + fEndBlock = newNumBlocks; + + if (newNumBlocks < GetVolume()->NumBlocks()) { + fShrinking = true; + } else { + fShrinking = false; + } // aTODO handle no resize needed / no data moving needed + //if (newReservedLength + //> GetVolume()->Log().Start() + GetVolume()->Log().Length()) { + + Start(VISIT_REGULAR | VISIT_INDICES | VISIT_REMOVED + /*| VISIT_ATTRIBUTE_DIRECTORIES can't move these yet*/); + + /* + if (newNumBlocks < GetVolume()->NumBlocks()) { + // shrinking + //move data to allowed + //do resize + //move journal(?) + } else if (newNumBlocks > GetVolume()->NumBlocks()) { + // growing + if (newReservedLength + > GetVolume()->Log().Start() + GetVolume()->Log().Length()) { + //move data out of the area we need as reserved + } + //move journal + //do resize + } else { + // perhaps we should inform the user that no resize happened? + } + */ + return B_OK; +} + + +status_t +ResizeVisitor::FinishResize() +{ + status_t status; + + if (fShrinking) { + status = _ResizeVolume(); + if (status != B_OK) + return status; + + status = GetVolume()->GetJournal(0)->MoveLog(fNewLog); + if (status != B_OK) + return status; + } else { + status = GetVolume()->GetJournal(0)->MoveLog(fNewLog); + if (status != B_OK) + return status; + + status = _ResizeVolume(); + if (status != B_OK) + return status; + } + return B_OK; +} + + +status_t +ResizeVisitor::VisitInode(Inode* inode, const char* treeName) +{ + status_t status; + off_t inodeBlock = inode->BlockNumber(); + + // start by moving the inode so we can place the stream close to it + // if possible + if (inodeBlock < fBeginBlock || inodeBlock >= fEndBlock) { + status = _MoveInode(inode); + if (status != B_OK) + return status; + } + + // move the stream if necessary + bool inRange; + status = inode->StreamInRange(fBeginBlock, fEndBlock, inRange); + if (status != B_OK) + return status; + + if (!inRange) { + status = inode->MoveStream(fBeginBlock, fEndBlock); + if (status != B_OK) + return status; + } + + return B_OK; +} + + +status_t +ResizeVisitor::OpenInodeFailed(status_t reason, ino_t id, Inode* parent, + char* treeName, TreeIterator* iterator) +{ + if (id < fBeginBlock || id >= fEndBlock) { + FATAL(("Could not open inode that needed to be moved at %" B_PRIdOFF + "\n", id)); + return reason; + } + + // if the inode is not outside the allowed area, we might be able to + // resize anyways + FATAL(("Could not open inode at %" B_PRIdOFF "\n", id)); + + if (fForce) + return B_OK; + + return reason; +} + + +status_t +ResizeVisitor::OpenBPlusTreeFailed(Inode* inode) +{ + FATAL(("Could not open b+tree from inode at %" B_PRIdOFF "\n", + inode->ID())); + + if (fForce) + return B_OK; + + return B_ERROR; +} + + +status_t +ResizeVisitor::TreeIterationFailed(status_t reason, Inode* parent) +{ + FATAL(("Tree iteration failed in parent at %" B_PRIdOFF "\n", + parent->ID())); + + if (fForce) + return B_OK; + + return reason; +} + + +status_t +ResizeVisitor::_ResizeVolume() +{ + status_t status; + BlockAllocator& allocator = GetVolume()->Allocator(); + + // check that the end blocks are free + if (fEndBlock < GetVolume()->NumBlocks()) { + status = allocator.CheckBlocks(fEndBlock, + GetVolume()->NumBlocks() - fEndBlock, false); + if (status != B_OK) + return status; + } + + // make sure we have space to resize the bitmap + if (1 + fBitmapBlocks > GetVolume()->Log().Start()) { + return B_ERROR; + } + + // clear bitmap blocks - aTODO maybe not use a transaction? + Transaction transaction(GetVolume(), 0); + + CachedBlock cached(GetVolume()); + for (off_t block = 1 + GetVolume()->NumBitmapBlocks(); + block < 1 + fBitmapBlocks; block++) { + uint8* buffer = cached.SetToWritable(transaction, block); + if (buffer == NULL) + return B_IO_ERROR; + + memset(buffer, 0, GetVolume()->BlockSize()); + } + cached.Unset(); + + status = transaction.Done(); + if (status != B_OK) + return status; + + // update superblock and volume information + disk_super_block& superBlock = GetVolume()->SuperBlock(); + + uint32 groupShift = GetVolume()->AllocationGroupShift(); + int32 blocksPerGroup = 1L << groupShift; + + // used to revert the volume super_block changes if we can't write them + // to disk, so we don't have to convert to and from host endianess + int64 oldNumBlocks = superBlock.num_blocks; + int32 oldNumAgs = superBlock.num_ags; + + superBlock.num_blocks = HOST_ENDIAN_TO_BFS_INT64(fEndBlock - fBeginBlock); + superBlock.num_ags = HOST_ENDIAN_TO_BFS_INT32( + (fBitmapBlocks + blocksPerGroup - 1) >> groupShift); + + status = GetVolume()->WriteSuperBlock(); + if (status != B_OK) { + superBlock.num_blocks = oldNumBlocks; + superBlock.num_ags = oldNumAgs; + return status; + } + + // reinitialize block allocator + status = GetVolume()->Allocator().Reinitialize(); + if (status != B_OK) + return status; + + return B_OK; +} + + +status_t +ResizeVisitor::_UpdateIndexReferences(Transaction& transaction, Inode* inode, + off_t newInodeID) +{ + // update user file attributes + AttributeIterator iterator(inode); + + char attributeName[B_FILE_NAME_LENGTH]; + size_t nameLength; + uint32 attributeType; + ino_t attributeID; + + uint8 key[BPLUSTREE_MAX_KEY_LENGTH]; + size_t keyLength; + + status_t status; + Index index(GetVolume()); + + while (iterator.GetNext(attributeName, &nameLength, &attributeType, + &attributeID) == B_OK) { + // ignore attribute if not in index + if (index.SetTo(attributeName) != B_OK) + continue; + + status = inode->ReadAttribute(attributeName, attributeType, 0, key, + &keyLength); + if (status != B_OK) + return status; + + status = index.UpdateInode(transaction, key, (uint16)keyLength, + inode->ID(), newInodeID); + if (status != B_OK) + return status; + } + + // update built-in attributes + if (inode->InNameIndex()) { + status = index.SetTo("name"); + if (status != B_OK) + return status; + + status = inode->GetName((char*)key, BPLUSTREE_MAX_KEY_LENGTH); + if (status != B_OK) + return status; + + status = index.UpdateInode(transaction, key, (uint16)strlen((char*)key), + inode->ID(), newInodeID); + if (status != B_OK) + return status; + } + if (inode->InSizeIndex()) { + status = index.SetTo("size"); + if (status != B_OK) + return status; + + off_t size = inode->Size(); + status = index.UpdateInode(transaction, (uint8*)&size, sizeof(int64), + inode->ID(), newInodeID); + if (status != B_OK) + return status; + } + if (inode->InLastModifiedIndex()) { + status = index.SetTo("last_modified"); + if (status != B_OK) + return status; + + off_t modified = inode->LastModified(); + status = index.UpdateInode(transaction, (uint8*)&modified, + sizeof(int64), inode->ID(), newInodeID); + if (status != B_OK) + return status; + } + return B_OK; + +} + + +status_t +ResizeVisitor::_UpdateParent(Transaction& transaction, Inode* inode, + off_t newInodeID) +{ + // get name of this inode + char name[B_FILE_NAME_LENGTH]; + status_t status = inode->GetName(name, B_FILE_NAME_LENGTH); + if (status != B_OK) + return status; + + // get Inode of parent + off_t parentBlock = GetVolume()->ToBlock(inode->Parent()); + + Vnode parentVnode(GetVolume(), parentBlock); + Inode* parent; + status = parentVnode.Get(&parent); + if (status != B_OK) + return status; + + // update inode id in parent + BPlusTree* tree = parent->Tree(); + return tree->Replace(transaction, (const uint8*)name, (uint16)strlen(name), + newInodeID); +} + + +status_t +ResizeVisitor::_MoveInode(Inode* inode) +{ + Transaction transaction(GetVolume(), 0); + + block_run run; + status_t status = GetVolume()->Allocator().AllocateBlocks(transaction, 0, 0, + 1, 1, run, fBeginBlock, fEndBlock); + // TODO: use a hint, maybe old position % new volume size? + // stuff that originally was in the beginning should probably + // stay close to it + if (status != B_OK) + return status; + + off_t newInodeID = GetVolume()->ToBlock(run); + + status = inode->Copy(transaction, newInodeID); + if (status != B_OK) + return status; + + status = _UpdateParent(transaction, inode, newInodeID); + if (status != B_OK) + return status; + + status = _UpdateParent(transaction, inode, newInodeID); + if (status != B_OK) + return status; + + status = GetVolume()->Free(transaction, inode->BlockRun()); + if (status != B_OK) + return status; + + return transaction.Done(); +} + + +status_t +ResizeVisitor::_TemporaryGetDiskSize(off_t& size) +{ + device_geometry geometry; + if (ioctl(GetVolume()->Device(), B_GET_GEOMETRY, &geometry) < 0) { + // maybe it's just a file + struct stat stat; + if (fstat(GetVolume()->Device(), &stat) < 0) + return B_ERROR; + + size = stat.st_size; + return B_OK; + } + + size = 1LL * geometry.head_count * geometry.cylinder_count + * geometry.sectors_per_track * geometry.bytes_per_sector; + + return B_OK; +} diff --git a/src/add-ons/kernel/file_systems/bfs/ResizeVisitor.h b/src/add-ons/kernel/file_systems/bfs/ResizeVisitor.h new file mode 100644 index 0000000..a8a93ff --- /dev/null +++ b/src/add-ons/kernel/file_systems/bfs/ResizeVisitor.h @@ -0,0 +1,58 @@ +#ifndef RESIZE_VISITOR_H +#define RESIZE_VISITOR_H + + +#include "system_dependencies.h" + +#include "FileSystemVisitor.h" + + +class Inode; +class Transaction; + + +class ResizeVisitor : public FileSystemVisitor { +public: + ResizeVisitor(Volume* volume) // aTODO tmp + : + FileSystemVisitor(volume), + fForce(false) {} + + status_t StartResize(off_t newSize); + status_t FinishResize(); + + virtual status_t VisitInode(Inode* inode, const char* treeName); + + virtual status_t OpenInodeFailed(status_t reason, ino_t id, + Inode* parent, char* treeName, + TreeIterator* iterator); + virtual status_t OpenBPlusTreeFailed(Inode* inode); + virtual status_t TreeIterationFailed(status_t reason, + Inode* parent); + +private: + status_t _ResizeVolume(); + + status_t _UpdateIndexReferences(Transaction& transaction, + Inode* inode, off_t newInodeID); + status_t _UpdateParent(Transaction& transaction, + Inode* inode, off_t newInodeID); + status_t _MoveInode(Inode* inode); + + status_t _TemporaryGetDiskSize(off_t& size); + +private: + bool fShrinking; + + off_t fBeginBlock; + off_t fEndBlock; + + off_t fBitmapBlocks; + + block_run fNewLog; + + bool fForce; +}; + + +#endif // RESIZE_VISITOR_H diff --git a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp index c44b04e..0af7618 100644 --- a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp @@ -614,148 +614,6 @@ bfs_get_vnode_name(fs_volume* _volume, fs_vnode* _node, char* buffer, static status_t -bfs_resize_update_index_references(Transaction& transaction, Inode* inode, - off_t newInodeID) -{ - // update user file attributes - AttributeIterator iterator(inode); - - char attributeName[B_FILE_NAME_LENGTH]; - size_t nameLength; - uint32 attributeType; - ino_t attributeID; - - uint8 key[BPLUSTREE_MAX_KEY_LENGTH]; - size_t keyLength; - - status_t status; - Index index(inode->GetVolume()); - - while (iterator.GetNext(attributeName, &nameLength, &attributeType, - &attributeID) == B_OK) { - // ignore attribute if not in index - if (index.SetTo(attributeName) != B_OK) - continue; - - status = inode->ReadAttribute(attributeName, attributeType, 0, key, - &keyLength); - if (status != B_OK) - return status; - - status = index.UpdateInode(transaction, key, (uint16)keyLength, - inode->ID(), newInodeID); - if (status != B_OK) - return status; - } - - // update built-in attributes - if (inode->InNameIndex()) { - status = index.SetTo("name"); - if (status != B_OK) - return status; - - status = inode->GetName((char*)key, BPLUSTREE_MAX_KEY_LENGTH); - if (status != B_OK) - return status; - - status = index.UpdateInode(transaction, key, (uint16)strlen((char*)key), - inode->ID(), newInodeID); - if (status != B_OK) - return status; - } - if (inode->InSizeIndex()) { - status = index.SetTo("size"); - if (status != B_OK) - return status; - - off_t size = inode->Size(); - status = index.UpdateInode(transaction, (uint8*)&size, sizeof(int64), - inode->ID(), newInodeID); - if (status != B_OK) - return status; - } - if (inode->InLastModifiedIndex()) { - status = index.SetTo("last_modified"); - if (status != B_OK) - return status; - - off_t modified = inode->LastModified(); - status = index.UpdateInode(transaction, (uint8*)&modified, - sizeof(int64), inode->ID(), newInodeID); - if (status != B_OK) - return status; - } - return B_OK; -} - - -static status_t -bfs_resize_update_parent(Transaction& transaction, Inode* inode, - off_t newInodeID) -{ - Volume* volume = inode->GetVolume(); - - // get name of this inode - char name[B_FILE_NAME_LENGTH]; - status_t status = inode->GetName(name, B_FILE_NAME_LENGTH); - if (status != B_OK) - return status; - - // get Inode of parent - block_run parentBlockRun = inode->Parent(); - off_t parentBlock = parentBlockRun.Start() - + (parentBlockRun.AllocationGroup() - << volume->AllocationGroupShift()); - - Vnode parentVnode(volume, parentBlock); - Inode* parent; - status = parentVnode.Get(&parent); - if (status != B_OK) - return status; - - // update inode id in parent - BPlusTree* tree = parent->Tree(); - return tree->Replace(transaction, (const uint8*)name, (uint16)strlen(name), - newInodeID); -} - - -static status_t -bfs_resize_move_inode(Volume* volume, Inode* inode) -{ - Transaction transaction(volume, 0 /* what's this? */); - - block_run run; - status_t status = volume->Allocator().AllocateBlocks(transaction, 0, 0, 1, - 1, run); - // we don't care about where we move at the moment - if (status != B_OK) - return status; - - off_t newInodeID = run.Start() - + (run.AllocationGroup() << volume->AllocationGroupShift()); - - status = inode->Copy(transaction, newInodeID); - if (status != B_OK) - return status; - - status = bfs_resize_update_parent(transaction, inode, newInodeID); - if (status != B_OK) - return status; - - status = bfs_resize_update_index_references(transaction, inode, newInodeID); - if (status != B_OK) - return status; - - status = volume->Free(transaction, inode->BlockRun()); - if (status != B_OK) - return status; - - return transaction.Done(); -} - - -static status_t bfs_ioctl(fs_volume* _volume, fs_vnode* _node, void* _cookie, uint32 cmd, void* buffer, size_t bufferLength) { @@ -861,10 +719,10 @@ bfs_ioctl(fs_volume* _volume, fs_vnode* _node, void* _cookie, uint32 cmd, case 56743: { // move inode - Vnode vnode(volume, 692); - Inode *inode; - vnode.Get(&inode); - bfs_resize_move_inode(volume, inode); + //Vnode vnode(volume, 692); + //Inode *inode; + //vnode.Get(&inode); + //bfs_resize_move_inode(volume, inode); return B_OK; } diff --git a/src/tools/bfs_shell/Jamfile b/src/tools/bfs_shell/Jamfile index 1a297e9..8ff483e 100644 --- a/src/tools/bfs_shell/Jamfile +++ b/src/tools/bfs_shell/Jamfile @@ -56,6 +56,7 @@ local bfsSource = Inode.cpp Journal.cpp Query.cpp + ResizeVisitor.cpp Volume.cpp kernel_interface.cpp ############################################################################ Commit: f96bcb2110c5de77d511e80f54268d8ecde10faf Author: ahenriksson <sausageboy@xxxxxxxxx> Date: Tue Jul 10 12:36:02 2012 UTC Added resize code invokation to kernel_interface.cpp ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/file_systems/bfs/Volume.h b/src/add-ons/kernel/file_systems/bfs/Volume.h index f7f3c35..729fe30 100644 --- a/src/add-ons/kernel/file_systems/bfs/Volume.h +++ b/src/add-ons/kernel/file_systems/bfs/Volume.h @@ -16,6 +16,7 @@ class CheckVisitor; class Journal; class Inode; class Query; +class ResizeVisitor; enum volume_flags { @@ -121,6 +122,10 @@ public: { return find_thread(NULL) == fCheckingThread; } CheckVisitor*& GetCheckVisitor() { return fCheckVisitor; } + // resizing + // TODO / aTODO: do we need SetResizingThread? + ResizeVisitor*& GetResizeVisitor() { return fResizeVisitor; } + // cache access status_t WriteSuperBlock(); status_t FlushDevice(); @@ -177,6 +182,8 @@ protected: thread_id fCheckingThread; CheckVisitor* fCheckVisitor; + ResizeVisitor* fResizeVisitor; + InodeList fRemovedInodes; }; diff --git a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp index 0af7618..58bb3f3 100644 --- a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp @@ -14,6 +14,7 @@ #include "Index.h" #include "BPlusTree.h" #include "Query.h" +#include "ResizeVisitor.h" #include "Attribute.h" #include "bfs_control.h" #include "bfs_disk_system.h" @@ -716,6 +717,34 @@ bfs_ioctl(fs_volume* _volume, fs_vnode* _node, void* _cookie, uint32 cmd, return volume->WriteSuperBlock(); } + case 56744: + { + // start + INFORM(("Resize start\n")); + ResizeVisitor*& resizer = volume->GetResizeVisitor(); + resizer = new ResizeVisitor(volume); + + return resizer->StartResize(7000*2048); + } + case 56745: + { + // finish + INFORM(("Resize finish\n")); + ResizeVisitor*& resizer = volume->GetResizeVisitor(); + + status_t status = resizer->FinishResize(); + delete resizer; + + return status; + } + case 56746: + { + // move next + INFORM(("Resize next\n")); + ResizeVisitor*& resizer = volume->GetResizeVisitor(); + + return resizer->Next(); + } case 56743: { // move inode