Annotation of XNU/iokit/Families/IOStorage/IOPartitionScheme.cpp, revision 1.1.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.