xref: /haiku/src/system/kernel/disk_device_manager/disk_device_manager.cpp (revision 25a7b01d15612846f332751841da3579db313082)
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*
write_lock_disk_device(partition_id partitionID)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
write_unlock_disk_device(partition_id partitionID)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*
read_lock_disk_device(partition_id partitionID)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
read_unlock_disk_device(partition_id partitionID)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
find_disk_device(const char * path)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
find_partition(const char * path)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*
get_disk_device(partition_id partitionID)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*
get_partition(partition_id partitionID)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*
get_parent_partition(partition_id partitionID)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*
get_child_partition(partition_id partitionID,int32 index)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
open_partition(partition_id partitionID,int openMode)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*
create_child_partition(partition_id partitionID,int32 index,off_t offset,off_t size,partition_id childID)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
delete_partition(partition_id partitionID)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
partition_modified(partition_id partitionID)200 partition_modified(partition_id partitionID)
201 {
202 	// TODO: implemented
203 }
204 
205 
206 status_t
scan_partition(partition_id partitionID)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
get_default_partition_content_name(partition_id partitionID,const char * fileSystemName,char * buffer,size_t bufferSize)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
find_disk_system(const char * name)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
update_disk_device_job_progress(disk_job_id jobID,float progress)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
update_disk_device_job_extra_progress(disk_job_id jobID,const char * info)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
set_disk_device_job_error_message(disk_job_id jobID,const char * message)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
update_disk_device_job_interrupt_properties(disk_job_id jobID,uint32 interruptProperties)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