/* * Copyright (c) 2001-2005 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ #include "AppleRAID.h" const OSSymbol * gAppleRAIDConcatName; #define super AppleRAIDSet OSDefineMetaClassAndStructors(AppleRAIDConcatSet, AppleRAIDSet); AppleRAIDSet * AppleRAIDConcatSet::createRAIDSet(AppleRAIDMember * firstMember) { AppleRAIDConcatSet *raidSet = new AppleRAIDConcatSet; IOLog1("AppleRAIDConcatSet::createRAIDSet(%p) called, new set = %p *********\n", firstMember, raidSet); if (!gAppleRAIDConcatName) gAppleRAIDConcatName = OSSymbol::withCString(kAppleRAIDLevelNameConcat); // XXX free while (raidSet){ if (!raidSet->init()) break; if (!raidSet->initWithHeader(firstMember->getHeader(), true)) break; if (raidSet->resizeSet(raidSet->getMemberCount())) return raidSet; break; } if (raidSet) raidSet->release(); return 0; } bool AppleRAIDConcatSet::init() { IOLog1("AppleRAIDConcatSet::init() called\n"); if (super::init() == false) return false; arMemberBlockCounts = 0; arExpectingLiveAdd = 0; setProperty(kAppleRAIDLevelNameKey, kAppleRAIDLevelNameConcat); return true; } void AppleRAIDConcatSet::free(void) { if (arMemberBlockCounts) IODelete(arMemberBlockCounts, UInt64, arMemberCount); super::free(); } //8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888 //8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888 //8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888 bool AppleRAIDConcatSet::addSpare(AppleRAIDMember * member) { if (super::addSpare(member) == false) return false; member->changeMemberState(kAppleRAIDMemberStateBroken); return true; } bool AppleRAIDConcatSet::addMember(AppleRAIDMember * member) { if (super::addMember(member) == false) return false; OSNumber * number = OSDynamicCast(OSNumber, member->getHeaderProperty(kAppleRAIDChunkCountKey)); if (!number) return false; UInt64 memberBlockCount = number->unsigned64BitValue(); UInt32 memberIndex = member->getMemberIndex(); arMemberBlockCounts[memberIndex] = memberBlockCount; // total up the block count as we go arSetBlockCount += memberBlockCount; arSetMediaSize = arSetBlockCount * arSetBlockSize; return true; } bool AppleRAIDConcatSet::removeMember(AppleRAIDMember * member, IOOptionBits options) { UInt32 memberIndex = member->getMemberIndex(); UInt64 memberBlockCount = arMemberBlockCounts[memberIndex]; IOLog1("AppleRAIDConcatSet::removeMember(%p) called for index %d block count %lld\n", member, (int)memberIndex, memberBlockCount); // remove this member's blocks from the total block count arSetBlockCount -= memberBlockCount; arSetMediaSize = arSetBlockCount * arSetBlockSize; return super::removeMember(member, options); } bool AppleRAIDConcatSet::resizeSet(UInt32 newMemberCount) { UInt32 oldMemberCount = arMemberCount; UInt64 *oldBlockCounts = arMemberBlockCounts; arMemberBlockCounts = IONew(UInt64, newMemberCount); bzero(arMemberBlockCounts, sizeof(UInt64) * newMemberCount); if (oldBlockCounts) { bcopy(oldBlockCounts, arMemberBlockCounts, sizeof(UInt64) * oldMemberCount); IODelete(oldBlockCounts, sizeof(UInt64), oldMemberCount); } if (super::resizeSet(newMemberCount) == false) return false; if (oldMemberCount && arMemberCount > oldMemberCount) arExpectingLiveAdd += arMemberCount - oldMemberCount; return true; } bool AppleRAIDConcatSet::startSet(void) { if (super::startSet() == false) return false; // the set remains paused when a new member is added if (arExpectingLiveAdd) { arExpectingLiveAdd--; if (arExpectingLiveAdd == 0) unpauseSet(); } return true; } bool AppleRAIDConcatSet::publishSet(void) { if (arExpectingLiveAdd) { IOLog1("AppleRAIDConcat::publishSet() publish ignored.\n"); return false; } return super::publishSet(); } void AppleRAIDConcatSet::unpauseSet() { if (arExpectingLiveAdd) { IOLog1("AppleRAIDConcat::unpauseSet() unpause ignored.\n"); return; } super::unpauseSet(); } UInt64 AppleRAIDConcatSet::getMemberSize(UInt32 memberIndex) const { assert(arMemberBlockCounts); assert(memberIndex < arMemberCount); return arMemberBlockCounts[memberIndex] * arSetBlockSize;; } AppleRAIDMemoryDescriptor * AppleRAIDConcatSet::allocateMemoryDescriptor(AppleRAIDStorageRequest *storageRequest, UInt32 memberIndex) { return AppleRAIDConcatMemoryDescriptor::withStorageRequest(storageRequest, memberIndex); } // AppleRAIDConcatMemoryDescriptor // AppleRAIDConcatMemoryDescriptor // AppleRAIDConcatMemoryDescriptor #undef super #define super AppleRAIDMemoryDescriptor OSDefineMetaClassAndStructors(AppleRAIDConcatMemoryDescriptor, AppleRAIDMemoryDescriptor); AppleRAIDMemoryDescriptor * AppleRAIDConcatMemoryDescriptor::withStorageRequest(AppleRAIDStorageRequest *storageRequest, UInt32 memberIndex) { AppleRAIDMemoryDescriptor *memoryDescriptor = new AppleRAIDConcatMemoryDescriptor; if (memoryDescriptor != 0) { if (!memoryDescriptor->initWithStorageRequest(storageRequest, memberIndex)) { memoryDescriptor->release(); memoryDescriptor = 0; } } return memoryDescriptor; } bool AppleRAIDConcatMemoryDescriptor::initWithStorageRequest(AppleRAIDStorageRequest *storageRequest, UInt32 memberIndex) { if (!super::initWithStorageRequest(storageRequest, memberIndex)) return false; AppleRAIDConcatSet * set = (AppleRAIDConcatSet *)mdStorageRequest->srRAIDSet; mdMemberStart = 0; mdMemberEnd = set->getMemberSize(0) - 1; for (UInt32 index = 1; index <= memberIndex; index++) { mdMemberStart += set->getMemberSize(index - 1); mdMemberEnd += set->getMemberSize(index); } return true; } bool AppleRAIDConcatMemoryDescriptor::configureForMemoryDescriptor(IOMemoryDescriptor *memoryDescriptor, UInt64 byteStart, UInt32 activeIndex) { UInt32 byteCount = memoryDescriptor->getLength(); UInt64 byteEnd = byteStart + byteCount - 1; IOLogRW("concat start=%llu end=%llu bytestart=%llu byteCount=%lu\n", mdMemberStart, mdMemberEnd, byteStart, byteCount); assert(mdMemberIndex == activeIndex); if ((byteEnd < mdMemberStart) || (byteStart > mdMemberEnd)) return false; if (byteStart < mdMemberStart) { mdMemberByteStart = 0; mdMemberOffset = mdMemberStart - byteStart; byteCount -= mdMemberOffset; } else { mdMemberByteStart = byteStart - mdMemberStart; mdMemberOffset = 0; } if (byteEnd > mdMemberEnd) { byteCount -= byteEnd - mdMemberEnd; } _length = byteCount; mdMemoryDescriptor = memoryDescriptor; _direction = memoryDescriptor->getDirection(); IOLogRW("concat mdbytestart=%llu _length=0x%lx\n", byteStart, _length); return true; } IOPhysicalAddress AppleRAIDConcatMemoryDescriptor::getPhysicalSegment(IOByteCount offset, IOByteCount *length) { IOByteCount raidOffset = offset + mdMemberOffset; IOPhysicalAddress physAddress; physAddress = mdMemoryDescriptor->getPhysicalSegment(raidOffset, length); return physAddress; }