xref: /haiku/src/system/kernel/disk_device_manager/disk_device_manager.cpp (revision 1b8f7f13a3dc70e0e903cb94248220b40b732204)
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