xref: /haiku/src/system/kernel/disk_device_manager/disk_device_manager.cpp (revision cf02b29e4e0dd6d61c4bb25fcc8620e99d4908bf)
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, false)) {
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, false)) {
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, false)) {
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, false)) {
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 int
158 open_partition(partition_id partitionID, int openMode)
159 {
160 	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
161 	KPartition* partition = manager->FindPartition(partitionID);
162 	if (partition == NULL)
163 		return B_BAD_VALUE;
164 
165 	int fd = -1;
166 	status_t result = partition->Open(openMode, &fd);
167 	if (result != B_OK)
168 		return -1;
169 
170 	return fd;
171 }
172 
173 
174 // create_child_partition
175 partition_data*
176 create_child_partition(partition_id partitionID, int32 index, off_t offset,
177 	off_t size, partition_id childID)
178 {
179 	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
180 	if (KPartition* partition = manager->FindPartition(partitionID)) {
181 		KPartition* child = NULL;
182 		if (partition->CreateChild(childID, index, offset, size, &child)
183 				== B_OK) {
184 			return child->PartitionData();
185 		} else {
186 			DBG(OUT("  creating child (%ld, %ld) failed\n", partitionID,
187 			index));
188 		}
189 	} else
190 		DBG(OUT("  partition %ld not found\n", partitionID));
191 
192 	return NULL;
193 }
194 
195 
196 // delete_partition
197 bool
198 delete_partition(partition_id partitionID)
199 {
200 	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
201 	if (KPartition* partition = manager->FindPartition(partitionID)) {
202 		if (KPartition* parent = partition->Parent())
203 			return parent->RemoveChild(partition);
204 	}
205 	return false;
206 }
207 
208 
209 // partition_modified
210 void
211 partition_modified(partition_id partitionID)
212 {
213 	// TODO: implemented
214 }
215 
216 
217 // scan_partition
218 status_t
219 scan_partition(partition_id partitionID)
220 {
221 	// get the partition
222 	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
223 	KPartition* partition = manager->RegisterPartition(partitionID);
224 	if (partition == NULL)
225 		return B_ENTRY_NOT_FOUND;
226 	PartitionRegistrar _(partition, true);
227 
228 	// scan it
229 	return manager->ScanPartition(partition);
230 }
231 
232 
233 // get_default_partition_content_name
234 status_t
235 get_default_partition_content_name(partition_id partitionID,
236 	const char* fileSystemName, char* buffer, size_t bufferSize)
237 {
238 	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
239 	KPartition* partition = manager->RegisterPartition(partitionID);
240 	if (partition == NULL)
241 		return B_ENTRY_NOT_FOUND;
242 
243 	double size = partition->ContentSize();
244 	partition->Unregister();
245 
246 	const char* const suffixes[] = {
247 		"", "K", "M", "G", "T", "P", "E", NULL
248 	};
249 
250 	int index = 0;
251 	while (size >= 1024 && suffixes[index + 1]) {
252 		size /= 1024;
253 		index++;
254 	}
255 
256 	// Our kernel snprintf() ignores the precision argument, so we manually
257 	// do one digit precision.
258 	uint64 result = uint64(size * 10 + 0.5);
259 
260 	snprintf(buffer, bufferSize, "%s Volume (%ld.%ld %sB)", fileSystemName,
261 		int32(result / 10), int32(result % 10), suffixes[index]);
262 
263 	return B_OK;
264 }
265 
266 
267 // find_disk_system
268 disk_system_id
269 find_disk_system(const char* name)
270 {
271 	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
272 	if (ManagerLocker locker = manager) {
273 		if (KDiskSystem* diskSystem = manager->FindDiskSystem(name))
274 			return diskSystem->ID();
275 	}
276 	return -1;
277 }
278 
279 
280 // update_disk_device_job_progress
281 bool
282 update_disk_device_job_progress(disk_job_id jobID, float progress)
283 {
284 #if 0
285 	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
286 	if (ManagerLocker locker = manager) {
287 		if (KDiskDeviceJob* job = manager->FindJob(jobID)) {
288 			job->UpdateProgress(progress);
289 			return true;
290 		}
291 	}
292 #endif
293 	return false;
294 }
295 
296 
297 // update_disk_device_job_extra_progress
298 bool
299 update_disk_device_job_extra_progress(disk_job_id jobID, const char* info)
300 {
301 #if 0
302 	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
303 	if (ManagerLocker locker = manager) {
304 		if (KDiskDeviceJob* job = manager->FindJob(jobID)) {
305 			job->UpdateExtraProgress(info);
306 			return true;
307 		}
308 	}
309 #endif
310 	return false;
311 }
312 
313 
314 // set_disk_device_job_error_message
315 bool
316 set_disk_device_job_error_message(disk_job_id jobID, const char* message)
317 {
318 #if 0
319 	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
320 	if (ManagerLocker locker = manager) {
321 		if (KDiskDeviceJob* job = manager->FindJob(jobID)) {
322 			job->SetErrorMessage(message);
323 			return true;
324 		}
325 	}
326 #endif
327 	return false;
328 }
329 
330 
331 // update_disk_device_job_interrupt_properties
332 uint32
333 update_disk_device_job_interrupt_properties(disk_job_id jobID,
334 											uint32 interruptProperties)
335 {
336 #if 0
337 	bool paused = false;
338 	KDiskDeviceManager* manager = KDiskDeviceManager::Default();
339 	do {
340 		sem_id pauseSemaphore = -1;
341 		if (ManagerLocker locker = manager) {
342 			// get the job and the respective job queue
343 			if (KDiskDeviceJob* job = manager->FindJob(jobID)) {
344 				if (KDiskDeviceJobQueue* jobQueue = job->JobQueue()) {
345 					// terminate if canceled.
346 					if (jobQueue->IsCanceled()) {
347 						if (jobQueue->ShallReverse())
348 							return B_DISK_DEVICE_JOB_REVERSE;
349 						return B_DISK_DEVICE_JOB_CANCEL;
350 					}
351 					// set the new interrupt properties only when not
352 					// requested to pause
353 					if (jobQueue->IsPauseRequested())
354 						pauseSemaphore = jobQueue->ReadyToPause();
355 					else
356 						job->SetInterruptProperties(interruptProperties);
357 				}
358 			}
359 		}
360 		// pause, if requested; redo the loop then
361 		paused = (pauseSemaphore >= 0);
362 		if (paused) {
363 			acquire_sem(pauseSemaphore);
364 			pauseSemaphore = -1;
365 		}
366 	} while (paused);
367 #endif
368 	return B_DISK_DEVICE_JOB_CONTINUE;
369 }
370 
371