]> git.saurik.com Git - apple/xnu.git/blob - iokit/Families/IOStorage/IOPartitionScheme.cpp
xnu-123.5.tar.gz
[apple/xnu.git] / iokit / Families / IOStorage / IOPartitionScheme.cpp
1 /*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23 #include <IOKit/storage/IOPartitionScheme.h>
24
25 #define super IOStorage
26 OSDefineMetaClassAndStructors(IOPartitionScheme, IOStorage)
27
28 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
29
30 IOMedia * IOPartitionScheme::getProvider() const
31 {
32 //
33 // Obtain this object's provider. We override the superclass's method
34 // to return a more specific subclass of OSObject -- an IOMedia. This
35 // method serves simply as a convenience to subclass developers.
36 //
37
38 return (IOMedia *) IOService::getProvider();
39 }
40
41 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
42
43 bool IOPartitionScheme::init(OSDictionary * properties = 0)
44 {
45 //
46 // Initialize this object's minimal state.
47 //
48
49 if (super::init(properties) == false) return false;
50
51 _openLevel = kIOStorageAccessNone;
52 _openReaders = OSSet::withCapacity(16);
53 _openReaderWriters = OSSet::withCapacity(16);
54
55 if (_openReaders == 0 || _openReaderWriters == 0) return false;
56
57 return true;
58 }
59
60 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
61
62 void IOPartitionScheme::free()
63 {
64 //
65 // Free all of this object's outstanding resources.
66 //
67
68 if (_openReaders) _openReaders->release();
69 if (_openReaderWriters) _openReaderWriters->release();
70
71 super::free();
72 }
73
74 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
75
76 bool IOPartitionScheme::handleOpen(IOService * client,
77 IOOptionBits options,
78 void * argument)
79 {
80 //
81 // The handleOpen method grants or denies permission to access this object
82 // to an interested client. The argument is an IOStorageAccess value that
83 // specifies the level of access desired -- reader or reader-writer.
84 //
85 // This method can be invoked to upgrade or downgrade the access level for
86 // an existing client as well. The previous access level will prevail for
87 // upgrades that fail, of course. A downgrade should never fail. If the
88 // new access level should be the same as the old for a given client, this
89 // method will do nothing and return success. In all cases, one, singular
90 // close-per-client is expected for all opens-per-client received.
91 //
92 // This implementation replaces the IOService definition of handleOpen().
93 //
94 // We are guaranteed that no other opens or closes will be processed until
95 // we make our decision, change our state, and return from this method.
96 //
97
98 IOStorageAccess access = (IOStorageAccess) argument;
99 IOStorageAccess level;
100
101 assert(client);
102 assert( access == kIOStorageAccessReader ||
103 access == kIOStorageAccessReaderWriter );
104
105 //
106 // A partition scheme multiplexes the opens it receives from several clients
107 // and sends one open to the level below that satisfies the highest level of
108 // access.
109 //
110
111 unsigned writers = _openReaderWriters->getCount();
112
113 if (_openReaderWriters->containsObject(client)) writers--;
114 if (access == kIOStorageAccessReaderWriter) writers++;
115
116 level = (writers) ? kIOStorageAccessReaderWriter : kIOStorageAccessReader;
117
118 //
119 // Determine whether the levels below us accept this open or not (we avoid
120 // the open if the required access is the access we already hold).
121 //
122
123 if (_openLevel != level) // (has open level changed?)
124 {
125 IOStorage * provider = OSDynamicCast(IOStorage, getProvider());
126
127 if (provider && provider->open(this, options, level) == false)
128 return false;
129 }
130
131 //
132 // Process the open.
133 //
134
135 if (access == kIOStorageAccessReader)
136 {
137 _openReaders->setObject(client);
138
139 _openReaderWriters->removeObject(client); // (for a downgrade)
140 }
141 else // (access == kIOStorageAccessReaderWriter)
142 {
143 _openReaderWriters->setObject(client);
144
145 _openReaders->removeObject(client); // (for an upgrade)
146 }
147
148 _openLevel = level;
149
150 return true;
151 }
152
153 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
154
155 bool IOPartitionScheme::handleIsOpen(const IOService * client) const
156 {
157 //
158 // The handleIsOpen method determines whether the specified client, or any
159 // client if none is specificed, presently has an open on this object.
160 //
161 // This implementation replaces the IOService definition of handleIsOpen().
162 //
163 // We are guaranteed that no other opens or closes will be processed until
164 // we return from this method.
165 //
166
167 if (client == 0) return (_openLevel != kIOStorageAccessNone);
168
169 return ( _openReaderWriters->containsObject(client) ||
170 _openReaders->containsObject(client) );
171 }
172
173 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
174
175 void IOPartitionScheme::handleClose(IOService * client, IOOptionBits options)
176 {
177 //
178 // The handleClose method closes the client's access to this object.
179 //
180 // This implementation replaces the IOService definition of handleClose().
181 //
182 // We are guaranteed that no other opens or closes will be processed until
183 // we change our state and return from this method.
184 //
185
186 assert(client);
187
188 //
189 // Process the close.
190 //
191
192 if (_openReaderWriters->containsObject(client)) // (is it a reader-writer?)
193 {
194 _openReaderWriters->removeObject(client);
195 }
196 else if (_openReaders->containsObject(client)) // (is the client a reader?)
197 {
198 _openReaders->removeObject(client);
199 }
200 else // (is the client is an imposter?)
201 {
202 assert(0);
203 return;
204 }
205
206 //
207 // Reevaluate the open we have on the level below us. If no opens remain,
208 // we close, or if no reader-writer remains, but readers do, we downgrade.
209 //
210
211 IOStorageAccess level;
212
213 if (_openReaderWriters->getCount()) level = kIOStorageAccessReaderWriter;
214 else if (_openReaders->getCount()) level = kIOStorageAccessReader;
215 else level = kIOStorageAccessNone;
216
217 if (_openLevel != level) // (has open level changed?)
218 {
219 IOStorage * provider = OSDynamicCast(IOStorage, getProvider());
220
221 assert(level != kIOStorageAccessReaderWriter);
222
223 if (provider)
224 {
225 if (level == kIOStorageAccessNone) // (is a close in order?)
226 {
227 provider->close(this, options);
228 }
229 else // (is a downgrade in order?)
230 {
231 bool success;
232 success = provider->open(this, 0, level);
233 assert(success); // (should never fail, unless avoided deadlock)
234 }
235 }
236
237 _openLevel = level; // (set new open level)
238 }
239 }
240
241 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
242
243 void IOPartitionScheme::read(IOService * /* client */,
244 UInt64 byteStart,
245 IOMemoryDescriptor * buffer,
246 IOStorageCompletion completion)
247 {
248 //
249 // Read data from the storage object at the specified byte offset into the
250 // specified buffer, asynchronously. When the read completes, the caller
251 // will be notified via the specified completion action.
252 //
253 // The buffer will be retained for the duration of the read.
254 //
255 // For simple partition schemes, the default behavior is to simply pass the
256 // read through to the provider media. More complex partition schemes such
257 // as RAID will need to do extra processing here.
258 //
259
260 getProvider()->read(this, byteStart, buffer, completion);
261 }
262
263 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
264
265 void IOPartitionScheme::write(IOService * /* client */,
266 UInt64 byteStart,
267 IOMemoryDescriptor * buffer,
268 IOStorageCompletion completion)
269 {
270 //
271 // Write data into the storage object at the specified byte offset from the
272 // specified buffer, asynchronously. When the write completes, the caller
273 // will be notified via the specified completion action.
274 //
275 // The buffer will be retained for the duration of the write.
276 //
277 // For simple partition schemes, the default behavior is to simply pass the
278 // write through to the provider media. More complex partition schemes such
279 // as RAID will need to do extra processing here.
280 //
281
282 getProvider()->write(this, byteStart, buffer, completion);
283 }
284
285 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
286
287 IOReturn IOPartitionScheme::synchronizeCache(IOService * client)
288 {
289 return getProvider()->synchronizeCache(this);
290 }
291
292 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
293
294 OSMetaClassDefineReservedUnused(IOPartitionScheme, 0);
295
296 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
297
298 OSMetaClassDefineReservedUnused(IOPartitionScheme, 1);
299
300 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
301
302 OSMetaClassDefineReservedUnused(IOPartitionScheme, 2);
303
304 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
305
306 OSMetaClassDefineReservedUnused(IOPartitionScheme, 3);
307
308 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
309
310 OSMetaClassDefineReservedUnused(IOPartitionScheme, 4);
311
312 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
313
314 OSMetaClassDefineReservedUnused(IOPartitionScheme, 5);
315
316 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
317
318 OSMetaClassDefineReservedUnused(IOPartitionScheme, 6);
319
320 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
321
322 OSMetaClassDefineReservedUnused(IOPartitionScheme, 7);
323
324 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
325
326 OSMetaClassDefineReservedUnused(IOPartitionScheme, 8);
327
328 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
329
330 OSMetaClassDefineReservedUnused(IOPartitionScheme, 9);
331
332 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
333
334 OSMetaClassDefineReservedUnused(IOPartitionScheme, 10);
335
336 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
337
338 OSMetaClassDefineReservedUnused(IOPartitionScheme, 11);
339
340 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
341
342 OSMetaClassDefineReservedUnused(IOPartitionScheme, 12);
343
344 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
345
346 OSMetaClassDefineReservedUnused(IOPartitionScheme, 13);
347
348 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
349
350 OSMetaClassDefineReservedUnused(IOPartitionScheme, 14);
351
352 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
353
354 OSMetaClassDefineReservedUnused(IOPartitionScheme, 15);
355
356 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
357
358 OSMetaClassDefineReservedUnused(IOPartitionScheme, 16);
359
360 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
361
362 OSMetaClassDefineReservedUnused(IOPartitionScheme, 17);
363
364 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
365
366 OSMetaClassDefineReservedUnused(IOPartitionScheme, 18);
367
368 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
369
370 OSMetaClassDefineReservedUnused(IOPartitionScheme, 19);
371
372 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
373
374 OSMetaClassDefineReservedUnused(IOPartitionScheme, 20);
375
376 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
377
378 OSMetaClassDefineReservedUnused(IOPartitionScheme, 21);
379
380 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
381
382 OSMetaClassDefineReservedUnused(IOPartitionScheme, 22);
383
384 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
385
386 OSMetaClassDefineReservedUnused(IOPartitionScheme, 23);
387
388 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
389
390 OSMetaClassDefineReservedUnused(IOPartitionScheme, 24);
391
392 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
393
394 OSMetaClassDefineReservedUnused(IOPartitionScheme, 25);
395
396 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
397
398 OSMetaClassDefineReservedUnused(IOPartitionScheme, 26);
399
400 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
401
402 OSMetaClassDefineReservedUnused(IOPartitionScheme, 27);
403
404 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
405
406 OSMetaClassDefineReservedUnused(IOPartitionScheme, 28);
407
408 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
409
410 OSMetaClassDefineReservedUnused(IOPartitionScheme, 29);
411
412 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
413
414 OSMetaClassDefineReservedUnused(IOPartitionScheme, 30);
415
416 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
417
418 OSMetaClassDefineReservedUnused(IOPartitionScheme, 31);