status_t _user_set_partition_parameters(partition_id partitionID, int32* _changeCounter, partition_id childID, int32* _childChangeCounter, const char* _parameters) { // copy parameters in UserStringParameter<true> parameters; int32 changeCounter; int32 childChangeCounter; status_t error = parameters.Init(_parameters, B_DISK_DEVICE_MAX_PARAMETER_SIZE); if (error == B_OK) error = copy_from_user_value(changeCounter, _changeCounter); if (error == B_OK) error = copy_from_user_value(childChangeCounter, _childChangeCounter); if (error != B_OK) return error; // get the partition KDiskDeviceManager* manager = KDiskDeviceManager::Default(); KPartition* partition = manager->WriteLockPartition(partitionID); if (partition == NULL) 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 == NULL) 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 == NULL) 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 error = copy_to_user_value(_changeCounter, partition->ChangeCounter()); if (error == B_OK) error = copy_to_user_value(_childChangeCounter, child->ChangeCounter()); return error; }
status_t _user_delete_child_partition(partition_id partitionID, int32* _changeCounter, partition_id childID, int32 childChangeCounter) { // copy parameters in int32 changeCounter; status_t error; if ((error = copy_from_user_value(changeCounter, _changeCounter)) != B_OK) return error; // get the partition KDiskDeviceManager* manager = KDiskDeviceManager::Default(); KPartition* partition = manager->WriteLockPartition(partitionID); if (partition == NULL) 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 == NULL) 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 == NULL) 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; // return change counter return copy_to_user_value(_changeCounter, partition->ChangeCounter()); }
status_t _user_resize_partition(partition_id partitionID, int32* _changeCounter, partition_id childID, int32* _childChangeCounter, off_t size, off_t contentSize) { // copy parameters in int32 changeCounter; int32 childChangeCounter; status_t error = copy_from_user_value(changeCounter, _changeCounter); if (error == B_OK) error = copy_from_user_value(childChangeCounter, _childChangeCounter); if (error != B_OK) return error; // get the partition KDiskDeviceManager* manager = KDiskDeviceManager::Default(); KPartition* partition = manager->WriteLockPartition(partitionID); if (partition == NULL) 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 == NULL) 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 == NULL) 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; // return change counters error = copy_to_user_value(_changeCounter, partition->ChangeCounter()); if (error == B_OK) error = copy_to_user_value(_childChangeCounter, child->ChangeCounter()); return error; }
status_t _user_set_partition_name(partition_id partitionID, int32* _changeCounter, partition_id childID, int32* _childChangeCounter, const char* _name) { // copy parameters in UserStringParameter<false> 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; } // get the partition 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; } // 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; // 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; }