From 58b7de1cda63791426fa5ce1182e81a2a9bdce0a Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Mon, 29 Sep 2003 21:44:47 +0000 Subject: [PATCH] Implemented the resize job. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4870 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../disk_device_manager/jobs/KResizeJob.cpp | 90 +++++++++++++++++-- .../disk_device_manager/jobs/KResizeJob.h | 5 +- 2 files changed, 87 insertions(+), 8 deletions(-) diff --git a/src/kernel/core/disk_device_manager/jobs/KResizeJob.cpp b/src/kernel/core/disk_device_manager/jobs/KResizeJob.cpp index 1c22266536..f537992b83 100644 --- a/src/kernel/core/disk_device_manager/jobs/KResizeJob.cpp +++ b/src/kernel/core/disk_device_manager/jobs/KResizeJob.cpp @@ -3,7 +3,14 @@ #include #include +#include +#include +#include +#include +#include +#include +#include "ddm_operation_validation.h" #include "KResizeJob.h" // debugging @@ -13,11 +20,11 @@ // constructor KResizeJob::KResizeJob(partition_id parentID, partition_id partitionID, - off_t size, bool resizeContents) + off_t size) : KDiskDeviceJob(B_DISK_DEVICE_JOB_RESIZE, partitionID, parentID), - fResizeContents(resizeContents) + fSize(size) { - SetDescription("uninitializing partition"); + SetDescription("resizing partition"); } // destructor @@ -29,8 +36,81 @@ KResizeJob::~KResizeJob() status_t KResizeJob::Do() { -// TODO: implement DBG(OUT("KResizeJob::Do(%ld)\n", PartitionID())); - return B_OK; + // get the partition + KDiskDeviceManager *manager = KDiskDeviceManager::Default(); + KPartition *partition = manager->WriteLockPartition(PartitionID()); + if (partition) { + PartitionRegistrar registrar(partition, true); + PartitionRegistrar deviceRegistrar(partition->Device(), true); + DeviceWriteLocker locker(partition->Device(), true); + // basic checks + if (!partition->ParentDiskSystem()) { + SetErrorMessage("Partition has no parent disk system!"); + return B_BAD_VALUE; + } + // if size remains the same, then nothing's to do + if (partition->Size() == fSize) + return B_OK; + // check new size + off_t size = fSize; + off_t contentSize = fSize; + status_t error = validate_resize_partition(partition, + partition->ChangeCounter(), &size, &contentSize, false); + if (error != B_OK) { + SetErrorMessage("Validation of the new partition size failed."); + return error; + } + if (size != fSize) { + SetErrorMessage("Requested size is not valid."); + return B_ERROR; + } + // all descendants should be marked busy/descendant busy + struct IsNotBusyVisitor : KPartitionVisitor { + virtual bool VisitPre(KPartition *partition) + { + return !(partition->IsBusy() || partition->IsDescendantBusy()); + } + } isNotBusyVisitor; + if (partition->VisitEachDescendant(&isNotBusyVisitor)) { + SetErrorMessage("Can't resize non-busy partition!"); + return B_ERROR; + } + // things look good: get all infos needed for resizing + KDiskSystem *parentDiskSystem = partition->ParentDiskSystem(); + KDiskSystem *childDiskSystem = partition->DiskSystem(); + DiskSystemLoader loader1(parentDiskSystem); + DiskSystemLoader loader2(childDiskSystem); + off_t oldSize = partition->Size(); + off_t oldContentSize = partition->ContentSize(); + // unlock the device and resize the beast + locker.Unset(); + // if growing, resize partition first + if (oldSize < fSize) { + status_t error = parentDiskSystem->ResizeChild(partition, fSize, + this); + if (error != B_OK) + return error; + } + // resize contents + if (childDiskSystem && oldContentSize != contentSize) { + status_t error = childDiskSystem->Resize(partition, contentSize, + this); + if (error != B_OK) + return error; + } + // if shrinking, resize partition last + if (oldSize > fSize) { + status_t error = parentDiskSystem->ResizeChild(partition, fSize, + this); + if (error != B_OK) + return error; + } + } else { + SetErrorMessage("Couldn't find partition."); + return B_ENTRY_NOT_FOUND; + } + // cannot come here + return B_ERROR; } diff --git a/src/kernel/core/disk_device_manager/jobs/KResizeJob.h b/src/kernel/core/disk_device_manager/jobs/KResizeJob.h index c8717d0f0f..bdad327392 100644 --- a/src/kernel/core/disk_device_manager/jobs/KResizeJob.h +++ b/src/kernel/core/disk_device_manager/jobs/KResizeJob.h @@ -10,14 +10,13 @@ namespace DiskDevice { class KResizeJob : public KDiskDeviceJob { public: - KResizeJob(partition_id parentID, partition_id partitionID, off_t size, - bool resizeContents); + KResizeJob(partition_id parentID, partition_id partitionID, off_t size); virtual ~KResizeJob(); virtual status_t Do(); private: - bool fResizeContents; + off_t fSize; }; } // namespace DiskDevice