[haiku-commits] BRANCH ahenriksson-github.production - in src: add-ons/kernel/file_systems/bfs tools/bfs_shell bin kits/storage/disk_device add-ons/disk_systems/intel

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

added 8 changesets to branch 'refs/remotes/ahenriksson-github/production'
old head: 8b54ad6ef747ef971a51e95c855fb6ec6e89e061
new head: 0e8f38ab332a8d0d43e9c03a07c076b9a8c3f759

----------------------------------------------------------------------------

a8f4a6b: Fix locking in resize code

be09956: Rework resize code to fit better with resizing infrastructure

34e2a64: Fix logic in disk_device regarding original and shadow values
  
  OriginalSize() etc. functions are added to access the BPartition's
  original values.
  
  I add Original* functions as needed by DiskDeviceJobGenerator, and the
  functions of the corresponding block in the header, since I don't
  really know if all of them make sense.

1e59a21: Fill in Resize() call in KFileSystem

b70891c: Resize support in the BFS disk system add-on

81840c6: Resize support in the intel partitioning disk system add-on

21578de: Add resizefs utility

0e8f38a: Add a resizing back door for use with bfs_shell
  
  The resizefs command in bfs_shell is changed to use this interface.

                                      [ ahenriksson <sausageboy@xxxxxxxxx> ]

----------------------------------------------------------------------------

21 files changed, 617 insertions(+), 480 deletions(-)
build/jam/HaikuImage                               |    4 +-
headers/private/storage/Partition.h                |   17 ++
src/add-ons/disk_systems/bfs/BFSAddOn.cpp          |   47 ++-
src/add-ons/disk_systems/bfs/BFSAddOn.h            |    9 +
.../disk_systems/intel/PartitionMapAddOn.cpp       |   60 ++++
src/add-ons/disk_systems/intel/PartitionMapAddOn.h |   10 +
.../kernel/file_systems/bfs/BlockAllocator.cpp     |   18 +-
.../kernel/file_systems/bfs/BlockAllocator.h       |    3 +-
src/add-ons/kernel/file_systems/bfs/Index.cpp      |    2 +
.../kernel/file_systems/bfs/ResizeVisitor.cpp      |  253 ++++++++--------
.../kernel/file_systems/bfs/ResizeVisitor.h        |   23 +-
src/add-ons/kernel/file_systems/bfs/Volume.cpp     |   25 +-
src/add-ons/kernel/file_systems/bfs/Volume.h       |    7 -
src/add-ons/kernel/file_systems/bfs/bfs_control.h  |   49 +--
.../kernel/file_systems/bfs/kernel_interface.cpp   |   92 +++---
src/bin/Jamfile                                    |    1 +
src/bin/resizefs.cpp                               |  132 ++++++++
.../storage/disk_device/DiskDeviceJobGenerator.cpp |   31 +-
src/kits/storage/disk_device/Partition.cpp         |  102 +++++++
.../kernel/disk_device_manager/KFileSystem.cpp     |   16 +-
src/tools/bfs_shell/command_resizefs.cpp           |  196 +-----------

############################################################################

Commit:      a8f4a6bb2af66dd1284dbb53e452acb6f74aa195

Author:      ahenriksson <sausageboy@xxxxxxxxx>
Date:        Tue Jul 31 13:03:13 2012 UTC

Fix locking in resize code

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp 
b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp
index 8e220f7..cf935d1 100644
--- a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp
+++ b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp
@@ -519,7 +519,7 @@ BlockAllocator::~BlockAllocator()
 
 
 status_t
-BlockAllocator::Initialize(bool full)
+BlockAllocator::Initialize(bool full, bool alreadyLocked)
 {
        fNumGroups = fVolume->AllocationGroups();
        fBlocksPerGroup = fVolume->SuperBlock().BlocksPerAllocationGroup();
@@ -532,8 +532,10 @@ BlockAllocator::Initialize(bool full)
        if (!full)
                return B_OK;
 
-       recursive_lock_lock(&fLock);
-               // the lock will be released by the _Initialize() method
+       if (!alreadyLocked) {
+               recursive_lock_lock(&fLock);
+                       // the lock will be released by the _Initialize() method
+       }
 
        thread_id id = 
spawn_kernel_thread((thread_func)BlockAllocator::_Initialize,
                "bfs block allocator", B_LOW_PRIORITY, this);
@@ -609,16 +611,19 @@ BlockAllocator::InitializeAndClearBitmap(Transaction& 
transaction)
 status_t
 BlockAllocator::Reinitialize()
 {
-       RecursiveLocker locker(fLock);
+       recursive_lock_lock(&fLock);
+               // the lock will be unlocked in the call to Initialize()
 
        // 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)
+       if (status != B_OK) {
+               recursive_lock_unlock(&fLock);
                return status;
+       }
 
        delete[] fGroups;
-       return Initialize();
+       return Initialize(true, true);
 }
 
 
@@ -1244,6 +1249,7 @@ BlockAllocator::CheckBlocks(off_t start, off_t length, 
bool allocated,
        uint32 blockOffset = start % fVolume->BlockSize();
 
        AllocationBlock cached(fVolume);
+       RecursiveLocker locker(fLock);
 
        while (groupBlock < fGroups[group].NumBlocks() && length > 0) {
                if (cached.SetTo(fGroups[group], groupBlock) != B_OK)
diff --git a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.h 
b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.h
index c22707f..cd494d2 100644
--- a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.h
+++ b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.h
@@ -26,7 +26,8 @@ public:
                                                        BlockAllocator(Volume* 
volume);
                                                        ~BlockAllocator();
 
-                       status_t                Initialize(bool full = true);
+                       status_t                Initialize(bool full = true,
+                                                               bool 
alreadyLocked = false);
                        status_t                
InitializeAndClearBitmap(Transaction& transaction);
                        status_t                Reinitialize();
 
diff --git a/src/add-ons/kernel/file_systems/bfs/Index.cpp 
b/src/add-ons/kernel/file_systems/bfs/Index.cpp
index c66a879..8da3996 100644
--- a/src/add-ons/kernel/file_systems/bfs/Index.cpp
+++ b/src/add-ons/kernel/file_systems/bfs/Index.cpp
@@ -389,6 +389,8 @@ status_t
 Index::UpdateInode(Transaction& transaction, const uint8* key, uint16 length,
        off_t oldInodeID, off_t newInodeID)
 {
+       Node()->WriteLockInTransaction(transaction);
+
        // remove node and insert it with the new id (we can't use
        // BPlusTree::Replace, as it doesn't handle trees where duplicates
        // are allowed)
diff --git a/src/add-ons/kernel/file_systems/bfs/ResizeVisitor.cpp 
b/src/add-ons/kernel/file_systems/bfs/ResizeVisitor.cpp
index 4156dfc..7c368bc 100644
--- a/src/add-ons/kernel/file_systems/bfs/ResizeVisitor.cpp
+++ b/src/add-ons/kernel/file_systems/bfs/ResizeVisitor.cpp
@@ -333,6 +333,8 @@ ResizeVisitor::_UpdateParent(Transaction& transaction, 
Inode* inode,
        if (status != B_OK)
                return status;
 
+       parent->WriteLockInTransaction(transaction);
+
        // update inode id in parent
        if (inode->IsAttributeDirectory()) {
                parent->Attributes() = GetVolume()->ToBlockRun(newInodeID);
@@ -511,6 +513,8 @@ ResizeVisitor::_UpdateChildren(Transaction& transaction, 
Inode* inode,
                if (status != B_OK)
                        return status;
 
+               childInode->WriteLockInTransaction(transaction);
+
                childInode->Node().parent = GetVolume()->ToBlockRun(newInodeID);
                childInode->WriteBack(transaction);
 

############################################################################

Commit:      be09956f5ad17413e935f0a60798d46d88a5fd36

Author:      ahenriksson <sausageboy@xxxxxxxxx>
Date:        Mon Jul 23 17:49:29 2012 UTC

Rework resize code to fit better with resizing infrastructure

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/file_systems/bfs/ResizeVisitor.cpp 
b/src/add-ons/kernel/file_systems/bfs/ResizeVisitor.cpp
index 7c368bc..481615ed 100644
--- a/src/add-ons/kernel/file_systems/bfs/ResizeVisitor.cpp
+++ b/src/add-ons/kernel/file_systems/bfs/ResizeVisitor.cpp
@@ -22,148 +22,94 @@ ResizeVisitor::ResizeVisitor(Volume* volume)
 }
 
 
-void
-ResizeVisitor::StartResize()
+status_t
+ResizeVisitor::Resize(off_t size, disk_job_id job)
 {
-       _SetError(B_OK);
-
-       uint32 blockSize = GetVolume()->BlockSize();
-       uint32 blockShift = GetVolume()->BlockShift();
-
-       // fill in old values in the control
-       Control().stats.bitmap_blocks_old = GetVolume()->NumBitmapBlocks();
-       Control().stats.log_start_old = GetVolume()->Log().Start();
-       Control().stats.log_length_old = GetVolume()->Log().Length();
-
-       Control().stats.block_size = GetVolume()->BlockSize();
-
-       // calculate new values for the log and number of bitmap blocks
-       fNumBlocks = (Control().new_size + blockSize - 1) >> blockShift;
-               // round up to a whole block
-
-       uint16 logLength = 2048;
-       if (fNumBlocks <= 20480)
-               logLength = 512;
-       if (Control().new_size > 1LL * 1024 * 1024 * 1024)
-               logLength = 4096;
-
-       fBitmapBlocks = (fNumBlocks + blockSize * 8 - 1) / (blockSize * 8);
-       fNewLog.SetTo(0, 1 + fBitmapBlocks, logLength);
-
-       off_t reservedLength = 1 + fBitmapBlocks + logLength;
-
-       // fill in new values
-       Control().stats.bitmap_blocks_new = fBitmapBlocks;
-       Control().stats.log_start_new = 1 + fBitmapBlocks;
-       Control().stats.log_length_new = logLength;
-
+       _CalculateNewSizes(size);
 
-       // See if the resize is actually possible
-
-       // the new size is limited by what we can fit into the first allocation
-       // group
-       if (reservedLength > (1UL << GetVolume()->AllocationGroupShift())) {
-               _SetError(B_BAD_VALUE, BFS_SIZE_TOO_LARGE);
-               return;
-       }
-
-       status_t status = GetVolume()->UpdateDeviceSize();
-       if (status != B_OK) {
-               _SetError(status);
-               return;
-       }
+       status_t status = _IsResizePossible(size);
+       if (status != B_OK)
+               return status;
 
-       if (GetVolume()->DeviceSize() < (fNumBlocks << blockShift)) {
-               _SetError(B_BAD_VALUE, BFS_DISK_TOO_SMALL);
-               return;
+       if (fNumBlocks == GetVolume()->NumBlocks()) {
+               INFORM(("Resize: New size was equal to old.\n"));
+               return B_OK;
        }
 
-       if (GetVolume()->UsedBlocks() > fNumBlocks) {
-               _SetError(B_BAD_VALUE, BFS_NO_SPACE);
-               return;
-       }
-
-       // stop now if we're only checking out the effects of a resize
-       if (Control().flags & BFS_CHECK_RESIZE)
-               return;
-
        // make sure no unsynced transaction causes invalidated blocks to linger
        // in the block cache when we write data with write_pos
+       // TODO: how does this work when the file system is mounted?
        status = GetVolume()->GetJournal(0)->FlushLogAndBlocks();
        if (status != B_OK) {
-               _SetError(status);
-               return;
+               FATAL(("Resize: Failed to flush log!\n"));
+               return status;
        }
 
-       fBeginBlock = reservedLength;
-
-       if (fNumBlocks < GetVolume()->NumBlocks()) {
-               fShrinking = true;
-               fEndBlock = fNumBlocks;
-       } else {
-               fShrinking = false;
-               fEndBlock = GetVolume()->NumBlocks();
-       }
+       update_disk_device_job_progress(job, 0.0);
 
        Start(VISIT_REGULAR | VISIT_INDICES | VISIT_REMOVED
                | VISIT_ATTRIBUTE_DIRECTORIES);
-}
 
+       // move file system data out of the way
+       while (true) {
+               fError = false;
 
-void
-ResizeVisitor::FinishResize()
-{
-       if (Control().status != B_OK) {
-               _SetError(B_OK);
-               return;
-       }
+               status = Next();
+               if (fError)
+                       return status;
 
-       _SetError(B_OK);
-       status_t status;
+               if (status == B_ENTRY_NOT_FOUND)
+                       break;
+       }
 
+       // move log and change file system size in the superblock
        if (fShrinking) {
                status = _ResizeVolume();
                if (status != B_OK) {
-                       _SetError(status, BFS_CHANGE_SIZE_FAILED);
-                       return;
+                       FATAL(("Resize: Failed to update file system size!\n"));
+                       return status;
                }
 
                status = GetVolume()->GetJournal(0)->MoveLog(fNewLog);
                if (status != B_OK) {
-                       _SetError(status, BFS_MOVE_LOG_FAILED);
-                       return;
+                       FATAL(("Resize: Failed to move the log area!\n"));
+                       return status;
                }
        } else {
                status = GetVolume()->GetJournal(0)->MoveLog(fNewLog);
                if (status != B_OK) {
-                       _SetError(status, BFS_MOVE_LOG_FAILED);
-                       return;
+                       FATAL(("Resize: Failed to move the log area!\n"));
+                       return status;
                }
 
                status = _ResizeVolume();
                if (status != B_OK) {
-                       _SetError(status, BFS_CHANGE_SIZE_FAILED);
-                       return;
+                       FATAL(("Resize: Failed to update file system size!\n"));
+                       return status;
                }
        }
+
+       update_disk_device_job_progress(job, 1.0);
+       return B_OK;
 }
 
 
 status_t
 ResizeVisitor::VisitInode(Inode* inode, const char* treeName)
 {
-       Control().inode = inode->ID();
+       // get the name so we can show it to the user if something goes wrong
+       // TODO: we don't really have to do this for every inode we visit
+       char name[B_FILE_NAME_LENGTH];
        
-       // set name
        if (treeName == NULL) {
-               if (inode->GetName(Control().name) < B_OK) {
+               if (inode->GetName(name) < B_OK) {
                        if (inode->IsContainer())
-                               strcpy(Control().name, "(dir has no name)");
+                               strcpy(name, "(dir has no name)");
                        else
-                               strcpy(Control().name, "(node has no name)");
+                               strcpy(name, "(node has no name)");
                }
        } else
-               strcpy(Control().name, treeName);
+               strcpy(name, treeName);
 
        WriteLocker writeLocker(inode->Lock());
 
@@ -181,7 +127,9 @@ ResizeVisitor::VisitInode(Inode* inode, const char* 
treeName)
                status = _MoveInode(inode, newInodeID, treeName);
                if (status != B_OK) {
                        mark_vnode_busy(GetVolume()->FSVolume(), inode->ID(), 
false);
-                       _SetError(status, BFS_MOVE_INODE_FAILED);
+                       FATAL(("Resize: Failed to move inode %" B_PRIdINO
+                               ", \"%s\"!\n", inode->ID(), name));
+                       fError = true;
                        return status;
                }
 
@@ -189,7 +137,9 @@ ResizeVisitor::VisitInode(Inode* inode, const char* 
treeName)
                        newInodeID);
                if (status != B_OK) {
                        mark_vnode_busy(GetVolume()->FSVolume(), inode->ID(), 
false);
-                       _SetError(status, BFS_MOVE_INODE_FAILED);
+                       FATAL(("Resize: Failed to change ID in vnode, inode %" 
B_PRIdINO
+                               ", \"%s\"!\n", inode->ID(), name));
+                       fError = true;
                        return status;
                }
 
@@ -197,25 +147,26 @@ ResizeVisitor::VisitInode(Inode* inode, const char* 
treeName)
 
                // accessing the inode with the new ID
                mark_vnode_busy(GetVolume()->FSVolume(), inode->ID(), false);
-
-               Control().stats.inodes_moved++;
        }
 
        // move the stream if necessary
        bool inRange;
        status = inode->StreamInRange(fBeginBlock, fEndBlock, inRange);
        if (status != B_OK) {
-               _SetError(status, BFS_MOVE_STREAM_FAILED);
+               FATAL(("Resize: Failed to check file stream, inode %" B_PRIdINO
+                       ", \"%s\"!\n", inode->ID(), name));
+               fError = true;
                return status;
        }
 
        if (!inRange) {
                status = inode->MoveStream(fBeginBlock, fEndBlock);
                if (status != B_OK) {
-                       _SetError(status, BFS_MOVE_STREAM_FAILED);
+                       FATAL(("Resize: Failed to move file stream, inode %" 
B_PRIdINO
+                               ", \"%s\"!\n", inode->ID(), name));
+                       fError = true;
                        return status;
                }
-               Control().stats.streams_moved++;
        }
 
        return B_OK;
@@ -228,7 +179,7 @@ ResizeVisitor::OpenInodeFailed(status_t reason, ino_t id, 
Inode* parent,
 {
        FATAL(("Could not open inode at %" B_PRIdOFF "\n", id));
 
-       _SetError(reason);
+       fError = true;
        return reason;
 }
 
@@ -239,7 +190,7 @@ ResizeVisitor::OpenBPlusTreeFailed(Inode* inode)
        FATAL(("Could not open b+tree from inode at %" B_PRIdOFF "\n",
                inode->ID()));
 
-       _SetError(B_ERROR);
+       fError = true;
        return B_ERROR;
 }
 
@@ -250,11 +201,73 @@ ResizeVisitor::TreeIterationFailed(status_t reason, 
Inode* parent)
        FATAL(("Tree iteration failed in parent at %" B_PRIdOFF "\n",
                parent->ID()));
 
-       _SetError(reason);
+       fError = true;
        return reason;
 }
 
 
+void
+ResizeVisitor::_CalculateNewSizes(off_t size)
+{
+       uint32 blockSize = GetVolume()->BlockSize();
+       uint32 blockShift = GetVolume()->BlockShift();
+
+       fNumBlocks = size >> blockShift;
+
+       fBitmapBlocks = (fNumBlocks + blockSize * 8 - 1) / (blockSize * 8);
+               // divide total number of blocks by the number of bits in a 
bitmap
+               // block, rounding up
+
+       off_t logLength = Volume::CalculateLogSize(fNumBlocks, size);
+
+       fNewLog.SetTo(0, 1 + fBitmapBlocks, logLength);
+       fReservedLength = 1 + fBitmapBlocks + logLength;
+
+       fBeginBlock = fReservedLength;
+
+       if (fNumBlocks < GetVolume()->NumBlocks()) {
+               fShrinking = true;
+               fEndBlock = fNumBlocks;
+       } else {
+               fShrinking = false;
+               fEndBlock = GetVolume()->NumBlocks();
+       }
+}
+
+
+status_t
+ResizeVisitor::_IsResizePossible(off_t size)
+{
+       if ((size % GetVolume()->BlockSize()) != 0) {
+               FATAL(("Resize: New size not multiple of block size!\n"));
+               return B_BAD_VALUE;
+       }
+
+       // the new size is limited by what we can fit into the first allocation
+       // group
+       if (fReservedLength > (1UL << GetVolume()->AllocationGroupShift())) {
+               FATAL(("Resize: Reserved area is too large for allocation 
group!\n"));
+               return B_BAD_VALUE;
+       }
+
+       status_t status = GetVolume()->UpdateDeviceSize();
+       if (status != B_OK)
+               return status;
+
+       if (GetVolume()->DeviceSize() < size) {
+               FATAL(("Resize: Device too small for new size\n"));
+               return B_BAD_VALUE;
+       }
+
+       if (GetVolume()->UsedBlocks() > fNumBlocks) {
+               FATAL(("Resize: Not enough free space for resize!\n"));
+               return B_BAD_VALUE;
+       }
+
+       return B_OK;
+}
+
+
 status_t
 ResizeVisitor::_ResizeVolume()
 {
@@ -268,11 +281,11 @@ ResizeVisitor::_ResizeVolume()
                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);
 
@@ -290,7 +303,7 @@ ResizeVisitor::_ResizeVolume()
        status = transaction.Done();
        if (status != B_OK)
                return status;
-       
+
        // update superblock and volume information
        disk_super_block& superBlock = GetVolume()->SuperBlock();
 
@@ -629,23 +642,3 @@ ResizeVisitor::_MoveInode(Inode* inode, off_t& newInodeID, 
const char* treeName)
 
        return B_OK;
 }
-
-
-bool
-ResizeVisitor::_ControlValid()
-{
-       if (Control().magic != BFS_IOCTL_RESIZE_MAGIC) {
-               FATAL(("invalid resize_control!\n"));
-               return false;
-       }
-
-       return true;
-}
-
-
-void
-ResizeVisitor::_SetError(status_t status, uint32 failurePoint)
-{
-       Control().status = status;
-       Control().failure_point = failurePoint;
-}
diff --git a/src/add-ons/kernel/file_systems/bfs/ResizeVisitor.h 
b/src/add-ons/kernel/file_systems/bfs/ResizeVisitor.h
index 246205f..41f5535 100644
--- a/src/add-ons/kernel/file_systems/bfs/ResizeVisitor.h
+++ b/src/add-ons/kernel/file_systems/bfs/ResizeVisitor.h
@@ -20,10 +20,7 @@ class ResizeVisitor : public FileSystemVisitor {
 public:
                                                                
ResizeVisitor(Volume* volume);
 
-       void                                            StartResize();
-       void                                            FinishResize();
-
-       resize_control&                         Control() { return fControl; }
+                       status_t                        Resize(off_t size, 
disk_job_id job);
 
        virtual status_t                        VisitInode(Inode* inode, const 
char* treeName);
 
@@ -35,6 +32,8 @@ public:
                                                                        Inode* 
parent);
 
 private:
+                       void                            
_CalculateNewSizes(off_t size);
+                       status_t                        _IsResizePossible(off_t 
size);
                        status_t                        _ResizeVolume();
 
                        // moving the inode
@@ -56,23 +55,19 @@ private:
                        status_t                        _MoveInode(Inode* 
inode, off_t& newInodeID,
                                                                        const 
char* treeName);
 
-                       bool                            _ControlValid();
-
-                       void                            _SetError(status_t 
status,
-                                                                       uint32 
failurePoint = BFS_OTHER_ERROR);
-
 private:
-                       resize_control          fControl;
-                       bool                            fShrinking;
+                       bool                            fError;
 
                        off_t                           fNumBlocks;
+                       off_t                           fBitmapBlocks;
+                       off_t                           fReservedLength;
+
+                       block_run                       fNewLog;
 
                        off_t                           fBeginBlock;
                        off_t                           fEndBlock;
 
-                       off_t                           fBitmapBlocks;
-
-                       block_run                       fNewLog;
+                       bool                            fShrinking;
 };
 
 
diff --git a/src/add-ons/kernel/file_systems/bfs/Volume.cpp 
b/src/add-ons/kernel/file_systems/bfs/Volume.cpp
index a212e8b..a04eaab 100644
--- a/src/add-ons/kernel/file_systems/bfs/Volume.cpp
+++ b/src/add-ons/kernel/file_systems/bfs/Volume.cpp
@@ -251,8 +251,7 @@ Volume::Volume(fs_volume* volume)
        fDirtyCachedBlocks(0),
        fFlags(0),
        fCheckingThread(-1),
-       fCheckVisitor(NULL),
-       fResizeVisitor(NULL)
+       fCheckVisitor(NULL)
 {
        mutex_init(&fLock, "bfs volume");
        mutex_init(&fQueryLock, "bfs queries");
@@ -640,28 +639,6 @@ Volume::DeleteCheckVisitor()
 }
 
 
-status_t
-Volume::CreateResizeVisitor()
-{
-       if (fResizeVisitor != NULL)
-               return B_BUSY;
-
-       fResizeVisitor = new(std::nothrow) ::ResizeVisitor(this);
-       if (fResizeVisitor == NULL)
-               return B_NO_MEMORY;
-
-       return B_OK;
-}
-
-
-void
-Volume::DeleteResizeVisitor()
-{
-       delete fResizeVisitor;
-       fResizeVisitor = NULL;
-}
-
-
 //     #pragma mark - Disk scanning and initialization
 
 
diff --git a/src/add-ons/kernel/file_systems/bfs/Volume.h 
b/src/add-ons/kernel/file_systems/bfs/Volume.h
index 94972f6..6e877b7 100644
--- a/src/add-ons/kernel/file_systems/bfs/Volume.h
+++ b/src/add-ons/kernel/file_systems/bfs/Volume.h
@@ -127,11 +127,6 @@ public:
                        void                    DeleteCheckVisitor();
                        ::CheckVisitor* CheckVisitor() { return fCheckVisitor; }
 
-                       // resizing
-                       status_t                CreateResizeVisitor();
-                       void                    DeleteResizeVisitor();
-                       ::ResizeVisitor* ResizeVisitor() { return 
fResizeVisitor; }
-
                        // cache access
                        status_t                WriteSuperBlock();
                        status_t                FlushDevice();
@@ -190,8 +185,6 @@ protected:
                        thread_id               fCheckingThread;
                        ::CheckVisitor* fCheckVisitor;
 
-                       ::ResizeVisitor* fResizeVisitor;
-
                        InodeList               fRemovedInodes;
 };
 
diff --git a/src/add-ons/kernel/file_systems/bfs/bfs_control.h 
b/src/add-ons/kernel/file_systems/bfs/bfs_control.h
index 186002a..d5b859e 100644
--- a/src/add-ons/kernel/file_systems/bfs/bfs_control.h
+++ b/src/add-ons/kernel/file_systems/bfs/bfs_control.h
@@ -1,6 +1,5 @@
 /*
  * Copyright 2001-2012, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx
- * Copyright 2012, Andreas Henriksson, sausageboy@xxxxxxxxx
  * This file may be used under the terms of the MIT License.
  */
 #ifndef BFS_CONTROL_H
@@ -100,52 +99,4 @@ struct check_control {
 #define BFS_IOCTL_CHECK_MAGIC  'BChk'
 
 
-/* ioctls to resize the file system
- * usage is analogous to that of "chkbfs" above
- */
-#define BFS_IOCTL_START_RESIZE         14205
-#define BFS_IOCTL_FINISH_RESIZE                14206
-#define BFS_IOCTL_MOVE_NEXT_NODE       14207
-
-struct resize_control {
-       uint32          magic;
-       uint32          flags;
-       uint64          new_size;
-       char            name[B_FILE_NAME_LENGTH];
-       ino_t           inode;
-       uint32          failure_point;
-       struct {
-               uint64  inodes_moved;
-               uint64  streams_moved;
-
-               uint16  bitmap_blocks_new;
-               uint16  log_start_new;
-               uint16  log_length_new;
-
-               uint16  bitmap_blocks_old;
-               uint16  log_start_old;
-               uint16  log_length_old;
-
-               uint32  block_size;
-       } stats;
-       status_t        status;
-};
-
-/* resize flags */
-#define BFS_CHECK_RESIZE               1
-
-/* resize points of failure */
-#define BFS_OTHER_ERROR                        1
-#define BFS_SIZE_TOO_LARGE             2
-#define BFS_DISK_TOO_SMALL             3
-#define BFS_NO_SPACE                   4
-#define BFS_MOVE_LOG_FAILED            5
-#define BFS_MOVE_INODE_FAILED  6
-#define BFS_MOVE_STREAM_FAILED 7
-#define BFS_CHANGE_SIZE_FAILED 8
-
-/* magic resize constant */
-#define BFS_IOCTL_RESIZE_MAGIC 'BRsz'
-
-
 #endif /* BFS_CONTROL_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 e6aab3c..24f43c9 100644
--- a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp
+++ b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp
@@ -720,60 +720,6 @@ bfs_ioctl(fs_volume* _volume, fs_vnode* _node, void* 
_cookie, uint32 cmd,
 
                        return volume->WriteSuperBlock();
                }
-               case BFS_IOCTL_START_RESIZE:
-               {
-                       status_t status = volume->CreateResizeVisitor();
-                       if (status != B_OK)
-                               return status;
-
-                       ResizeVisitor* resizer = volume->ResizeVisitor();
-
-                       if (user_memcpy(&resizer->Control(), buffer,
-                                       sizeof(resize_control)) != B_OK) {
-                               return B_BAD_ADDRESS;
-                       }
-
-                       resizer->StartResize();
-
-                       status = user_memcpy(buffer, &resizer->Control(),
-                               sizeof(resize_control));
-
-                       if (resizer->Control().status != B_OK
-                               || (resizer->Control().flags & 
BFS_CHECK_RESIZE)) {
-                               volume->DeleteResizeVisitor();
-                       }
-
-                       return status;
-               }
-               case BFS_IOCTL_FINISH_RESIZE:
-               {
-                       ResizeVisitor* resizer = volume->ResizeVisitor();
-                       if (resizer == NULL)
-                               return B_NO_INIT;
-
-                       resizer->FinishResize();
-
-                       status_t status = user_memcpy(buffer, 
&resizer->Control(),
-                               sizeof(resize_control));
-
-                       volume->DeleteResizeVisitor();
-                       return status;
-               }
-               case BFS_IOCTL_MOVE_NEXT_NODE:
-               {
-                       ResizeVisitor* resizer = volume->ResizeVisitor();
-                       if (resizer == NULL)
-                               return B_NO_INIT;
-
-                       if (resizer->Next() == B_ENTRY_NOT_FOUND) {
-                               // are we really done, or is this an error?
-                               if (resizer->Control().status == B_OK)
-                                       return B_ENTRY_NOT_FOUND;
-                       }
-
-                       return user_memcpy(buffer, &resizer->Control(),
-                               sizeof(resize_control));
-               }
 
 #ifdef DEBUG_FRAGMENTER
                case 56741:
@@ -2318,13 +2264,43 @@ static uint32
 bfs_get_supported_operations(partition_data* partition, uint32 mask)
 {
        // TODO: We should at least check the partition size.
-       return B_DISK_SYSTEM_SUPPORTS_INITIALIZING
+       return B_DISK_SYSTEM_SUPPORTS_RESIZING_WHILE_MOUNTED
+               | B_DISK_SYSTEM_SUPPORTS_INITIALIZING
                | B_DISK_SYSTEM_SUPPORTS_CONTENT_NAME
                | B_DISK_SYSTEM_SUPPORTS_WRITING;
 }
 
 
 static status_t
+bfs_resize(int fd, partition_id partitionID, off_t size, disk_job_id job)
+{
+#ifndef BFS_SHELL
+       // get Volume pointer from partitionID
+       if (read_lock_disk_device(partitionID) == NULL)
+               return B_ERROR;
+
+       partition_data* partition = get_partition(partitionID);
+       read_unlock_disk_device(partitionID);
+
+       if (partition == NULL)
+               return B_ERROR;
+
+       Volume* volume = (Volume*)partition->mount_cookie;
+       if (volume == NULL)
+               return B_ERROR;
+
+       // do the resize
+       ResizeVisitor resizer(volume);
+       return resizer.Resize(size, job);
+#else
+       // fs_shell can't use this interface as it doesn't have the
+       // partion_data concept
+       return B_ERROR;
+#endif
+}
+
+
+static status_t
 bfs_initialize(int fd, partition_id partitionID, const char* name,
        const char* parameterString, off_t /*partitionSize*/, disk_job_id job)
 {
@@ -2548,7 +2524,7 @@ static file_system_module_info sBeFileSystem = {
 //     | B_DISK_SYSTEM_SUPPORTS_DEFRAGMENTING_WHILE_MOUNTED
 //     | B_DISK_SYSTEM_SUPPORTS_CHECKING_WHILE_MOUNTED
 //     | B_DISK_SYSTEM_SUPPORTS_REPAIRING_WHILE_MOUNTED
-//     | B_DISK_SYSTEM_SUPPORTS_RESIZING_WHILE_MOUNTED
+       | B_DISK_SYSTEM_SUPPORTS_RESIZING_WHILE_MOUNTED
 //     | B_DISK_SYSTEM_SUPPORTS_MOVING_WHILE_MOUNTED
 //     | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_NAME_WHILE_MOUNTED
 //     | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_PARAMETERS_WHILE_MOUNTED
@@ -2578,7 +2554,7 @@ static file_system_module_info sBeFileSystem = {
        /* writing */
        NULL,   // defragment
        NULL,   // repair
-       NULL,   // resize
+       bfs_resize,
        NULL,   // move
        NULL,   // set_content_name
        NULL,   // set_content_parameters

############################################################################

Commit:      34e2a649b5c64cf263b5bc620407c17b59d76a23

Author:      ahenriksson <sausageboy@xxxxxxxxx>
Date:        Tue Jul 31 15:35:26 2012 UTC

Fix logic in disk_device regarding original and shadow values

OriginalSize() etc. functions are added to access the BPartition's
original values.

I add Original* functions as needed by DiskDeviceJobGenerator, and the
functions of the corresponding block in the header, since I don't
really know if all of them make sense.

----------------------------------------------------------------------------

diff --git a/headers/private/storage/Partition.h 
b/headers/private/storage/Partition.h
index 2f897c6..5a22de6 100644
--- a/headers/private/storage/Partition.h
+++ b/headers/private/storage/Partition.h
@@ -73,6 +73,23 @@ public:
                                                                        const 
char* parameters = NULL);
                        status_t                        Unmount(uint32 
unmountFlags = 0);
 
+       // Information about the unmodified partition
+
+                       off_t                           OriginalOffset() const;
+                       off_t                           OriginalSize() const;
+                       off_t                           OriginalContentSize() 
const;
+                       uint32                          OriginalBlockSize() 
const;
+                       int32                           OriginalIndex() const;
+                       uint32                          OriginalStatus() const;
+
+                       const char*                     OriginalName() const;
+                       const char*                     OriginalContentName() 
const;
+                       const char*                     OriginalType() const;
+                       const char*                     OriginalContentType() 
const;
+                       partition_id            OriginalID() const;
+                       const char*                     OriginalParameters() 
const;
+                       const char*                     
OriginalContentParameters() const;
+
        // Hierarchy Info
 
                        BDiskDevice*            Device() const;
diff --git a/src/kits/storage/disk_device/DiskDeviceJobGenerator.cpp 
b/src/kits/storage/disk_device/DiskDeviceJobGenerator.cpp
index 3b46f88..9c26163 100644
--- a/src/kits/storage/disk_device/DiskDeviceJobGenerator.cpp
+++ b/src/kits/storage/disk_device/DiskDeviceJobGenerator.cpp
@@ -193,7 +193,7 @@ DiskDeviceJobGenerator::_GenerateCleanupJobs(BPartition* 
partition)
 // all descendants of a partition to be uninitialized or removed.
        if (BMutablePartition* shadow = _GetMutablePartition(partition)) {
                if ((shadow->ChangeFlags() & B_PARTITION_CHANGED_INITIALIZATION)
-                       && partition->fPartitionData->content_type) {
+                       && partition->OriginalContentType()) {
                        // partition changes initialization
                        status_t error = _GenerateUninitializeJob(partition);
                        if (error != B_OK)
@@ -224,12 +224,12 @@ 
DiskDeviceJobGenerator::_GeneratePlacementJobs(BPartition* partition)
                // Don't resize/move partitions that have an unrecognized 
contents.
                // They must have been uninitialized before.
                if (shadow->Status() == B_PARTITION_UNRECOGNIZED
-                       && (shadow->Size() != partition->Size()
-                               || shadow->Offset() != partition->Offset())) {
+                       && (shadow->Size() != partition->OriginalSize()
+                               || shadow->Offset() != 
partition->OriginalOffset())) {
                        return B_ERROR;
                }
 
-               if (shadow->Size() > partition->Size()) {
+               if (shadow->Size() > partition->OriginalSize()) {
                        // size grows: resize first
                        status_t error = _GenerateResizeJob(partition);
                        if (error != B_OK)
@@ -241,7 +241,7 @@ DiskDeviceJobGenerator::_GeneratePlacementJobs(BPartition* 
partition)
                if (error != B_OK)
                        return error;
 
-               if (shadow->Size() < partition->Size()) {
+               if (shadow->Size() < partition->OriginalSize()) {
                        // size shrinks: resize now
                        status_t error = _GenerateResizeJob(partition);
                        if (error != B_OK)
@@ -287,7 +287,7 @@ 
DiskDeviceJobGenerator::_GenerateChildPlacementJobs(BPartition* partition)
                                moveBack++;
 
                        // resize the child, if it shall shrink
-                       if (childShadow->Size() < child->Size()) {
+                       if (childShadow->Size() < child->OriginalSize()) {
                                status_t error = _GeneratePlacementJobs(child);
                                if (error != B_OK)
                                        return error;
@@ -354,7 +354,7 @@ 
DiskDeviceJobGenerator::_GenerateChildPlacementJobs(BPartition* partition)
        // their descendants
        for (int32 i = 0; BPartition* child = partition->_ChildAt(i); i++) {
                if (BMutablePartition* childShadow = 
_GetMutablePartition(child)) {
-                       if (childShadow->Size() >= child->Size()) {
+                       if (childShadow->Size() >= child->OriginalSize()) {
                                status_t error = _GeneratePlacementJobs(child);
                                if (error != B_OK)
                                        return error;
@@ -371,13 +371,11 @@ status_t
 DiskDeviceJobGenerator::_GenerateRemainingJobs(BPartition* parent,
        BPartition* partition)
 {
-       user_partition_data* partitionData = partition->fPartitionData;
-
        uint32 changeFlags
                = partition->fDelegate->MutablePartition()->ChangeFlags();
 
        // create the partition, if not existing yet
-       if (!partitionData) {
+       if (!partition->fPartitionData) {
                if (!parent)
                        return B_BAD_VALUE;
 
@@ -389,7 +387,7 @@ DiskDeviceJobGenerator::_GenerateRemainingJobs(BPartition* 
parent,
 
                // name
                if ((changeFlags & B_PARTITION_CHANGED_NAME)
-                       || compare_string(partition->Name(), 
partitionData->name)) {
+                       || compare_string(partition->Name(), 
partition->OriginalName())) {
                        if (!parent)
                                return B_BAD_VALUE;
 
@@ -400,7 +398,7 @@ DiskDeviceJobGenerator::_GenerateRemainingJobs(BPartition* 
parent,
 
                // type
                if ((changeFlags & B_PARTITION_CHANGED_TYPE)
-                       || compare_string(partition->Type(), 
partitionData->type)) {
+                       || compare_string(partition->Type(), 
partition->OriginalType())) {
                        if (!parent)
                                return B_BAD_VALUE;
 
@@ -412,7 +410,7 @@ DiskDeviceJobGenerator::_GenerateRemainingJobs(BPartition* 
parent,
                // parameters
                if ((changeFlags & B_PARTITION_CHANGED_PARAMETERS)
                        || compare_string(partition->Parameters(),
-                               partitionData->parameters)) {
+                               partition->OriginalParameters())) {
                        if (!parent)
                                return B_BAD_VALUE;
 
@@ -434,7 +432,7 @@ DiskDeviceJobGenerator::_GenerateRemainingJobs(BPartition* 
parent,
                        // content name
                        if ((changeFlags & B_PARTITION_CHANGED_NAME)
                                || compare_string(partition->ContentName(),
-                                       partitionData->content_name)) {
+                                       partition->OriginalContentName())) {
                                status_t error = 
_GenerateSetContentNameJob(partition);
                                if (error != B_OK)
                                        return error;
@@ -443,7 +441,7 @@ DiskDeviceJobGenerator::_GenerateRemainingJobs(BPartition* 
parent,
                        // content parameters
                        if ((changeFlags & B_PARTITION_CHANGED_PARAMETERS)
                                || 
compare_string(partition->ContentParameters(),
-                                       partitionData->content_parameters)) {
+                                       
partition->OriginalContentParameters())) {
                                status_t error = 
_GenerateSetContentParametersJob(partition);
                                if (error != B_OK)
                                        return error;
@@ -669,6 +667,9 @@ DiskDeviceJobGenerator::_GenerateResizeJob(BPartition* 
partition)
        if (error != B_OK)
                return error;
 
+       TRACE("DiskDeviceJobGenerator::GenerateResizeJob() - 4\n");
+       TRACE("DiskDeviceJobGenerator::GenerateResizeJob() - 5\n");
+
        return _AddJob(new(nothrow) ResizeJob(parentReference, reference,
                partition->Size(), partition->ContentSize()));
 }
diff --git a/src/kits/storage/disk_device/Partition.cpp 
b/src/kits/storage/disk_device/Partition.cpp
index 8bd5fea..518956f 100644
--- a/src/kits/storage/disk_device/Partition.cpp
+++ b/src/kits/storage/disk_device/Partition.cpp
@@ -642,6 +642,108 @@ BPartition::Unmount(uint32 unmountFlags)
 }
 
 
+// OriginalOffset
+off_t
+BPartition::OriginalOffset() const
+{
+       return fPartitionData->offset;
+}
+
+
+// OriginalSize
+off_t
+BPartition::OriginalSize() const
+{
+       return fPartitionData->size;
+}
+
+
+// OriginalContentSize
+off_t
+BPartition::OriginalContentSize() const
+{
+       return fPartitionData->content_size;
+}
+
+// OriginalBlockSize
+uint32
+BPartition::OriginalBlockSize() const
+{
+       return fPartitionData->block_size;
+}
+
+
+// OriginalIndex
+int32
+BPartition::OriginalIndex() const
+{
+       return fPartitionData->index;
+}
+
+
+// OriginalStatus
+uint32
+BPartition::OriginalStatus() const
+{
+       return fPartitionData->status;
+}
+
+// OriginalName
+const char*
+BPartition::OriginalName() const
+{
+       return fPartitionData->name;
+}
+
+
+// OriginalContentName
+const char*
+BPartition::OriginalContentName() const
+{
+       return fPartitionData->content_name;
+}
+
+
+// OriginalType
+const char*
+BPartition::OriginalType() const
+{
+       return fPartitionData->type;
+}
+
+
+// OriginalContentType
+const char*
+BPartition::OriginalContentType() const
+{
+       return fPartitionData->content_type;
+}
+
+
+// OriginalID
+int32
+BPartition::OriginalID() const
+{
+       return fPartitionData->id;
+}
+
+
+// OriginalParameters
+const char*
+BPartition::OriginalParameters() const
+{
+       return fPartitionData->parameters;
+}
+
+
+// OriginalContentParameters
+const char*
+BPartition::OriginalContentParameters() const
+{
+       return fPartitionData->content_parameters;
+}
+
+
 // Device
 /*!    \brief Returns the device this partition resides on.
        \return The device this partition resides on.

############################################################################

Commit:      1e59a21a0171b41def0da092596856fd3a5242a7

Author:      ahenriksson <sausageboy@xxxxxxxxx>
Date:        Tue Jul 31 10:42:58 2012 UTC

Fill in Resize() call in KFileSystem

----------------------------------------------------------------------------

diff --git a/src/system/kernel/disk_device_manager/KFileSystem.cpp 
b/src/system/kernel/disk_device_manager/KFileSystem.cpp
index 90f0018..cba020c 100644
--- a/src/system/kernel/disk_device_manager/KFileSystem.cpp
+++ b/src/system/kernel/disk_device_manager/KFileSystem.cpp
@@ -127,8 +127,20 @@ KFileSystem::Repair(KPartition* partition, bool checkOnly, 
disk_job_id job)
 status_t
 KFileSystem::Resize(KPartition* partition, off_t size, disk_job_id job)
 {
-       // to be implemented
-       return B_ERROR;
+       if (!partition || !fModule)
+               return B_ERROR;
+       if (!fModule->resize)
+               return B_NOT_SUPPORTED;
+
+       int fd = -1;
+       status_t result = partition->Open(O_RDWR, &fd);
+       if (result != B_OK)
+               return result;
+
+       result = fModule->resize(fd, partition->ID(), size, job);
+
+       close(fd);
+       return result;
 }
 
 

############################################################################

Commit:      b70891c7bcb223c06ab8e11ae59778de341f155c

Author:      ahenriksson <sausageboy@xxxxxxxxx>
Date:        Tue Jul 31 10:46:39 2012 UTC

Resize support in the BFS disk system add-on

----------------------------------------------------------------------------

diff --git a/src/add-ons/disk_systems/bfs/BFSAddOn.cpp 
b/src/add-ons/disk_systems/bfs/BFSAddOn.cpp
index b33c828..5f57689 100644
--- a/src/add-ons/disk_systems/bfs/BFSAddOn.cpp
+++ b/src/add-ons/disk_systems/bfs/BFSAddOn.cpp
@@ -48,7 +48,7 @@ static const uint32 kDiskSystemFlags =
 //     | B_DISK_SYSTEM_SUPPORTS_DEFRAGMENTING_WHILE_MOUNTED
        | B_DISK_SYSTEM_SUPPORTS_CHECKING_WHILE_MOUNTED
        | B_DISK_SYSTEM_SUPPORTS_REPAIRING_WHILE_MOUNTED
-//     | B_DISK_SYSTEM_SUPPORTS_RESIZING_WHILE_MOUNTED
+       | B_DISK_SYSTEM_SUPPORTS_RESIZING_WHILE_MOUNTED
 //     | B_DISK_SYSTEM_SUPPORTS_MOVING_WHILE_MOUNTED
 //     | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_NAME_WHILE_MOUNTED
 //     | B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_PARAMETERS_WHILE_MOUNTED
@@ -334,6 +334,51 @@ BFSPartitionHandle::Repair(bool checkOnly)
 }
 
 
+status_t
+BFSPartitionHandle::ValidateResize(off_t* size)
+{
+       return _FitSize(size);
+}
+
+
+status_t
+BFSPartitionHandle::Resize(off_t size)
+{
+       off_t fittedSize = size;
+       status_t status = _FitSize(&fittedSize);
+       if (status != B_OK)
+               return status;
+
+       if (fittedSize != size)
+               return B_BAD_VALUE;
+
+       Partition()->SetContentSize(size);
+
+       return B_OK;
+}
+
+
+status_t
+BFSPartitionHandle::_FitSize(off_t* size)
+{
+       BVolume volume(Partition()->VolumeID());
+       status_t status = volume.InitCheck();
+       if (status != B_OK)
+               return status;
+
+       if (*size < volume.Capacity() - volume.FreeBytes())
+               return B_DEVICE_FULL;
+
+       // TODO: we should check that the allocation groups are large enough to
+       // do the resize, but we'd need to ask the file system in some fashion.
+
+       // round down to BFS block size
+       *size -= *size % volume.BlockSize();
+
+       return B_OK;
+}
+
+
 // #pragma mark -
 
 
diff --git a/src/add-ons/disk_systems/bfs/BFSAddOn.h 
b/src/add-ons/disk_systems/bfs/BFSAddOn.h
index 252c0da..d24b9ec 100644
--- a/src/add-ons/disk_systems/bfs/BFSAddOn.h
+++ b/src/add-ons/disk_systems/bfs/BFSAddOn.h
@@ -8,6 +8,9 @@
 #include <DiskSystemAddOn.h>
 
 
+struct fs_info;
+
+
 class BFSAddOn : public BDiskSystemAddOn {
 public:
                                                                BFSAddOn();
@@ -42,6 +45,12 @@ public:
        virtual uint32                          SupportedOperations(uint32 
mask);
 
        virtual status_t                        Repair(bool checkOnly);
+
+       virtual status_t                        ValidateResize(off_t* size);
+       virtual status_t                        Resize(off_t size);
+
+private:
+                       status_t                        _FitSize(off_t* size);
 };
 
 

############################################################################

Commit:      81840c641c25b3a4404000d7256692795b897c7f

Author:      ahenriksson <sausageboy@xxxxxxxxx>
Date:        Wed Jul 25 12:46:42 2012 UTC

Resize support in the intel partitioning disk system add-on

----------------------------------------------------------------------------

diff --git a/src/add-ons/disk_systems/intel/PartitionMapAddOn.cpp 
b/src/add-ons/disk_systems/intel/PartitionMapAddOn.cpp
index 4dc6b2a..c4c27e5 100644
--- a/src/add-ons/disk_systems/intel/PartitionMapAddOn.cpp
+++ b/src/add-ons/disk_systems/intel/PartitionMapAddOn.cpp
@@ -531,3 +531,63 @@ PartitionMapHandle::DeleteChild(BMutablePartition* child)
 
        return error;
 }
+
+
+status_t
+PartitionMapHandle::ValidateResizeChild(const BMutablePartition* child,
+       off_t* size)
+{
+       _FitSizeToSpace(child, size);
+       return B_OK;
+}
+
+
+status_t
+PartitionMapHandle::ResizeChild(BMutablePartition* child, off_t size)
+{
+       // is the new size valid?
+       off_t fittedSize = size;
+       _FitSizeToSpace(child, &fittedSize);
+
+       if (fittedSize != size)
+               return B_BAD_VALUE;
+
+       if (child->ContentSize() > size)
+               return B_BAD_VALUE;
+
+       // update data structures
+       ::Partition* resizingPartition = 
fPartitionMap.PartitionAt(child->Index());
+
+       resizingPartition->SetSize(size);
+       child->SetSize(size);
+
+       return B_OK;
+}
+
+
+void
+PartitionMapHandle::_FitSizeToSpace(const BMutablePartition* child, off_t* 
size)
+{
+       int32 index = child->Index();
+       const ::Partition* resizingPartition = fPartitionMap.PartitionAt(index);
+
+       off_t newEndOffset = resizingPartition->Offset() + *size;
+
+       // check if any other partition overlaps the resized partition
+       int32 partitionCount = fPartitionMap.CountPartitions();
+
+       for (int32 i = 0; i < partitionCount; i++) {
+               if (i == index)
+                       continue;
+
+               const ::Partition* otherPartition = 
fPartitionMap.PartitionAt(i);
+
+               if (resizingPartition->Offset() <= otherPartition->Offset()
+                       && otherPartition->Offset() < newEndOffset) {
+                       // update size so the resizing partition fills the
+                       // availible space
+                       *size = otherPartition->Offset() - 
resizingPartition->Offset();
+                       newEndOffset = resizingPartition->Offset() + *size;
+               }
+       }
+}
diff --git a/src/add-ons/disk_systems/intel/PartitionMapAddOn.h 
b/src/add-ons/disk_systems/intel/PartitionMapAddOn.h
index ecd3ea2..78ae21c 100644
--- a/src/add-ons/disk_systems/intel/PartitionMapAddOn.h
+++ b/src/add-ons/disk_systems/intel/PartitionMapAddOn.h
@@ -64,6 +64,16 @@ public:
                                                                        
BMutablePartition** child);
        virtual status_t                        DeleteChild(BMutablePartition* 
child);
 
+       virtual status_t                        ValidateResizeChild(
+                                                                       const 
BMutablePartition* child,
+                                                                       off_t* 
size);
+       virtual status_t                        ResizeChild(BMutablePartition* 
child,
+                                                                       off_t 
size);
+
+private:
+                       void                            _FitSizeToSpace(const 
BMutablePartition* child,
+                                                                       off_t* 
size);
+
 private:
                        PartitionMap            fPartitionMap;
 };

############################################################################

Commit:      21578deb73c80c8f08f9c97a142aa4116a8408e3

Author:      ahenriksson <sausageboy@xxxxxxxxx>
Date:        Tue Jul 31 10:24:42 2012 UTC

Add resizefs utility

----------------------------------------------------------------------------

diff --git a/build/jam/HaikuImage b/build/jam/HaikuImage
index ffc8d7e..a9f244b 100644
--- a/build/jam/HaikuImage
+++ b/build/jam/HaikuImage
@@ -52,8 +52,8 @@ SYSTEM_BIN = "[" addattr alert arp base64 basename bash bc 
beep bfsinfo
        passwd paste patch pathchk pc ping ping6 play playfile playsound playwav
        pr prio printenv printf profile ps ptx pwd
        query quit
-       rc readlink ReadOnlyBootPrompt reindex release renice rlog rm rmattr
-       rmindex rmdir roster route
+       rc readlink ReadOnlyBootPrompt reindex release renice resizefs rlog rm
+       rmattr rmindex rmdir roster route
        safemode screen_blanker screenmode screenshot sdiff setdecor setmime 
settype
        setversion setvolume seq sha1sum shar shred shuf shutdown sleep sort
        spamdbm
diff --git a/src/bin/Jamfile b/src/bin/Jamfile
index 2a59586..1c30369 100644
--- a/src/bin/Jamfile
+++ b/src/bin/Jamfile
@@ -100,6 +100,7 @@ StdBinCommands
        play.cpp
        query.cpp
        quit.cpp
+       resizefs.cpp
        roster.cpp
        setversion.cpp
        trash.cpp
diff --git a/src/bin/resizefs.cpp b/src/bin/resizefs.cpp
new file mode 100644
index 0000000..b66a3c9
--- /dev/null
+++ b/src/bin/resizefs.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2012, Andreas Henriksson, sausageboy@xxxxxxxxxx
+ * Copyright 2008, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include <stdio.h>
+
+#include <DiskDevice.h>
+#include <DiskDeviceRoster.h>
+#include <DiskSystem.h>
+
+
+extern "C" const char* __progname;
+static const char* kProgramName = __progname;
+
+
+int
+main(int argc, char** argv)
+{
+       if (argc != 3) {
+               fprintf(stderr, "Usage: %s <device> <size>\n", kProgramName);
+               return 1;
+       }
+
+       int64 size;
+       if (sscanf(argv[2], "%" B_SCNd64, &size) < 1) {
+               fprintf(stderr, "%s: The new size \"%s\" is not a number\n",
+                       kProgramName, argv[2]);
+               return 1;
+       }
+
+       BDiskDeviceRoster roster;
+       BPartition* partition;
+       BDiskDevice device;
+
+       status_t status = roster.GetPartitionForPath(argv[1], &device,
+               &partition);
+       if (status != B_OK) {
+               if (strncmp(argv[1], "/dev", 4)) {
+                       // try mounted volume
+                       status = roster.FindPartitionByMountPoint(argv[1], 
&device,
+                               &partition) ? B_OK : B_BAD_VALUE;
+               }
+
+               // TODO: try to register file device
+
+               if (status != B_OK) {
+                       fprintf(stderr, "%s: Failed to get disk device for path 
\"%s\": "
+                               "%s\n", kProgramName, argv[1], 
strerror(status));
+                       return 1;
+               }
+       }
+
+       // Prepare the device for modifications
+
+       status = device.PrepareModifications();
+       if (status != B_OK) {
+               fprintf(stderr, "%s: Could not prepare the device for 
modifications: "
+                       "%s\n", kProgramName, strerror(status));
+               return false;
+       }
+
+       // Check if the partition supports resizing
+
+       bool canResizeWhileMounted;
+       bool canResize = partition->CanResize(NULL, &canResizeWhileMounted);
+
+       if (!canResize && !canResizeWhileMounted) {
+               fprintf(stderr, "%s: The disk system does not support 
resizing.\n",
+                       kProgramName);
+               return 1;
+       }
+
+       if (partition->IsMounted() && !canResizeWhileMounted) {
+               fprintf(stderr, "%s: The disk system does not support resizing 
a "
+                       "mounted volume.\n", kProgramName);
+               return 1;
+       }
+       if (!partition->IsMounted() && !canResize) {
+               fprintf(stderr, "%s: The disk system does not support resizing 
a "
+                       "volume that is not mounted.\n", kProgramName);
+               return 1;
+       }
+
+       BDiskSystem diskSystem;
+       status = partition->GetDiskSystem(&diskSystem);
+       if (status != B_OK) {
+               fprintf(stderr, "%s: Failed to get disk system for partition: 
%s\n",
+                       kProgramName, strerror(status));
+               return 1;
+       }
+
+       // Validate the requested size
+
+       off_t validatedSize = size;
+       status = partition->ValidateResize(&validatedSize);
+       if (status != B_OK) {
+               fprintf(stderr, "%s: Failed to validate the size: %s\n", 
kProgramName,
+                       strerror(status));
+               return 1;
+       }
+
+       if (validatedSize != size) {
+               printf("The requested size (%" B_PRId64 " bytes) was not 
accepted.\n"
+                       "Resize to %" B_PRId64 " bytes instead? (y/N): ", size,
+                       (int64)validatedSize);
+
+               int c = getchar();
+               if (c != 'y')
+                       return 0;
+       }
+
+       // Resize the volume
+
+       status = partition->Resize(validatedSize);
+       if (status != B_OK) {
+               fprintf(stderr, "%s: Resizing failed: %s\n", kProgramName,
+                       strerror(status));
+               return 1;
+       }
+
+       status = device.CommitModifications();
+       if (status != B_OK) {
+               fprintf(stderr, "%s: Failed to commit modifications: %s\n",
+                       kProgramName, strerror(status));
+               return 1;
+       }
+
+       return 0;
+}

############################################################################

Commit:      0e8f38ab332a8d0d43e9c03a07c076b9a8c3f759

Author:      ahenriksson <sausageboy@xxxxxxxxx>
Date:        Mon Jul 23 17:51:26 2012 UTC

Add a resizing back door for use with bfs_shell

The resizefs command in bfs_shell is changed to use this interface.

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/file_systems/bfs/bfs_control.h 
b/src/add-ons/kernel/file_systems/bfs/bfs_control.h
index d5b859e..95c5fe2 100644
--- a/src/add-ons/kernel/file_systems/bfs/bfs_control.h
+++ b/src/add-ons/kernel/file_systems/bfs/bfs_control.h
@@ -99,4 +99,10 @@ struct check_control {
 #define BFS_IOCTL_CHECK_MAGIC  'BChk'
 
 
+/* A "back door" to side-step the regular resize interface, primarily for
+ * testing with bfs_shell. The parameter is a uint64 with the desired size.
+ */
+#define BFS_IOCTL_RESIZE               14205
+
+
 #endif /* BFS_CONTROL_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 24f43c9..a191757 100644
--- a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp
+++ b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp
@@ -720,6 +720,18 @@ bfs_ioctl(fs_volume* _volume, fs_vnode* _node, void* 
_cookie, uint32 cmd,
 
                        return volume->WriteSuperBlock();
                }
+               case BFS_IOCTL_RESIZE:
+               {
+                       if (bufferLength != sizeof(uint64))
+                               return B_BAD_VALUE;
+
+                       uint64 size;
+                       if (user_memcpy((uint8*)&size, buffer, sizeof(uint64)) 
!= B_OK)
+                               return B_BAD_ADDRESS;
+
+                       ResizeVisitor resizer(volume);
+                       return resizer.Resize(size, -1);
+               }
 
 #ifdef DEBUG_FRAGMENTER
                case 56741:
diff --git a/src/tools/bfs_shell/command_resizefs.cpp 
b/src/tools/bfs_shell/command_resizefs.cpp
index 22e7906..e2cfe28 100644
--- a/src/tools/bfs_shell/command_resizefs.cpp
+++ b/src/tools/bfs_shell/command_resizefs.cpp
@@ -14,42 +14,17 @@
 namespace FSShell {
 
 
-void Usage(const char* name);
-
-void PrintInformation(const resize_control& result);
-void PrintError(const resize_control& result);
-void PrintStats(const resize_control& result);
-const char* FailureToString(uint32 failurePoint);
-
-
 fssh_status_t
 command_resizefs(int argc, const char* const* argv)
 {
-       // get command line options
-       bool hasNewSize = false;
-       uint64 newSize = 0;
-
-       bool check = false;
-
-       for (int i = 1; i < argc; i++) {
-               if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--check"))
-                       check = true;
-               else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
-                       Usage(argv[0]);
-                       return B_OK;
-               } else {
-                       if (fssh_sscanf(argv[i], "%" B_SCNu64, &newSize) < 1) {
-                               fssh_dprintf("Unknown argument or invalid 
size\n\n");
-                               Usage(argv[0]);
-                               return B_ERROR;
-                       }
-                       hasNewSize = true;
-               }
+       if (argc != 2) {
+               fssh_dprintf("Usage: %s <new size>\n", argv[0]);
+               return B_ERROR;
        }
-       
-       if (!hasNewSize) {
-               fssh_dprintf("No size specified\n\n");
-               Usage(argv[0]);
+
+       uint64 newSize;
+       if (fssh_sscanf(argv[1], "%" B_SCNu64, &newSize) < 1) {
+               fssh_dprintf("Unknown argument or invalid size\n");
                return B_ERROR;
        }
 
@@ -59,161 +34,18 @@ command_resizefs(int argc, const char* const* argv)
                return rootDir;
        }
 
-       struct resize_control result;
-       memset(&result, 0, sizeof(result));
-       result.magic = BFS_IOCTL_RESIZE_MAGIC;
-
-       if (check)
-               result.flags |= BFS_CHECK_RESIZE;
-
-       result.new_size = newSize;
-       
-       // start resizing
-       fssh_status_t status = _kern_ioctl(rootDir, BFS_IOCTL_START_RESIZE,
-               &result, sizeof(result));
-
-       if (status != B_OK) {
-               fssh_dprintf("Error: Couldn't perform 'start' ioctl\n");
-           return status;
-       }
-
-       PrintInformation(result);
-       if (result.status != B_OK) {
-               PrintError(result);
-               _kern_close(rootDir);
-               return result.status;
-       }
-
-       if (check) {
-               _kern_close(rootDir);
-               fssh_dprintf("Resizing appears to be possible.\n");
-               return B_OK;
-       }
-
-       bool resizeFailed = false;
-       uint64 counter = 0;
-
-       // move all files out of the way
-       while (true) {
-               status = _kern_ioctl(rootDir, BFS_IOCTL_MOVE_NEXT_NODE, &result,
-                       sizeof(result));
-               if (status == B_ENTRY_NOT_FOUND)
-                       break;
-
-               if (++counter % 50 == 0)
-                       fssh_dprintf("%9Ld nodes processed\x1b[1A\n", counter);
-
-               // we couldn't return the resizefs_control struct
-               if (status != B_OK) {
-                       fssh_dprintf("Error: Couldn't perform 'next' ioctl\n");
-                       break;
-               }
-
-               if (result.status != B_OK) {
-                       PrintError(result);
-                       resizeFailed = true;
-                       break;
-               }
-       }
-
-       // finish the resize
-       if (_kern_ioctl(rootDir, BFS_IOCTL_FINISH_RESIZE, &result, 
sizeof(result))
-                       != B_OK) {
-               _kern_close(rootDir);
-               fssh_dprintf("Error: Couldn't perform 'finish' ioctl\n");
-               return errno;
-       }
+       status_t status = _kern_ioctl(rootDir, BFS_IOCTL_RESIZE,
+               &newSize, sizeof(newSize));
 
        _kern_close(rootDir);
 
-       if (result.status != B_OK) {
-               PrintError(result);
-               resizeFailed = true;
-       }
-
-       PrintStats(result);
-
-       if (resizeFailed)
-               fssh_dprintf("Failed to resize file system.\n");
-       else
-               fssh_dprintf("File system successfully resized!\n");
-
-       return result.status;
-}
-
-
-void
-Usage(const char* name)
-{
-       fssh_dprintf("Usage: %s <new size> [options]\n"
-               "\t-c, --check   Don't resize, just check if it would be 
possible\n"
-               "\t-h, --help    Print this message\n", name);
-}
-
-
-void
-PrintInformation(const resize_control& result)
-{
-       fssh_dprintf("New file system information:\n");
-       fssh_dprintf("\tBitmap:     %" B_PRIu16 " blocks (was %" B_PRIu16 ")\n",
-               result.stats.bitmap_blocks_new, result.stats.bitmap_blocks_old);
-       fssh_dprintf("\tLog start:  block %" B_PRIu16 " (was %" B_PRIu16 ")\n",
-               result.stats.log_start_new, result.stats.log_start_old);
-       fssh_dprintf("\tLog length: %" B_PRIu16 " blocks (was %" B_PRIu16 ")\n",
-               result.stats.log_length_new, result.stats.log_length_old);
-       fssh_dprintf("\tBlock size: %" B_PRIu16 " bytes\n\n",
-               result.stats.block_size);
-}
-
-
-void
-PrintError(const resize_control& result)
-{
-       fssh_dprintf("Error:  %s.\n", FailureToString(result.failure_point));
-       fssh_dprintf("Status: %s\n", fssh_strerror(result.status));
-
-       if ((result.failure_point == BFS_MOVE_INODE_FAILED)
-               || (result.failure_point == BFS_MOVE_STREAM_FAILED)) {
-               fssh_dprintf("\tIn inode %" B_PRIdINO ", \"%s\"\n", 
result.inode,
-                       result.name);
+       if (status != B_OK) {
+               fssh_dprintf("Resizing failed, status: %s\n", 
fssh_strerror(status));
+               return status;
        }
 
-       fssh_dprintf("\n");
-}
-
-
-void
-PrintStats(const resize_control& result)
-{
-       fssh_dprintf("        Inodes moved:       %" B_PRIu64 "\n",
-               result.stats.inodes_moved);
-       fssh_dprintf("\tData streams moved: %" B_PRIu64 "\n\n",
-               result.stats.streams_moved);
-}
-
-
-const char*
-FailureToString(uint32 failurePoint)
-{
-       switch (failurePoint) {
-               case BFS_OTHER_ERROR:
-                       return "Other error";
-               case BFS_SIZE_TOO_LARGE:
-                       return "Can't grow disk this much";
-               case BFS_DISK_TOO_SMALL:
-                       return "Not enough room on device to grow file system";
-               case BFS_NO_SPACE:
-                       return "Not enough space left";
-               case BFS_MOVE_LOG_FAILED:
-                       return "Failed to move the file system log";
-               case BFS_MOVE_INODE_FAILED:
-                       return "Failed to move inode";
-               case BFS_MOVE_STREAM_FAILED:
-                       return "Failed to move file data";
-               case BFS_CHANGE_SIZE_FAILED:
-                       return "Failed to update file system size";
-       }
-       return "(Can't get type of failure)";
+       fssh_dprintf("File system successfully resized!\n");
+       return B_OK;
 }
 
 


Other related posts:

  • » [haiku-commits] BRANCH ahenriksson-github.production - in src: add-ons/kernel/file_systems/bfs tools/bfs_shell bin kits/storage/disk_device add-ons/disk_systems/intel - ahenriksson-github . production