diff --git a/headers/private/kernel/disk_device_manager/KDiskSystem.h b/headers/private/kernel/disk_device_manager/KDiskSystem.h index 3f6e99821e..5a74e265b6 100644 --- a/headers/private/kernel/disk_device_manager/KDiskSystem.h +++ b/headers/private/kernel/disk_device_manager/KDiskSystem.h @@ -3,114 +3,116 @@ * Distributed under the terms of the MIT License. * * Authors: - * Ingo Weinhold + * Ingo Weinhold */ #ifndef _K_DISK_DEVICE_SYSTEM_H #define _K_DISK_DEVICE_SYSTEM_H #include "disk_device_manager.h" + struct user_disk_system_info; + namespace BPrivate { namespace DiskDevice { -//class KDiskDeviceJob; + class KPartition; + //! \brief Common ancestor for disk system add-on wrappers class KDiskSystem { public: - KDiskSystem(const char *name); - virtual ~KDiskSystem(); + KDiskSystem(const char *name); + virtual ~KDiskSystem(); - virtual status_t Init(); + virtual status_t Init(); -// void SetID(disk_system_id id); - disk_system_id ID() const; - const char *Name() const; - const char *PrettyName(); - uint32 Flags() const; +// void SetID(disk_system_id id); + disk_system_id ID() const; - bool IsFileSystem() const; - bool IsPartitioningSystem() const; + const char* Name() const; + const char* PrettyName(); + uint32 Flags() const; - void GetInfo(user_disk_system_info *info); + bool IsFileSystem() const; + bool IsPartitioningSystem() const; + + void GetInfo(user_disk_system_info* info); // manager will be locked - status_t Load(); // load/unload -- can be nested - void Unload(); // - bool IsLoaded() const; + status_t Load(); // load/unload -- can be nested + void Unload(); // + bool IsLoaded() const; // Scanning // Device must be write locked. - virtual float Identify(KPartition *partition, void **cookie); - virtual status_t Scan(KPartition *partition, void *cookie); - virtual void FreeIdentifyCookie(KPartition *partition, void *cookie); - virtual void FreeCookie(KPartition *partition); - virtual void FreeContentCookie(KPartition *partition); + virtual float Identify(KPartition* partition, void** cookie); + virtual status_t Scan(KPartition* partition, void* cookie); + virtual void FreeIdentifyCookie(KPartition* partition, + void* cookie); + virtual void FreeCookie(KPartition* partition); + virtual void FreeContentCookie(KPartition* partition); // Writing - // Device should not be locked. + // Device should not be locked, but all affected partitions are marked + // busy, meaning that no one else is allowed to modify it (and we only, + // if we get a write lock). -#if 0 - virtual status_t Defragment(KPartition *partition, KDiskDeviceJob *job); - virtual status_t Repair(KPartition *partition, bool checkOnly, - KDiskDeviceJob *job); - virtual status_t Resize(KPartition *partition, off_t size, - KDiskDeviceJob *job); - virtual status_t ResizeChild(KPartition *child, off_t size, - KDiskDeviceJob *job); - virtual status_t Move(KPartition *partition, off_t offset, - KDiskDeviceJob *job); - virtual status_t MoveChild(KPartition *child, off_t offset, - KDiskDeviceJob *job); - virtual status_t SetName(KPartition *partition, char *name, - KDiskDeviceJob *job); - virtual status_t SetContentName(KPartition *partition, char *name, - KDiskDeviceJob *job); - virtual status_t SetType(KPartition *partition, char *type, - KDiskDeviceJob *job); - virtual status_t SetParameters(KPartition *partition, - const char *parameters, - KDiskDeviceJob *job); - virtual status_t SetContentParameters(KPartition *partition, - const char *parameters, - KDiskDeviceJob *job); - virtual status_t Initialize(KPartition *partition, const char *name, - const char *parameters, KDiskDeviceJob *job); - 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); - virtual status_t DeleteChild(KPartition *child, KDiskDeviceJob *job); -// The KPartition* parameters for the writing methods are a bit `volatile', -// since the device will not be locked, when they are called. The KPartition -// is registered though, so that it is at least guaranteed that the object -// won't go away. -#endif // 0 + virtual status_t Defragment(KPartition* partition, + disk_job_id job); + virtual status_t Repair(KPartition* partition, bool checkOnly, + disk_job_id job); + virtual status_t Resize(KPartition* partition, off_t size, + disk_job_id job); + virtual status_t ResizeChild(KPartition* child, off_t size, + disk_job_id job); + virtual status_t Move(KPartition* partition, off_t offset, + disk_job_id job); + virtual status_t MoveChild(KPartition* child, off_t offset, + disk_job_id job); + virtual status_t SetName(KPartition* partition, const char* name, + disk_job_id job); + virtual status_t SetContentName(KPartition* partition, + const char* name, disk_job_id job); + virtual status_t SetType(KPartition* partition, const char* type, + disk_job_id job); + virtual status_t SetParameters(KPartition* partition, + const char* parameters, disk_job_id job); + virtual status_t SetContentParameters(KPartition* partition, + const char* parameters, disk_job_id job); + virtual status_t Initialize(KPartition* partition, + const char* name, const char* parameters, + disk_job_id job); + virtual status_t CreateChild(KPartition* partition, off_t offset, + off_t size, const char* type, + const char* name, const char* parameters, + disk_job_id job, KPartition** child = NULL, + partition_id childID = -1); + virtual status_t DeleteChild(KPartition* child, disk_job_id job); protected: - virtual status_t LoadModule(); - virtual void UnloadModule(); + virtual status_t LoadModule(); + virtual void UnloadModule(); - status_t SetPrettyName(const char *name); - void SetFlags(uint32 flags); + status_t SetPrettyName(const char* name); + void SetFlags(uint32 flags); - static int32 _NextID(); + static int32 _NextID(); private: - disk_system_id fID; - char *fName; - char *fPrettyName; - uint32 fFlags; - int32 fLoadCounter; + disk_system_id fID; + char* fName; + char* fPrettyName; + uint32 fFlags; + int32 fLoadCounter; - static int32 fNextID; + static int32 fNextID; }; + } // namespace DiskDevice } // namespace BPrivate diff --git a/headers/private/kernel/disk_device_manager/KFileSystem.h b/headers/private/kernel/disk_device_manager/KFileSystem.h index 3181f561ce..bda46ecf6f 100644 --- a/headers/private/kernel/disk_device_manager/KFileSystem.h +++ b/headers/private/kernel/disk_device_manager/KFileSystem.h @@ -6,60 +6,63 @@ * Ingo Weinhold * * KFileSystem implements the KDiskSystem interface for file systems. - * It works with the FS API. */ #ifndef _K_FILE_DISK_DEVICE_SYSTEM_H #define _K_FILE_DISK_DEVICE_SYSTEM_H #include "KDiskSystem.h" + 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); - virtual ~KFileSystem(); + KFileSystem(const char* name); + virtual ~KFileSystem(); - virtual status_t Init(); + virtual status_t Init(); // Scanning - virtual float Identify(KPartition *partition, void **cookie); - virtual status_t Scan(KPartition *partition, void *cookie); - virtual void FreeIdentifyCookie(KPartition *partition, void *cookie); - virtual void FreeContentCookie(KPartition *partition); + virtual float Identify(KPartition* partition, void** cookie); + virtual status_t Scan(KPartition* partition, void* cookie); + virtual void FreeIdentifyCookie(KPartition* partition, + void* cookie); + virtual void FreeContentCookie(KPartition* partition); // Writing -#if 0 - virtual status_t Defragment(KPartition *partition, KDiskDeviceJob *job); - virtual status_t Repair(KPartition *partition, bool checkOnly, - KDiskDeviceJob *job); - virtual status_t Resize(KPartition *partition, off_t size, - KDiskDeviceJob *job); - virtual status_t Move(KPartition *partition, off_t offset, - KDiskDeviceJob *job); - virtual status_t SetContentName(KPartition *partition, char *name, - KDiskDeviceJob *job); - virtual status_t SetContentParameters(KPartition *partition, - const char *parameters, - KDiskDeviceJob *job); - virtual status_t Initialize(KPartition *partition, const char *name, - const char *parameters, KDiskDeviceJob *job); -#endif // 0 + virtual status_t Defragment(KPartition* partition, + disk_job_id job); + virtual status_t Repair(KPartition* partition, bool checkOnly, + disk_job_id job); + virtual status_t Resize(KPartition* partition, off_t size, + disk_job_id job); + virtual status_t Move(KPartition* partition, off_t offset, + disk_job_id job); + virtual status_t SetContentName(KPartition* partition, + const char* name, disk_job_id job); + virtual status_t SetContentParameters(KPartition* partition, + const char* parameters, disk_job_id job); + virtual status_t Initialize(KPartition* partition, + const char* name, const char* parameters, + disk_job_id job); protected: - virtual status_t LoadModule(); - virtual void UnloadModule(); + virtual status_t LoadModule(); + virtual void UnloadModule(); private: - file_system_module_info *fModule; + file_system_module_info* fModule; }; + } // namespace DiskDevice } // namespace BPrivate diff --git a/headers/private/kernel/disk_device_manager/KPartitioningSystem.h b/headers/private/kernel/disk_device_manager/KPartitioningSystem.h index de82a1fb31..bbe4577033 100644 --- a/headers/private/kernel/disk_device_manager/KPartitioningSystem.h +++ b/headers/private/kernel/disk_device_manager/KPartitioningSystem.h @@ -10,11 +10,14 @@ #include "KDiskSystem.h" + struct partition_module_info; + namespace BPrivate { namespace DiskDevice { + /** * \brief Wrapper for the C interface of a partitioning system add-on. * @@ -22,62 +25,61 @@ namespace DiskDevice { */ class KPartitioningSystem : public KDiskSystem { public: - KPartitioningSystem(const char *name); - virtual ~KPartitioningSystem(); + KPartitioningSystem(const char* name); + virtual ~KPartitioningSystem(); - virtual status_t Init(); + virtual status_t Init(); // Scanning - virtual float Identify(KPartition *partition, void **cookie); - virtual status_t Scan(KPartition *partition, void *cookie); - virtual void FreeIdentifyCookie(KPartition *partition, void *cookie); - virtual void FreeCookie(KPartition *partition); - virtual void FreeContentCookie(KPartition *partition); + virtual float Identify(KPartition* partition, void** cookie); + virtual status_t Scan(KPartition* partition, void* cookie); + virtual void FreeIdentifyCookie(KPartition* partition, + void* cookie); + virtual void FreeCookie(KPartition* partition); + virtual void FreeContentCookie(KPartition* partition); // Writing -#if 0 - virtual status_t Repair(KPartition *partition, bool checkOnly, - KDiskDeviceJob *job); - virtual status_t Resize(KPartition *partition, off_t size, - KDiskDeviceJob *job); - virtual status_t ResizeChild(KPartition *child, off_t size, - KDiskDeviceJob *job); - virtual status_t Move(KPartition *partition, off_t offset, - KDiskDeviceJob *job); - virtual status_t MoveChild(KPartition *child, off_t offset, - KDiskDeviceJob *job); - virtual status_t SetName(KPartition *partition, char *name, - KDiskDeviceJob *job); - virtual status_t SetContentName(KPartition *partition, char *name, - KDiskDeviceJob *job); - virtual status_t SetType(KPartition *partition, char *type, - KDiskDeviceJob *job); - virtual status_t SetParameters(KPartition *partition, - const char *parameters, - KDiskDeviceJob *job); - virtual status_t SetContentParameters(KPartition *partition, - const char *parameters, - KDiskDeviceJob *job); - 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); - virtual status_t DeleteChild(KPartition *child, KDiskDeviceJob *job); - virtual status_t Initialize(KPartition *partition, const char *name, - const char *parameters, KDiskDeviceJob *job); -#endif // 0 + virtual status_t Repair(KPartition* partition, bool checkOnly, + disk_job_id job); + virtual status_t Resize(KPartition* partition, off_t size, + disk_job_id job); + virtual status_t ResizeChild(KPartition* child, off_t size, + disk_job_id job); + virtual status_t Move(KPartition* partition, off_t offset, + disk_job_id job); + virtual status_t MoveChild(KPartition* child, off_t offset, + disk_job_id job); + virtual status_t SetName(KPartition* partition, const char* name, + disk_job_id job); + virtual status_t SetContentName(KPartition* partition, + const char* name, disk_job_id job); + virtual status_t SetType(KPartition* partition, const char* type, + disk_job_id job); + virtual status_t SetParameters(KPartition* partition, + const char* parameters, disk_job_id job); + virtual status_t SetContentParameters(KPartition* partition, + const char* parameters, disk_job_id job); + virtual status_t Initialize(KPartition* partition, + const char* name, const char* parameters, + disk_job_id job); + virtual status_t CreateChild(KPartition* partition, off_t offset, + off_t size, const char* type, + const char* name, const char* parameters, + disk_job_id job, KPartition** child = NULL, + partition_id childID = -1); + virtual status_t DeleteChild(KPartition* child, disk_job_id job); protected: - virtual status_t LoadModule(); - virtual void UnloadModule(); + virtual status_t LoadModule(); + virtual void UnloadModule(); private: - partition_module_info *fModule; + partition_module_info* fModule; }; + } // namespace DiskDevice } // namespace BPrivate diff --git a/src/system/kernel/disk_device_manager/KDiskSystem.cpp b/src/system/kernel/disk_device_manager/KDiskSystem.cpp index 0594ac4ff9..906cdccfe0 100644 --- a/src/system/kernel/disk_device_manager/KDiskSystem.cpp +++ b/src/system/kernel/disk_device_manager/KDiskSystem.cpp @@ -190,11 +190,9 @@ KDiskSystem::FreeContentCookie(KPartition *partition) } -#if 0 - // Defragment status_t -KDiskSystem::Defragment(KPartition *partition, KDiskDeviceJob *job) +KDiskSystem::Defragment(KPartition* partition, disk_job_id job) { // to be implemented by derived classes return B_ERROR; @@ -203,8 +201,7 @@ KDiskSystem::Defragment(KPartition *partition, KDiskDeviceJob *job) // Repair status_t -KDiskSystem::Repair(KPartition *partition, bool checkOnly, - KDiskDeviceJob *job) +KDiskSystem::Repair(KPartition* partition, bool checkOnly, disk_job_id job) { // to be implemented by derived classes return B_ERROR; @@ -213,7 +210,7 @@ KDiskSystem::Repair(KPartition *partition, bool checkOnly, // Resize status_t -KDiskSystem::Resize(KPartition *partition, off_t size, KDiskDeviceJob *job) +KDiskSystem::Resize(KPartition* partition, off_t size, disk_job_id job) { // to be implemented by derived classes return B_ERROR; @@ -222,7 +219,7 @@ KDiskSystem::Resize(KPartition *partition, off_t size, KDiskDeviceJob *job) // ResizeChild status_t -KDiskSystem::ResizeChild(KPartition *child, off_t size, KDiskDeviceJob *job) +KDiskSystem::ResizeChild(KPartition* child, off_t size, disk_job_id job) { // to be implemented by derived classes return B_ERROR; @@ -231,7 +228,7 @@ KDiskSystem::ResizeChild(KPartition *child, off_t size, KDiskDeviceJob *job) // Move status_t -KDiskSystem::Move(KPartition *partition, off_t offset, KDiskDeviceJob *job) +KDiskSystem::Move(KPartition* partition, off_t offset, disk_job_id job) { // to be implemented by derived classes return B_ERROR; @@ -240,7 +237,7 @@ KDiskSystem::Move(KPartition *partition, off_t offset, KDiskDeviceJob *job) // MoveChild status_t -KDiskSystem::MoveChild(KPartition *child, off_t offset, KDiskDeviceJob *job) +KDiskSystem::MoveChild(KPartition* child, off_t offset, disk_job_id job) { // to be implemented by derived classes return B_ERROR; @@ -249,7 +246,7 @@ KDiskSystem::MoveChild(KPartition *child, off_t offset, KDiskDeviceJob *job) // SetName status_t -KDiskSystem::SetName(KPartition *partition, char *name, KDiskDeviceJob *job) +KDiskSystem::SetName(KPartition* partition, const char* name, disk_job_id job) { // to be implemented by derived classes return B_ERROR; @@ -258,8 +255,8 @@ KDiskSystem::SetName(KPartition *partition, char *name, KDiskDeviceJob *job) // SetContentName status_t -KDiskSystem::SetContentName(KPartition *partition, char *name, - KDiskDeviceJob *job) +KDiskSystem::SetContentName(KPartition* partition, const char* name, + disk_job_id job) { // to be implemented by derived classes return B_ERROR; @@ -268,7 +265,7 @@ KDiskSystem::SetContentName(KPartition *partition, char *name, // SetType status_t -KDiskSystem::SetType(KPartition *partition, char *type, KDiskDeviceJob *job) +KDiskSystem::SetType(KPartition* partition, const char *type, disk_job_id job) { // to be implemented by derived classes return B_ERROR; @@ -277,8 +274,8 @@ KDiskSystem::SetType(KPartition *partition, char *type, KDiskDeviceJob *job) // SetParameters status_t -KDiskSystem::SetParameters(KPartition *partition, const char *parameters, - KDiskDeviceJob *job) +KDiskSystem::SetParameters(KPartition* partition, const char* parameters, + disk_job_id job) { // to be implemented by derived classes return B_ERROR; @@ -287,8 +284,8 @@ KDiskSystem::SetParameters(KPartition *partition, const char *parameters, // SetContentParameters status_t -KDiskSystem::SetContentParameters(KPartition *partition, - const char *parameters, KDiskDeviceJob *job) +KDiskSystem::SetContentParameters(KPartition* partition, + const char* parameters, disk_job_id job) { // to be implemented by derived classes return B_ERROR; @@ -297,8 +294,8 @@ KDiskSystem::SetContentParameters(KPartition *partition, // Initialize status_t -KDiskSystem::Initialize(KPartition *partition, const char *name, - const char *parameters, KDiskDeviceJob *job) +KDiskSystem::Initialize(KPartition* partition, const char* name, + const char* parameters, disk_job_id job) { // to be implemented by derived classes return B_ERROR; @@ -307,10 +304,9 @@ KDiskSystem::Initialize(KPartition *partition, const char *name, // CreateChild status_t -KDiskSystem::CreateChild(KPartition *partition, off_t offset, off_t size, - const char *type, const char *parameters, - KDiskDeviceJob *job, KPartition **child, - partition_id childID) +KDiskSystem::CreateChild(KPartition* partition, off_t offset, off_t size, + const char* type, const char* name, const char* parameters, disk_job_id job, + KPartition **child, partition_id childID) { // to be implemented by derived classes return B_ERROR; @@ -319,14 +315,12 @@ KDiskSystem::CreateChild(KPartition *partition, off_t offset, off_t size, // DeleteChild status_t -KDiskSystem::DeleteChild(KPartition *child, KDiskDeviceJob *job) +KDiskSystem::DeleteChild(KPartition* child, disk_job_id job) { // to be implemented by derived classes return B_ERROR; } -#endif // 0 - // LoadModule status_t diff --git a/src/system/kernel/disk_device_manager/KFileSystem.cpp b/src/system/kernel/disk_device_manager/KFileSystem.cpp index ea3b6dffa3..7bb2721616 100644 --- a/src/system/kernel/disk_device_manager/KFileSystem.cpp +++ b/src/system/kernel/disk_device_manager/KFileSystem.cpp @@ -97,11 +97,9 @@ KFileSystem::FreeContentCookie(KPartition *partition) } -#if 0 - // Defragment status_t -KFileSystem::Defragment(KPartition *partition, KDiskDeviceJob *job) +KFileSystem::Defragment(KPartition* partition, disk_job_id job) { // to be implemented return B_ERROR; @@ -110,7 +108,7 @@ KFileSystem::Defragment(KPartition *partition, KDiskDeviceJob *job) // Repair status_t -KFileSystem::Repair(KPartition *partition, bool checkOnly, KDiskDeviceJob *job) +KFileSystem::Repair(KPartition* partition, bool checkOnly, disk_job_id job) { // to be implemented return B_ERROR; @@ -119,7 +117,7 @@ KFileSystem::Repair(KPartition *partition, bool checkOnly, KDiskDeviceJob *job) // Resize status_t -KFileSystem::Resize(KPartition *partition, off_t size, KDiskDeviceJob *job) +KFileSystem::Resize(KPartition* partition, off_t size, disk_job_id job) { // to be implemented return B_ERROR; @@ -128,7 +126,7 @@ KFileSystem::Resize(KPartition *partition, off_t size, KDiskDeviceJob *job) // Move status_t -KFileSystem::Move(KPartition *partition, off_t offset, KDiskDeviceJob *job) +KFileSystem::Move(KPartition* partition, off_t offset, disk_job_id job) { // to be implemented return B_ERROR; @@ -137,58 +135,50 @@ KFileSystem::Move(KPartition *partition, off_t offset, KDiskDeviceJob *job) // SetContentName status_t -KFileSystem::SetContentName(KPartition *partition, char *name, - KDiskDeviceJob *job) +KFileSystem::SetContentName(KPartition* partition, const char* name, + disk_job_id job) { // to be implemented return B_ERROR; } +// SetContentParameters status_t -KFileSystem::SetContentParameters(KPartition *partition, - const char *parameters, KDiskDeviceJob *job) +KFileSystem::SetContentParameters(KPartition* partition, + const char* parameters, disk_job_id job) { // to be implemented return B_ERROR; } +// Initialize status_t -KFileSystem::Initialize(KPartition *partition, const char *name, - const char *parameters, KDiskDeviceJob *job) +KFileSystem::Initialize(KPartition* partition, const char* name, + const char* parameters, disk_job_id job) { // check parameters - if (!partition || !job || !fModule) + if (!partition || !fModule) return B_BAD_VALUE; if (!fModule->initialize) return B_NOT_SUPPORTED; - // open partition device (we need a temporary read-lock) - KDiskDeviceManager *manager = KDiskDeviceManager::Default(); - if (!manager->ReadLockPartition(partition->ID())) - return B_ERROR; - DeviceReadLocker locker(partition->Device(), true); - + // open partition device int fd = -1; status_t result = partition->Open(O_RDWR, &fd); if (result != B_OK) return result; - off_t partitionSize = partition->Size(); - - locker.Unlock(); - - // call the module hook + // let the module do its job result = fModule->initialize(fd, partition->ID(), name, parameters, - partitionSize, job->ID()); + partition->Size(), job); + // cleanup and return close(fd); return result; } -#endif // 0 - // LoadModule status_t diff --git a/src/system/kernel/disk_device_manager/KPartitioningSystem.cpp b/src/system/kernel/disk_device_manager/KPartitioningSystem.cpp index dc42951386..09e6002eab 100644 --- a/src/system/kernel/disk_device_manager/KPartitioningSystem.cpp +++ b/src/system/kernel/disk_device_manager/KPartitioningSystem.cpp @@ -127,13 +127,11 @@ KPartitioningSystem::FreeContentCookie(KPartition *partition) } -#if 0 - // Repair //! Repairs a partition status_t -KPartitioningSystem::Repair(KPartition *partition, bool checkOnly, - KDiskDeviceJob *job) +KPartitioningSystem::Repair(KPartition* partition, bool checkOnly, + disk_job_id job) { // to be implemented return B_ERROR; @@ -143,34 +141,22 @@ KPartitioningSystem::Repair(KPartition *partition, bool checkOnly, // Resize //! Resizes a partition status_t -KPartitioningSystem::Resize(KPartition *partition, off_t size, - KDiskDeviceJob *job) +KPartitioningSystem::Resize(KPartition* partition, off_t size, disk_job_id job) { // check parameters - if (!partition || !job || size < 0) + if (!partition || size < 0 || !fModule) return B_BAD_VALUE; if (!fModule->resize) - return B_ENTRY_NOT_FOUND; + return B_NOT_SUPPORTED; - // lock partition and open partition device - KDiskDeviceManager *manager = KDiskDeviceManager::Default(); - KPartition *_partition = manager->WriteLockPartition(partition->ID()); - if (!_partition) - return B_ERROR; + // open partition device 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; - } + status_t result = partition->Open(O_RDWR, &fd); + if (result != B_OK) + return result; // let the module do its job - status_t result = fModule->resize(fd, partition->ID(), size, job->ID()); + result = fModule->resize(fd, partition->ID(), size, job); // cleanup and return close(fd); @@ -181,35 +167,22 @@ KPartitioningSystem::Resize(KPartition *partition, off_t size, // ResizeChild //! Resizes child of a partition status_t -KPartitioningSystem::ResizeChild(KPartition *child, off_t size, - KDiskDeviceJob *job) +KPartitioningSystem::ResizeChild(KPartition* child, off_t size, disk_job_id job) { // check parameters - if (!child || !job || !child->Parent() || size < 0) + if (!child || !child->Parent() || size < 0 || !fModule) return B_BAD_VALUE; if (!fModule->resize_child) - return B_ENTRY_NOT_FOUND; + return B_NOT_SUPPORTED; - // 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; + // open partition device 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; - } + 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->resize_child(fd, child->ID(), size, job->ID()); + result = fModule->resize_child(fd, child->ID(), size, job); // cleanup and return close(fd); @@ -220,34 +193,22 @@ KPartitioningSystem::ResizeChild(KPartition *child, off_t size, // Move //! Moves a partition status_t -KPartitioningSystem::Move(KPartition *partition, off_t offset, - KDiskDeviceJob *job) +KPartitioningSystem::Move(KPartition* partition, off_t offset, disk_job_id job) { // check parameters - if (!partition || !job) + if (!partition) return B_BAD_VALUE; if (!fModule->move) - return B_ENTRY_NOT_FOUND; + return B_NOT_SUPPORTED; - // lock partition and open partition device - KDiskDeviceManager *manager = KDiskDeviceManager::Default(); - KPartition *_partition = manager->WriteLockPartition(partition->ID()); - if (!_partition) - return B_ERROR; + // open partition device 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; - } + 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()); + result = fModule->move(fd, partition->ID(), offset, job); // cleanup and return close(fd); @@ -258,36 +219,23 @@ KPartitioningSystem::Move(KPartition *partition, off_t offset, // MoveChild //! Moves child of a partition status_t -KPartitioningSystem::MoveChild(KPartition *child, off_t offset, - KDiskDeviceJob *job) +KPartitioningSystem::MoveChild(KPartition* child, off_t offset, disk_job_id job) { // check parameters - if (!child || !job || !child->Parent()) + if (!child || !child->Parent() || !fModule) return B_BAD_VALUE; if (!fModule->move_child) - return B_ENTRY_NOT_FOUND; + return B_NOT_SUPPORTED; - // 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; + // open partition device 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; - } + 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()); + result = fModule->move_child(fd, child->Parent()->ID(), child->ID(), offset, + job); // cleanup and return close(fd); @@ -298,34 +246,24 @@ KPartitioningSystem::MoveChild(KPartition *child, off_t offset, // SetName //! Sets name of a partition status_t -KPartitioningSystem::SetName(KPartition *partition, char *name, - KDiskDeviceJob *job) +KPartitioningSystem::SetName(KPartition* child, const char* name, + disk_job_id job) { // check parameters - if (!partition || !job || !name) + if (!child || !child->Parent() || !fModule) return B_BAD_VALUE; if (!fModule->set_name) - return B_ENTRY_NOT_FOUND; + return B_NOT_SUPPORTED; - // lock partition and open partition device - KDiskDeviceManager *manager = KDiskDeviceManager::Default(); - KPartition *_partition = manager->WriteLockPartition(partition->ID()); - if (!_partition) - return B_ERROR; + // open partition device 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; - } + 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->set_name(fd, partition->ID(), name, job->ID()); + result = fModule->set_name(fd, child->ID(), name, job); +// TODO: Change hook interface! // cleanup and return close(fd); @@ -336,35 +274,23 @@ KPartitioningSystem::SetName(KPartition *partition, char *name, // SetContentName //! Sets name of the content of a partition status_t -KPartitioningSystem::SetContentName(KPartition *partition, char *name, - KDiskDeviceJob *job) +KPartitioningSystem::SetContentName(KPartition* partition, const char* name, + disk_job_id job) { // check parameters - if (!partition || !job || !name) + if (!partition || !fModule) return B_BAD_VALUE; if (!fModule->set_content_name) - return B_ENTRY_NOT_FOUND; + return B_NOT_SUPPORTED; - // lock partition and open partition device - KDiskDeviceManager *manager = KDiskDeviceManager::Default(); - KPartition *_partition = manager->WriteLockPartition(partition->ID()); - if (!_partition) - return B_ERROR; + // open partition device 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; - } + 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()); + result = fModule->set_content_name(fd, partition->ID(), name, job); // cleanup and return close(fd); @@ -375,34 +301,24 @@ KPartitioningSystem::SetContentName(KPartition *partition, char *name, // SetType //! Sets type of a partition status_t -KPartitioningSystem::SetType(KPartition *partition, char *type, - KDiskDeviceJob *job) +KPartitioningSystem::SetType(KPartition* child, const char* type, + disk_job_id job) { // check parameters - if (!partition || !job || !type) + if (!child || !child->Parent() || !type || !fModule) return B_BAD_VALUE; if (!fModule->set_type) - return B_ENTRY_NOT_FOUND; + return B_NOT_SUPPORTED; - // lock partition and open partition device - KDiskDeviceManager *manager = KDiskDeviceManager::Default(); - KPartition *_partition = manager->WriteLockPartition(partition->ID()); - if (!_partition) - return B_ERROR; + // open partition device 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; - } + 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->set_type(fd, partition->ID(), type, job->ID()); + result = fModule->set_type(fd, child->Parent()->ID(), type, job); +// TODO: Change hook interface! // cleanup and return close(fd); @@ -413,35 +329,24 @@ KPartitioningSystem::SetType(KPartition *partition, char *type, // SetParameters //! Sets parameters of a partition status_t -KPartitioningSystem::SetParameters(KPartition *partition, - const char *parameters, KDiskDeviceJob *job) +KPartitioningSystem::SetParameters(KPartition* child, const char* parameters, + disk_job_id job) { // check parameters - if (!partition || !job || !parameters) + if (!child || !child->Parent() || !fModule) return B_BAD_VALUE; if (!fModule->set_parameters) - return B_ENTRY_NOT_FOUND; + return B_NOT_SUPPORTED; - // lock partition and open partition device - KDiskDeviceManager *manager = KDiskDeviceManager::Default(); - KPartition *_partition = manager->WriteLockPartition(partition->ID()); - if (!_partition) - return B_ERROR; + // open partition device 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; - } + 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->set_parameters(fd, partition->ID(), parameters, - job->ID()); + result = fModule->set_parameters(fd, child->ID(), parameters, job); +// TODO: Change hook interface! // cleanup and return close(fd); @@ -452,35 +357,24 @@ KPartitioningSystem::SetParameters(KPartition *partition, // SetContentParameters //! Sets parameters of the content of a partition status_t -KPartitioningSystem::SetContentParameters(KPartition *partition, - const char *parameters, KDiskDeviceJob *job) +KPartitioningSystem::SetContentParameters(KPartition* partition, + const char* parameters, disk_job_id job) { // check parameters - if (!partition || !job || !parameters) + if (!partition || !fModule) return B_BAD_VALUE; if (!fModule->set_content_parameters) - return B_ENTRY_NOT_FOUND; + return B_NOT_SUPPORTED; - // lock partition and open partition device - KDiskDeviceManager *manager = KDiskDeviceManager::Default(); - KPartition *_partition = manager->WriteLockPartition(partition->ID()); - if (!_partition) - return B_ERROR; + // open partition device 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; - } + 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()); + result = fModule->set_content_parameters(fd, partition->ID(), parameters, + job); // cleanup and return close(fd); @@ -491,39 +385,24 @@ KPartitioningSystem::SetContentParameters(KPartition *partition, // Initialize //! Initializes a partition with this partitioning system status_t -KPartitioningSystem::Initialize(KPartition *partition, const char *name, - const char *parameters, KDiskDeviceJob *job) +KPartitioningSystem::Initialize(KPartition* partition, const char* name, + const char* parameters, disk_job_id job) { // check parameters - if (!partition || !job /*|| !parameters*/) + if (!partition || !fModule) return B_BAD_VALUE; if (!fModule->initialize) - return B_ENTRY_NOT_FOUND; + return B_NOT_SUPPORTED; - // lock partition and open partition device - KDiskDeviceManager *manager = KDiskDeviceManager::Default(); -// TODO: This looks overly complicated. - KPartition *_partition = manager->WriteLockPartition(partition->ID()); - if (!_partition) - return B_ERROR; + // open partition device int fd = -1; - off_t partitionSize; - { - 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; - - partitionSize = partition->Size(); - } + 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, - partitionSize, job->ID()); + result = fModule->initialize(fd, partition->ID(), name, parameters, + partition->Size(), job); // cleanup and return close(fd); @@ -534,39 +413,29 @@ KPartitioningSystem::Initialize(KPartition *partition, const char *name, // CreateChild //! Creates a child partition status_t -KPartitioningSystem::CreateChild(KPartition *partition, off_t offset, - off_t size, const char *type, const char *parameters, KDiskDeviceJob *job, - KPartition **child, partition_id childID) +KPartitioningSystem::CreateChild(KPartition* partition, off_t offset, + off_t size, const char* type, const char* name, const char* parameters, + disk_job_id job, KPartition** child, partition_id childID) { // check parameters - if (!partition || !job || !type /*|| !parameters*/ || !child) + if (!partition || !type || !parameters || !child || !fModule) return B_BAD_VALUE; if (!fModule->create_child) - return B_ENTRY_NOT_FOUND; + return B_NOT_SUPPORTED; - // lock partition and open partition device - KDiskDeviceManager *manager = KDiskDeviceManager::Default(); - KPartition *_partition = manager->WriteLockPartition(partition->ID()); - if (!_partition) - return B_ERROR; + // open partition device 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; - } + 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); + result = fModule->create_child(fd, partition->ID(), offset, size, + type, parameters, job, &childID); +// TODO: Added name parameter to create_child() hook. // find and return the child - *child = manager->FindPartition(childID, false); + *child = KDiskDeviceManager::Default()->FindPartition(childID); // cleanup and return close(fd); @@ -577,14 +446,12 @@ KPartitioningSystem::CreateChild(KPartition *partition, off_t offset, // DeleteChild //! Deletes a child partition status_t -KPartitioningSystem::DeleteChild(KPartition *child, KDiskDeviceJob *job) +KPartitioningSystem::DeleteChild(KPartition* child, disk_job_id job) { // to be implemented return B_ERROR; } -#endif // 0 - // LoadModule status_t 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 539b64c674..3c36f973b9 100644 --- a/src/system/kernel/disk_device_manager/ddm_userland_interface.cpp +++ b/src/system/kernel/disk_device_manager/ddm_userland_interface.cpp @@ -22,6 +22,11 @@ using namespace BPrivate::DiskDevice; #define ERROR(x) +// TODO: Replace all instances, when it has been decided how to handle +// notifications during jobs. +#define DUMMY_JOB_ID 0 + + // TODO: Add user address checks and check return values of user_memcpy()! @@ -46,6 +51,124 @@ ddm_strlcpy(char *to, const char *from, size_t size, } +// copy_from_user_value +template +static inline status_t +copy_from_user_value(Type& value, const Type* userValue) +{ + if (!userValue) + return B_BAD_VALUE; + + if (!IS_USER_ADDRESS(userValue)) + return B_BAD_ADDRESS; + + return user_memcpy(&value, userValue, sizeof(Type)); +} + + +// copy_to_user_value +template +static inline status_t +copy_to_user_value(Type* userValue, const Type& value) +{ + if (!userValue) + return B_BAD_VALUE; + + if (!IS_USER_ADDRESS(userValue)) + return B_BAD_ADDRESS; + + return user_memcpy(userValue, &value, sizeof(Type)); +} + + +// UserStringParameter +template +struct UserStringParameter { + char* value; + + inline UserStringParameter() + : value(NULL) + { + } + + inline ~UserStringParameter() + { + free(value); + } + + inline status_t Init(const char* userValue, size_t maxSize) + { + if (userValue == NULL) { + if (!kAllowsNull) + return B_BAD_VALUE; + + return B_OK; + } + + if (!IS_USER_ADDRESS(userValue)) + return B_BAD_ADDRESS; + + value = (char*)malloc(maxSize); + if (value == NULL) + return B_NO_MEMORY; + + ssize_t bytesCopied = user_strlcpy(value, userValue, maxSize); + if (bytesCopied < 0) + return bytesCopied; + + if ((size_t)bytesCopied >= maxSize) + return B_BUFFER_OVERFLOW; + + return B_OK; + } +}; + + +// UserMemoryParameter +template +struct UserMemoryParameter { + Type* value; + + inline UserMemoryParameter() + : value(NULL) + { + } + + inline ~UserMemoryParameter() + { + free(value); + } + + inline status_t Init(const Type* userValue, size_t size) + { + if (userValue == NULL) { + if (!kAllowsNull) + return B_BAD_VALUE; + + value = NULL; + return B_OK; + } + + if (!IS_USER_ADDRESS(userValue)) + return B_BAD_ADDRESS; + + value = (Type*)malloc(size); + if (value == NULL) + return B_NO_MEMORY; + + return user_memcpy(value, userValue, size); + } + + inline status_t Init(const Type* userValue, size_t size, size_t maxSize) + { + if (size > maxSize) + return B_BAD_VALUE; + + return Init(userValue, size); + } +}; + + #if 0 // move_descendants static void @@ -383,101 +506,208 @@ _user_find_disk_system(const char *_name, user_disk_system_info *_info) // _user_defragment_partition status_t -_user_defragment_partition(partition_id partitionID, int32* changeCounter) +_user_defragment_partition(partition_id partitionID, int32* _changeCounter) { -#if 0 - KDiskDeviceManager *manager = KDiskDeviceManager::Default(); + // copy parameters in + int32 changeCounter; + + status_t error; + if ((error = copy_from_user_value(changeCounter, _changeCounter)) != B_OK) + return error; + // get the partition - KPartition *partition = manager->WriteLockPartition(partitionID); + KDiskDeviceManager* manager = KDiskDeviceManager::Default(); + KPartition* partition = manager->WriteLockPartition(partitionID); if (!partition) return B_ENTRY_NOT_FOUND; + PartitionRegistrar registrar1(partition, true); PartitionRegistrar registrar2(partition->Device(), true); DeviceWriteLocker locker(partition->Device(), true); - // check whether the disk system supports defragmenting - status_t error = validate_defragment_partition(partition, changeCounter); + + // check change counter + if (changeCounter != partition->ChangeCounter()) + return B_BAD_VALUE; + + // the partition must be initialized + KDiskSystem* diskSystem = partition->DiskSystem(); + if (!diskSystem) + return B_BAD_VALUE; + + // mark the partition busy and unlock + if (!partition->CheckAndMarkBusy(false)) + return B_BUSY; + locker.Unlock(); + + // defragment + error = diskSystem->Defragment(partition, DUMMY_JOB_ID); + + // re-lock and unmark busy + locker.Lock(); + partition->UnmarkBusy(false); + if (error != B_OK) return error; - // set the defragmenting flag - partition->Changed(B_PARTITION_CHANGED_DEFRAGMENTATION); + + // return change counter + if ((error = copy_to_user_value(_changeCounter, partition->ChangeCounter())) + != B_OK) { + return error; + } + return B_OK; -#endif -return B_BAD_VALUE; } // _user_repair_partition status_t -_user_repair_partition(partition_id partitionID, int32* changeCounter, +_user_repair_partition(partition_id partitionID, int32* _changeCounter, bool checkOnly) { -#if 0 - KDiskDeviceManager *manager = KDiskDeviceManager::Default(); + // copy parameters in + int32 changeCounter; + + status_t error; + if ((error = copy_from_user_value(changeCounter, _changeCounter)) != B_OK) + return error; + // get the partition - KPartition *partition = manager->WriteLockPartition(partitionID); + KDiskDeviceManager* manager = KDiskDeviceManager::Default(); + KPartition* partition = manager->WriteLockPartition(partitionID); if (!partition) return B_ENTRY_NOT_FOUND; + PartitionRegistrar registrar1(partition, true); PartitionRegistrar registrar2(partition->Device(), true); DeviceWriteLocker locker(partition->Device(), true); - // check whether the disk system supports defragmenting - status_t error = validate_repair_partition(partition, changeCounter, - checkOnly); + + // check change counter + if (changeCounter != partition->ChangeCounter()) + return B_BAD_VALUE; + + // the partition must be initialized + KDiskSystem* diskSystem = partition->DiskSystem(); + if (!diskSystem) + return B_BAD_VALUE; + + // mark the partition busy and unlock + if (!partition->CheckAndMarkBusy(false)) + return B_BUSY; + locker.Unlock(); + + // repair/check + error = diskSystem->Repair(partition, checkOnly, DUMMY_JOB_ID); + + // re-lock and unmark busy + locker.Lock(); + partition->UnmarkBusy(false); + if (error != B_OK) return error; - // set the respective flag - if (checkOnly) - partition->Changed(B_PARTITION_CHANGED_CHECK); - else - partition->Changed(B_PARTITION_CHANGED_REPAIR); + + // return change counter + if ((error = copy_to_user_value(_changeCounter, partition->ChangeCounter())) + != B_OK) { + return error; + } + return B_OK; -#endif -return B_BAD_VALUE; } // _user_resize_partition status_t -_user_resize_partition(partition_id partitionID, int32* changeCounter, - partition_id childID, int32* childChangeCounter, off_t size, +_user_resize_partition(partition_id partitionID, int32* _changeCounter, + partition_id childID, int32* _childChangeCounter, off_t size, off_t contentSize) { -#if 0 - KDiskDeviceManager *manager = KDiskDeviceManager::Default(); + // copy parameters in + int32 changeCounter; + int32 childChangeCounter; + + status_t error; + if ((error = copy_from_user_value(changeCounter, _changeCounter)) != B_OK + || (error = copy_from_user_value(childChangeCounter, + _childChangeCounter)) != B_OK) { + return error; + } + // get the partition - KPartition *partition = manager->WriteLockPartition(partitionID); + KDiskDeviceManager* manager = KDiskDeviceManager::Default(); + KPartition* partition = manager->WriteLockPartition(partitionID); if (!partition) return B_ENTRY_NOT_FOUND; + PartitionRegistrar registrar1(partition, true); PartitionRegistrar registrar2(partition->Device(), true); DeviceWriteLocker locker(partition->Device(), true); - // check the size - if (size == partition->Size()) - return B_OK; - off_t proposedSize = size; - off_t contentSize = 0; - status_t error = validate_resize_partition(partition, changeCounter, - &proposedSize, &contentSize); - if (error != B_OK) - return error; - if (proposedSize != size) + + // register child + KPartition* child = manager->RegisterPartition(childID); + if (!child) + return B_ENTRY_NOT_FOUND; + + PartitionRegistrar registrar3(child, true); + + // check change counters + if (changeCounter != partition->ChangeCounter() + || childChangeCounter != child->ChangeCounter()) { return B_BAD_VALUE; - // new size is fine -- resize the thing - partition->SetSize(size); - partition->Changed(B_PARTITION_CHANGED_SIZE); - // implicit partitioning system changes - error = partition->Parent()->DiskSystem()->ShadowPartitionChanged( - partition->Parent(), partition, B_PARTITION_RESIZE_CHILD); + } + + // the partition must be initialized + KDiskSystem* diskSystem = partition->DiskSystem(); + if (!diskSystem) + return B_BAD_VALUE; + + // child must indeed be a child of partition + if (child->Parent() != partition) + return B_BAD_VALUE; + + // check sizes + if (size < 0 || contentSize < 0 || size < contentSize + || size > partition->ContentSize()) { + return B_BAD_VALUE; + } + + // mark the partitions busy and unlock + if (partition->IsBusy() || child->IsBusy()) + return B_BUSY; + partition->SetBusy(true); + child->SetBusy(true); + locker.Unlock(); + + // resize contents first, if shrinking + if (child->DiskSystem() && contentSize < child->ContentSize()) + error = child->DiskSystem()->Resize(child, contentSize, DUMMY_JOB_ID); + + // resize the partition + if (error == B_OK && size != child->Size()) + error = diskSystem->ResizeChild(child, size, DUMMY_JOB_ID); + + // resize contents last, if growing + if (error == B_OK && child->DiskSystem() + && contentSize > child->ContentSize()) { + error = child->DiskSystem()->Resize(child, contentSize, DUMMY_JOB_ID); + } + + // re-lock and unmark busy + locker.Lock(); + partition->SetBusy(false); + child->SetBusy(false); + if (error != B_OK) return error; - // implicit content disk system changes - if (partition->DiskSystem()) { - error = partition->DiskSystem()->ShadowPartitionChanged( - partition, NULL, B_PARTITION_RESIZE); + + // return change counters + if ((error = copy_to_user_value(_changeCounter, partition->ChangeCounter())) + != B_OK + || (error = copy_to_user_value(_childChangeCounter, + child->ChangeCounter())) != B_OK) { + return error; } - return error; -#endif -return B_BAD_VALUE; + + return B_OK; } @@ -525,255 +755,397 @@ return B_BAD_VALUE; // _user_set_partition_name status_t -_user_set_partition_name(partition_id partitionID, int32* changeCounter, - partition_id childID, int32* childChangeCounter, const char* name) +_user_set_partition_name(partition_id partitionID, int32* _changeCounter, + partition_id childID, int32* _childChangeCounter, const char* _name) { -#if 0 - if (!_name) - return B_BAD_VALUE; - char name[B_DISK_DEVICE_NAME_LENGTH]; - status_t error = ddm_strlcpy(name, _name, B_DISK_DEVICE_NAME_LENGTH); - if (error) + // copy parameters in + UserStringParameter name; + int32 changeCounter; + int32 childChangeCounter; + + status_t error; + if ((error = name.Init(_name, B_DISK_DEVICE_NAME_LENGTH)) != B_OK + || (error = copy_from_user_value(changeCounter, _changeCounter)) + != B_OK + || (error = copy_from_user_value(childChangeCounter, + _childChangeCounter)) != B_OK) { return error; - KDiskDeviceManager *manager = KDiskDeviceManager::Default(); + } + // get the partition - KPartition *partition = manager->WriteLockPartition(partitionID); + KDiskDeviceManager* manager = KDiskDeviceManager::Default(); + KPartition* partition = manager->WriteLockPartition(partitionID); if (!partition) return B_ENTRY_NOT_FOUND; + PartitionRegistrar registrar1(partition, true); PartitionRegistrar registrar2(partition->Device(), true); DeviceWriteLocker locker(partition->Device(), true); - // check name - char proposedName[B_DISK_DEVICE_NAME_LENGTH]; - strcpy(proposedName, name); - error = validate_set_partition_name(partition, changeCounter, proposedName); - if (error != B_OK) - return error; - if (strcmp(name, proposedName)) + + // register child + KPartition* child = manager->RegisterPartition(childID); + if (!child) + return B_ENTRY_NOT_FOUND; + + PartitionRegistrar registrar3(child, true); + + // check change counters + if (changeCounter != partition->ChangeCounter() + || childChangeCounter != child->ChangeCounter()) { return B_BAD_VALUE; - // set name - error = partition->SetName(name); + } + + // the partition must be initialized + KDiskSystem* diskSystem = partition->DiskSystem(); + if (!diskSystem) + return B_BAD_VALUE; + + // child must indeed be a child of partition + if (child->Parent() != partition) + return B_BAD_VALUE; + + // mark the partitions busy and unlock + if (partition->IsBusy() || child->IsBusy()) + return B_BUSY; + partition->SetBusy(true); + child->SetBusy(true); + locker.Unlock(); + + // set the child name + error = diskSystem->SetName(child, name.value, DUMMY_JOB_ID); + + // re-lock and unmark busy + locker.Lock(); + partition->SetBusy(false); + child->SetBusy(false); + if (error != B_OK) return error; - partition->Changed(B_PARTITION_CHANGED_NAME); - // implicit partitioning system changes - return partition->Parent()->DiskSystem()->ShadowPartitionChanged( - partition->Parent(), partition, B_PARTITION_SET_NAME); -#endif -return B_BAD_VALUE; + + // return change counters + if ((error = copy_to_user_value(_changeCounter, partition->ChangeCounter())) + != B_OK + || (error = copy_to_user_value(_childChangeCounter, + child->ChangeCounter())) != B_OK) { + return error; + } + + return B_OK; } // _user_set_partition_content_name status_t -_user_set_partition_content_name(partition_id partitionID, int32* changeCounter, - const char* name) +_user_set_partition_content_name(partition_id partitionID, + int32* _changeCounter, const char* _name) { -#if 0 - if (!_name) - return B_BAD_VALUE; - char name[B_DISK_DEVICE_NAME_LENGTH]; - status_t error = ddm_strlcpy(name, _name, B_DISK_DEVICE_NAME_LENGTH); - if (error) + // copy parameters in + UserStringParameter name; + int32 changeCounter; + + status_t error; + if ((error = name.Init(_name, B_DISK_DEVICE_NAME_LENGTH)) != B_OK + || (error = copy_from_user_value(changeCounter, _changeCounter)) + != B_OK) { return error; - KDiskDeviceManager *manager = KDiskDeviceManager::Default(); + } + // get the partition - KPartition *partition = manager->WriteLockPartition(partitionID); + KDiskDeviceManager* manager = KDiskDeviceManager::Default(); + KPartition* partition = manager->WriteLockPartition(partitionID); if (!partition) return B_ENTRY_NOT_FOUND; + PartitionRegistrar registrar1(partition, true); PartitionRegistrar registrar2(partition->Device(), true); DeviceWriteLocker locker(partition->Device(), true); - // check name - char proposedName[B_DISK_DEVICE_NAME_LENGTH]; - strcpy(proposedName, name); - error = validate_set_partition_content_name(partition, - changeCounter, proposedName); - if (error != B_OK) - return error; - if (strcmp(name, proposedName)) + + // check change counter + if (changeCounter != partition->ChangeCounter()) return B_BAD_VALUE; - // set name - error = partition->SetContentName(name); + + // the partition must be initialized + KDiskSystem* diskSystem = partition->DiskSystem(); + if (!diskSystem) + return B_BAD_VALUE; + + // mark the partition busy and unlock + if (!partition->CheckAndMarkBusy(false)) + return B_BUSY; + locker.Unlock(); + + // set content parameters + error = diskSystem->SetContentName(partition, name.value, DUMMY_JOB_ID); + + // re-lock and unmark busy + locker.Lock(); + partition->UnmarkBusy(false); + if (error != B_OK) return error; - partition->Changed(B_PARTITION_CHANGED_CONTENT_NAME); - // implicit content disk system changes - return partition->DiskSystem()->ShadowPartitionChanged( - partition, NULL, B_PARTITION_SET_CONTENT_NAME); -#endif -return B_BAD_VALUE; + + // return change counter + if ((error = copy_to_user_value(_changeCounter, partition->ChangeCounter())) + != B_OK) { + return error; + } + + return B_OK; } // _user_set_partition_type status_t -_user_set_partition_type(partition_id partitionID, int32* changeCounter, - partition_id childID, int32* childChangeCounter, const char* type) +_user_set_partition_type(partition_id partitionID, int32* _changeCounter, + partition_id childID, int32* _childChangeCounter, const char* _type) { -#if 0 - if (!_type) - return B_BAD_VALUE; - char type[B_DISK_DEVICE_TYPE_LENGTH]; - status_t error = ddm_strlcpy(type, _type, B_DISK_DEVICE_TYPE_LENGTH); - if (error) + // copy parameters in + UserStringParameter type; + int32 changeCounter; + int32 childChangeCounter; + + status_t error; + if ((error = type.Init(_type, B_DISK_DEVICE_TYPE_LENGTH)) != B_OK + || (error = copy_from_user_value(changeCounter, _changeCounter)) + != B_OK + || (error = copy_from_user_value(childChangeCounter, + _childChangeCounter)) != B_OK) { return error; - KDiskDeviceManager *manager = KDiskDeviceManager::Default(); + } + // get the partition - KPartition *partition = manager->WriteLockPartition(partitionID); + KDiskDeviceManager* manager = KDiskDeviceManager::Default(); + KPartition* partition = manager->WriteLockPartition(partitionID); if (!partition) return B_ENTRY_NOT_FOUND; + PartitionRegistrar registrar1(partition, true); PartitionRegistrar registrar2(partition->Device(), true); DeviceWriteLocker locker(partition->Device(), true); - // check type - error = validate_set_partition_type(partition, changeCounter, type); + + // register child + KPartition* child = manager->RegisterPartition(childID); + if (!child) + return B_ENTRY_NOT_FOUND; + + PartitionRegistrar registrar3(child, true); + + // check change counters + if (changeCounter != partition->ChangeCounter() + || childChangeCounter != child->ChangeCounter()) { + return B_BAD_VALUE; + } + + // the partition must be initialized + KDiskSystem* diskSystem = partition->DiskSystem(); + if (!diskSystem) + return B_BAD_VALUE; + + // child must indeed be a child of partition + if (child->Parent() != partition) + return B_BAD_VALUE; + + // mark the partition busy and unlock + if (partition->IsBusy() || child->IsBusy()) + return B_BUSY; + partition->SetBusy(true); + child->SetBusy(true); + locker.Unlock(); + + // set the child type + error = diskSystem->SetType(child, type.value, DUMMY_JOB_ID); + + // re-lock and unmark busy + locker.Lock(); + partition->SetBusy(false); + child->SetBusy(false); + if (error != B_OK) return error; - // set type - error = partition->SetType(type); - if (error != B_OK) + + // return change counters + if ((error = copy_to_user_value(_changeCounter, partition->ChangeCounter())) + != B_OK + || (error = copy_to_user_value(_childChangeCounter, + child->ChangeCounter())) != B_OK) { return error; - partition->Changed(B_PARTITION_CHANGED_TYPE); - // implicit partitioning system changes - return partition->Parent()->DiskSystem()->ShadowPartitionChanged( - partition->Parent(), partition, B_PARTITION_SET_TYPE); -#endif -return B_BAD_VALUE; + } + + return B_OK; } // _user_set_partition_parameters status_t -_user_set_partition_parameters(partition_id partitionID, int32* changeCounter, - partition_id childID, int32* childChangeCounter, const char* parameters, +_user_set_partition_parameters(partition_id partitionID, int32* _changeCounter, + partition_id childID, int32* _childChangeCounter, const char* _parameters, size_t parametersSize) { -#if 0 - if (!_parameters || parametersSize > B_DISK_DEVICE_MAX_PARAMETER_SIZE) - return B_BAD_VALUE; - char *parameters = NULL; - if (_parameters) { - parameters = static_cast(malloc(parametersSize)); - if (parameters) - user_memcpy(parameters, _parameters, parametersSize); - else - return B_NO_MEMORY; + // copy parameters in + UserMemoryParameter parameters; + int32 changeCounter; + int32 childChangeCounter; + + status_t error; + if ((error = parameters.Init(_parameters, parametersSize, + B_DISK_DEVICE_MAX_PARAMETER_SIZE)) != B_OK + || (error = copy_from_user_value(changeCounter, _changeCounter)) + != B_OK + || (error = copy_from_user_value(childChangeCounter, + _childChangeCounter)) != B_OK) { + return error; } - KDiskDeviceManager *manager = KDiskDeviceManager::Default(); + // get the partition - KPartition *partition = manager->WriteLockPartition(partitionID); - status_t error = partition ? (status_t)B_OK : (status_t)B_ENTRY_NOT_FOUND; - if (!error) { - PartitionRegistrar registrar1(partition, true); - PartitionRegistrar registrar2(partition->Device(), true); - DeviceWriteLocker locker(partition->Device(), true); - // check parameters - error = validate_set_partition_parameters(partition, - changeCounter, parameters); - if (!error) { - // set type - error = partition->SetParameters(parameters); - if (!error) { - partition->Changed(B_PARTITION_CHANGED_PARAMETERS); - // implicit partitioning system changes - error = partition->Parent()->DiskSystem() - ->ShadowPartitionChanged(partition->Parent(), partition, - B_PARTITION_SET_PARAMETERS); - } - } + KDiskDeviceManager* manager = KDiskDeviceManager::Default(); + KPartition* partition = manager->WriteLockPartition(partitionID); + if (!partition) + return B_ENTRY_NOT_FOUND; + + PartitionRegistrar registrar1(partition, true); + PartitionRegistrar registrar2(partition->Device(), true); + DeviceWriteLocker locker(partition->Device(), true); + + // register child + KPartition* child = manager->RegisterPartition(childID); + if (!child) + return B_ENTRY_NOT_FOUND; + + PartitionRegistrar registrar3(child, true); + + // check change counters + if (changeCounter != partition->ChangeCounter() + || childChangeCounter != child->ChangeCounter()) { + return B_BAD_VALUE; } - free(parameters); - return error; -#endif -return B_BAD_VALUE; + + // the partition must be initialized + KDiskSystem* diskSystem = partition->DiskSystem(); + if (!diskSystem) + return B_BAD_VALUE; + + // child must indeed be a child of partition + if (child->Parent() != partition) + return B_BAD_VALUE; + + // mark the partition busy and unlock + if (partition->IsBusy() || child->IsBusy()) + return B_BUSY; + partition->SetBusy(true); + child->SetBusy(true); + locker.Unlock(); + + // set the child parameters + error = diskSystem->SetParameters(child, parameters.value, DUMMY_JOB_ID); + + // re-lock and unmark busy + locker.Lock(); + partition->SetBusy(false); + child->SetBusy(false); + + if (error != B_OK) + return error; + + // return change counters + if ((error = copy_to_user_value(_changeCounter, partition->ChangeCounter())) + != B_OK + || (error = copy_to_user_value(_childChangeCounter, + child->ChangeCounter())) != B_OK) { + return error; + } + + return B_OK; } // _user_set_partition_content_parameters status_t _user_set_partition_content_parameters(partition_id partitionID, - int32* changeCounter, const char* parameters, size_t parametersSize) + int32* _changeCounter, const char* _parameters, size_t parametersSize) { -#if 0 - if (!_parameters || parametersSize > B_DISK_DEVICE_MAX_PARAMETER_SIZE) - return B_BAD_VALUE; - char *parameters = NULL; - if (_parameters) { - parameters = static_cast(malloc(parametersSize)); - if (parameters) - user_memcpy(parameters, _parameters, parametersSize); - else - return B_NO_MEMORY; + // copy parameters in + UserMemoryParameter parameters; + int32 changeCounter; + + status_t error; + if ((error = parameters.Init(_parameters, parametersSize, + B_DISK_DEVICE_MAX_PARAMETER_SIZE)) != B_OK + || (error = copy_from_user_value(changeCounter, _changeCounter)) + != B_OK) { + return error; } - KDiskDeviceManager *manager = KDiskDeviceManager::Default(); + // get the partition - KPartition *partition = manager->WriteLockPartition(partitionID); - status_t error = partition ? (status_t)B_OK : (status_t)B_ENTRY_NOT_FOUND; - if (!error) { - PartitionRegistrar registrar1(partition, true); - PartitionRegistrar registrar2(partition->Device(), true); - DeviceWriteLocker locker(partition->Device(), true); - // check parameters - error = validate_set_partition_content_parameters(partition, - changeCounter, parameters); - if (!error) { - // set name - error = partition->SetContentParameters(parameters); - if (!error) { - partition->Changed(B_PARTITION_CHANGED_CONTENT_PARAMETERS); - // implicit content disk system changes - error = partition->DiskSystem()->ShadowPartitionChanged( - partition, NULL, B_PARTITION_SET_CONTENT_PARAMETERS); - } - } + KDiskDeviceManager* manager = KDiskDeviceManager::Default(); + KPartition* partition = manager->WriteLockPartition(partitionID); + if (!partition) + return B_ENTRY_NOT_FOUND; + + PartitionRegistrar registrar1(partition, true); + PartitionRegistrar registrar2(partition->Device(), true); + DeviceWriteLocker locker(partition->Device(), true); + + // check change counter + if (changeCounter != partition->ChangeCounter()) + return B_BAD_VALUE; + + // the partition must be initialized + KDiskSystem* diskSystem = partition->DiskSystem(); + if (!diskSystem) + return B_BAD_VALUE; + + // mark the partition busy and unlock + if (!partition->CheckAndMarkBusy(true)) + return B_BUSY; + locker.Unlock(); + + // set content parameters + error = diskSystem->SetContentParameters(partition, parameters.value, + DUMMY_JOB_ID); + + // re-lock and unmark busy + locker.Lock(); + partition->UnmarkBusy(true); + + if (error != B_OK) + return error; + + // return change counter + if ((error = copy_to_user_value(_changeCounter, partition->ChangeCounter())) + != B_OK) { + return error; } - free(partition); - return error; -#endif -return B_BAD_VALUE; + + return B_OK; } // _user_initialize_partition status_t -_user_initialize_partition(partition_id partitionID, int32* changeCounter, - const char* diskSystemName, const char* name, const char* parameters, +_user_initialize_partition(partition_id partitionID, int32* _changeCounter, + const char* _diskSystemName, const char* _name, const char* _parameters, size_t parametersSize) { -#if 0 - if (!_diskSystemName || parametersSize > B_DISK_DEVICE_MAX_PARAMETER_SIZE) - return B_BAD_VALUE; + // copy parameters in + UserStringParameter diskSystemName; + UserStringParameter name; + UserMemoryParameter parameters; + int32 changeCounter; - // copy disk system name - char diskSystemName[B_DISK_SYSTEM_NAME_LENGTH]; - status_t error = ddm_strlcpy(diskSystemName, _diskSystemName, - B_DISK_SYSTEM_NAME_LENGTH); - - // copy name - char name[B_DISK_DEVICE_NAME_LENGTH]; - if (!error && _name) - error = ddm_strlcpy(name, _name, B_DISK_DEVICE_NAME_LENGTH); - - if (error) + status_t error; + if ((error = diskSystemName.Init(_diskSystemName, + B_DISK_SYSTEM_NAME_LENGTH)) != B_OK + || (error = name.Init(_name, B_DISK_DEVICE_NAME_LENGTH)) != B_OK + || (error = parameters.Init(_parameters, parametersSize, + B_DISK_DEVICE_MAX_PARAMETER_SIZE)) != B_OK + || (error = copy_from_user_value(changeCounter, _changeCounter)) + != B_OK) { return error; - - // copy parameters - MemoryDeleter parameterDeleter; - char *parameters = NULL; - if (_parameters) { - parameters = static_cast(malloc(parametersSize)); - if (!parameters) - return B_NO_MEMORY; - parameterDeleter.SetTo(parameters); - - if (user_memcpy(parameters, _parameters, parametersSize) != B_OK) - return B_BAD_ADDRESS; } // get the partition - KDiskDeviceManager *manager = KDiskDeviceManager::Default(); - KPartition *partition = manager->WriteLockPartition(partitionID); + KDiskDeviceManager* manager = KDiskDeviceManager::Default(); + KPartition* partition = manager->WriteLockPartition(partitionID); if (!partition) return B_ENTRY_NOT_FOUND; @@ -781,166 +1153,238 @@ _user_initialize_partition(partition_id partitionID, int32* changeCounter, PartitionRegistrar registrar2(partition->Device(), true); DeviceWriteLocker locker(partition->Device(), true); - // get the disk system - KDiskSystem *diskSystem = manager->LoadDiskSystem(diskSystemName); + // check change counter + if (changeCounter != partition->ChangeCounter()) + return B_BAD_VALUE; + + // the partition must be uninitialized + if (partition->DiskSystem()) + return B_BAD_VALUE; + + // load the new disk system + KDiskSystem *diskSystem = manager->LoadDiskSystem(diskSystemName.value); if (!diskSystem) return B_ENTRY_NOT_FOUND; DiskSystemLoader loader(diskSystem, true); - // check parameters - char proposedName[B_DISK_DEVICE_NAME_LENGTH]; - if (_name) - strcpy(proposedName, name); + // mark the partition busy and unlock + if (!partition->CheckAndMarkBusy(true)) + return B_BUSY; + locker.Unlock(); + + // let the disk system initialize the partition + error = diskSystem->Initialize(partition, name.value, parameters.value, + DUMMY_JOB_ID); + + // re-lock and unmark busy + locker.Lock(); + partition->UnmarkBusy(true); - error = validate_initialize_partition(partition, changeCounter, - diskSystemName, _name ? proposedName : NULL, parameters); if (error != B_OK) return error; - if (_name && strcmp(name, proposedName) != 0) - return B_BAD_VALUE; - - // unitialize the partition's contents and set the new - // parameters - if ((error = partition->UninitializeContents(true)) != B_OK) - return error; partition->SetDiskSystem(diskSystem); - if ((error = partition->SetContentName(_name ? name : NULL)) != B_OK) + // return change counter + error = copy_to_user_value(_changeCounter, partition->ChangeCounter()); + if (error != B_OK) return error; - partition->Changed(B_PARTITION_CHANGED_CONTENT_NAME); - if ((error = partition->SetContentParameters(parameters)) != B_OK) - return error; - partition->Changed(B_PARTITION_CHANGED_CONTENT_PARAMETERS); - - partition->Changed(B_PARTITION_CHANGED_INITIALIZATION); - - // implicit content disk system changes - return partition->DiskSystem()->ShadowPartitionChanged( - partition, NULL, B_PARTITION_INITIALIZE); -#endif -return B_BAD_VALUE; + return B_OK; } // _user_uninitialize_partition status_t -_user_uninitialize_partition(partition_id partitionID, int32* changeCounter) +_user_uninitialize_partition(partition_id partitionID, int32* _changeCounter) { -#if 0 - KDiskDeviceManager *manager = KDiskDeviceManager::Default(); + // copy parameters in + int32 changeCounter; + + status_t error; + if ((error = copy_from_user_value(changeCounter, _changeCounter)) != B_OK) + return error; + // get the partition - KPartition *partition = manager->WriteLockPartition(partitionID); + KDiskDeviceManager* manager = KDiskDeviceManager::Default(); + KPartition* partition = manager->WriteLockPartition(partitionID); if (!partition) return B_ENTRY_NOT_FOUND; + PartitionRegistrar registrar1(partition, true); PartitionRegistrar registrar2(partition->Device(), true); DeviceWriteLocker locker(partition->Device(), true); - // unitialize the partition's contents and set the new parameters - return partition->UninitializeContents(true); -#endif -return B_BAD_VALUE; + + // check change counter + if (changeCounter != partition->ChangeCounter()) + return B_BAD_VALUE; + + // the partition must be initialized + if (!partition->DiskSystem()) + return B_BAD_VALUE; + + // check busy + if (partition->IsBusy(true)) + return B_BUSY; + +// TODO: We should also check, if any partition is mounted! + + // uninitialize + error = partition->UninitializeContents(true); + if (error != B_OK) + return error; + + // return change counter + error = copy_to_user_value(_changeCounter, partition->ChangeCounter()); + if (error != B_OK) + return error; + + return B_OK; } // _user_create_child_partition status_t -_user_create_child_partition(partition_id partitionID, int32* changeCounter, - off_t offset, off_t size, const char* type, const char* name, - const char* parameters, size_t parametersSize, partition_id* childID, +_user_create_child_partition(partition_id partitionID, int32* _changeCounter, + off_t offset, off_t size, const char* _type, const char* _name, + const char* _parameters, size_t parametersSize, partition_id* childID, int32* childChangeCounter) { -#if 0 - if (!_type || parametersSize > B_DISK_DEVICE_MAX_PARAMETER_SIZE) - return B_BAD_VALUE; - char type[B_DISK_DEVICE_TYPE_LENGTH]; - char *parameters = NULL; - status_t error = ddm_strlcpy(type, _type, B_DISK_DEVICE_TYPE_LENGTH); - if (error) + // copy parameters in + UserStringParameter type; + UserStringParameter name; + UserMemoryParameter parameters; + int32 changeCounter; + + status_t error; + if ((error = type.Init(_type, B_DISK_DEVICE_TYPE_LENGTH)) != B_OK + || (error = name.Init(_name, B_DISK_DEVICE_NAME_LENGTH)) != B_OK + || (error = parameters.Init(_parameters, parametersSize, + B_DISK_DEVICE_MAX_PARAMETER_SIZE)) != B_OK + || (error = copy_from_user_value(changeCounter, _changeCounter)) + != B_OK) { return error; - if (_parameters) { - parameters = static_cast(malloc(parametersSize)); - if (parameters) - user_memcpy(parameters, _parameters, parametersSize); - else - return B_NO_MEMORY; } - KDiskDeviceManager *manager = KDiskDeviceManager::Default(); + // get the partition - KPartition *partition = manager->WriteLockPartition(partitionID); - error = partition ? (status_t)B_OK : (status_t)B_ENTRY_NOT_FOUND; - if (!error) { - PartitionRegistrar registrar1(partition, true); - PartitionRegistrar registrar2(partition->Device(), true); - DeviceWriteLocker locker(partition->Device(), true); - // check the parameters - off_t proposedOffset = offset; - off_t proposedSize = size; - int32 index = 0; - error = validate_create_child_partition(partition, changeCounter, - &proposedOffset, &proposedSize, type, parameters, &index); - if (!error) { - error = (proposedOffset == offset && proposedSize == size) - ? B_OK : B_BAD_VALUE; - if (!error) { - // create the child - KPartition *child = NULL; - error = partition->CreateChild(-1, index, &child); - if (!error) { - partition->Changed(B_PARTITION_CHANGED_CHILDREN); - if (_childID) { - partition_id childID = child->ID(); - user_memcpy(_childID, &childID, sizeof(childID)); - } - // set the parameters - child->SetOffset(offset); - child->SetSize(size); - error = child->SetType(type); - } - if (!error) { - error = child->SetParameters(parameters); - } - if (!error) { - // implicit partitioning system changes - error = partition->DiskSystem()->ShadowPartitionChanged( - partition, child, B_PARTITION_CREATE_CHILD); - } - } - } + KDiskDeviceManager* manager = KDiskDeviceManager::Default(); + KPartition* partition = manager->WriteLockPartition(partitionID); + if (!partition) + return B_ENTRY_NOT_FOUND; + + PartitionRegistrar registrar1(partition, true); + PartitionRegistrar registrar2(partition->Device(), true); + DeviceWriteLocker locker(partition->Device(), true); + + // check change counter + if (changeCounter != partition->ChangeCounter()) + return B_BAD_VALUE; + + // the partition must be initialized + KDiskSystem* diskSystem = partition->DiskSystem(); + if (!diskSystem) + return B_BAD_VALUE; + + // mark the partition busy and unlock + if (!partition->CheckAndMarkBusy(false)) + return B_BUSY; + locker.Unlock(); + + // create the child + KPartition *child = NULL; + error = diskSystem->CreateChild(partition, offset, size, type.value, + name.value, parameters.value, DUMMY_JOB_ID, &child, -1); + + // re-lock and unmark busy + locker.Lock(); + partition->UnmarkBusy(false); + + if (error != B_OK) + return error; + + if (child == NULL) + return B_ERROR; + + child->UnmarkBusy(true); + + // return change counter and child ID + if ((error = copy_to_user_value(_changeCounter, partition->ChangeCounter())) + != B_OK + || (error = copy_to_user_value(childID, child->ID())) != B_OK) { + return error; } - free(parameters); - return error; -#endif -return B_BAD_VALUE; + + return B_OK; } // _user_delete_child_partition status_t -_user_delete_child_partition(partition_id partitionID, int32* changeCounter, +_user_delete_child_partition(partition_id partitionID, int32* _changeCounter, partition_id childID, int32 childChangeCounter) { -#if 0 - KDiskDeviceManager *manager = KDiskDeviceManager::Default(); + // copy parameters in + int32 changeCounter; + + status_t error; + if ((error = copy_from_user_value(changeCounter, _changeCounter)) != B_OK) + return error; + // get the partition - KPartition *partition = manager->WriteLockPartition(partitionID); + KDiskDeviceManager* manager = KDiskDeviceManager::Default(); + KPartition* partition = manager->WriteLockPartition(partitionID); if (!partition) return B_ENTRY_NOT_FOUND; + PartitionRegistrar registrar1(partition, true); PartitionRegistrar registrar2(partition->Device(), true); DeviceWriteLocker locker(partition->Device(), true); - // check whether delete the child is OK - status_t error = validate_delete_child_partition(partition, changeCounter); + + // register child + KPartition* child = manager->RegisterPartition(childID); + if (!child) + return B_ENTRY_NOT_FOUND; + + PartitionRegistrar registrar3(child, true); + + // check change counters + if (changeCounter != partition->ChangeCounter() + || childChangeCounter != child->ChangeCounter()) { + return B_BAD_VALUE; + } + + // the partition must be initialized + KDiskSystem* diskSystem = partition->DiskSystem(); + if (!diskSystem) + return B_BAD_VALUE; + + // child must indeed be a child of partition + if (child->Parent() != partition) + return B_BAD_VALUE; + + // mark the partition and child busy and unlock + if (partition->IsBusy() || !child->CheckAndMarkBusy(true)) + return B_BUSY; + partition->SetBusy(true); + locker.Unlock(); + + // delete the child + error = diskSystem->DeleteChild(child, DUMMY_JOB_ID); + + // re-lock and unmark busy + locker.Lock(); + partition->SetBusy(false); + child->UnmarkBusy(true); + if (error != B_OK) return error; - // delete the child - KPartition *parent = partition->Parent(); - if (!parent->RemoveChild(partition)) - return B_ERROR; - parent->Changed(B_PARTITION_CHANGED_CHILDREN); + + // return change counter + if ((error = copy_to_user_value(_changeCounter, partition->ChangeCounter())) + != B_OK) { + return error; + } + return B_OK; -#endif -return B_BAD_VALUE; }