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