From 4419d699ecc4e43bbdb7b76acb09c057e44a975a Mon Sep 17 00:00:00 2001 From: Jessica Hamilton Date: Fri, 23 Dec 2016 18:19:01 +1300 Subject: [PATCH] partitioning: pass along reference to parent when uninitializing. * Fixes problems with setting the partition name after uninitializing a partition in DriveSetup. Previously, UninitializeJob() was followed by SetStringJob(), but the kernel was updating the change counter for the parent partition when uninitializing a partition, leading to SetStringJob() having an incorrect change counter for the parent partition. Now the parent change counter will be correct when SetStringJob() runs. --- headers/build/private/kernel/syscalls.h | 17 ++++++++-------- .../disk_device_manager/KDiskDeviceUtils.h | 5 ++++- .../ddm_userland_interface.h | 3 ++- headers/private/system/syscalls.h | 3 ++- src/build/libhaikucompat/syscalls.cpp | 3 ++- .../disk_device/DiskDeviceJobGenerator.cpp | 10 +++++++++- .../disk_device/jobs/UninitializeJob.cpp | 19 ++++++++++++------ .../disk_device/jobs/UninitializeJob.h | 3 ++- .../ddm_userland_interface.cpp | 20 ++++++++++++++++++- 9 files changed, 62 insertions(+), 21 deletions(-) diff --git a/headers/build/private/kernel/syscalls.h b/headers/build/private/kernel/syscalls.h index 3e4e739cc6..9b47c2e5fc 100644 --- a/headers/build/private/kernel/syscalls.h +++ b/headers/build/private/kernel/syscalls.h @@ -194,7 +194,7 @@ extern status_t _kern_unlock_node(int fd); // extern status_t _kern_set_timezone(int32 timezoneOffset, bool daylightSavingTime); // extern status_t _kern_set_tzfilename(const char *filename, size_t length, bool isGMT); // extern status_t _kern_get_tzfilename(char *filename, size_t length, bool *_isGMT); -// +// // extern bigtime_t _kern_system_time(); // extern status_t _kern_snooze_etc(bigtime_t time, int timebase, int32 flags); @@ -210,10 +210,10 @@ extern status_t _kern_unlock_node(int fd); // extern area_id _kern_transfer_area(area_id area, void **_address, uint32 addressSpec, // team_id target); // extern status_t _kern_set_area_protection(area_id area, uint32 newProtection); -// extern area_id _kern_clone_area(const char *name, void **_address, uint32 addressSpec, +// extern area_id _kern_clone_area(const char *name, void **_address, uint32 addressSpec, // uint32 protection, area_id sourceArea); // extern status_t _kern_init_heap_address_range(addr_t base, addr_t size); -// +// // area_id sys_vm_map_file(const char *name, void **address, int addr_type, // addr_t size, int lock, int mapping, const char *path, off_t offset); @@ -237,7 +237,7 @@ extern status_t _kern_unlock_node(int fd); // debug support functions // extern void _kern_debugger(const char *message); // extern int _kern_disable_debugger(int state); -// +// // extern status_t _kern_install_default_debugger(port_id debuggerPort); // extern port_id _kern_install_team_debugger(team_id team, // port_id debuggerPort); @@ -252,7 +252,7 @@ extern status_t _kern_unlock_node(int fd); // extern int32 _kern_atomic_test_and_set(vint32 *value, int32 newValue, int32 testAgainst); // extern int32 _kern_atomic_add(vint32 *value, int32 addValue); // extern int32 _kern_atomic_and(vint32 *value, int32 andValue); -// extern int32 _kern_atomic_or(vint32 *value, int32 orValue); +// extern int32 _kern_atomic_or(vint32 *value, int32 orValue); // extern int32 _kern_atomic_get(vint32 *value); // #endif // ATOMIC_FUNCS_ARE_SYSCALLS @@ -261,7 +261,7 @@ extern status_t _kern_unlock_node(int fd); // extern int64 _kern_atomic_test_and_set64(vint64 *value, int64 newValue, int64 testAgainst); // extern int64 _kern_atomic_add64(vint64 *value, int64 addValue); // extern int64 _kern_atomic_and64(vint64 *value, int64 andValue); -// extern int64 _kern_atomic_or64(vint64 *value, int64 orValue); +// extern int64 _kern_atomic_or64(vint64 *value, int64 orValue); // extern int64 _kern_atomic_get64(vint64 *value); // #endif // ATOMIC64_FUNCS_ARE_SYSCALLS @@ -281,7 +281,7 @@ extern status_t _kern_unlock_node(int fd); // extern area_id _kern_register_messaging_service(sem_id lockingSem, // sem_id counterSem); // extern status_t _kern_unregister_messaging_service(); -// +// // extern void _kern_clear_caches(void *address, size_t length, uint32 flags); // #ifdef __INTEL__ @@ -397,7 +397,8 @@ extern status_t _kern_initialize_partition(partition_id partitionID, const char *name, const char *parameters, size_t parametersSize); extern status_t _kern_uninitialize_partition(partition_id partitionID, - int32 changeCounter); + int32 changeCounter, partition_id parentID, + int32 parentChangeCounter); extern status_t _kern_create_child_partition(partition_id partitionID, int32 changeCounter, off_t offset, off_t size, const char *type, const char *parameters, size_t parametersSize, diff --git a/headers/private/kernel/disk_device_manager/KDiskDeviceUtils.h b/headers/private/kernel/disk_device_manager/KDiskDeviceUtils.h index cf0b5e8d75..e91f255906 100644 --- a/headers/private/kernel/disk_device_manager/KDiskDeviceUtils.h +++ b/headers/private/kernel/disk_device_manager/KDiskDeviceUtils.h @@ -109,13 +109,16 @@ class AutoLockerPartitionRegistration { public: inline bool Lock(KPartition *partition) { + if (partition == NULL) + return true; partition->Register(); return true; } inline void Unlock(KPartition *partition) { - partition->Unregister(); + if (partition != NULL) + partition->Unregister(); } }; diff --git a/headers/private/kernel/disk_device_manager/ddm_userland_interface.h b/headers/private/kernel/disk_device_manager/ddm_userland_interface.h index a5a1febb3d..9ebe5e5d4b 100644 --- a/headers/private/kernel/disk_device_manager/ddm_userland_interface.h +++ b/headers/private/kernel/disk_device_manager/ddm_userland_interface.h @@ -77,7 +77,8 @@ status_t _user_initialize_partition(partition_id partitionID, int32* changeCounter, const char* diskSystemName, const char* name, const char* parameters); status_t _user_uninitialize_partition(partition_id partitionID, - int32* changeCounter); + int32* changeCounter, partition_id parentID, + int32* parentChangeCounter); status_t _user_create_child_partition(partition_id partitionID, int32* changeCounter, off_t offset, off_t size, diff --git a/headers/private/system/syscalls.h b/headers/private/system/syscalls.h index b203434412..35fe2a1632 100644 --- a/headers/private/system/syscalls.h +++ b/headers/private/system/syscalls.h @@ -617,7 +617,8 @@ extern status_t _kern_initialize_partition(partition_id partitionID, int32* changeCounter, const char* diskSystemName, const char* name, const char* parameters); extern status_t _kern_uninitialize_partition(partition_id partitionID, - int32* changeCounter); + int32* changeCounter, partition_id parentID, + int32* parentChangeCounter); extern status_t _kern_create_child_partition(partition_id partitionID, int32* changeCounter, off_t offset, off_t size, const char* type, const char* name, diff --git a/src/build/libhaikucompat/syscalls.cpp b/src/build/libhaikucompat/syscalls.cpp index 1e8c9adb62..b88e736646 100644 --- a/src/build/libhaikucompat/syscalls.cpp +++ b/src/build/libhaikucompat/syscalls.cpp @@ -374,7 +374,8 @@ _kern_initialize_partition(partition_id partitionID, int32 changeCounter, status_t -_kern_uninitialize_partition(partition_id partitionID, int32 changeCounter) +_kern_uninitialize_partition(partition_id partitionID, int32 changeCounter, + partition_id parentID, int32 parentChangeCounter) { return B_ERROR; } diff --git a/src/kits/storage/disk_device/DiskDeviceJobGenerator.cpp b/src/kits/storage/disk_device/DiskDeviceJobGenerator.cpp index 3b46f883a7..f132286994 100644 --- a/src/kits/storage/disk_device/DiskDeviceJobGenerator.cpp +++ b/src/kits/storage/disk_device/DiskDeviceJobGenerator.cpp @@ -523,7 +523,15 @@ DiskDeviceJobGenerator::_GenerateUninitializeJob(BPartition* partition) if (error != B_OK) return error; - return _AddJob(new(nothrow) UninitializeJob(reference)); + BPartition* parent = partition->Parent(); + PartitionReference* parentReference = NULL; + if (parent != NULL) { + error = _GetPartitionReference(parent, parentReference); + if (error != B_OK) + return error; + } + + return _AddJob(new(nothrow) UninitializeJob(reference, parentReference)); } diff --git a/src/kits/storage/disk_device/jobs/UninitializeJob.cpp b/src/kits/storage/disk_device/jobs/UninitializeJob.cpp index d99f790d7a..798abf6f44 100644 --- a/src/kits/storage/disk_device/jobs/UninitializeJob.cpp +++ b/src/kits/storage/disk_device/jobs/UninitializeJob.cpp @@ -11,8 +11,9 @@ // constructor -UninitializeJob::UninitializeJob(PartitionReference* partition) - : DiskDeviceJob(partition) +UninitializeJob::UninitializeJob(PartitionReference* partition, + PartitionReference* parent) + : DiskDeviceJob(parent, partition) { } @@ -27,14 +28,20 @@ UninitializeJob::~UninitializeJob() status_t UninitializeJob::Do() { - int32 changeCounter = fPartition->ChangeCounter(); - status_t error = _kern_uninitialize_partition(fPartition->PartitionID(), - &changeCounter); + bool haveParent = fPartition != NULL; + int32 changeCounter = fChild->ChangeCounter(); + int32 parentChangeCounter = haveParent ? fPartition->ChangeCounter() : 0; + partition_id parentID = haveParent ? fPartition->PartitionID() : -1; + + status_t error = _kern_uninitialize_partition(fChild->PartitionID(), + &changeCounter, parentID, &parentChangeCounter); if (error != B_OK) return error; - fPartition->SetChangeCounter(changeCounter); + fChild->SetChangeCounter(changeCounter); + if (haveParent) + fPartition->SetChangeCounter(parentChangeCounter); return B_OK; } diff --git a/src/kits/storage/disk_device/jobs/UninitializeJob.h b/src/kits/storage/disk_device/jobs/UninitializeJob.h index 21e7d03312..04f7f7901e 100644 --- a/src/kits/storage/disk_device/jobs/UninitializeJob.h +++ b/src/kits/storage/disk_device/jobs/UninitializeJob.h @@ -14,7 +14,8 @@ namespace BPrivate { class UninitializeJob : public DiskDeviceJob { public: - UninitializeJob(PartitionReference* partition); + UninitializeJob(PartitionReference* partition, + PartitionReference* parent = NULL); virtual ~UninitializeJob(); virtual status_t Do(); 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 14e535306d..6c42ce747a 100644 --- a/src/system/kernel/disk_device_manager/ddm_userland_interface.cpp +++ b/src/system/kernel/disk_device_manager/ddm_userland_interface.cpp @@ -1218,14 +1218,20 @@ _user_initialize_partition(partition_id partitionID, int32* _changeCounter, status_t -_user_uninitialize_partition(partition_id partitionID, int32* _changeCounter) +_user_uninitialize_partition(partition_id partitionID, int32* _changeCounter, + partition_id parentID, int32* _parentChangeCounter) { // copy parameters in int32 changeCounter; + int32 parentChangeCounter; + bool haveParent = parentID >= 0; status_t error; if ((error = copy_from_user_value(changeCounter, _changeCounter)) != B_OK) return error; + if (haveParent && (error = copy_from_user_value(parentChangeCounter, + _parentChangeCounter)) != B_OK) + return error; // get the partition KDiskDeviceManager* manager = KDiskDeviceManager::Default(); @@ -1237,9 +1243,18 @@ _user_uninitialize_partition(partition_id partitionID, int32* _changeCounter) PartitionRegistrar registrar2(partition->Device(), true); DeviceWriteLocker locker(partition->Device(), true); + // register parent + KPartition* parent = NULL; + if (haveParent) + parent = manager->RegisterPartition(parentID); + + PartitionRegistrar registrar3(parent, true); + // check change counter if (changeCounter != partition->ChangeCounter()) return B_BAD_VALUE; + if (haveParent && parentChangeCounter != parent->ChangeCounter()) + return B_BAD_VALUE; // the partition must be initialized if (!partition->DiskSystem()) @@ -1275,6 +1290,9 @@ _user_uninitialize_partition(partition_id partitionID, int32* _changeCounter) error = copy_to_user_value(_changeCounter, partition->ChangeCounter()); if (error != B_OK) return error; + if (haveParent && (error = copy_to_user_value(_parentChangeCounter, + parent->ChangeCounter())) != B_OK) + return error; return B_OK; }