diff --git a/headers/os/drivers/disk_device_manager.h b/headers/os/drivers/disk_device_manager.h index ba59f44269..b86641bf8c 100644 --- a/headers/os/drivers/disk_device_manager.h +++ b/headers/os/drivers/disk_device_manager.h @@ -14,9 +14,11 @@ extern "C" { #endif -// C API partition representation -// Fields marked [sys] are set by the system and are not to be changed by -// the disk system modules. +/** \brief C API partition representation + * + * Fields marked [sys] are set by the system and are not to be changed by + * the disk system modules. + */ typedef struct partition_data { partition_id id; // [sys] off_t offset; diff --git a/headers/private/kernel/disk_device_manager/KDiskDeviceJob.h b/headers/private/kernel/disk_device_manager/KDiskDeviceJob.h index b226588f4b..560c8c749a 100644 --- a/headers/private/kernel/disk_device_manager/KDiskDeviceJob.h +++ b/headers/private/kernel/disk_device_manager/KDiskDeviceJob.h @@ -4,6 +4,7 @@ #define _K_DISK_DEVICE_JOB_H #include "disk_device_manager.h" +#include struct user_disk_device_job_info; @@ -12,19 +13,41 @@ namespace DiskDevice { class KDiskDeviceJobQueue; +/** + * Represents some action executed on the disk device. + * + * - + */ class KDiskDeviceJob { public: + /** + * Creates a new job + * + * \param type actual type of the job (see DiskDeviceDefs.h for details) + * \param partitionID the partition/device on which the action should be executed + * \param scopeID partition/device which is the highest in the hierarchy (i.e. closest + * to the root) that can be affected by the action + * - every descendant of this partition is marked busy and all ancestors are marked descendant- + busy + */ KDiskDeviceJob(uint32 type, partition_id partitionID, partition_id scopeID = -1); virtual ~KDiskDeviceJob(); + /** + * Unique identification of the job + */ disk_job_id ID() const; void SetJobQueue(KDiskDeviceJobQueue *queue); KDiskDeviceJobQueue *JobQueue() const; + /** + * Gets actual type of the action + */ uint32 Type() const; + void SetStatus(uint32 status); uint32 Status() const; @@ -54,9 +77,25 @@ public: // triggers a notification float Progress() const; + status_t GetInfo(user_disk_device_job_info *info); status_t GetProgressInfo(disk_device_job_progress_info *info); + /** + * Do the actual work of the job. + * + * - is supposed to be implemented in descendants + * - doesn't have any parameter - every operation needs different ones -> they're passed + * to the constructor + * - the implementations will + * - check the parameters given in constructor (e.g. if given partition exists...) + * - check whether the partition has needed disk system (its own or parent - depends + * on the operation) + * - using the disk system, validate the operation for given params + * - finally execute the action + * + * \return B_OK when everything went OK, some error otherwise + */ virtual status_t Do() = 0; private: @@ -76,6 +115,29 @@ private: float fProgress; static disk_job_id fNextID; + +private: + /** + * Visitor which checks if every descendant of given partition is busy or descendant-busy + */ + struct IsNotBusyVisitor : KPartitionVisitor { + virtual bool VisitPre(KPartition * partition); + }; + IsNotBusyVisitor fNotBusyVisitor; + +protected: + //some stuff useful for all descendants + + /** + * Checks if there's any descendant which is not busy/descendant-busy. + * + * - the condition of busy descendant is common for many disk device operations -> + * many jobs can use this + * + * \param partition the root of checked subtree of the whole partition hieararchy + */ + bool isPartitionNotBusy( KPartition * partition ); + }; } // namespace DiskDevice diff --git a/headers/private/kernel/disk_device_manager/KDiskSystem.h b/headers/private/kernel/disk_device_manager/KDiskSystem.h index 76871115ff..f789a5d7c2 100644 --- a/headers/private/kernel/disk_device_manager/KDiskSystem.h +++ b/headers/private/kernel/disk_device_manager/KDiskSystem.h @@ -13,6 +13,7 @@ namespace DiskDevice { class KDiskDeviceJob; class KPartition; +/// \brief Common ancestor for disk system add-on wrappers class KDiskSystem { public: KDiskSystem(const char *name); diff --git a/headers/private/kernel/disk_device_manager/KFileSystem.h b/headers/private/kernel/disk_device_manager/KFileSystem.h index ab13cf2eaa..dbd5a227d0 100644 --- a/headers/private/kernel/disk_device_manager/KFileSystem.h +++ b/headers/private/kernel/disk_device_manager/KFileSystem.h @@ -13,6 +13,7 @@ struct file_system_module_info; namespace BPrivate { namespace DiskDevice { +/// \brief Wrapper for the C interface of a filesystem add-on. class KFileSystem : public KDiskSystem { public: KFileSystem(const char *name); diff --git a/headers/private/kernel/disk_device_manager/KPartition.h b/headers/private/kernel/disk_device_manager/KPartition.h index a14f49c634..aa55b0a0cd 100644 --- a/headers/private/kernel/disk_device_manager/KPartition.h +++ b/headers/private/kernel/disk_device_manager/KPartition.h @@ -21,6 +21,7 @@ class KPath; class KPhysicalPartition; class KShadowPartition; +/// \brief Class representing a single partition. class KPartition { public: KPartition(partition_id id = -1); diff --git a/headers/private/kernel/disk_device_manager/KPartitioningSystem.h b/headers/private/kernel/disk_device_manager/KPartitioningSystem.h index 6f8609bdb0..737575fbba 100644 --- a/headers/private/kernel/disk_device_manager/KPartitioningSystem.h +++ b/headers/private/kernel/disk_device_manager/KPartitioningSystem.h @@ -10,6 +10,11 @@ struct partition_module_info; namespace BPrivate { namespace DiskDevice { +/** + * \brief Wrapper for the C interface of a partitioning system add-on. + * + * See \ref ddm_modules.h for better description of the interface. + */ class KPartitioningSystem : public KDiskSystem { public: KPartitioningSystem(const char *name); @@ -19,7 +24,9 @@ public: // Scanning + /// Try to identify a given partition virtual float Identify(KPartition *partition, void **cookie); + /// Scan the partition virtual status_t Scan(KPartition *partition, void *cookie); virtual void FreeIdentifyCookie(KPartition *partition, void *cookie); virtual void FreeCookie(KPartition *partition); @@ -27,88 +34,132 @@ public: // Querying + /// Check whether the add-on supports repairing this partition. virtual bool SupportsRepairing(KPartition *partition, bool checkOnly, bool *whileMounted); + /// Check whether the add-on supports resizing this partition. virtual bool SupportsResizing(KPartition *partition, bool *whileMounted); + /// Check whether the add-on supports resizing children of this partition. virtual bool SupportsResizingChild(KPartition *child); + /// Check whether the add-on supports moving this partition. virtual bool SupportsMoving(KPartition *partition, bool *isNoOp); + /// Check whether the add-on supports moving children of this partition. virtual bool SupportsMovingChild(KPartition *child); + /// Check whether the add-on supports setting name of this partition. virtual bool SupportsSettingName(KPartition *partition); + /// Check whether the add-on supports setting name to content of this partition. virtual bool SupportsSettingContentName(KPartition *partition, bool *whileMounted); + /// Check whether the add-on supports setting type of this partition. virtual bool SupportsSettingType(KPartition *partition); + /// Check whether the add-on supports setting parameters of this partition. virtual bool SupportsSettingParameters(KPartition *partition); + /// Check whether the add-on supports setting parameters to content of this partition. virtual bool SupportsSettingContentParameters(KPartition *partition, bool *whileMounted); + /// Check whether the add-on supports initializing this partition. virtual bool SupportsInitializing(KPartition *partition); + /// Check whether the add-on supports initializing a child of this partition. virtual bool SupportsInitializingChild(KPartition *child, const char *diskSystem); + /// Check whether the add-on supports creating children of this partition. virtual bool SupportsCreatingChild(KPartition *partition); + /// Check whether the add-on supports deleting children of this partition. virtual bool SupportsDeletingChild(KPartition *child); + /// Check whether the add-on is a subsystem for a given partition. virtual bool IsSubSystemFor(KPartition *partition); + /// Validates parameters for resizing a partition virtual bool ValidateResize(KPartition *partition, off_t *size); + /// Validates parameters for resizing a child partition virtual bool ValidateResizeChild(KPartition *child, off_t *size); + /// Validates parameters for moving a partition virtual bool ValidateMove(KPartition *partition, off_t *start); + /// Validates parameters for moving a child partition virtual bool ValidateMoveChild(KPartition *child, off_t *start); + /// Validates parameters for setting name of a partition virtual bool ValidateSetName(KPartition *partition, char *name); + /// Validates parameters for setting name to content of a partition virtual bool ValidateSetContentName(KPartition *partition, char *name); + /// Validates parameters for setting type of a partition virtual bool ValidateSetType(KPartition *partition, const char *type); + /// Validates parameters for setting parameters of a partition virtual bool ValidateSetParameters(KPartition *partition, const char *parameters); + /// Validates parameters for setting parameters to content of a partition virtual bool ValidateSetContentParameters(KPartition *parameters, const char *parameters); + /// Validates parameters for initializing a partition virtual bool ValidateInitialize(KPartition *partition, char *name, const char *parameters); + /// Validates parameters for creating child of a partition virtual bool ValidateCreateChild(KPartition *partition, off_t *start, off_t *size, const char *type, const char *parameters, int32 *index); + /// Counts partitionable spaces on a partition virtual int32 CountPartitionableSpaces(KPartition *partition); + /// Retrieves a list of partitionable spaces on a partition virtual status_t GetPartitionableSpaces(KPartition *partition, partitionable_space_data *buffer, int32 count, int32 *actualCount = NULL); + /// Iterates through supported partition types virtual status_t GetNextSupportedType(KPartition *partition, int32 *cookie, char *type); + /// Translates the "pretty" content type to an internal type virtual status_t GetTypeForContentType(const char *contentType, char *type); // Shadow partition modification + /// Calls for additional modifications when shadow partition is changed virtual status_t ShadowPartitionChanged(KPartition *partition, uint32 operation); // Writing + /// Repairs a partition virtual status_t Repair(KPartition *partition, bool checkOnly, KDiskDeviceJob *job); + /// Resizes a partition virtual status_t Resize(KPartition *partition, off_t size, KDiskDeviceJob *job); + /// Resizes child of a partition virtual status_t ResizeChild(KPartition *child, off_t size, KDiskDeviceJob *job); + /// Moves a partition virtual status_t Move(KPartition *partition, off_t offset, KDiskDeviceJob *job); + /// Moves child of a partition virtual status_t MoveChild(KPartition *child, off_t offset, KDiskDeviceJob *job); + /// Sets name to a partition virtual status_t SetName(KPartition *partition, char *name, KDiskDeviceJob *job); + /// Sets name to content of a partition virtual status_t SetContentName(KPartition *partition, char *name, KDiskDeviceJob *job); + /// Sets type of a partition virtual status_t SetType(KPartition *partition, char *type, KDiskDeviceJob *job); + /// Sets parameters of a partition virtual status_t SetParameters(KPartition *partition, const char *parameters, KDiskDeviceJob *job); + /// Sets parameters to content of a partition virtual status_t SetContentParameters(KPartition *partition, const char *parameters, KDiskDeviceJob *job); + /// Creates a child partition virtual status_t CreateChild(KPartition *partition, off_t offset, off_t size, const char *type, const char *parameters, KDiskDeviceJob *job, KPartition **child = NULL, partition_id childID = -1); + /// Deletes a child partition virtual status_t DeleteChild(KPartition *child, KDiskDeviceJob *job); + /// Initializes a partition with this partitioning system virtual status_t Initialize(KPartition *partition, const char *name, const char *parameters, KDiskDeviceJob *job); diff --git a/headers/private/kernel/disk_device_manager/KPhysicalPartition.h b/headers/private/kernel/disk_device_manager/KPhysicalPartition.h index e3780002b4..a254a1ce92 100644 --- a/headers/private/kernel/disk_device_manager/KPhysicalPartition.h +++ b/headers/private/kernel/disk_device_manager/KPhysicalPartition.h @@ -12,6 +12,7 @@ class KDiskDevice; class KDiskSystem; class KShadowPartition; +/// \brief Class representing an existing partition. class KPhysicalPartition : public KPartition { public: KPhysicalPartition(partition_id id = -1); diff --git a/headers/private/kernel/disk_device_manager/KShadowPartition.h b/headers/private/kernel/disk_device_manager/KShadowPartition.h index d9a8817e86..7a52134ba6 100644 --- a/headers/private/kernel/disk_device_manager/KShadowPartition.h +++ b/headers/private/kernel/disk_device_manager/KShadowPartition.h @@ -11,6 +11,9 @@ namespace DiskDevice { class KPhysicalPartition; +/// \brief Class representing a shadow of an existing partition. +/// +/// See \ref path_kernel_structures for more information. class KShadowPartition : public KPartition, private KPartitionListener { public: KShadowPartition(KPhysicalPartition *physicalPartition); diff --git a/src/system/kernel/disk_device_manager/Jamfile b/src/system/kernel/disk_device_manager/Jamfile index 6d21c3a38a..67ac109daa 100644 --- a/src/system/kernel/disk_device_manager/Jamfile +++ b/src/system/kernel/disk_device_manager/Jamfile @@ -42,7 +42,9 @@ KernelMergeObject kernel_disk_device_manager.o : KRepairJob.cpp KResizeJob.cpp KScanPartitionJob.cpp + KSetNameJob.cpp KSetParametersJob.cpp + KSetTypeJob.cpp KUninitializeJob.cpp # utilities diff --git a/src/system/kernel/disk_device_manager/KDiskDeviceJob.cpp b/src/system/kernel/disk_device_manager/KDiskDeviceJob.cpp index b28fb4f15c..60fc883c32 100644 --- a/src/system/kernel/disk_device_manager/KDiskDeviceJob.cpp +++ b/src/system/kernel/disk_device_manager/KDiskDeviceJob.cpp @@ -243,3 +243,17 @@ KDiskDeviceJob::_NextID() // fNextID disk_job_id KDiskDeviceJob::fNextID = 0; + +// IsNotBusyVisitor +bool KDiskDeviceJob::IsNotBusyVisitor::VisitPre( KPartition * partition ) { + return !(partition->IsBusy() || partition->IsDescendantBusy()); +} + + +bool KDiskDeviceJob::isPartitionNotBusy( KPartition * partition ) { + if( !partition ) { + return false; + } + + return partition->VisitEachDescendant(&fNotBusyVisitor); +} diff --git a/src/system/kernel/disk_device_manager/KDiskDeviceJobFactory.cpp b/src/system/kernel/disk_device_manager/KDiskDeviceJobFactory.cpp index 0876eb64c3..7aaf9bc95e 100644 --- a/src/system/kernel/disk_device_manager/KDiskDeviceJobFactory.cpp +++ b/src/system/kernel/disk_device_manager/KDiskDeviceJobFactory.cpp @@ -10,8 +10,18 @@ #include "KDiskDeviceJob.h" #include "KDiskDeviceJobFactory.h" + +#include "KCreateChildJob.h" +#include "KDefragmentJob.h" +#include "KDeleteChildJob.h" +#include "KInitializeJob.h" +#include "KMoveJob.h" +#include "KRepairJob.h" #include "KResizeJob.h" #include "KScanPartitionJob.h" +#include "KSetNameJob.h" +#include "KSetParametersJob.h" +#include "KSetTypeJob.h" #include "KUninitializeJob.h" using namespace std; @@ -30,8 +40,7 @@ KDiskDeviceJobFactory::~KDiskDeviceJobFactory() KDiskDeviceJob * KDiskDeviceJobFactory::CreateDefragmentJob(partition_id partitionID) { - // not implemented - return NULL; + return new(nothrow) KDefragmentJob(partitionID); } @@ -39,8 +48,7 @@ KDiskDeviceJob * KDiskDeviceJobFactory::CreateRepairJob(partition_id partitionID, bool checkOnly) { - // not implemented - return NULL; + return new(nothrow) KRepairJob(partitionID, checkOnly); } @@ -56,8 +64,8 @@ KDiskDeviceJob * KDiskDeviceJobFactory::CreateMoveJob(partition_id parentID, partition_id partitionID, off_t offset, const partition_id *contentsToMove, int32 contentsToMoveCount) { - // not implemented - return NULL; + // TODO: this is wierd, what in hell are contentsToMove etc? + return new(nothrow) KMoveJob(parentID, partitionID, offset); } @@ -65,8 +73,7 @@ KDiskDeviceJob * KDiskDeviceJobFactory::CreateSetNameJob(partition_id parentID, partition_id partitionID, const char *name) { - // not implemented - return NULL; + return new(nothrow) KSetNameJob(parentID, partitionID, name, 0); } @@ -74,8 +81,7 @@ KDiskDeviceJob * KDiskDeviceJobFactory::CreateSetContentNameJob(partition_id partitionID, const char *name) { - // not implemented - return NULL; + return new(nothrow) KSetNameJob(0, partitionID, 0, name); } @@ -83,8 +89,7 @@ KDiskDeviceJob * KDiskDeviceJobFactory::CreateSetTypeJob(partition_id parentID, partition_id partitionID, const char *type) { - // not implemented - return NULL; + return new(nothrow) KSetTypeJob(parentID, partitionID, type); } @@ -92,8 +97,7 @@ KDiskDeviceJob * KDiskDeviceJobFactory::CreateSetParametersJob(partition_id parentID, partition_id partitionID, const char *parameters) { - // not implemented - return NULL; + return new(nothrow) KSetParametersJob(parentID, partitionID, parameters, 0); } @@ -101,8 +105,7 @@ KDiskDeviceJob * KDiskDeviceJobFactory::CreateSetContentParametersJob(partition_id partitionID, const char *parameters) { - // not implemented - return NULL; + return new(nothrow) KSetParametersJob(0, partitionID, 0, parameters); } @@ -110,8 +113,7 @@ KDiskDeviceJob * KDiskDeviceJobFactory::CreateInitializeJob(partition_id partitionID, disk_system_id diskSystemID, const char *name, const char *parameters) { - // not implemented - return NULL; + return new(nothrow) KInitializeJob(partitionID, diskSystemID, name, parameters); } @@ -127,8 +129,7 @@ KDiskDeviceJobFactory::CreateCreateChildJob(partition_id partitionID, partition_id childID, off_t offset, off_t size, const char *type, const char *parameters) { - // not implemented - return NULL; + return new(nothrow) KCreateChildJob(partitionID, childID, offset, size, type, parameters); } @@ -136,8 +137,7 @@ KDiskDeviceJob * KDiskDeviceJobFactory::CreateDeleteChildJob(partition_id parentID, partition_id partitionID) { - // not implemented - return NULL; + return new(nothrow) KDeleteChildJob(parentID, partitionID); } diff --git a/src/system/kernel/disk_device_manager/KPartitioningSystem.cpp b/src/system/kernel/disk_device_manager/KPartitioningSystem.cpp index 045bcef052..d3d4ef84f5 100644 --- a/src/system/kernel/disk_device_manager/KPartitioningSystem.cpp +++ b/src/system/kernel/disk_device_manager/KPartitioningSystem.cpp @@ -1,4 +1,7 @@ -// KPartitioningSystem.cpp +/** \file KPartitioningSystem.cpp + * + * \brief Implementation of \ref KPartitioningSystem class + */ #include #include @@ -499,17 +502,17 @@ KPartitioningSystem::Resize(KPartition *partition, off_t size, return B_ENTRY_NOT_FOUND; // lock partition and open partition device KDiskDeviceManager *manager = KDiskDeviceManager::Default(); - KPartition *_partition = manager->ReadLockPartition(partition->ID()); + KPartition *_partition = manager->WriteLockPartition(partition->ID()); if (!_partition) return B_ERROR; int fd = -1; { PartitionRegistrar registrar(_partition, true); PartitionRegistrar deviceRegistrar(_partition->Device(), true); - DeviceReadLocker locker(_partition->Device(), true); + DeviceWriteLocker locker(_partition->Device(), true); if (partition != _partition) return B_ERROR; - status_t result = partition->Open(O_RDONLY, &fd); + status_t result = partition->Open(O_RDWR, &fd); if (result != B_OK) return result; } @@ -526,25 +529,24 @@ KPartitioningSystem::ResizeChild(KPartition *child, off_t size, KDiskDeviceJob *job) { // check parameters - if (!child || !job || size < 0) + if (!child || !job || !child->Parent() || size < 0) return B_BAD_VALUE; if (!fModule->resize_child) return B_ENTRY_NOT_FOUND; // lock partition and open (parent) partition device KDiskDeviceManager *manager = KDiskDeviceManager::Default(); - KPartition *_partition = manager->ReadLockPartition(child->ID()); + KPartition *_partition = manager->WriteLockPartition(child->ID()); + KPartition *_parent = manager->WriteLockPartition(child->Parent()->ID()); if (!_partition) return B_ERROR; int fd = -1; { PartitionRegistrar registrar(_partition, true); PartitionRegistrar deviceRegistrar(_partition->Device(), true); - DeviceReadLocker locker(_partition->Device(), true); + DeviceWriteLocker locker(_partition->Device(), true); if (child != _partition) return B_ERROR; - if (!child->Parent()) - return B_BAD_VALUE; - status_t result = child->Parent()->Open(O_RDONLY, &fd); + status_t result = child->Parent()->Open(O_RDWR, &fd); if (result != B_OK) return result; } @@ -560,8 +562,32 @@ status_t KPartitioningSystem::Move(KPartition *partition, off_t offset, KDiskDeviceJob *job) { - // to be implemented - return B_ERROR; + // check parameters + if (!partition || !job) + return B_BAD_VALUE; + if (!fModule->move) + return B_ENTRY_NOT_FOUND; + // lock partition and open partition device + KDiskDeviceManager *manager = KDiskDeviceManager::Default(); + KPartition *_partition = manager->WriteLockPartition(partition->ID()); + if (!_partition) + return B_ERROR; + int fd = -1; + { + PartitionRegistrar registrar(_partition, true); + PartitionRegistrar deviceRegistrar(_partition->Device(), true); + DeviceWriteLocker locker(_partition->Device(), true); + if (partition != _partition) + return B_ERROR; + status_t result = partition->Open(O_RDWR, &fd); + if (result != B_OK) + return result; + } + // let the module do its job + status_t result = fModule->move(fd, partition->ID(), offset, job->ID()); + // cleanup and return + close(fd); + return result; } // MoveChild @@ -569,8 +595,33 @@ status_t KPartitioningSystem::MoveChild(KPartition *child, off_t offset, KDiskDeviceJob *job) { - // to be implemented - return B_ERROR; + // check parameters + if (!child || !job || !child->Parent()) + return B_BAD_VALUE; + if (!fModule->move_child) + return B_ENTRY_NOT_FOUND; + // lock partition and open (parent) partition device + KDiskDeviceManager *manager = KDiskDeviceManager::Default(); + KPartition *_partition = manager->WriteLockPartition(child->ID()); + KPartition *_parent = manager->WriteLockPartition(child->Parent()->ID()); + if (!_partition) + return B_ERROR; + int fd = -1; + { + PartitionRegistrar registrar(_partition, true); + PartitionRegistrar deviceRegistrar(_partition->Device(), true); + DeviceWriteLocker locker(_partition->Device(), true); + if (child != _partition) + return B_ERROR; + status_t result = child->Parent()->Open(O_RDWR, &fd); + if (result != B_OK) + return result; + } + // let the module do its job + status_t result = fModule->move_child(fd, child->Parent()->ID(), child->ID(), offset, job->ID()); + // cleanup and return + close(fd); + return result; } // SetName @@ -578,8 +629,32 @@ status_t KPartitioningSystem::SetName(KPartition *partition, char *name, KDiskDeviceJob *job) { - // to be implemented - return B_ERROR; + // check parameters + if (!partition || !job || !name) + return B_BAD_VALUE; + if (!fModule->set_name) + return B_ENTRY_NOT_FOUND; + // lock partition and open partition device + KDiskDeviceManager *manager = KDiskDeviceManager::Default(); + KPartition *_partition = manager->WriteLockPartition(partition->ID()); + if (!_partition) + return B_ERROR; + int fd = -1; + { + PartitionRegistrar registrar(_partition, true); + PartitionRegistrar deviceRegistrar(_partition->Device(), true); + DeviceWriteLocker locker(_partition->Device(), true); + if (partition != _partition) + return B_ERROR; + status_t result = partition->Open(O_RDWR, &fd); + if (result != B_OK) + return result; + } + // let the module do its job + status_t result = fModule->set_name(fd, partition->ID(), name, job->ID()); + // cleanup and return + close(fd); + return result; } // SetContentName @@ -587,8 +662,32 @@ status_t KPartitioningSystem::SetContentName(KPartition *partition, char *name, KDiskDeviceJob *job) { - // to be implemented - return B_ERROR; + // check parameters + if (!partition || !job || !name) + return B_BAD_VALUE; + if (!fModule->set_content_name) + return B_ENTRY_NOT_FOUND; + // lock partition and open partition device + KDiskDeviceManager *manager = KDiskDeviceManager::Default(); + KPartition *_partition = manager->WriteLockPartition(partition->ID()); + if (!_partition) + return B_ERROR; + int fd = -1; + { + PartitionRegistrar registrar(_partition, true); + PartitionRegistrar deviceRegistrar(_partition->Device(), true); + DeviceWriteLocker locker(_partition->Device(), true); + if (partition != _partition) + return B_ERROR; + status_t result = partition->Open(O_RDWR, &fd); + if (result != B_OK) + return result; + } + // let the module do its job + status_t result = fModule->set_content_name(fd, partition->ID(), name, job->ID()); + // cleanup and return + close(fd); + return result; } // SetType @@ -596,8 +695,32 @@ status_t KPartitioningSystem::SetType(KPartition *partition, char *type, KDiskDeviceJob *job) { - // to be implemented - return B_ERROR; + // check parameters + if (!partition || !job || !type) + return B_BAD_VALUE; + if (!fModule->set_type) + return B_ENTRY_NOT_FOUND; + // lock partition and open partition device + KDiskDeviceManager *manager = KDiskDeviceManager::Default(); + KPartition *_partition = manager->WriteLockPartition(partition->ID()); + if (!_partition) + return B_ERROR; + int fd = -1; + { + PartitionRegistrar registrar(_partition, true); + PartitionRegistrar deviceRegistrar(_partition->Device(), true); + DeviceWriteLocker locker(_partition->Device(), true); + if (partition != _partition) + return B_ERROR; + status_t result = partition->Open(O_RDWR, &fd); + if (result != B_OK) + return result; + } + // let the module do its job + status_t result = fModule->set_type(fd, partition->ID(), type, job->ID()); + // cleanup and return + close(fd); + return result; } // SetParameters @@ -605,8 +728,32 @@ status_t KPartitioningSystem::SetParameters(KPartition *partition, const char *parameters, KDiskDeviceJob *job) { - // to be implemented - return B_ERROR; + // check parameters + if (!partition || !job || !parameters) + return B_BAD_VALUE; + if (!fModule->set_parameters) + return B_ENTRY_NOT_FOUND; + // lock partition and open partition device + KDiskDeviceManager *manager = KDiskDeviceManager::Default(); + KPartition *_partition = manager->WriteLockPartition(partition->ID()); + if (!_partition) + return B_ERROR; + int fd = -1; + { + PartitionRegistrar registrar(_partition, true); + PartitionRegistrar deviceRegistrar(_partition->Device(), true); + DeviceWriteLocker locker(_partition->Device(), true); + if (partition != _partition) + return B_ERROR; + status_t result = partition->Open(O_RDWR, &fd); + if (result != B_OK) + return result; + } + // let the module do its job + status_t result = fModule->set_parameters(fd, partition->ID(), parameters, job->ID()); + // cleanup and return + close(fd); + return result; } // SetContentParameters @@ -615,8 +762,32 @@ KPartitioningSystem::SetContentParameters(KPartition *partition, const char *parameters, KDiskDeviceJob *job) { - // to be implemented - return B_ERROR; + // check parameters + if (!partition || !job || !parameters) + return B_BAD_VALUE; + if (!fModule->set_content_parameters) + return B_ENTRY_NOT_FOUND; + // lock partition and open partition device + KDiskDeviceManager *manager = KDiskDeviceManager::Default(); + KPartition *_partition = manager->WriteLockPartition(partition->ID()); + if (!_partition) + return B_ERROR; + int fd = -1; + { + PartitionRegistrar registrar(_partition, true); + PartitionRegistrar deviceRegistrar(_partition->Device(), true); + DeviceWriteLocker locker(_partition->Device(), true); + if (partition != _partition) + return B_ERROR; + status_t result = partition->Open(O_RDWR, &fd); + if (result != B_OK) + return result; + } + // let the module do its job + status_t result = fModule->set_content_parameters(fd, partition->ID(), parameters, job->ID()); + // cleanup and return + close(fd); + return result; } // Initialize @@ -624,8 +795,32 @@ status_t KPartitioningSystem::Initialize(KPartition *partition, const char *name, const char *parameters, KDiskDeviceJob *job) { - // to be implemented - return B_ERROR; + // check parameters + if (!partition || !job || !name /*|| !parameters*/) + return B_BAD_VALUE; + if (!fModule->initialize) + return B_ENTRY_NOT_FOUND; + // lock partition and open partition device + KDiskDeviceManager *manager = KDiskDeviceManager::Default(); + KPartition *_partition = manager->WriteLockPartition(partition->ID()); + if (!_partition) + return B_ERROR; + int fd = -1; + { + PartitionRegistrar registrar(_partition, true); + PartitionRegistrar deviceRegistrar(_partition->Device(), true); + DeviceWriteLocker locker(_partition->Device(), true); + if (partition != _partition) + return B_ERROR; + status_t result = partition->Open(O_RDWR, &fd); + if (result != B_OK) + return result; + } + // let the module do its job + status_t result = fModule->initialize(fd, partition->ID(), name, parameters, job->ID()); + // cleanup and return + close(fd); + return result; } // CreateChild @@ -635,8 +830,37 @@ KPartitioningSystem::CreateChild(KPartition *partition, off_t offset, const char *parameters, KDiskDeviceJob *job, KPartition **child, partition_id childID) { - // to be implemented - return B_ERROR; + // check parameters + if (!partition || !job || !type /*|| !parameters*/ || !child) + return B_BAD_VALUE; + if (!fModule->create_child) + return B_ENTRY_NOT_FOUND; + // lock partition and open partition device + KDiskDeviceManager *manager = KDiskDeviceManager::Default(); + KPartition *_partition = manager->WriteLockPartition(partition->ID()); + if (!_partition) + return B_ERROR; + int fd = -1; + { + PartitionRegistrar registrar(_partition, true); + PartitionRegistrar deviceRegistrar(_partition->Device(), true); + DeviceWriteLocker locker(_partition->Device(), true); + if (partition != _partition) + return B_ERROR; + status_t result = partition->Open(O_RDWR, &fd); + if (result != B_OK) + return result; + } + // let the module do its job + status_t result = fModule->create_child(fd, partition->ID(), offset, size, + type, parameters, job->ID(), &childID); + + // find and return the child + *child = manager->FindPartition(childID, false); + + // cleanup and return + close(fd); + return result; } // DeleteChild diff --git a/src/system/kernel/disk_device_manager/ddm_userland_interface.cpp b/src/system/kernel/disk_device_manager/ddm_userland_interface.cpp index 743e6ecdcd..8f04e61b68 100644 --- a/src/system/kernel/disk_device_manager/ddm_userland_interface.cpp +++ b/src/system/kernel/disk_device_manager/ddm_userland_interface.cpp @@ -1,4 +1,7 @@ -// ddm_userland_interface.cpp +/** \file ddm_userland_interface.cpp + * + * \brief Interface for userspace calls. + */ #include @@ -721,7 +724,7 @@ _user_supports_initializing_partition(partition_id partitionID, int32 changeCounter, const char *_diskSystemName) { - if (_diskSystemName) + if (!_diskSystemName) return false; char diskSystemName[B_DISK_SYSTEM_NAME_LENGTH]; status_t error = ddm_strlcpy(diskSystemName, _diskSystemName, B_DISK_SYSTEM_NAME_LENGTH); @@ -969,10 +972,10 @@ _user_validate_initialize_partition(partition_id partitionID, error = validate_initialize_partition(partition, changeCounter, diskSystemName, name, parameters); } - if (!error) - error = ddm_strlcpy(_name, name, B_DISK_DEVICE_NAME_LENGTH); + if (!error) + error = ddm_strlcpy(name, _name, B_DISK_DEVICE_NAME_LENGTH); free(parameters); - return error; + return error; } // _user_validate_create_child_partition @@ -1548,6 +1551,7 @@ _user_initialize_partition(partition_id partitionID, int32 changeCounter, } if (!error) { partition->Changed(B_PARTITION_CHANGED_CONTENT_PARAMETERS); + partition->Changed(B_PARTITION_CHANGED_INITIALIZATION); // implicit content disk system changes error = partition->DiskSystem()->ShadowPartitionChanged( partition, B_PARTITION_INITIALIZE); diff --git a/src/system/kernel/disk_device_manager/jobs/KCreateChildJob.cpp b/src/system/kernel/disk_device_manager/jobs/KCreateChildJob.cpp index 72c41fd938..a53af21c4d 100644 --- a/src/system/kernel/disk_device_manager/jobs/KCreateChildJob.cpp +++ b/src/system/kernel/disk_device_manager/jobs/KCreateChildJob.cpp @@ -1,3 +1,114 @@ // KCreateChildJob.cpp #include "KCreateChildJob.h" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ddm_operation_validation.h" + + + +KCreateChildJob::KCreateChildJob(partition_id partition, partition_id child, off_t offset, + off_t size, const char *type, const char *parameters) + : KDiskDeviceJob( B_DISK_DEVICE_JOB_CREATE, partition, partition ), + fChildID( child ), fOffset( offset ), fSize( size ), + fType ( !type ? NULL : strcpy ( new char[strlen(type)+1], type ) ), + fParameters( !parameters ? NULL : strcpy( new char[strlen(parameters)+1], parameters ) ) +{ + SetDescription( "creating child of the partition" ); +} + +KCreateChildJob::~KCreateChildJob() {} + +/** + * Do the actual creation + * + * \note in time of calling the \c KDiskSystem function for creating child, the partition is NOT locked + */ +status_t KCreateChildJob::Do() { + 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); + + + if (!partition->DiskSystem()) { + SetErrorMessage("Partition has no disk system!"); + return B_BAD_VALUE; + } + + + + // all descendants should be marked busy/descendant busy + if ( isPartitionNotBusy( partition ) ) { + SetErrorMessage("Can't create child of non-busy partition!"); + return B_ERROR; + } + + + KPartition * childPartition = manager->WriteLockPartition( fChildID ); + if( !childPartition ) { + //TODO + } + + + off_t newOffset = fOffset; + off_t newSize = fSize; + + + status_t validation_result = validate_create_child_partition ( + partition, partition->ChangeCounter(), + &newOffset, &fSize, fType, + fParameters, NULL, false + ); + + if( validation_result != B_OK ) { + SetErrorMessage( "Validating of creating new child failed!" ); + return validation_result; + } + + if( newOffset != fOffset ) { + SetErrorMessage( "Requested offset is not valid." ); + return B_ERROR; + } + + if( newSize != fSize ) { + SetErrorMessage( "Requested size is not valid" ); + } + + KDiskSystem *diskSystem = partition->DiskSystem(); + DiskSystemLoader loader(diskSystem); + KPartition * newChild = 0; + + locker.Unlock(); + + status_t create_result = diskSystem->CreateChild( + partition, newOffset, newSize, fType, + fParameters, this, &newChild, fChildID ); + + if( create_result != B_OK ) { + SetErrorMessage( "Creating new partition child failed!" ); + return create_result; + } + + return B_OK; + } + else { + SetErrorMessage( "Couldn't find partition." ); + return B_ENTRY_NOT_FOUND; + } +} diff --git a/src/system/kernel/disk_device_manager/jobs/KCreateChildJob.h b/src/system/kernel/disk_device_manager/jobs/KCreateChildJob.h index d0a631b324..629d1d073c 100644 --- a/src/system/kernel/disk_device_manager/jobs/KCreateChildJob.h +++ b/src/system/kernel/disk_device_manager/jobs/KCreateChildJob.h @@ -8,13 +8,32 @@ namespace BPrivate { namespace DiskDevice { +/** + * Create new child of given partition + */ class KCreateChildJob : public KDiskDeviceJob { public: + /** + * Creates the job. + * + * \param partition whose children should we create + * \param child new child ID + * \param offset where the child should start + * \param size size of the new child + * \param parameters additional parameters for the operation + */ KCreateChildJob(partition_id partition, partition_id child, off_t offset, - off_t size, const char *parameters); + off_t size, const char *type, const char *parameters); virtual ~KCreateChildJob(); virtual status_t Do(); + +private: + partition_id fChildID; + off_t fOffset, fSize; + char * fType; + char * fParameters; + }; } // namespace DiskDevice diff --git a/src/system/kernel/disk_device_manager/jobs/KDefragmentJob.cpp b/src/system/kernel/disk_device_manager/jobs/KDefragmentJob.cpp index 58fa11aff3..2c88448ba6 100644 --- a/src/system/kernel/disk_device_manager/jobs/KDefragmentJob.cpp +++ b/src/system/kernel/disk_device_manager/jobs/KDefragmentJob.cpp @@ -1,3 +1,92 @@ // KDefragmentJob.cpp #include "KDefragmentJob.h" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ddm_operation_validation.h" + + +KDefragmentJob::KDefragmentJob(partition_id partition) + : KDiskDeviceJob( B_DISK_DEVICE_JOB_DEFRAGMENT, partition, partition ) +{ + SetDescription( "defragmenting partition" ); +} + + +KDefragmentJob::~KDefragmentJob() {} + +status_t KDefragmentJob::Do(){ + + 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); + + //some basic checks + + if (!partition->DiskSystem()) { + SetErrorMessage("Partition has no disk system!"); + return B_BAD_VALUE; + } + + + // all descendants should be marked busy/descendant busy + if ( isPartitionNotBusy( partition ) ) { + SetErrorMessage("Can't defragment non-busy partition!"); + return B_ERROR; + } + + bool whileMounted; + //OK, seems alright, let's validate the job + status_t validation_result = validate_defragment_partition( + partition, partition->ChangeCounter(), + &whileMounted, false); + + if( validation_result != B_OK ) { + SetErrorMessage( "Validation of defragmenting partition failed."); + return validation_result; + } + + if( !whileMounted && partition->IsMounted() ) { + SetErrorMessage( "This partition cannot be defragmented while mounted." ); + return B_ERROR; + } + + //everything OK, let's do the job! + + KDiskSystem *diskSystem = partition->DiskSystem(); + DiskSystemLoader loader(diskSystem); + + locker.Unlock(); + + status_t defrag_result = diskSystem->Defragment( partition, this ); + + if( defrag_result != B_OK ) { + SetErrorMessage( "Defragmenting partition failed!" ); + return defrag_result; + } + + return B_OK; + + + } else { + SetErrorMessage( "Couldn't find partition!" ); + return B_ENTRY_NOT_FOUND; + } + +} diff --git a/src/system/kernel/disk_device_manager/jobs/KDefragmentJob.h b/src/system/kernel/disk_device_manager/jobs/KDefragmentJob.h index 28e3982308..d3f3230ccd 100644 --- a/src/system/kernel/disk_device_manager/jobs/KDefragmentJob.h +++ b/src/system/kernel/disk_device_manager/jobs/KDefragmentJob.h @@ -8,8 +8,17 @@ namespace BPrivate { namespace DiskDevice { +/** + * Defragments the device + */ class KDefragmentJob : public KDiskDeviceJob { public: + /** + * Creates the job + * + * \param partition which device should we defragment + */ + KDefragmentJob(partition_id partition); virtual ~KDefragmentJob(); diff --git a/src/system/kernel/disk_device_manager/jobs/KDeleteChildJob.cpp b/src/system/kernel/disk_device_manager/jobs/KDeleteChildJob.cpp index 5eb856a830..db471ffe59 100644 --- a/src/system/kernel/disk_device_manager/jobs/KDeleteChildJob.cpp +++ b/src/system/kernel/disk_device_manager/jobs/KDeleteChildJob.cpp @@ -1,3 +1,80 @@ // KDeleteChildJob.cpp #include "KDeleteChildJob.h" + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ddm_operation_validation.h" + + + +KDeleteChildJob::KDeleteChildJob(partition_id parent, partition_id partition) + : KDiskDeviceJob( B_DISK_DEVICE_JOB_DELETE, partition, parent ) +{ + SetDescription( "deleting child of the partition" ); +} + +KDeleteChildJob::~KDeleteChildJob() {} + +status_t KDeleteChildJob::Do(){ + 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); + + + if (!partition->ParentDiskSystem()) { + SetErrorMessage("Partition has no parent disk system!"); + return B_BAD_VALUE; + } + + // all descendants should be marked busy/descendant busy + if ( isPartitionNotBusy( partition ) ) { + SetErrorMessage("Can't delete child of non-busy partition!"); + return B_ERROR; + } + + status_t validation_result = validate_delete_child_partition( + partition, partition->ChangeCounter(), + false); + + if( validation_result != B_OK ) { + SetErrorMessage( "Validation of deleting child failed!" ); + return validation_result; + } + + //everything OK, let's do the job! + KDiskSystem *parentDiskSystem = partition->ParentDiskSystem(); + DiskSystemLoader loader(parentDiskSystem ); + + locker.Unlock(); + + status_t delete_result = parentDiskSystem->DeleteChild( partition, this ); + + if( delete_result != B_OK ) { + SetErrorMessage( "Deleting child failed!" ); + return delete_result; + } + + return B_OK; + + } else { + SetErrorMessage( "Couldn't find partition!" ); + return B_ENTRY_NOT_FOUND; + } +} diff --git a/src/system/kernel/disk_device_manager/jobs/KDeleteChildJob.h b/src/system/kernel/disk_device_manager/jobs/KDeleteChildJob.h index fec4cd5a1a..67955dd26e 100644 --- a/src/system/kernel/disk_device_manager/jobs/KDeleteChildJob.h +++ b/src/system/kernel/disk_device_manager/jobs/KDeleteChildJob.h @@ -8,8 +8,17 @@ namespace BPrivate { namespace DiskDevice { +/** + * Deletes specific child of a partition/device + */ class KDeleteChildJob : public KDiskDeviceJob { public: + /** + * Creates the job + * + * \param parent device of the deleted partition + * \param partition partition supposed to be removed + */ KDeleteChildJob(partition_id parent, partition_id partition); virtual ~KDeleteChildJob(); diff --git a/src/system/kernel/disk_device_manager/jobs/KInitializeJob.cpp b/src/system/kernel/disk_device_manager/jobs/KInitializeJob.cpp index ededba4573..a090dad555 100644 --- a/src/system/kernel/disk_device_manager/jobs/KInitializeJob.cpp +++ b/src/system/kernel/disk_device_manager/jobs/KInitializeJob.cpp @@ -1,3 +1,105 @@ // KInitializeJob.cpp +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ddm_operation_validation.h" #include "KInitializeJob.h" + +// debugging +//#define DBG(x) +#define DBG(x) x +#define OUT dprintf + + +KInitializeJob::KInitializeJob(partition_id partition, disk_system_id diskSystemID, + const char *name, const char *parameters) + : KDiskDeviceJob( B_DISK_DEVICE_JOB_INITIALIZE, partition, partition ), + fDiskSystemID( diskSystemID ), + fName( !name ? NULL : strcpy( new char[strlen(name)+1], name ) ), + fParameters( !parameters ? NULL : strcpy( new char[strlen(parameters)+1], parameters ) ) +{ + SetDescription( "initializing the partition with given disk system" ); +} + +KInitializeJob::~KInitializeJob() { + delete[] fParameters; +} + +status_t KInitializeJob::Do() { +DBG(OUT("KInitializeJob::Do(%ld)\n", PartitionID())); + 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; +// } + + // all descendants should be marked busy/descendant busy + if ( isPartitionNotBusy( partition ) ) { + SetErrorMessage("Can't initialize non-busy partition!"); + return B_ERROR; + } + +/* if( !fParameters ) { + //no parameters for the operation + SetErrorMessage( "No parameters for partition initialization." ); + return B_ERROR; + }*/ + + + //TODO shouldn't we load the disk system AFTER the validation? + KDiskSystem *diskSystemToInit = manager->LoadDiskSystem( fDiskSystemID ); + if( ! diskSystemToInit ) { + SetErrorMessage( "Given DiskSystemID doesn't correspond to any known DiskSystem."); + return B_BAD_VALUE; + } + DiskSystemLoader loader2(diskSystemToInit); + + status_t validation_result = validate_initialize_partition( + partition, partition->ChangeCounter(), + diskSystemToInit->Name(), fName, + fParameters, false ); + + if( validation_result != B_OK ) { + SetErrorMessage( "Validation of initializing partition failed!" ); + return validation_result; + } + + //everything seems OK -> let's do the job + locker.Unlock(); + + status_t init_result = diskSystemToInit->Initialize( partition, fName, fParameters, this ); + + if( init_result != B_OK ) { + SetErrorMessage( "Initialization of partition failed!" ); + return init_result; + } + + partition->SetDiskSystem(diskSystemToInit); + + return B_OK; + + + } else { + SetErrorMessage( "Couldn't find partition." ); + return B_ENTRY_NOT_FOUND; + } + +} diff --git a/src/system/kernel/disk_device_manager/jobs/KInitializeJob.h b/src/system/kernel/disk_device_manager/jobs/KInitializeJob.h index 055cd75243..f66b498a43 100644 --- a/src/system/kernel/disk_device_manager/jobs/KInitializeJob.h +++ b/src/system/kernel/disk_device_manager/jobs/KInitializeJob.h @@ -8,13 +8,29 @@ namespace BPrivate { namespace DiskDevice { +/** + * Initializes the device with given disk system (i.e. partitioning or file system) + */ class KInitializeJob : public KDiskDeviceJob { public: + /** + * Creates the job. + * + * \param partition the partition to initialize + * \param diskSystemID which disk system the partition should be initialized with + * \param parameters additional parameters for the operation + */ KInitializeJob(partition_id partition, disk_system_id diskSystemID, - const char *parameters); + const char *name, const char *parameters); virtual ~KInitializeJob(); virtual status_t Do(); + +private: + disk_system_id fDiskSystemID; + char * fName; + char * fParameters; + }; } // namespace DiskDevice diff --git a/src/system/kernel/disk_device_manager/jobs/KMoveJob.cpp b/src/system/kernel/disk_device_manager/jobs/KMoveJob.cpp index 948aa5d40e..85953ecca6 100644 --- a/src/system/kernel/disk_device_manager/jobs/KMoveJob.cpp +++ b/src/system/kernel/disk_device_manager/jobs/KMoveJob.cpp @@ -1,3 +1,98 @@ // KMoveJob.cpp - #include "KMoveJob.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ddm_operation_validation.h" + + + +// debugging +//#define DBG(x) +#define DBG(x) x +#define OUT dprintf + +KMoveJob::KMoveJob(partition_id parentID, partition_id partitionID, off_t offset) + : KDiskDeviceJob(B_DISK_DEVICE_JOB_MOVE, partitionID, parentID ), + fNewOffset(offset) +{ + SetDescription( "moving partition" ); +} + +KMoveJob::~KMoveJob() {} + + +status_t KMoveJob::Do() { + + DBG(OUT( "KMoveJob::Do(%ld)\n", PartitionID() )); + + //get the partition + KDiskDeviceManager * manager = KDiskDeviceManager::Default(); + KPartition *partition = manager->WriteLockPartition(PartitionID()); + if (partition) { + //OK, we have the partition, do some checks + 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(partition->Offset() == fNewOffset ) { + //we are already on the right place -> nothing to do... + return B_OK; + } + + off_t new_offset = fNewOffset; + + status_t validate_result = validate_move_partition(partition, partition->ChangeCounter(), + &new_offset, true, false ); //TODO posledni 2 parametry???? + if( validate_result != B_OK ) { + SetErrorMessage( "Validation of the new partition offset failed." ); + return validate_result; + } + + if( new_offset != fNewOffset ) { + SetErrorMessage( "Requested partition offset not valid." ); + return B_ERROR; + } + + // all descendants should be marked busy/descendant busy + if ( isPartitionNotBusy( partition ) ) { + SetErrorMessage("Can't move non-busy partition!"); + return B_ERROR; + } + + //get all necessary objects + KDiskSystem *parentDiskSystem = partition->ParentDiskSystem(); + KDiskSystem *childDiskSystem = partition->DiskSystem(); + + + locker.Unlock(); + + status_t move_result = parentDiskSystem->Move( partition, fNewOffset, this ); + if( move_result != B_OK ) { + SetErrorMessage( "Moving of partition failed." ); + } + return move_result; + //do the move + + } else { + SetErrorMessage("Couldn't find partition."); + return B_ENTRY_NOT_FOUND; + } + return B_ERROR; +} diff --git a/src/system/kernel/disk_device_manager/jobs/KMoveJob.h b/src/system/kernel/disk_device_manager/jobs/KMoveJob.h index de96c9ff02..f525d34c58 100644 --- a/src/system/kernel/disk_device_manager/jobs/KMoveJob.h +++ b/src/system/kernel/disk_device_manager/jobs/KMoveJob.h @@ -3,17 +3,31 @@ #ifndef _K_DISK_DEVICE_MOVE_JOB_H #define _K_DISK_DEVICE_MOVE_JOB_H -#include "KDiskDeviceJob.h" +#include "KDiskDeviceJob.h" namespace BPrivate { namespace DiskDevice { +/** + * Moves given child of a partition/device + */ class KMoveJob : public KDiskDeviceJob { public: - KMoveJob(partition_id parent, partition_id partition, off_t offset); + /** + * Creates the job. + * + * \param parentID the device whose child should be moved + * \param partitionID the child to move + * \param offset where to move + */ + KMoveJob(partition_id parentID, partition_id partitionID, off_t offset); virtual ~KMoveJob(); virtual status_t Do(); + + +private: + off_t fNewOffset; }; } // namespace DiskDevice diff --git a/src/system/kernel/disk_device_manager/jobs/KRepairJob.cpp b/src/system/kernel/disk_device_manager/jobs/KRepairJob.cpp index 9261a41e58..0a6ad415f0 100644 --- a/src/system/kernel/disk_device_manager/jobs/KRepairJob.cpp +++ b/src/system/kernel/disk_device_manager/jobs/KRepairJob.cpp @@ -1,3 +1,95 @@ // KRepairJob.cpp #include "KRepairJob.h" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ddm_operation_validation.h" + + + + + + +KRepairJob::KRepairJob(partition_id partition, bool checkOnly) + : KDiskDeviceJob( B_DISK_DEVICE_JOB_REPAIR, partition, partition ), + fCheckOnly( checkOnly ) +{ + SetDescription( "repairing partition" ); +} +KRepairJob::~KRepairJob() {} + +status_t KRepairJob::Do(){ + + 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->DiskSystem() ) { + SetErrorMessage( "Partition has no disk system." ); + return B_BAD_VALUE; + } + + if ( isPartitionNotBusy( partition ) ) { + SetErrorMessage("Can't repair non-busy partition!"); + return B_ERROR; + } + + bool whileMounted; + + status_t validation_result = validate_repair_partition( + partition, partition->ChangeCounter(), + fCheckOnly, &whileMounted, + false); + + if( validation_result != B_OK ) { + SetErrorMessage( "Validation repairing partition failed!" ); + return validation_result; + } + + //everything OK, let's do the job + KDiskSystem * diskSystem = partition->DiskSystem(); + DiskSystemLoader loader(diskSystem); + + locker.Unlock(); + + status_t repair_result = diskSystem->Repair( partition, fCheckOnly, this ); + + if( repair_result != B_OK ) { + if( fCheckOnly ) { + SetErrorMessage( "Checking for repairing partition failed!" ); + } else { + SetErrorMessage( "Repairing partition failed!" ); + } + return repair_result; + } + + return B_OK; + + }else { + SetErrorMessage( "Couldn't find partition!" ); + return B_ENTRY_NOT_FOUND; + } + + + + + + +} diff --git a/src/system/kernel/disk_device_manager/jobs/KRepairJob.h b/src/system/kernel/disk_device_manager/jobs/KRepairJob.h index a666bed994..421d9cd0d1 100644 --- a/src/system/kernel/disk_device_manager/jobs/KRepairJob.h +++ b/src/system/kernel/disk_device_manager/jobs/KRepairJob.h @@ -8,12 +8,25 @@ namespace BPrivate { namespace DiskDevice { +/** + * Repair partition (or check for repairs) + */ class KRepairJob : public KDiskDeviceJob { public: - KRepairJob(partition_id partition); + /** + * Creates the job. + * + * \param partition the partition which should be repared + * \param checkOnly when true, the partition is only checked, but no actual + * repairs are proceeded + */ + KRepairJob(partition_id partition, bool checkOnly); virtual ~KRepairJob(); virtual status_t Do(); + +private: + bool fCheckOnly; }; } // namespace DiskDevice diff --git a/src/system/kernel/disk_device_manager/jobs/KResizeJob.h b/src/system/kernel/disk_device_manager/jobs/KResizeJob.h index bdad327392..606be1d7c9 100644 --- a/src/system/kernel/disk_device_manager/jobs/KResizeJob.h +++ b/src/system/kernel/disk_device_manager/jobs/KResizeJob.h @@ -8,8 +8,18 @@ namespace BPrivate { namespace DiskDevice { +/** + * Resizes a partition. + */ class KResizeJob : public KDiskDeviceJob { public: + /** + * Creates the job. + * + * \param parentID the device whose child should be resized + * \param partitionID the partition which should be resized + * \param size new size for the partition + */ KResizeJob(partition_id parentID, partition_id partitionID, off_t size); virtual ~KResizeJob(); diff --git a/src/system/kernel/disk_device_manager/jobs/KScanPartitionJob.cpp b/src/system/kernel/disk_device_manager/jobs/KScanPartitionJob.cpp index 443e737814..383fc83f18 100644 --- a/src/system/kernel/disk_device_manager/jobs/KScanPartitionJob.cpp +++ b/src/system/kernel/disk_device_manager/jobs/KScanPartitionJob.cpp @@ -33,6 +33,12 @@ KScanPartitionJob::~KScanPartitionJob() status_t KScanPartitionJob::Do() { +/*#ifdef _BOOT_MODE + OUT( "\nScanJob boot mode\n\n" ); +#else + OUT( "\nScanJob NOT boot mode\n\n" ); +#endif*/ + // get the partition KDiskDeviceManager *manager = KDiskDeviceManager::Default(); KPartition *partition = manager->WriteLockPartition(PartitionID()); diff --git a/src/system/kernel/disk_device_manager/jobs/KScanPartitionJob.h b/src/system/kernel/disk_device_manager/jobs/KScanPartitionJob.h index 8a8db88804..a33b48261f 100644 --- a/src/system/kernel/disk_device_manager/jobs/KScanPartitionJob.h +++ b/src/system/kernel/disk_device_manager/jobs/KScanPartitionJob.h @@ -10,14 +10,25 @@ namespace DiskDevice { class KPartition; +/** + * Scans partition and tries to find the most suitable disk system for it + */ class KScanPartitionJob : public KDiskDeviceJob { public: + /** + * Creates the job. + * + * \param partitionID the partition to scan + */ KScanPartitionJob(partition_id partitionID); virtual ~KScanPartitionJob(); virtual status_t Do(); private: + /** + * Do the actual scan. + */ status_t _ScanPartition(KPartition *partition); }; diff --git a/src/system/kernel/disk_device_manager/jobs/KSetParametersJob.cpp b/src/system/kernel/disk_device_manager/jobs/KSetParametersJob.cpp index 2e40a4beca..e46d172c4b 100644 --- a/src/system/kernel/disk_device_manager/jobs/KSetParametersJob.cpp +++ b/src/system/kernel/disk_device_manager/jobs/KSetParametersJob.cpp @@ -1,3 +1,129 @@ // KSetParametersJob.cpp + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + #include "KSetParametersJob.h" +#include "ddm_operation_validation.h" + + + +KSetParametersJob::KSetParametersJob(partition_id parent, partition_id partition, + const char *parameters, const char *contentParameters) + : KDiskDeviceJob(B_DISK_DEVICE_JOB_SET_TYPE, partition, parent), + fParams( !parameters ? NULL : strcpy( new char[strlen(parameters)+1], parameters )), + fContentParams( + !contentParameters ? NULL : + strcpy( new char[strlen(contentParameters)+1], contentParameters)) +{ + SetDescription( "setting partition parameters&content parameters" ); +} + + +KSetParametersJob::~KSetParametersJob(){} + +status_t KSetParametersJob::Do(){ + KDiskDeviceManager *manager = KDiskDeviceManager::Default(); + KPartition *partition = manager->WriteLockPartition(PartitionID()); + if (partition) { + if( !fParams && !fContentParams ) { + SetErrorMessage( "No parameter to set." ); + return B_BAD_VALUE; + } + PartitionRegistrar registrar(partition, true); + PartitionRegistrar deviceRegistrar(partition->Device(), true); + + //TODO is lock necessary? + DeviceWriteLocker locker(partition->Device(), true); + + + + + // all descendants should be marked busy/descendant busy + if ( isPartitionNotBusy( partition ) ) { + SetErrorMessage("Can't set parameters for non-busy partition!"); + return B_ERROR; + } + + //TODO unlock? + + if( fParams ) { + // basic checks + + if (!partition->ParentDiskSystem()) { + SetErrorMessage("Partition has no parent disk system!"); + return B_BAD_VALUE; + } + + //TODO mayebe give copy of parameters? + //we have some parameters to set + status_t validation_result = validate_set_partition_parameters( partition, partition->ChangeCounter(), fParams, false ); + + KDiskSystem *parentDiskSystem = partition->ParentDiskSystem(); + DiskSystemLoader loader(parentDiskSystem); + + if( validation_result != B_OK ) { + SetErrorMessage( "Validation of setting partition parameters failed." ); + return validation_result; + } + + locker.Unlock(); + status_t set_pars_result = parentDiskSystem->SetParameters( partition, fParams, this ); + + if( set_pars_result != B_OK ) { + SetErrorMessage( "Setting partition parameters failed." ); + } + } + + + if( fContentParams ) { + // basic checks + + if (!partition->DiskSystem()) { + SetErrorMessage("Partition has no disk system!"); + return B_BAD_VALUE; + } + + + + status_t validation_result = validate_set_partition_content_parameters ( + partition, partition->ChangeCounter(), fContentParams, false ); + + if( validation_result != B_OK ) { + SetErrorMessage( "Validation of setting partition content parameters failed." ); + return validation_result; + } + + KDiskSystem *diskSystem = partition->DiskSystem(); + DiskSystemLoader loader(diskSystem); + + locker.Unlock(); + status_t set_cont_pars_result = diskSystem->SetContentParameters( + partition, fContentParams, this ); + + if( set_cont_pars_result != B_OK ) { + SetErrorMessage( "Setting partition content parameters failed." ); + } + } + + + return B_OK; + + + } else { + SetErrorMessage( "Couldn't find partition" ); + return B_ENTRY_NOT_FOUND; + } + +} diff --git a/src/system/kernel/disk_device_manager/jobs/KSetParametersJob.h b/src/system/kernel/disk_device_manager/jobs/KSetParametersJob.h index 418dfc33cb..efcad338ea 100644 --- a/src/system/kernel/disk_device_manager/jobs/KSetParametersJob.h +++ b/src/system/kernel/disk_device_manager/jobs/KSetParametersJob.h @@ -3,18 +3,36 @@ #ifndef _K_DISK_DEVICE_SET_PARAMETERS_JOB_H #define _K_DISK_DEVICE_SET_PARAMETERS_JOB_H +#include "KDiskDeviceJob.h" + namespace BPrivate { namespace DiskDevice { -#include "KDiskDeviceJob.h" +/** + * Sets the parameters for partition and/or for its content + * + * - can set both partition parameters and parameters for its content - + * but it's possible to create it with only one of these parameters + */ class KSetParametersJob : public KDiskDeviceJob { public: + /** + * Creates the job. + * + * \param partition the partition whose params (or content params) should be set + * \param parameters the new parameters for the partition + * \param contentParameters the new parameters for partition's content + */ KSetParametersJob(partition_id parent, partition_id partition, const char *parameters, const char *contentParameters); virtual ~KSetParametersJob(); virtual status_t Do(); + + +private: + char * fParams, * fContentParams; }; } // namespace DiskDevice diff --git a/src/system/kernel/disk_device_manager/jobs/KUninitializeJob.h b/src/system/kernel/disk_device_manager/jobs/KUninitializeJob.h index daf8077890..f77b51cd3d 100644 --- a/src/system/kernel/disk_device_manager/jobs/KUninitializeJob.h +++ b/src/system/kernel/disk_device_manager/jobs/KUninitializeJob.h @@ -8,8 +8,14 @@ namespace BPrivate { namespace DiskDevice { +/** + * Uninitializes the partition/device + */ class KUninitializeJob : public KDiskDeviceJob { public: + /** + * Creates the job + */ KUninitializeJob(partition_id partitionID); virtual ~KUninitializeJob();