[haiku-commits] BRANCH ahenriksson-github.production - src/add-ons/kernel/file_systems/bfs

  • From: ahenriksson-github.production <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 10 Jul 2012 20:49:12 +0200 (CEST)

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


Other related posts: