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 IOCommand 26OSDefineMetaClassAndStructors(AppleRAIDStorageRequest, IOCommand); 27 28void AppleRAIDStorageRequest::free(void) 29{ 30 UInt32 index; 31 32 if (srRequestStatus != 0) IODelete(srRequestStatus, IOReturn, srRequestsAllocated); 33 if (srRequestByteCounts != 0) IODelete(srRequestByteCounts, UInt64, srRequestsAllocated); 34 if (srActiveMembers != 0) IODelete(srActiveMembers, AppleRAIDMember *, srMemberCount); 35 36 if (srMemoryDescriptors != 0) { 37 38 for (index = 0; index < srRequestsAllocated; index++) { 39 if (srMemoryDescriptors[index]) { 40 srMemoryDescriptors[index]->release(); 41 } 42 } 43 44 IODelete(srMemoryDescriptors, AppleRAIDMemoryDescriptor *, srRequestsAllocated); 45 46 srMemoryDescriptors = 0; 47 } 48 49 super::free(); 50} 51 52AppleRAIDStorageRequest *AppleRAIDStorageRequest::withAppleRAIDSet(AppleRAIDSet *set) 53{ 54 AppleRAIDStorageRequest *storageRequest = new AppleRAIDStorageRequest; 55 56 if (storageRequest != 0) { 57 if (!storageRequest->initWithAppleRAIDSet(set)) { 58 storageRequest->release(); 59 storageRequest = 0; 60 } 61 } 62 63 return storageRequest; 64} 65 66 67bool AppleRAIDStorageRequest::initWithAppleRAIDSet(AppleRAIDSet *set) 68{ 69 UInt32 index; 70 71 if (!super::init()) return false; 72 73 // anything that can change, must go thru this 74 srRAIDSet = set; 75 76 // these can not change 77 srEventSource = set->arSetEventSource; 78 srSetBlockSize = set->arMaxReadRequestFactor ? (set->arSetBlockSize * set->arMaxReadRequestFactor) : set->arSetBlockSize; 79 srMemberCount = set->getMemberCount(); 80 srRequestCount = set->getMaxRequestCount(); 81 srRequestsAllocated = set->getMaxRequestCount(); 82 srMemberBaseOffset = set->getBase(); 83 84 srRequestStatus = IONew(IOReturn, srRequestsAllocated); 85 if (srRequestStatus == 0) return false; 86 87 srRequestByteCounts = IONew(UInt64, srRequestsAllocated); 88 if (srRequestByteCounts == 0) return false; 89 90 srActiveMembers = IONew(AppleRAIDMember *, srMemberCount); 91 if (srActiveMembers == 0) return false; 92 93 srMemoryDescriptors = IONew(AppleRAIDMemoryDescriptor *, srRequestsAllocated); 94 if (srMemoryDescriptors == 0) return false; 95 96 for (index = 0; index < srRequestsAllocated; index++) { 97 srMemoryDescriptors[index] = set->allocateMemoryDescriptor(this, index); 98 if (!srMemoryDescriptors[index]) return false; 99 } 100 101 return true; 102} 103 104 105void AppleRAIDStorageRequest::extractRequest(IOService **client, UInt64 *byteStart, 106 IOMemoryDescriptor **buffer, IOStorageCompletion *completion) 107{ 108 // copy out what we need to restart this i/o 109 110 *client = srClient; 111 *byteStart = srByteStart; 112 *buffer = srMemoryDescriptor; 113 *completion = srClientsCompletion; 114} 115 116void AppleRAIDStorageRequest::read(IOService *client, UInt64 byteStart, IOMemoryDescriptor *buffer, 117 IOStorageAttributes * attributes, IOStorageCompletion * completion) 118{ 119 UInt32 index, virtIndex; 120 AppleRAIDMember *member; 121 bool isOnline; 122 AppleRAIDMemoryDescriptor *memoryDescriptor; 123 IOStorageCompletion internalCompletion; 124 125 srClient = client; 126 srClientsCompletion = *completion; 127 srCompletedCount = 0; 128 srMemoryDescriptor = buffer; 129 srMemoryDescriptorDirection = buffer->getDirection(); 130 srByteCount = buffer->getLength(); 131 srByteStart = byteStart; 132 133 srRequestCount = srRAIDSet->getMaxRequestCount(); 134 srActiveCount = srRAIDSet->getActiveCount(); 135 srRAIDSet->activeReadMembers(srActiveMembers, srByteStart, srByteCount); 136 137 // XXX this is hideously inefficent, it adds a context switch per i/o request 138 // XXX replace event source code with a direct runAction call? 139 internalCompletion.target = srEventSource; 140 internalCompletion.action = srEventSource->getStorageCompletionAction(); 141 142 for (virtIndex = 0; virtIndex < srMemberCount; virtIndex++) { 143 144 member = srActiveMembers[virtIndex]; 145 isOnline = (uintptr_t)(member) >= 0x1000; 146 index = isOnline ? member->getMemberIndex() : (uintptr_t)member; 147 memoryDescriptor = srMemoryDescriptors[index]; 148 149 if (isOnline && memoryDescriptor->configureForMemoryDescriptor(buffer, byteStart, virtIndex)) { 150 internalCompletion.parameter = memoryDescriptor; 151 member->read(srRAIDSet, srMemberBaseOffset + memoryDescriptor->mdMemberByteStart, 152 memoryDescriptor, attributes, &internalCompletion); 153 } else { 154 // XXX this is lame, just have completion code check active count instead of the member count 155 // XXX instead of this we could just set the byte count and status here 156 // this would speed up any io request that does not hit all disks in the set 157 // would need to handle the case of all the members being DOA? 158 // there is also a race if we switch the count on the fly 159 srEventSource->completeRequest(memoryDescriptor, kIOReturnSuccess, 0); 160 } 161 } 162} 163 164void AppleRAIDStorageRequest::write(IOService *client, UInt64 byteStart, IOMemoryDescriptor *buffer, 165 IOStorageAttributes * attributes, IOStorageCompletion * completion) 166{ 167 UInt32 index, virtIndex; 168 AppleRAIDMember *member; 169 bool isOnline; 170 AppleRAIDMemoryDescriptor *memoryDescriptor; 171 IOStorageCompletion internalCompletion; 172 173 srClient = client; 174 srClientsCompletion = *completion; 175 srCompletedCount = 0; 176 srMemoryDescriptor = buffer; 177 srMemoryDescriptorDirection = buffer->getDirection(); 178 srByteCount = buffer->getLength(); 179 srByteStart = byteStart; 180 181 srRequestCount = srRAIDSet->getMaxRequestCount(); 182 srActiveCount = srRAIDSet->getActiveCount(); 183 srRAIDSet->activeWriteMembers(srActiveMembers, srByteStart, srByteCount); 184 185 internalCompletion.target = srEventSource; 186 internalCompletion.action = srEventSource->getStorageCompletionAction(); 187 188 for (virtIndex = 0; virtIndex < srMemberCount; virtIndex++) { 189 190 member = srActiveMembers[virtIndex]; 191 isOnline = (uintptr_t)(member) >= 0x1000; 192 index = isOnline ? member->getMemberIndex() : (uintptr_t)member; 193 memoryDescriptor = srMemoryDescriptors[index]; 194 195 if (isOnline && memoryDescriptor->configureForMemoryDescriptor(buffer, byteStart, virtIndex)) { 196 internalCompletion.parameter = memoryDescriptor; 197 member->write(srRAIDSet, srMemberBaseOffset + memoryDescriptor->mdMemberByteStart, 198 memoryDescriptor, attributes, &internalCompletion); 199 } else { 200 srEventSource->completeRequest(memoryDescriptor, kIOReturnSuccess, 0); 201 } 202 } 203} 204