1/* 2 * Copyright (c) 2001-2007 Apple 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 "AppleRAID.h" 24 25#define super AppleRAIDSet 26OSDefineMetaClassAndStructors(AppleRAIDConcatSet, AppleRAIDSet); 27 28AppleRAIDSet * AppleRAIDConcatSet::createRAIDSet(AppleRAIDMember * firstMember) 29{ 30 AppleRAIDConcatSet *raidSet = new AppleRAIDConcatSet; 31 32 IOLog1("AppleRAIDConcatSet::createRAIDSet(%p) called, new set = %p *********\n", firstMember, raidSet); 33 34 while (raidSet){ 35 36 if (!raidSet->init()) break; 37 if (!raidSet->initWithHeader(firstMember->getHeader(), true)) break; 38 if (raidSet->resizeSet(raidSet->getMemberCount())) return raidSet; 39 40 break; 41 } 42 43 if (raidSet) raidSet->release(); 44 45 return 0; 46} 47 48 49bool AppleRAIDConcatSet::init() 50{ 51 IOLog1("AppleRAIDConcatSet::init() called\n"); 52 53 if (super::init() == false) return false; 54 55 arMemberBlockCounts = 0; 56 arExpectingLiveAdd = 0; 57 58 setProperty(kAppleRAIDLevelNameKey, kAppleRAIDLevelNameConcat); 59 60 arAllocateRequestMethod = OSMemberFunctionCast(IOCommandGate::Action, this, &AppleRAIDSet::allocateRAIDRequest); 61 62 return true; 63} 64 65void AppleRAIDConcatSet::free(void) 66{ 67 if (arMemberBlockCounts) IODelete(arMemberBlockCounts, UInt64, arMemberCount); 68 69 super::free(); 70} 71 72//8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888 73//8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888 74//8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888 75 76bool AppleRAIDConcatSet::addSpare(AppleRAIDMember * member) 77{ 78 if (super::addSpare(member) == false) return false; 79 80 member->changeMemberState(kAppleRAIDMemberStateBroken); 81 82 return true; 83} 84 85bool AppleRAIDConcatSet::addMember(AppleRAIDMember * member) 86{ 87 if (super::addMember(member) == false) return false; 88 89 OSNumber * number = OSDynamicCast(OSNumber, member->getHeaderProperty(kAppleRAIDChunkCountKey)); 90 if (!number) return false; 91 UInt64 memberBlockCount = number->unsigned64BitValue(); 92 93 UInt32 memberIndex = member->getMemberIndex(); 94 arMemberBlockCounts[memberIndex] = memberBlockCount; 95 96 // total up the block count as we go 97 arSetBlockCount += memberBlockCount; 98 arSetMediaSize = arSetBlockCount * arSetBlockSize; 99 100 return true; 101} 102 103bool AppleRAIDConcatSet::removeMember(AppleRAIDMember * member, IOOptionBits options) 104{ 105 UInt32 memberIndex = member->getMemberIndex(); 106 UInt64 memberBlockCount = arMemberBlockCounts[memberIndex]; 107 108 IOLog1("AppleRAIDConcatSet::removeMember(%p) called for index %d block count %lld\n", 109 member, (int)memberIndex, memberBlockCount); 110 111 // remove this member's blocks from the total block count 112 arSetBlockCount -= memberBlockCount; 113 arSetMediaSize = arSetBlockCount * arSetBlockSize; 114 arMemberBlockCounts[memberIndex] = 0; 115 116 return super::removeMember(member, options); 117} 118 119#ifndef MIN 120#define MIN(a,b) (((a)<(b))?(a):(b)) 121#endif 122 123bool AppleRAIDConcatSet::resizeSet(UInt32 newMemberCount) 124{ 125 UInt32 oldMemberCount = arMemberCount; 126 UInt64 *oldBlockCounts = arMemberBlockCounts; 127 128 arMemberBlockCounts = IONew(UInt64, newMemberCount); 129 bzero(arMemberBlockCounts, sizeof(UInt64) * newMemberCount); 130 131 if (oldBlockCounts) { 132 bcopy(oldBlockCounts, arMemberBlockCounts, sizeof(UInt64) * MIN(newMemberCount, oldMemberCount)); 133 IODelete(oldBlockCounts, sizeof(UInt64), oldMemberCount); 134 } 135 136 if (super::resizeSet(newMemberCount) == false) return false; 137 138 if (oldMemberCount && arMemberCount > oldMemberCount) arExpectingLiveAdd += arMemberCount - oldMemberCount; 139 140 return true; 141} 142 143bool AppleRAIDConcatSet::startSet(void) 144{ 145 if (super::startSet() == false) return false; 146 147 // the set remains paused when a new member is added 148 if (arExpectingLiveAdd) { 149 arExpectingLiveAdd--; 150 if (arExpectingLiveAdd == 0) unpauseSet(); 151 } 152 153 return true; 154} 155 156bool AppleRAIDConcatSet::publishSet(void) 157{ 158 if (arExpectingLiveAdd) { 159 IOLog1("AppleRAIDConcat::publishSet() publish ignored.\n"); 160 return false; 161 } 162 163 return super::publishSet(); 164} 165 166void AppleRAIDConcatSet::unpauseSet() 167{ 168 if (arExpectingLiveAdd) { 169 IOLog1("AppleRAIDConcat::unpauseSet() unpause ignored.\n"); 170 return; 171 } 172 173 super::unpauseSet(); 174} 175 176UInt64 AppleRAIDConcatSet::getMemberSize(UInt32 memberIndex) const 177{ 178 assert(arMemberBlockCounts); 179 assert(memberIndex < arMemberCount); 180 181 return arMemberBlockCounts[memberIndex] * arSetBlockSize;; 182} 183 184AppleRAIDMemoryDescriptor * AppleRAIDConcatSet::allocateMemoryDescriptor(AppleRAIDStorageRequest *storageRequest, UInt32 memberIndex) 185{ 186 return AppleRAIDConcatMemoryDescriptor::withStorageRequest(storageRequest, memberIndex); 187} 188 189 190// AppleRAIDConcatMemoryDescriptor 191// AppleRAIDConcatMemoryDescriptor 192// AppleRAIDConcatMemoryDescriptor 193 194 195#undef super 196#define super AppleRAIDMemoryDescriptor 197OSDefineMetaClassAndStructors(AppleRAIDConcatMemoryDescriptor, AppleRAIDMemoryDescriptor); 198 199AppleRAIDMemoryDescriptor * 200AppleRAIDConcatMemoryDescriptor::withStorageRequest(AppleRAIDStorageRequest *storageRequest, UInt32 memberIndex) 201{ 202 AppleRAIDMemoryDescriptor *memoryDescriptor = new AppleRAIDConcatMemoryDescriptor; 203 204 if (memoryDescriptor != 0) { 205 if (!memoryDescriptor->initWithStorageRequest(storageRequest, memberIndex)) { 206 memoryDescriptor->release(); 207 memoryDescriptor = 0; 208 } 209 } 210 211 return memoryDescriptor; 212} 213 214bool AppleRAIDConcatMemoryDescriptor::initWithStorageRequest(AppleRAIDStorageRequest *storageRequest, UInt32 memberIndex) 215{ 216 if (!super::initWithStorageRequest(storageRequest, memberIndex)) return false; 217 218 AppleRAIDConcatSet * set = (AppleRAIDConcatSet *)mdStorageRequest->srRAIDSet; 219 220 mdMemberStart = 0; 221 mdMemberEnd = set->getMemberSize(0) - 1; 222 223 for (UInt32 index = 1; index <= memberIndex; index++) { 224 225 mdMemberStart += set->getMemberSize(index - 1); 226 mdMemberEnd += set->getMemberSize(index); 227 } 228 229 return true; 230} 231 232bool AppleRAIDConcatMemoryDescriptor::configureForMemoryDescriptor(IOMemoryDescriptor *memoryDescriptor, UInt64 byteStart, UInt32 activeIndex) 233{ 234 UInt32 byteCount = memoryDescriptor->getLength(); 235 UInt64 byteEnd = byteStart + byteCount - 1; 236 237 IOLogRW("concat start=%llu end=%llu bytestart=%llu byteCount=%u\n", mdMemberStart, mdMemberEnd, byteStart, (uint32_t)byteCount); 238 239 assert(mdMemberIndex == activeIndex); 240 241 if ((byteEnd < mdMemberStart) || (byteStart > mdMemberEnd)) return false; 242 243 if (byteStart < mdMemberStart) { 244 mdMemberByteStart = 0; 245 mdMemberOffset = mdMemberStart - byteStart; 246 byteCount -= mdMemberOffset; 247 } else { 248 mdMemberByteStart = byteStart - mdMemberStart; 249 mdMemberOffset = 0; 250 } 251 252 if (byteEnd > mdMemberEnd) { 253 byteCount -= byteEnd - mdMemberEnd; 254 } 255 256 _length = byteCount; 257 258 mdMemoryDescriptor = memoryDescriptor; 259 260 _flags = (_flags & ~kIOMemoryDirectionMask) | memoryDescriptor->getDirection(); 261 262 IOLogRW("concat mdbytestart=%llu _length=0x%x\n", byteStart, (uint32_t)_length); 263 264 return true; 265} 266 267addr64_t AppleRAIDConcatMemoryDescriptor::getPhysicalSegment(IOByteCount offset, IOByteCount *length, IOOptionBits options) 268{ 269 IOByteCount setOffset = offset + mdMemberOffset; 270 addr64_t physAddress; 271 272 physAddress = mdMemoryDescriptor->getPhysicalSegment(setOffset, length, options); 273 274 return physAddress; 275} 276