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