AppleRAIDStripeSet.cpp [plain text]
#include "AppleRAID.h"
const OSSymbol * gAppleRAIDStripeName;
#define super AppleRAIDSet
OSDefineMetaClassAndStructors(AppleRAIDStripeSet, AppleRAIDSet);
AppleRAIDSet * AppleRAIDStripeSet::createRAIDSet(AppleRAIDMember * firstMember)
{
AppleRAIDStripeSet *raidSet = new AppleRAIDStripeSet;
IOLog1("AppleRAIDStripeSet::createRAIDSet(%p) called, new set = %p *********\n", firstMember, raidSet);
if (!gAppleRAIDStripeName) gAppleRAIDStripeName = OSSymbol::withCString(kAppleRAIDLevelNameStripe);
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 AppleRAIDStripeSet::init()
{
IOLog1("AppleRAIDStripeSet::init() called\n");
if (super::init() == false) return false;
setProperty(kAppleRAIDLevelNameKey, kAppleRAIDLevelNameStripe);
return true;
}
void AppleRAIDStripeSet::free(void)
{
super::free();
}
bool AppleRAIDStripeSet::addSpare(AppleRAIDMember * member)
{
if (super::addSpare(member) == false) return false;
member->changeMemberState(kAppleRAIDMemberStateBroken);
return true;
}
bool AppleRAIDStripeSet::addMember(AppleRAIDMember * member)
{
if (super::addMember(member) == false) return false;
OSNumber * number = OSDynamicCast(OSNumber, member->getHeaderProperty(kAppleRAIDChunkCountKey));
if (!number) return false;
arSetBlockCount = number->unsigned64BitValue() * arMemberCount;
arSetMediaSize = arSetBlockCount * arSetBlockSize;
return true;
}
bool AppleRAIDStripeSet::startSet(void)
{
if (super::startSet() == false) return false;
UInt32 pagesPerChunk;
UInt64 maxBlockCount, maxSegmentCount;
OSNumber * tmpNumber, * tmpNumber2;
pagesPerChunk = arSetBlockSize / PAGE_SIZE;
AppleRAIDMember * anyMember = NULL;
for (UInt32 memberIndex = 0; memberIndex < arMemberCount; memberIndex++) {
if (anyMember = arMembers[memberIndex]) break;
}
if (!anyMember) return false;
tmpNumber = OSDynamicCast(OSNumber, anyMember->getProperty(kIOMaximumBlockCountReadKey, gIOServicePlane));
tmpNumber2 = OSDynamicCast(OSNumber, anyMember->getProperty(kIOMaximumSegmentCountReadKey, gIOServicePlane));
if ((tmpNumber != 0) && (tmpNumber2 != 0)) {
maxBlockCount = tmpNumber->unsigned64BitValue();
maxSegmentCount = tmpNumber2->unsigned64BitValue();
maxBlockCount *= arMemberCount;
maxSegmentCount *= arMemberCount;
setProperty(kIOMaximumBlockCountReadKey, maxBlockCount, 64);
setProperty(kIOMaximumSegmentCountReadKey, maxSegmentCount, 64);
}
tmpNumber = OSDynamicCast(OSNumber, anyMember->getProperty(kIOMaximumBlockCountWriteKey, gIOServicePlane));
tmpNumber2 = OSDynamicCast(OSNumber, anyMember->getProperty(kIOMaximumSegmentCountWriteKey, gIOServicePlane));
if ((tmpNumber != 0) && (tmpNumber2 != 0)) {
maxBlockCount = tmpNumber->unsigned64BitValue();
maxSegmentCount = tmpNumber2->unsigned64BitValue();
maxBlockCount *= arMemberCount;
maxSegmentCount *= arMemberCount;
setProperty(kIOMaximumBlockCountWriteKey, maxBlockCount, 64);
setProperty(kIOMaximumSegmentCountWriteKey, maxSegmentCount, 64);
}
return true;
}
AppleRAIDMemoryDescriptor * AppleRAIDStripeSet::allocateMemoryDescriptor(AppleRAIDStorageRequest *storageRequest, UInt32 memberIndex)
{
return AppleRAIDStripeMemoryDescriptor::withStorageRequest(storageRequest, memberIndex);
}
#undef super
#define super AppleRAIDMemoryDescriptor
OSDefineMetaClassAndStructors(AppleRAIDStripeMemoryDescriptor, AppleRAIDMemoryDescriptor);
AppleRAIDMemoryDescriptor *
AppleRAIDStripeMemoryDescriptor::withStorageRequest(AppleRAIDStorageRequest *storageRequest, UInt32 memberIndex)
{
AppleRAIDMemoryDescriptor *memoryDescriptor = new AppleRAIDStripeMemoryDescriptor;
if (memoryDescriptor != 0) {
if (!memoryDescriptor->initWithStorageRequest(storageRequest, memberIndex)) {
memoryDescriptor->release();
memoryDescriptor = 0;
}
}
return memoryDescriptor;
}
bool AppleRAIDStripeMemoryDescriptor::initWithStorageRequest(AppleRAIDStorageRequest *storageRequest, UInt32 memberIndex)
{
if (!super::initWithStorageRequest(storageRequest, memberIndex)) return false;
mdMemberCount = storageRequest->srMemberCount;
mdSetBlockSize = storageRequest->srSetBlockSize;
return true;
}
bool AppleRAIDStripeMemoryDescriptor::configureForMemoryDescriptor(IOMemoryDescriptor *memoryDescriptor, UInt64 byteStart, UInt32 activeIndex)
{
UInt32 raidBlockStop, raidBlockEndOffset;
UInt32 startMember, stopMember;
UInt32 blockCount, memberBlockCount, memberBlockStart;
UInt32 byteCount = memoryDescriptor->getLength();
assert(mdMemberIndex == activeIndex);
mdSetBlockStart = byteStart / mdSetBlockSize;
mdSetBlockOffset = byteStart % mdSetBlockSize;
startMember = mdSetBlockStart % mdMemberCount;
raidBlockStop = (byteStart + byteCount - 1) / mdSetBlockSize;
raidBlockEndOffset = (byteStart + byteCount - 1) % mdSetBlockSize;
stopMember = raidBlockStop % mdMemberCount;
blockCount = raidBlockStop - mdSetBlockStart + 1;
memberBlockCount = blockCount / mdMemberCount;
memberBlockStart = mdSetBlockStart / mdMemberCount;
if (((mdMemberCount + mdMemberIndex - startMember) % mdMemberCount) < (blockCount % mdMemberCount)) memberBlockCount++;
if (startMember > mdMemberIndex) memberBlockStart++;
mdMemberByteStart = (UInt64)memberBlockStart * mdSetBlockSize;
_length = memberBlockCount * mdSetBlockSize;
if (startMember == mdMemberIndex) {
mdMemberByteStart += mdSetBlockOffset;
_length -= mdSetBlockOffset;
}
if (stopMember == mdMemberIndex) _length -= mdSetBlockSize - raidBlockEndOffset - 1;
mdMemoryDescriptor = memoryDescriptor;
_direction = memoryDescriptor->getDirection();
return _length != 0;
}
IOPhysicalAddress AppleRAIDStripeMemoryDescriptor::getPhysicalSegment(IOByteCount offset, IOByteCount *length)
{
UInt32 memberBlockNumber = (mdMemberByteStart + offset) / mdSetBlockSize;
UInt32 memberBlockOffset = (mdMemberByteStart + offset) % mdSetBlockSize;
UInt32 raidBlockNumber = memberBlockNumber * mdMemberCount + mdMemberIndex - mdSetBlockStart;
IOByteCount raidOffset = raidBlockNumber * mdSetBlockSize + memberBlockOffset - mdSetBlockOffset;
IOPhysicalAddress physAddress;
physAddress = mdMemoryDescriptor->getPhysicalSegment(raidOffset, length);
memberBlockOffset = mdSetBlockSize - memberBlockOffset;
if (*length > memberBlockOffset) *length = memberBlockOffset;
return physAddress;
}