1 // disk_device_manager.cpp 2 3 #include <KernelExport.h> 4 #include <stdio.h> 5 6 #include "disk_device_manager.h" 7 #include "KDiskDevice.h" 8 #include "KDiskDeviceJob.h" 9 #include "KDiskDeviceJobQueue.h" 10 #include "KDiskDeviceManager.h" 11 #include "KDiskDeviceUtils.h" 12 #include "KDiskSystem.h" 13 #include "KPartition.h" 14 15 16 // debugging 17 //#define DBG(x) 18 #define DBG(x) x 19 #define OUT dprintf 20 21 22 // write_lock_disk_device 23 disk_device_data * 24 write_lock_disk_device(partition_id partitionID) 25 { 26 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 27 if (KDiskDevice *device = manager->RegisterDevice(partitionID)) { 28 if (device->WriteLock()) 29 return device->DeviceData(); 30 // Only unregister, when the locking fails. The guarantees, that the 31 // lock owner also has a reference. 32 device->Unregister(); 33 } 34 return NULL; 35 } 36 37 38 // write_unlock_disk_device 39 void 40 write_unlock_disk_device(partition_id partitionID) 41 { 42 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 43 if (KDiskDevice *device = manager->RegisterDevice(partitionID)) { 44 bool isLocked = device->IsWriteLocked(); 45 if (isLocked) { 46 device->WriteUnlock(); 47 device->Unregister(); 48 } 49 device->Unregister(); 50 } 51 } 52 53 54 // read_lock_disk_device 55 disk_device_data * 56 read_lock_disk_device(partition_id partitionID) 57 { 58 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 59 if (KDiskDevice *device = manager->RegisterDevice(partitionID)) { 60 if (device->ReadLock()) 61 return device->DeviceData(); 62 // Only unregister, when the locking fails. The guarantees, that the 63 // lock owner also has a reference. 64 device->Unregister(); 65 } 66 return NULL; 67 } 68 69 70 // read_unlock_disk_device 71 void 72 read_unlock_disk_device(partition_id partitionID) 73 { 74 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 75 if (KDiskDevice *device = manager->RegisterDevice(partitionID)) { 76 bool isLocked = device->IsReadLocked(false); 77 if (isLocked) { 78 device->ReadUnlock(); 79 device->Unregister(); 80 } 81 device->Unregister(); 82 } 83 } 84 85 86 // find_disk_device 87 int32 88 find_disk_device(const char *path) 89 { 90 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 91 partition_id id = -1; 92 if (KDiskDevice *device = manager->RegisterDevice(path)) { 93 id = device->ID(); 94 device->Unregister(); 95 } 96 return id; 97 } 98 99 100 // find_partition 101 int32 102 find_partition(const char *path) 103 { 104 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 105 partition_id id = -1; 106 if (KPartition *partition = manager->RegisterPartition(path)) { 107 id = partition->ID(); 108 partition->Unregister(); 109 } 110 return id; 111 } 112 113 114 // get_disk_device 115 disk_device_data * 116 get_disk_device(partition_id partitionID) 117 { 118 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 119 KDiskDevice *device = manager->FindDevice(partitionID, false); 120 return (device ? device->DeviceData() : NULL); 121 } 122 123 124 // get_physical_partition 125 partition_data* 126 get_physical_partition(partition_id partitionID) 127 { 128 KDiskDeviceManager* manager = KDiskDeviceManager::Default(); 129 KPartition* partition = manager->FindPartition(partitionID, true); 130 return (partition ? partition->PartitionData() : NULL); 131 } 132 133 134 // get_partition 135 partition_data * 136 get_partition(partition_id partitionID) 137 { 138 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 139 KPartition *partition = manager->FindPartition(partitionID, false); 140 return (partition ? partition->PartitionData() : NULL); 141 } 142 143 144 // get_parent_partition 145 partition_data * 146 get_parent_partition(partition_id partitionID) 147 { 148 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 149 KPartition *partition = manager->FindPartition(partitionID); 150 if (partition && partition->Parent()) 151 return partition->Parent()->PartitionData(); 152 return NULL; 153 } 154 155 156 // get_child_partition 157 partition_data * 158 get_child_partition(partition_id partitionID, int32 index) 159 { 160 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 161 if (KPartition *partition = manager->FindPartition(partitionID)) { 162 if (KPartition *child = partition->ChildAt(index)) 163 return child->PartitionData(); 164 } 165 return NULL; 166 } 167 168 169 // compare_partition_data_offset 170 static int 171 compare_partition_data_offset(const void* _a, const void* _b) 172 { 173 const partition_data* a = *(const partition_data**)_a; 174 const partition_data* b = *(const partition_data**)_b; 175 176 if (a->offset == b->offset) 177 return 0; 178 179 return a->offset < b->offset ? -1 : 1; 180 } 181 182 183 // create_child_partition 184 partition_data * 185 create_child_partition(partition_id partitionID, int32 index, 186 partition_id childID) 187 { 188 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 189 if (KPartition *partition = manager->FindPartition(partitionID)) { 190 KPartition *child = NULL; 191 if (partition->CreateChild(childID, index, &child) == B_OK) 192 return child->PartitionData(); 193 else 194 DBG(OUT(" creating child (%ld, %ld) failed\n", partitionID, index)); 195 } 196 else 197 DBG(OUT(" partition %ld not found\n", partitionID)); 198 return NULL; 199 } 200 201 202 // delete_partition 203 bool 204 delete_partition(partition_id partitionID) 205 { 206 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 207 if (KPartition *partition = manager->FindPartition(partitionID)) { 208 if (KPartition *parent = partition->Parent()) 209 return parent->RemoveChild(partition); 210 } 211 return false; 212 } 213 214 215 // partition_modified 216 void 217 partition_modified(partition_id partitionID) 218 { 219 // TODO: implemented 220 } 221 222 223 // scan_partition 224 status_t 225 scan_partition(partition_id partitionID) 226 { 227 // get the partition 228 KDiskDeviceManager* manager = KDiskDeviceManager::Default(); 229 KPartition* partition = manager->RegisterPartition(partitionID); 230 if (partition == NULL) 231 return B_ENTRY_NOT_FOUND; 232 PartitionRegistrar _(partition, true); 233 234 // scan it 235 return manager->ScanPartition(partition, false); 236 } 237 238 239 // find_disk_system 240 disk_system_id 241 find_disk_system(const char *name) 242 { 243 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 244 if (ManagerLocker locker = manager) { 245 if (KDiskSystem *diskSystem = manager->FindDiskSystem(name)) 246 return diskSystem->ID(); 247 } 248 return -1; 249 } 250 251 252 // update_disk_device_job_progress 253 bool 254 update_disk_device_job_progress(disk_job_id jobID, float progress) 255 { 256 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 257 if (ManagerLocker locker = manager) { 258 if (KDiskDeviceJob *job = manager->FindJob(jobID)) { 259 job->UpdateProgress(progress); 260 return true; 261 } 262 } 263 return false; 264 } 265 266 267 // update_disk_device_job_extra_progress 268 bool 269 update_disk_device_job_extra_progress(disk_job_id jobID, const char *info) 270 { 271 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 272 if (ManagerLocker locker = manager) { 273 if (KDiskDeviceJob *job = manager->FindJob(jobID)) { 274 job->UpdateExtraProgress(info); 275 return true; 276 } 277 } 278 return false; 279 } 280 281 282 // set_disk_device_job_error_message 283 bool 284 set_disk_device_job_error_message(disk_job_id jobID, const char *message) 285 { 286 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 287 if (ManagerLocker locker = manager) { 288 if (KDiskDeviceJob *job = manager->FindJob(jobID)) { 289 job->SetErrorMessage(message); 290 return true; 291 } 292 } 293 return false; 294 } 295 296 297 // update_disk_device_job_interrupt_properties 298 uint32 299 update_disk_device_job_interrupt_properties(disk_job_id jobID, 300 uint32 interruptProperties) 301 { 302 bool paused = false; 303 KDiskDeviceManager *manager = KDiskDeviceManager::Default(); 304 do { 305 sem_id pauseSemaphore = -1; 306 if (ManagerLocker locker = manager) { 307 // get the job and the respective job queue 308 if (KDiskDeviceJob *job = manager->FindJob(jobID)) { 309 if (KDiskDeviceJobQueue *jobQueue = job->JobQueue()) { 310 // terminate if canceled. 311 if (jobQueue->IsCanceled()) { 312 if (jobQueue->ShallReverse()) 313 return B_DISK_DEVICE_JOB_REVERSE; 314 return B_DISK_DEVICE_JOB_CANCEL; 315 } 316 // set the new interrupt properties only when not 317 // requested to pause 318 if (jobQueue->IsPauseRequested()) 319 pauseSemaphore = jobQueue->ReadyToPause(); 320 else 321 job->SetInterruptProperties(interruptProperties); 322 } 323 } 324 } 325 // pause, if requested; redo the loop then 326 paused = (pauseSemaphore >= 0); 327 if (paused) { 328 acquire_sem(pauseSemaphore); 329 pauseSemaphore = -1; 330 } 331 } while (paused); 332 return B_DISK_DEVICE_JOB_CONTINUE; 333 } 334 335