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