From bf95c9aee6c36516e5e98a4f8953659c402bbf74 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sun, 7 Oct 2007 15:39:35 +0000 Subject: [PATCH] * The shadow_changed() FS and partitioning system hooks take an additional partition_data* child parameter now. * _user_get_partitionable_spaces() doesn't need to copy the buffer into the kernel, since it is no input parameter. It also copies back the actual partitionable spaces count on error, now -- B_BUFFER_OVERFLOW is returned when the buffer was too small, but then the count must be returned too. * Fixed several instances of syscall implementations that unloaded a disk system, although they didn't load it in the first place. This screwed up the load count with undesirable consequences. * _user_create_child_partition() would set the size to the supplied offset. * Fixed broken loop in KPhysicalPartition::CreateShadowPartition(). * KPartition::RemoveChild() notified the listeners about the wrong event. * Intel partitioning module: - The *_get_partitionable_spaces() correctly return B_BUFFER_OVERFLOW now, if the supplied buffer is too small. - Implemented a part of pm_shadow_changed(), which creates and updates the PartitionMap, so that the validate_*() hooks have a chance to work at all. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22475 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/drivers/fs_interface.h | 2 +- headers/private/fs_shell/fssh_fs_interface.h | 2 +- .../kernel/disk_device_manager/KDiskSystem.h | 2 +- .../kernel/disk_device_manager/KFileSystem.h | 2 +- .../disk_device_manager/KPartitioningSystem.h | 2 +- .../kernel/disk_device_manager/ddm_modules.h | 3 +- .../intel/PartitionMap.cpp | 57 ++++-- .../partitioning_systems/intel/PartitionMap.h | 11 +- .../partitioning_systems/intel/intel.cpp | 1 - .../kernel/partitioning_systems/intel/intel.h | 2 + .../intel/write_support.cpp | 174 +++++++++++++++++- .../intel/write_support.h | 6 +- .../disk_device_manager/KDiskSystem.cpp | 5 +- .../disk_device_manager/KFileSystem.cpp | 6 +- .../kernel/disk_device_manager/KPartition.cpp | 2 +- .../KPartitioningSystem.cpp | 5 +- .../KPhysicalPartition.cpp | 29 ++- .../ddm_userland_interface.cpp | 112 ++++++----- 18 files changed, 335 insertions(+), 88 deletions(-) diff --git a/headers/os/drivers/fs_interface.h b/headers/os/drivers/fs_interface.h index ab92091a59..e53330797f 100644 --- a/headers/os/drivers/fs_interface.h +++ b/headers/os/drivers/fs_interface.h @@ -219,7 +219,7 @@ typedef struct file_system_module_info { /* shadow partition modification (device is write locked) */ status_t (*shadow_changed)(partition_data *partition, - uint32 operation); + partition_data *child, uint32 operation); /* writing (the device is NOT locked) */ status_t (*defragment)(int fd, partition_id partition, diff --git a/headers/private/fs_shell/fssh_fs_interface.h b/headers/private/fs_shell/fssh_fs_interface.h index adc251ad0c..e83ebb1393 100644 --- a/headers/private/fs_shell/fssh_fs_interface.h +++ b/headers/private/fs_shell/fssh_fs_interface.h @@ -257,7 +257,7 @@ typedef struct fssh_file_system_module_info { /* shadow partition modification (device is write locked) */ fssh_status_t (*shadow_changed)(fssh_partition_data *partition, - uint32_t operation); + fssh_partition_data *child, uint32_t operation); /* writing (the device is NOT locked) */ fssh_status_t (*defragment)(int fd, fssh_partition_id partition, diff --git a/headers/private/kernel/disk_device_manager/KDiskSystem.h b/headers/private/kernel/disk_device_manager/KDiskSystem.h index a8f57db489..6d013dc1b2 100644 --- a/headers/private/kernel/disk_device_manager/KDiskSystem.h +++ b/headers/private/kernel/disk_device_manager/KDiskSystem.h @@ -100,7 +100,7 @@ public: // Device must be write locked. virtual status_t ShadowPartitionChanged(KPartition *partition, - uint32 operation); + KPartition *child, uint32 operation); // Writing // Device should not be locked. diff --git a/headers/private/kernel/disk_device_manager/KFileSystem.h b/headers/private/kernel/disk_device_manager/KFileSystem.h index d431496824..7cd5e20ab0 100644 --- a/headers/private/kernel/disk_device_manager/KFileSystem.h +++ b/headers/private/kernel/disk_device_manager/KFileSystem.h @@ -48,7 +48,7 @@ public: // Shadow partition modification virtual status_t ShadowPartitionChanged(KPartition *partition, - uint32 operation); + KPartition *child, uint32 operation); // Writing diff --git a/headers/private/kernel/disk_device_manager/KPartitioningSystem.h b/headers/private/kernel/disk_device_manager/KPartitioningSystem.h index b61a9e8598..370a21a7a0 100644 --- a/headers/private/kernel/disk_device_manager/KPartitioningSystem.h +++ b/headers/private/kernel/disk_device_manager/KPartitioningSystem.h @@ -74,7 +74,7 @@ public: // Shadow partition modification virtual status_t ShadowPartitionChanged(KPartition *partition, - uint32 operation); + KPartition *child, uint32 operation); // Writing diff --git a/headers/private/kernel/disk_device_manager/ddm_modules.h b/headers/private/kernel/disk_device_manager/ddm_modules.h index e00de1e47c..d13781ef8f 100644 --- a/headers/private/kernel/disk_device_manager/ddm_modules.h +++ b/headers/private/kernel/disk_device_manager/ddm_modules.h @@ -68,7 +68,8 @@ typedef struct partition_module_info { // shadow partition modification // (device is write locked) - status_t (*shadow_changed)(partition_data* partition, uint32 operation); + status_t (*shadow_changed)(partition_data* partition, + partition_data *child, uint32 operation); // writing diff --git a/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp b/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp index bcc7a1373e..2201fc12c2 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp +++ b/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.cpp @@ -386,17 +386,6 @@ PrimaryPartition::PrimaryPartition() { } -// constructor -PrimaryPartition::PrimaryPartition(const partition_descriptor *descriptor, - off_t ptsOffset) - : Partition(), - fHead(NULL), - fTail(NULL), - fLogicalPartitionCount(0) -{ - SetTo(descriptor, ptsOffset); -} - // SetTo void PrimaryPartition::SetTo(const partition_descriptor *descriptor, off_t ptsOffset) @@ -419,6 +408,34 @@ PrimaryPartition::Unset() Partition::Unset(); } + +// Assign +status_t +PrimaryPartition::Assign(const PrimaryPartition& other) +{ + partition_descriptor descriptor; + other.GetPartitionDescriptor(&descriptor, 0); + SetTo(&descriptor, 0); + + const LogicalPartition* otherLogical = other.fHead; + while (otherLogical) { + off_t ptsOffset = otherLogical->PTSOffset(); + otherLogical->GetPartitionDescriptor(&descriptor, ptsOffset); + + LogicalPartition* logical = new(nothrow) LogicalPartition( + &descriptor, ptsOffset, this); + if (!logical) + return B_NO_MEMORY; + + AddLogicalPartition(logical); + + otherLogical = otherLogical->Next(); + } + + return B_OK; +} + + // LogicalPartitionAt LogicalPartition * PrimaryPartition::LogicalPartitionAt(int32 index) const @@ -527,6 +544,8 @@ LogicalPartition::Unset() // constructor PartitionMap::PartitionMap() { + for (int32 i = 0; i < 4; i++) + fPrimaries[i].SetIndex(i); } // destructor @@ -542,6 +561,21 @@ PartitionMap::Unset() fPrimaries[i].Unset(); } + +// Assign +status_t +PartitionMap::Assign(const PartitionMap& other) +{ + for (int32 i = 0; i < 4; i++) { + status_t error = fPrimaries[i].Assign(other.fPrimaries[i]); + if (error != B_OK) + return error; + } + + return B_OK; +} + + // PrimaryPartitionAt PrimaryPartition * PartitionMap::PrimaryPartitionAt(int32 index) @@ -562,6 +596,7 @@ PartitionMap::PrimaryPartitionAt(int32 index) const return partition; } + // CountPartitions int32 PartitionMap::CountPartitions() const diff --git a/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.h b/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.h index dd947296f4..d03042704f 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.h +++ b/src/add-ons/kernel/partitioning_systems/intel/PartitionMap.h @@ -165,11 +165,16 @@ private: class PrimaryPartition : public Partition { public: PrimaryPartition(); - PrimaryPartition(const partition_descriptor *descriptor, off_t ptsOffset); void SetTo(const partition_descriptor *descriptor, off_t ptsOffset); void Unset(); + status_t Assign(const PrimaryPartition& other); + + int32 Index() const { return fIndex; } + void SetIndex(int32 index) { fIndex = index; } + // private + // only if extended int32 CountLogicalPartitions() const { return fLogicalPartitionCount; } LogicalPartition *LogicalPartitionAt(int32 index) const; @@ -180,6 +185,7 @@ private: LogicalPartition *fHead; LogicalPartition *fTail; int32 fLogicalPartitionCount; + int32 fIndex; }; // LogicalPartition @@ -216,8 +222,11 @@ public: void Unset(); + status_t Assign(const PartitionMap& other); + PrimaryPartition *PrimaryPartitionAt(int32 index); const PrimaryPartition *PrimaryPartitionAt(int32 index) const; + int32 IndexOfPrimaryPartition(const PrimaryPartition* partition) const; int32 CountPartitions() const; int32 CountNonEmptyPartitions() const; diff --git a/src/add-ons/kernel/partitioning_systems/intel/intel.cpp b/src/add-ons/kernel/partitioning_systems/intel/intel.cpp index ea97e46974..941cff73ee 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/intel.cpp +++ b/src/add-ons/kernel/partitioning_systems/intel/intel.cpp @@ -131,7 +131,6 @@ pm_identify_partition(int fd, partition_data *partition, void **cookie) PartitionMapCookie *map = new(nothrow) PartitionMapCookie; if (!map) return -1; - map->ref_count = 1; // read the partition structure PartitionMapParser parser(fd, 0, partition->size); diff --git a/src/add-ons/kernel/partitioning_systems/intel/intel.h b/src/add-ons/kernel/partitioning_systems/intel/intel.h index c5a33964d3..41c81d5fb5 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/intel.h +++ b/src/add-ons/kernel/partitioning_systems/intel/intel.h @@ -13,6 +13,8 @@ // A PartitionMap with reference count. struct PartitionMapCookie : PartitionMap { + PartitionMapCookie() : ref_count(1) {} + int32 ref_count; }; diff --git a/src/add-ons/kernel/partitioning_systems/intel/write_support.cpp b/src/add-ons/kernel/partitioning_systems/intel/write_support.cpp index 8a09cdafcc..7274844393 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/write_support.cpp +++ b/src/add-ons/kernel/partitioning_systems/intel/write_support.cpp @@ -77,7 +77,8 @@ pm_get_supported_operations(partition_data* partition, uint32 mask = ~0) int32 countSpaces = 0; if (partition->child_count < 4 // free space check - && pm_get_partitionable_spaces(partition, NULL, 0, &countSpaces) == B_OK + && pm_get_partitionable_spaces(partition, NULL, 0, &countSpaces) + == B_BUFFER_OVERFLOW && countSpaces > 0) { flags |= B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD; } @@ -661,8 +662,12 @@ get_partitionable_spaces(partition_data *partition, if (positions) delete[] positions; - *_actualCount = actualCount; TRACE(("intel: get_partitionable_spaces - found: %ld\n", actualCount)); + + *_actualCount = actualCount; + + if (count < actualCount) + return B_BUFFER_OVERFLOW; return B_OK; } @@ -725,15 +730,162 @@ pm_get_next_supported_type(partition_data *partition, int32 *cookie, // pm_shadow_changed status_t -pm_shadow_changed(partition_data *partition, uint32 operation) +pm_shadow_changed(partition_data *partition, partition_data *child, + uint32 operation) { - TRACE(("intel: pm_shadow_changed\n")); + TRACE(("intel: pm_shadow_changed(%p, %p, %lu)\n", partition, child, + operation)); - if (!partition) - return B_BAD_VALUE; + switch (operation) { + case B_PARTITION_SHADOW: + { + // get the physical partition + partition_data* physicalPartition = get_physical_partition( + partition->id); + if (!physicalPartition) { + dprintf("intel: pm_shadow_changed(B_PARTITION_SHADOW): no " + "physical partition with ID %ld\n", partition->id); + return B_ERROR; + } - // nothing to do here - return B_OK; + // clone the map + if (!physicalPartition->content_cookie) { + dprintf("intel: pm_shadow_changed(B_PARTITION_SHADOW): no " + "content cookie, physical partition: %ld\n", partition->id); + return B_ERROR; + } + + PartitionMapCookie* map = new(nothrow) PartitionMapCookie; + if (!map) + return B_NO_MEMORY; + + status_t error = map->Assign( + *(PartitionMapCookie*)physicalPartition->content_cookie); + if (error != B_OK) { + delete map; + return error; + } + + partition->content_cookie = map; + + return B_OK; + } + + case B_PARTITION_SHADOW_CHILD: + { + // get the physical child partition + partition_data* physical = get_physical_partition(child->id); + if (!physical) { + dprintf("intel: pm_shadow_changed(B_PARTITION_SHADOW_CHILD): " + "no physical partition with ID %ld\n", child->id); + return B_ERROR; + } + + if (!physical->cookie) { + dprintf("intel: pm_shadow_changed(B_PARTITION_SHADOW_CHILD): " + "no cookie, physical partition: %ld\n", child->id); + return B_ERROR; + } + + // primary partition index + int32 index = ((PrimaryPartition*)physical->cookie)->Index(); + + if (!partition->content_cookie) { + dprintf("intel: pm_shadow_changed(B_PARTITION_SHADOW_CHILD): " + "no content cookie, physical partition: %ld\n", + partition->id); + return B_ERROR; + } + + // get the primary partition + PartitionMapCookie* map + = ((PartitionMapCookie*)partition->content_cookie); + PrimaryPartition* primary = map->PrimaryPartitionAt(index); + + if (!primary || primary->IsEmpty()) { + dprintf("intel: pm_shadow_changed(B_PARTITION_SHADOW_CHILD): " + "partition %ld is empty, primary index: %ld\n", child->id, + index); + return B_BAD_VALUE; + } + + child->cookie = primary; + + return B_OK; + } + + case B_PARTITION_INITIALIZE: + { + // create an empty partition map + PartitionMapCookie* map = new(nothrow) PartitionMapCookie; + if (!map) + return B_NO_MEMORY; + + partition->content_cookie = map; + + return B_OK; + } + + case B_PARTITION_CREATE_CHILD: + { + if (!partition->content_cookie) { + dprintf("intel: pm_shadow_changed(B_PARTITION_CREATE_CHILD): " + "no content cookie, partition: %ld\n", partition->id); + return B_ERROR; + } + + PartitionMapCookie* map + = ((PartitionMapCookie*)partition->content_cookie); + + // find an empty primary partition slot + PrimaryPartition* primary = NULL; + for (int32 i = 0; i < 4; i++) { + if (map->PrimaryPartitionAt(i)->IsEmpty()) { + primary = map->PrimaryPartitionAt(i); + break; + } + } + + if (!primary) { + dprintf("intel: pm_shadow_changed(B_PARTITION_CREATE_CHILD): " + "no empty primary slot, partition: %ld\n", partition->id); + return B_ERROR; + } + + // apply type + PartitionType type; + type.SetType(child->type); + if (!type.IsValid()) { + dprintf("intel: pm_shadow_changed(B_PARTITION_CREATE_CHILD): " + "invalid partition type, partition: %ld\n", partition->id); + return B_ERROR; + } + + primary->SetType(type.Type()); + + // TODO: Apply parameters! + + child->cookie = primary; + + return B_OK; + } + + case B_PARTITION_DEFRAGMENT: + case B_PARTITION_REPAIR: + case B_PARTITION_RESIZE: + case B_PARTITION_RESIZE_CHILD: + case B_PARTITION_MOVE: + case B_PARTITION_MOVE_CHILD: + case B_PARTITION_SET_NAME: + case B_PARTITION_SET_CONTENT_NAME: + case B_PARTITION_SET_TYPE: + case B_PARTITION_SET_PARAMETERS: + case B_PARTITION_SET_CONTENT_PARAMETERS: + case B_PARTITION_DELETE_CHILD: + break; + } + + return B_ERROR; } @@ -1249,7 +1401,8 @@ ep_get_supported_operations(partition_data* partition, uint32 mask = ~0) // creating child int32 countSpaces = 0; - if (pm_get_partitionable_spaces(partition, NULL, 0, &countSpaces) == B_OK + if (pm_get_partitionable_spaces(partition, NULL, 0, &countSpaces) + == B_BUFFER_OVERFLOW && countSpaces > 0) { flags |= B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD; } @@ -1500,7 +1653,8 @@ ep_get_next_supported_type(partition_data *partition, int32 *cookie, // ep_shadow_changed status_t -ep_shadow_changed(partition_data *partition, uint32 operation) +ep_shadow_changed(partition_data *partition, partition_data *child, + uint32 operation) { TRACE(("intel: ep_shadow_changed\n")); diff --git a/src/add-ons/kernel/partitioning_systems/intel/write_support.h b/src/add-ons/kernel/partitioning_systems/intel/write_support.h index be49d87531..50346142f1 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/write_support.h +++ b/src/add-ons/kernel/partitioning_systems/intel/write_support.h @@ -33,7 +33,8 @@ status_t pm_get_partitionable_spaces(partition_data *partition, int32 *actualCount); status_t pm_get_next_supported_type(partition_data *partition, int32 *cookie, char *_type); -status_t pm_shadow_changed(partition_data *partition, uint32 operation); +status_t pm_shadow_changed(partition_data *partition, partition_data *child, + uint32 operation); status_t pm_resize(int fd, partition_id partitionID, off_t size, disk_job_id job); @@ -77,7 +78,8 @@ status_t ep_get_partitionable_spaces(partition_data *partition, int32 *actualCount); status_t ep_get_next_supported_type(partition_data *partition, int32 *cookie, char *_type); -status_t ep_shadow_changed(partition_data *partition, uint32 operation); +status_t ep_shadow_changed(partition_data *partition, partition_data *child, + uint32 operation); status_t ep_resize(int fd, partition_id partitionID, off_t size, disk_job_id job); diff --git a/src/system/kernel/disk_device_manager/KDiskSystem.cpp b/src/system/kernel/disk_device_manager/KDiskSystem.cpp index bcb379216f..1cbc7bbddc 100644 --- a/src/system/kernel/disk_device_manager/KDiskSystem.cpp +++ b/src/system/kernel/disk_device_manager/KDiskSystem.cpp @@ -118,6 +118,7 @@ status_t KDiskSystem::Load() { ManagerLocker locker(KDiskDeviceManager::Default()); +dprintf("KDiskSystem::Load(): %s -> %ld\n", Name(), fLoadCounter + 1); status_t error = B_OK; if (fLoadCounter == 0) error = LoadModule(); @@ -132,6 +133,7 @@ void KDiskSystem::Unload() { ManagerLocker locker(KDiskDeviceManager::Default()); +dprintf("KDiskSystem::Unload(): %s -> %ld\n", Name(), fLoadCounter - 1); if (fLoadCounter > 0 && --fLoadCounter == 0) UnloadModule(); } @@ -361,7 +363,8 @@ KDiskSystem::GetNextSupportedType(KPartition *partition, int32 *cookie, // ShadowPartitionChanged status_t -KDiskSystem::ShadowPartitionChanged(KPartition *partition, uint32 operation) +KDiskSystem::ShadowPartitionChanged(KPartition *partition, KPartition *child, + uint32 operation) { // to be implemented by derived classes return B_ENTRY_NOT_FOUND; diff --git a/src/system/kernel/disk_device_manager/KFileSystem.cpp b/src/system/kernel/disk_device_manager/KFileSystem.cpp index b242c22c7a..030ad9b299 100644 --- a/src/system/kernel/disk_device_manager/KFileSystem.cpp +++ b/src/system/kernel/disk_device_manager/KFileSystem.cpp @@ -173,7 +173,8 @@ KFileSystem::ValidateInitialize(KPartition *partition, char *name, // ShadowPartitionChanged status_t -KFileSystem::ShadowPartitionChanged(KPartition *partition, uint32 operation) +KFileSystem::ShadowPartitionChanged(KPartition *partition, KPartition *child, + uint32 operation) { if (!partition) return B_BAD_VALUE; @@ -183,7 +184,8 @@ KFileSystem::ShadowPartitionChanged(KPartition *partition, uint32 operation) // make any additional changes. if (!fModule->shadow_changed) return B_OK; - return fModule->shadow_changed(partition->PartitionData(), operation); + return fModule->shadow_changed(partition->PartitionData(), + child ? child->PartitionData() : NULL, operation); } diff --git a/src/system/kernel/disk_device_manager/KPartition.cpp b/src/system/kernel/disk_device_manager/KPartition.cpp index 13adc4961b..a9a75a6b0b 100644 --- a/src/system/kernel/disk_device_manager/KPartition.cpp +++ b/src/system/kernel/disk_device_manager/KPartition.cpp @@ -680,7 +680,7 @@ KPartition::RemoveChild(int32 index) partition->SetParent(NULL); partition->SetDevice(NULL); // notify listeners - FireChildAdded(partition, index); + FireChildRemoved(partition, index); return true; } return false; diff --git a/src/system/kernel/disk_device_manager/KPartitioningSystem.cpp b/src/system/kernel/disk_device_manager/KPartitioningSystem.cpp index 765a8d1fbd..539d840b17 100644 --- a/src/system/kernel/disk_device_manager/KPartitioningSystem.cpp +++ b/src/system/kernel/disk_device_manager/KPartitioningSystem.cpp @@ -408,7 +408,7 @@ KPartitioningSystem::GetTypeForContentType(const char *contentType, char *type) //! Calls for additional modifications when shadow partition is changed status_t KPartitioningSystem::ShadowPartitionChanged(KPartition *partition, - uint32 operation) + KPartition *child, uint32 operation) { if (!partition) return B_BAD_VALUE; @@ -418,7 +418,8 @@ KPartitioningSystem::ShadowPartitionChanged(KPartition *partition, // have to make any additional changes. if (!fModule->shadow_changed) return B_OK; - return fModule->shadow_changed(partition->PartitionData(), operation); + return fModule->shadow_changed(partition->PartitionData(), + child ? child->PartitionData() : NULL, operation); } diff --git a/src/system/kernel/disk_device_manager/KPhysicalPartition.cpp b/src/system/kernel/disk_device_manager/KPhysicalPartition.cpp index f0f353f3f7..fb14873dbd 100644 --- a/src/system/kernel/disk_device_manager/KPhysicalPartition.cpp +++ b/src/system/kernel/disk_device_manager/KPhysicalPartition.cpp @@ -167,27 +167,54 @@ KPhysicalPartition::CreateShadowPartition() { if (fShadowPartition) return B_BAD_VALUE; + KDiskDeviceManager *manager = KDiskDeviceManager::Default(); if (ManagerLocker locker = manager) { // create shadow partition fShadowPartition = new(nothrow) KShadowPartition(this); if (!fShadowPartition) return B_NO_MEMORY; + // make it known to the manager if (!manager->PartitionAdded(fShadowPartition)) { delete fShadowPartition; fShadowPartition = NULL; return B_NO_MEMORY; } + + // notify the disk systems + // parent disk system + status_t error; + if (Parent()) { + error = Parent()->DiskSystem()->ShadowPartitionChanged( + Parent()->ShadowPartition(), fShadowPartition, + B_PARTITION_SHADOW_CHILD); + if (error != B_OK) { + UnsetShadowPartition(true); + return error; + } + } + + // this partition's disk system + if (fShadowPartition->DiskSystem()) { + error = fShadowPartition->DiskSystem()->ShadowPartitionChanged( + fShadowPartition, NULL, B_PARTITION_SHADOW); + if (error != B_OK) { + UnsetShadowPartition(true); + return error; + } + } } + // create shadows for children for (int32 i = 0; KPartition *child = ChildAt(i); i++) { status_t error = child->CreateShadowPartition(); if (error == B_OK) error = fShadowPartition->AddChild(child->ShadowPartition(), i); + // cleanup on error if (error != B_OK) { - for (int32 k = 0; k <= i; i++) + for (int32 k = 0; k <= i; k++) ChildAt(k)->UnsetShadowPartition(true); UnsetShadowPartition(true); return error; 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 242ddf9d2a..ed9a0ba07b 100644 --- a/src/system/kernel/disk_device_manager/ddm_userland_interface.cpp +++ b/src/system/kernel/disk_device_manager/ddm_userland_interface.cpp @@ -26,6 +26,10 @@ using namespace BPrivate::DiskDevice; // debugging #define ERROR(x) + +// TODO: Add user address checks and check return values of user_memcpy()! + + // ddm_strlcpy /*! \brief Wrapper around user_strlcpy() that returns a status_t indicating appropriate success or failure. @@ -70,7 +74,7 @@ move_descendants_contents(KPartition *partition) KDiskSystem *diskSystem = partition->DiskSystem(); if (diskSystem || partition->AlgorithmData()) { status_t error = diskSystem->ShadowPartitionChanged(partition, - B_PARTITION_RESIZE); + NULL, B_PARTITION_MOVE); if (error != B_OK) return error; } @@ -284,46 +288,58 @@ status_t _user_get_partitionable_spaces(partition_id partitionID, int32 changeCounter, partitionable_space_data *_buffer, int32 count, int32 *_actualCount) { - if (!_buffer && count > 0) + if (count > 0 && !_buffer) return B_BAD_VALUE; - // copy in + + if (count > 0 && !IS_USER_ADDRESS(_buffer) + || _actualCount && !IS_USER_ADDRESS(_actualCount)) { + return B_BAD_ADDRESS; + } + + // allocate buffer int32 bufferSize = count * sizeof(partitionable_space_data); - partitionable_space_data *buffer = count > 0 - ? reinterpret_cast(malloc(bufferSize)) - : NULL; - if (buffer) - user_memcpy(buffer, _buffer, bufferSize); + partitionable_space_data *buffer = NULL; + MemoryDeleter bufferDeleter; + if (count > 0) { + buffer = (partitionable_space_data*)malloc(bufferSize); + if (!buffer) + return B_NO_MEMORY; + bufferDeleter.SetTo(buffer); + } + status_t error = B_OK; + // get the partition KDiskDeviceManager *manager = KDiskDeviceManager::Default(); KPartition *partition = manager->ReadLockPartition(partitionID); - error = partition ? (status_t)B_OK : (status_t)B_ENTRY_NOT_FOUND; - if (!error) { - PartitionRegistrar registrar1(partition, true); - PartitionRegistrar registrar2(partition->Device(), true); - DeviceReadLocker locker(partition->Device(), true); - error = check_shadow_partition(partition, changeCounter) - ? B_OK : B_BAD_VALUE; - if (!error) { - // get the disk system - KDiskSystem *diskSystem = partition->DiskSystem(); - error = diskSystem ? (status_t)B_OK : (status_t)B_ENTRY_NOT_FOUND; - if (!error) { - // get the info - int32 actualCount; - error = diskSystem->GetPartitionableSpaces(partition, buffer, - count, &actualCount); - if (!error && _actualCount) { - user_memcpy(_actualCount, &actualCount, - sizeof(actualCount)); - } - } - } - } + if (!partition) + return B_ENTRY_NOT_FOUND; + + PartitionRegistrar registrar1(partition, true); + PartitionRegistrar registrar2(partition->Device(), true); + DeviceReadLocker locker(partition->Device(), true); + + if (!check_shadow_partition(partition, changeCounter)) + return B_BAD_VALUE; + + // get the disk system + KDiskSystem *diskSystem = partition->DiskSystem(); + if (!diskSystem) + return B_ENTRY_NOT_FOUND; + + // get the info + int32 actualCount; + error = diskSystem->GetPartitionableSpaces(partition, buffer, count, + &actualCount); + // copy out - if (!error && buffer) + if (_actualCount) + user_memcpy(_actualCount, &actualCount, sizeof(actualCount)); + // copy even on error + + if (error == B_OK && buffer) user_memcpy(_buffer, buffer, bufferSize); - free(buffer); + return error; } @@ -376,7 +392,6 @@ _user_get_disk_system_info(disk_system_id id, user_disk_system_info *_info) KDiskDeviceManager *manager = KDiskDeviceManager::Default(); if (ManagerLocker locker = manager) { if (KDiskSystem *diskSystem = manager->FindDiskSystem(id)) { - DiskSystemLoader _(diskSystem, true); user_disk_system_info info; diskSystem->GetInfo(&info); user_memcpy(_info, &info, sizeof(info)); @@ -399,7 +414,6 @@ _user_get_next_disk_system_info(int32 *_cookie, user_disk_system_info *_info) KDiskDeviceManager *manager = KDiskDeviceManager::Default(); if (ManagerLocker locker = manager) { if (KDiskSystem *diskSystem = manager->NextDiskSystem(&cookie)) { - DiskSystemLoader _(diskSystem, true); user_disk_system_info info; diskSystem->GetInfo(&info); user_memcpy(_info, &info, sizeof(info)); @@ -424,7 +438,6 @@ _user_find_disk_system(const char *_name, user_disk_system_info *_info) KDiskDeviceManager *manager = KDiskDeviceManager::Default(); if (ManagerLocker locker = manager) { if (KDiskSystem *diskSystem = manager->FindDiskSystem(name)) { - DiskSystemLoader _(diskSystem, true); user_disk_system_info info; diskSystem->GetInfo(&info); user_memcpy(_info, &info, sizeof(info)); @@ -1146,9 +1159,8 @@ _user_get_next_supported_partition_type(partition_id partitionID, char type[B_DISK_DEVICE_TYPE_LENGTH]; error = diskSystem->GetNextSupportedType(partition, &cookie, type); - if (!error) { + if (!error) error = ddm_strlcpy(_type, type, B_DISK_DEVICE_TYPE_LENGTH); - } } } } @@ -1352,13 +1364,13 @@ _user_resize_partition(partition_id partitionID, int32 changeCounter, partition->Changed(B_PARTITION_CHANGED_SIZE); // implicit partitioning system changes error = partition->Parent()->DiskSystem()->ShadowPartitionChanged( - partition, B_PARTITION_RESIZE_CHILD); + partition->Parent(), partition, B_PARTITION_RESIZE_CHILD); if (error != B_OK) return error; // implicit content disk system changes if (partition->DiskSystem()) { error = partition->DiskSystem()->ShadowPartitionChanged( - partition, B_PARTITION_RESIZE); + partition, NULL, B_PARTITION_RESIZE); } return error; } @@ -1393,7 +1405,7 @@ _user_move_partition(partition_id partitionID, int32 changeCounter, partition->Changed(B_PARTITION_CHANGED_OFFSET); // implicit partitioning system changes error = partition->Parent()->DiskSystem()->ShadowPartitionChanged( - partition, B_PARTITION_MOVE_CHILD); + partition->Parent(), partition, B_PARTITION_MOVE_CHILD); if (error != B_OK) return error; // implicit descendants' content disk system changes @@ -1435,7 +1447,7 @@ _user_set_partition_name(partition_id partitionID, int32 changeCounter, partition->Changed(B_PARTITION_CHANGED_NAME); // implicit partitioning system changes return partition->Parent()->DiskSystem()->ShadowPartitionChanged( - partition, B_PARTITION_SET_NAME); + partition->Parent(), partition, B_PARTITION_SET_NAME); } @@ -1474,7 +1486,7 @@ _user_set_partition_content_name(partition_id partitionID, int32 changeCounter, partition->Changed(B_PARTITION_CHANGED_CONTENT_NAME); // implicit content disk system changes return partition->DiskSystem()->ShadowPartitionChanged( - partition, B_PARTITION_SET_CONTENT_NAME); + partition, NULL, B_PARTITION_SET_CONTENT_NAME); } @@ -1508,7 +1520,7 @@ _user_set_partition_type(partition_id partitionID, int32 changeCounter, partition->Changed(B_PARTITION_CHANGED_TYPE); // implicit partitioning system changes return partition->Parent()->DiskSystem()->ShadowPartitionChanged( - partition, B_PARTITION_SET_TYPE); + partition->Parent(), partition, B_PARTITION_SET_TYPE); } @@ -1545,7 +1557,7 @@ _user_set_partition_parameters(partition_id partitionID, int32 changeCounter, partition->Changed(B_PARTITION_CHANGED_PARAMETERS); // implicit partitioning system changes error = partition->Parent()->DiskSystem() - ->ShadowPartitionChanged(partition, + ->ShadowPartitionChanged(partition->Parent(), partition, B_PARTITION_SET_PARAMETERS); } } @@ -1588,7 +1600,7 @@ _user_set_partition_content_parameters(partition_id partitionID, partition->Changed(B_PARTITION_CHANGED_CONTENT_PARAMETERS); // implicit content disk system changes error = partition->DiskSystem()->ShadowPartitionChanged( - partition, B_PARTITION_SET_CONTENT_PARAMETERS); + partition, NULL, B_PARTITION_SET_CONTENT_PARAMETERS); } } } @@ -1679,7 +1691,7 @@ _user_initialize_partition(partition_id partitionID, int32 changeCounter, // implicit content disk system changes return partition->DiskSystem()->ShadowPartitionChanged( - partition, B_PARTITION_INITIALIZE); + partition, NULL, B_PARTITION_INITIALIZE); } @@ -1749,16 +1761,16 @@ _user_create_child_partition(partition_id partitionID, int32 changeCounter, } // set the parameters child->SetOffset(offset); - child->SetSize(offset); + child->SetSize(size); error = child->SetType(type); } if (!error) { - error = partition->SetParameters(parameters); + error = child->SetParameters(parameters); } if (!error) { // implicit partitioning system changes error = partition->DiskSystem()->ShadowPartitionChanged( - partition, B_PARTITION_CREATE_CHILD); + partition, child, B_PARTITION_CREATE_CHILD); } } }