|
|
1.1 ! root 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: bool IOPartitionScheme::init(OSDictionary * properties = 0) ! 31: { ! 32: // ! 33: // Initialize this object's minimal state. ! 34: // ! 35: ! 36: if (super::init(properties) == false) return false; ! 37: ! 38: _openLevel = kAccessNone; ! 39: _openReaders = OSSet::withCapacity(16); ! 40: _openReaderWriters = OSSet::withCapacity(16); ! 41: ! 42: if (_openReaders == 0 || _openReaderWriters == 0) return false; ! 43: ! 44: return true; ! 45: } ! 46: ! 47: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! 48: ! 49: void IOPartitionScheme::free() ! 50: { ! 51: // ! 52: // Free all of this object's outstanding resources. ! 53: // ! 54: ! 55: if (_openReaders) _openReaders->release(); ! 56: if (_openReaderWriters) _openReaderWriters->release(); ! 57: ! 58: super::free(); ! 59: } ! 60: ! 61: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! 62: ! 63: bool IOPartitionScheme::handleOpen(IOService * client, ! 64: IOOptionBits options, ! 65: void * argument) ! 66: { ! 67: // ! 68: // The handleOpen method grants or denies permission to access this object ! 69: // to an interested client. The argument is an IOStorageAccess value that ! 70: // specifies the level of access desired -- reader or reader-writer. ! 71: // ! 72: // This method can be invoked to upgrade or downgrade the access level for ! 73: // an existing client as well. The previous access level will prevail for ! 74: // upgrades that fail, of course. A downgrade should never fail. If the ! 75: // new access level should be the same as the old for a given client, this ! 76: // method will do nothing and return success. In all cases, one, singular ! 77: // close-per-client is expected for all opens-per-client received. ! 78: // ! 79: // This implementation replaces the IOService definition of handleOpen(). ! 80: // ! 81: // We are guaranteed that no other opens or closes will be processed until ! 82: // we make our decision, change our state, and return from this method. ! 83: // ! 84: ! 85: IOStorageAccess access = (IOStorageAccess) (int) argument; ! 86: IOStorageAccess level; ! 87: ! 88: assert(client); ! 89: assert(access == kAccessReader || access == kAccessReaderWriter); ! 90: ! 91: // ! 92: // A partition scheme multiplexes the opens it receives from several clients ! 93: // and sends one open to the level below that satisfies the highest level of ! 94: // access. ! 95: // ! 96: ! 97: unsigned writers = _openReaderWriters->getCount(); ! 98: ! 99: if (_openReaderWriters->containsObject(client)) writers--; ! 100: if (access == kAccessReaderWriter) writers++; ! 101: ! 102: level = (writers) ? kAccessReaderWriter : kAccessReader; ! 103: ! 104: // ! 105: // Determine whether the levels below us accept this open or not (we avoid ! 106: // the open if the required access is the access we already hold). ! 107: // ! 108: ! 109: if (_openLevel != level) // (has open level changed?) ! 110: { ! 111: IOStorage * provider = OSDynamicCast(IOStorage, getProvider()); ! 112: ! 113: if (provider && provider->open(this, options, level) == false) ! 114: return false; ! 115: } ! 116: ! 117: // ! 118: // Process the open. ! 119: // ! 120: ! 121: if (access == kAccessReader) ! 122: { ! 123: _openReaders->setObject(client); ! 124: ! 125: _openReaderWriters->removeObject(client); // (for a downgrade) ! 126: } ! 127: else // (access == kAccessReaderWriter) ! 128: { ! 129: _openReaderWriters->setObject(client); ! 130: ! 131: _openReaders->removeObject(client); // (for an upgrade) ! 132: } ! 133: ! 134: _openLevel = level; ! 135: ! 136: return true; ! 137: } ! 138: ! 139: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! 140: ! 141: bool IOPartitionScheme::handleIsOpen(const IOService * client) const ! 142: { ! 143: // ! 144: // The handleIsOpen method determines whether the specified client, or any ! 145: // client if none is specificed, presently has an open on this object. ! 146: // ! 147: // This implementation replaces the IOService definition of handleIsOpen(). ! 148: // ! 149: // We are guaranteed that no other opens or closes will be processed until ! 150: // we return from this method. ! 151: // ! 152: ! 153: if (client == 0) return (_openLevel != kAccessNone); ! 154: ! 155: return ( _openReaderWriters->containsObject(client) || ! 156: _openReaders->containsObject(client) ); ! 157: } ! 158: ! 159: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! 160: ! 161: void IOPartitionScheme::handleClose(IOService * client, IOOptionBits options) ! 162: { ! 163: // ! 164: // The handleClose method closes the client's access to this object. ! 165: // ! 166: // This implementation replaces the IOService definition of handleClose(). ! 167: // ! 168: // We are guaranteed that no other opens or closes will be processed until ! 169: // we change our state and return from this method. ! 170: // ! 171: ! 172: assert(client); ! 173: ! 174: // ! 175: // Process the close. ! 176: // ! 177: ! 178: if (_openReaderWriters->containsObject(client)) // (is it a reader-writer?) ! 179: { ! 180: _openReaderWriters->removeObject(client); ! 181: } ! 182: else if (_openReaders->containsObject(client)) // (is the client a reader?) ! 183: { ! 184: _openReaders->removeObject(client); ! 185: } ! 186: else // (is the client is an imposter?) ! 187: { ! 188: assert(0); ! 189: return; ! 190: } ! 191: ! 192: // ! 193: // Reevaluate the open we have on the level below us. If no opens remain, ! 194: // we close, or if no reader-writer remains, but readers do, we downgrade. ! 195: // ! 196: ! 197: IOStorageAccess level; ! 198: ! 199: if (_openReaderWriters->getCount()) level = kAccessReaderWriter; ! 200: else if (_openReaders->getCount()) level = kAccessReader; ! 201: else level = kAccessNone; ! 202: ! 203: if (_openLevel != level) // (has open level changed?) ! 204: { ! 205: IOStorage * provider = OSDynamicCast(IOStorage, getProvider()); ! 206: ! 207: assert(level != kAccessReaderWriter); ! 208: ! 209: if (provider) ! 210: { ! 211: if (level == kAccessNone) // (is a close in order?) ! 212: { ! 213: provider->close(this, options); ! 214: } ! 215: else // (is a downgrade in order?) ! 216: { ! 217: bool success; ! 218: success = provider->open(this, 0, level); ! 219: assert(success); // (should never fail, unless avoided deadlock) ! 220: } ! 221: } ! 222: ! 223: _openLevel = level; // (set new open level) ! 224: } ! 225: } ! 226: ! 227: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! 228: ! 229: void IOPartitionScheme::read(IOService * /* client */, ! 230: UInt64 byteStart, ! 231: IOMemoryDescriptor * buffer, ! 232: IOStorageCompletion completion) ! 233: { ! 234: // ! 235: // Read data from the storage object at the specified byte offset into the ! 236: // specified buffer, asynchronously. When the read completes, the caller ! 237: // will be notified via the specified completion action. ! 238: // ! 239: // The buffer will be retained for the duration of the read. ! 240: // ! 241: // For simple partition schemes, the default behavior is to simply pass the ! 242: // read through to the provider media. More complex partition schemes such ! 243: // as RAID will need to do extra processing here. ! 244: // ! 245: ! 246: getProvider()->read(this, byteStart, buffer, completion); ! 247: } ! 248: ! 249: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! 250: ! 251: void IOPartitionScheme::write(IOService * /* client */, ! 252: UInt64 byteStart, ! 253: IOMemoryDescriptor * buffer, ! 254: IOStorageCompletion completion) ! 255: { ! 256: // ! 257: // Write data into the storage object at the specified byte offset from the ! 258: // specified buffer, asynchronously. When the write completes, the caller ! 259: // will be notified via the specified completion action. ! 260: // ! 261: // The buffer will be retained for the duration of the write. ! 262: // ! 263: // For simple partition schemes, the default behavior is to simply pass the ! 264: // write through to the provider media. More complex partition schemes such ! 265: // as RAID will need to do extra processing here. ! 266: // ! 267: ! 268: getProvider()->write(this, byteStart, buffer, completion); ! 269: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.