xref: /haiku/src/system/kernel/disk_device_manager/disk_device_manager.cpp (revision 4f00613311d0bd6b70fa82ce19931c41f071ea4e)
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 "KDiskDeviceJob.h"
9 #include "KDiskDeviceJobQueue.h"
10 #include "KDiskDeviceManager.h"
11 #include "KDiskDeviceUtils.h"
12 #include "KDiskSystem.h"
13 #include "KPartition.h"
14 
15 // debugging
16 //#define DBG(x)
17 #define DBG(x) x
18 #define OUT dprintf
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 // write_unlock_disk_device
36 void
37 write_unlock_disk_device(partition_id partitionID)
38 {
39 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
40 	if (KDiskDevice *device = manager->RegisterDevice(partitionID)) {
41 		bool isLocked = device->IsWriteLocked();
42 		if (isLocked) {
43 			device->WriteUnlock();
44 			device->Unregister();
45 		}
46 		device->Unregister();
47 	}
48 }
49 
50 // read_lock_disk_device
51 disk_device_data *
52 read_lock_disk_device(partition_id partitionID)
53 {
54 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
55 	if (KDiskDevice *device = manager->RegisterDevice(partitionID)) {
56 		if (device->ReadLock())
57 			return device->DeviceData();
58 		// Only unregister, when the locking fails. The guarantees, that the
59 		// lock owner also has a reference.
60 		device->Unregister();
61 	}
62 	return NULL;
63 }
64 
65 // read_unlock_disk_device
66 void
67 read_unlock_disk_device(partition_id partitionID)
68 {
69 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
70 	if (KDiskDevice *device = manager->RegisterDevice(partitionID)) {
71 		bool isLocked = device->IsReadLocked(false);
72 		if (isLocked) {
73 			device->ReadUnlock();
74 			device->Unregister();
75 		}
76 		device->Unregister();
77 	}
78 }
79 
80 // find_disk_device
81 int32
82 find_disk_device(const char *path)
83 {
84 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
85 	partition_id id = -1;
86 	if (KDiskDevice *device = manager->RegisterDevice(path)) {
87 		id = device->ID();
88 		device->Unregister();
89 	}
90 	return id;
91 }
92 
93 // find_partition
94 int32
95 find_partition(const char *path)
96 {
97 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
98 	partition_id id = -1;
99 	if (KPartition *partition = manager->RegisterPartition(path)) {
100 		id = partition->ID();
101 		partition->Unregister();
102 	}
103 	return id;
104 }
105 
106 // get_disk_device
107 disk_device_data *
108 get_disk_device(partition_id partitionID)
109 {
110 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
111 	KDiskDevice *device = manager->FindDevice(partitionID, false);
112 	return (device ? device->DeviceData() : NULL);
113 }
114 
115 // get_partition
116 partition_data *
117 get_partition(partition_id partitionID)
118 {
119 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
120 	KPartition *partition = manager->FindPartition(partitionID);
121 	return (partition ? partition->PartitionData() : NULL);
122 }
123 
124 // get_parent_partition
125 partition_data *
126 get_parent_partition(partition_id partitionID)
127 {
128 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
129 	KPartition *partition = manager->FindPartition(partitionID);
130 	if (partition && partition->Parent())
131 		return partition->Parent()->PartitionData();
132 	return NULL;
133 }
134 
135 // get_child_partition
136 partition_data *
137 get_child_partition(partition_id partitionID, int32 index)
138 {
139 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
140 	if (KPartition *partition = manager->FindPartition(partitionID)) {
141 		if (KPartition *child = partition->ChildAt(index))
142 			return child->PartitionData();
143 	}
144 	return NULL;
145 }
146 
147 // create_child_partition
148 partition_data *
149 create_child_partition(partition_id partitionID, int32 index,
150 					   partition_id childID)
151 {
152 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
153 	if (KPartition *partition = manager->FindPartition(partitionID)) {
154 		KPartition *child = NULL;
155 		if (partition->CreateChild(childID, index, &child) == B_OK)
156 			return child->PartitionData();
157 else
158 DBG(OUT("  creating child (%ld, %ld) failed\n", partitionID, index));
159 	}
160 else
161 DBG(OUT("  partition %ld not found\n", partitionID));
162 	return NULL;
163 }
164 
165 // delete_partition
166 bool
167 delete_partition(partition_id partitionID)
168 {
169 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
170 	if (KPartition *partition = manager->FindPartition(partitionID)) {
171 		if (KPartition *parent = partition->Parent())
172 			return parent->RemoveChild(partition);
173 	}
174 	return false;
175 }
176 
177 // partition_modified
178 void
179 partition_modified(partition_id partitionID)
180 {
181 	// not implemented
182 }
183 
184 // find_disk_system
185 disk_system_id
186 find_disk_system(const char *name)
187 {
188 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
189 	if (ManagerLocker locker = manager) {
190 		if (KDiskSystem *diskSystem = manager->FindDiskSystem(name))
191 			return diskSystem->ID();
192 	}
193 	return -1;
194 }
195 
196 // update_disk_device_job_progress
197 bool
198 update_disk_device_job_progress(disk_job_id jobID, float progress)
199 {
200 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
201 	if (ManagerLocker locker = manager) {
202 		if (KDiskDeviceJob *job = manager->FindJob(jobID)) {
203 			job->UpdateProgress(progress);
204 			return true;
205 		}
206 	}
207 	return false;
208 }
209 
210 // update_disk_device_job_extra_progress
211 bool
212 update_disk_device_job_extra_progress(disk_job_id jobID, const char *info)
213 {
214 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
215 	if (ManagerLocker locker = manager) {
216 		if (KDiskDeviceJob *job = manager->FindJob(jobID)) {
217 			job->UpdateExtraProgress(info);
218 			return true;
219 		}
220 	}
221 	return false;
222 }
223 
224 // set_disk_device_job_error_message
225 bool
226 set_disk_device_job_error_message(disk_job_id jobID, const char *message)
227 {
228 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
229 	if (ManagerLocker locker = manager) {
230 		if (KDiskDeviceJob *job = manager->FindJob(jobID)) {
231 			job->SetErrorMessage(message);
232 			return true;
233 		}
234 	}
235 	return false;
236 }
237 
238 // update_disk_device_job_interrupt_properties
239 uint32
240 update_disk_device_job_interrupt_properties(disk_job_id jobID,
241 											uint32 interruptProperties)
242 {
243 	bool paused = false;
244 	KDiskDeviceManager *manager = KDiskDeviceManager::Default();
245 	do {
246 		sem_id pauseSemaphore = -1;
247 		if (ManagerLocker locker = manager) {
248 			// get the job and the respective job queue
249 			if (KDiskDeviceJob *job = manager->FindJob(jobID)) {
250 				if (KDiskDeviceJobQueue *jobQueue = job->JobQueue()) {
251 					// terminate if canceled.
252 					if (jobQueue->IsCanceled()) {
253 						if (jobQueue->ShallReverse())
254 							return B_DISK_DEVICE_JOB_REVERSE;
255 						return B_DISK_DEVICE_JOB_CANCEL;
256 					}
257 					// set the new interrupt properties only when not
258 					// requested to pause
259 					if (jobQueue->IsPauseRequested())
260 						pauseSemaphore = jobQueue->ReadyToPause();
261 					else
262 						job->SetInterruptProperties(interruptProperties);
263 				}
264 			}
265 		}
266 		// pause, if requested; redo the loop then
267 		paused = (pauseSemaphore >= 0);
268 		if (paused) {
269 			acquire_sem(pauseSemaphore);
270 			pauseSemaphore = -1;
271 		}
272 	} while (paused);
273 	return B_DISK_DEVICE_JOB_CONTINUE;
274 }
275 
276