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