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