Annotation of XNU/iokit/Families/IOStorage/IOPartitionScheme.cpp, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.