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 AppleRAIDStorageRequest
26OSDefineMetaClassAndStructors(AppleLVMStorageRequest, AppleRAIDStorageRequest);
27
28
29AppleLVMStorageRequest * AppleLVMStorageRequest::withAppleRAIDSet(AppleRAIDSet *set)
30{
31    AppleLVMStorageRequest *storageRequest = new AppleLVMStorageRequest;
32
33    if (storageRequest != 0) {
34        if (!storageRequest->initWithAppleRAIDSet(set)) {
35            storageRequest->release();
36            storageRequest = 0;
37        }
38    }
39
40    return storageRequest;
41}
42
43
44void AppleLVMStorageRequest::read(IOService *client, UInt64 byteStart, IOMemoryDescriptor *buffer,
45				  IOStorageAttributes *attributes, IOStorageCompletion *completion)
46{
47    AppleRAIDMember		*member;
48    IOStorageCompletion		storageCompletion;
49    AppleRAIDMemoryDescriptor	*memoryDescriptor;
50
51    srClient			= client;
52    srClientsCompletion 	= *completion;
53    srCompletedCount		= 0;
54    srMemoryDescriptor 		= buffer;
55    srMemoryDescriptorDirection	= buffer->getDirection();
56    srByteCount 		= buffer->getLength();
57    srByteStart			= byteStart;
58
59    storageCompletion.target    = srEventSource;
60    storageCompletion.action    = srEventSource->getStorageCompletionActionLVG();
61
62    // only handle lv
63    AppleLVMVolume * lv = OSDynamicCast(AppleLVMVolume, client);
64    if (!lv) {
65	IOLog("AppleLVMStorageRequest::read() received a non-lvm request?\n");
66        IOStorage::complete(completion, kIOReturnInternalError, 0);
67	return;
68    }
69
70    // XXXSNAP
71    if (lv->getTypeID() == kLVMTypeSnapRO) {
72	lv = lv->parentVolume();    // XXX hack
73	assert(lv);
74    }
75
76    /*
77	each storage request has a fixed number of descriptors, if we need more than
78	that just recycle the current storage request (this)
79    */
80
81    UInt64 requestSize = srByteCount;
82    UInt64 requestStart = srByteStart;
83    UInt32 requestCountMax = srRAIDSet->getMaxRequestCount();
84    srRequestCount = 0;
85
86    IOLogRW(" lvm read (%u)  requestStart %llu requestSize %llu\n", (uint32_t)srRequestCount, requestStart, requestSize);
87
88    while (requestSize && srRequestCount < requestCountMax) {
89
90	memoryDescriptor = srMemoryDescriptors[srRequestCount];
91	assert(memoryDescriptor);
92
93	if (!memoryDescriptor->configureForMemoryDescriptor(buffer, requestStart, requestSize, lv)) {
94
95	    IOLog(" lvm read configure failed\n");
96
97	    // XXX set length to zero?
98
99	    break;
100	}
101
102	requestStart += memoryDescriptor->getLength();
103	requestSize -= memoryDescriptor->getLength();
104	srRequestCount++;
105
106	IOLogRW(" lvm read (%u)  requestStart %llu requestSize %llu\n", (uint32_t)srRequestCount, requestStart, requestSize);
107    }
108
109    if (requestSize) {
110
111	if (srRequestCount < requestCountMax) {
112
113	    // XXX something went very wrong
114
115	    IOLog(" lvm read failed #1, srByteStart %llu srByteCount %llu srRequestCount %u requestStart %llu requestSize %llu\n",
116		  srByteStart, srByteCount, (uint32_t)srRequestCount, requestStart, requestSize);
117
118	    IOStorage::complete(completion, kIOReturnInternalError, 0);
119	    return;
120	}
121
122	// XXX set storageCompletion to reschedule more i/o;
123	// srBytesScheduled  ??
124
125	IOLog(" lvm read failed #2, srByteStart %llu srByteCount %llu srRequestCount %u requestStart %llu requestSize %llu\n",
126	      srByteStart, srByteCount, (uint32_t)srRequestCount, requestStart, requestSize);
127
128        IOStorage::complete(completion, kIOReturnInternalError, 0);
129	return;
130    }
131
132    assert(srMemberBaseOffset == 0);
133
134    // second pass, kick off the i/o's if device exists
135
136    UInt32 i;
137    for (i=0; i < srRequestCount; i++) {
138
139	memoryDescriptor = srMemoryDescriptors[i];
140	storageCompletion.parameter = memoryDescriptor;
141
142	member = srRAIDSet->arMembers[memoryDescriptor->mdMemberIndex];
143
144	if (member) {
145	    storageCompletion.parameter = memoryDescriptor;
146	    member->read(srRAIDSet, memoryDescriptor->mdMemberByteStart, memoryDescriptor, attributes, &storageCompletion);
147	} else {
148	    srEventSource->completeRequest(memoryDescriptor, kIOReturnSuccess, 0);   // no bytes & no error in completion
149	}
150    }
151}
152
153
154// XXX the read and write code is almost the same, could merge them together?
155
156
157void AppleLVMStorageRequest::write(IOService * client, UInt64 byteStart, IOMemoryDescriptor *buffer,
158				   IOStorageAttributes *attributes, IOStorageCompletion *completion)
159{
160    AppleRAIDMember		*member;
161    IOStorageCompletion		storageCompletion;
162    AppleRAIDMemoryDescriptor	*memoryDescriptor;
163
164    srClient			= client;
165    srClientsCompletion 	= *completion;
166    srCompletedCount		= 0;
167    srMemoryDescriptor 		= buffer;
168    srMemoryDescriptorDirection	= buffer->getDirection();
169    srByteCount 		= buffer->getLength();
170    srByteStart			= byteStart;
171
172    storageCompletion.target    = srEventSource;
173    storageCompletion.action    = srEventSource->getStorageCompletionActionLVG();
174
175    // only handle lv
176    AppleLVMVolume * lv = OSDynamicCast(AppleLVMVolume, client);
177    if (!lv) {
178	IOLog("AppleLVMStorageRequest::write() received a non-lvm request?\n");
179        IOStorage::complete(completion, kIOReturnInternalError, 0);
180	return;
181    }
182
183    // XXXSNAP
184    if (lv->getTypeID() == kLVMTypeSnapRO) {
185	lv = lv->parentVolume();    // XXX hack
186	assert(lv);
187    }
188
189    /*
190	each storage request has a fixed number of descriptors, if we need more than
191	that just recycle the current storage request (this)
192    */
193
194    UInt64 requestSize = srByteCount;
195    UInt64 requestStart = srByteStart;
196    UInt32 requestCountMax = srRAIDSet->getMaxRequestCount();
197    srRequestCount = 0;
198
199    IOLogRW(" lvm write (%u) requestStart %llu requestSize %llu\n", (uint32_t)srRequestCount, requestStart, requestSize);
200
201    while (requestSize && srRequestCount < requestCountMax) {
202
203	memoryDescriptor = srMemoryDescriptors[srRequestCount];
204	assert(memoryDescriptor);
205
206	if (!memoryDescriptor->configureForMemoryDescriptor(buffer, requestStart, requestSize, lv)) {
207
208	    IOLog(" lvm write configure failed\n");
209
210	    // XXX set length to zero?
211
212	    break;
213	}
214
215	requestStart += memoryDescriptor->getLength();
216	requestSize -= memoryDescriptor->getLength();
217	srRequestCount++;
218
219	IOLogRW(" lvm write (%u) requestStart %llu requestSize %llu\n", (uint32_t)srRequestCount, requestStart, requestSize);
220    }
221
222    if (requestSize) {
223
224	if (srRequestCount < requestCountMax) {
225
226	    // XXX something went very wrong
227
228	    IOLog(" lvm write failed #1, srByteStart %llu srByteCount %llu srRequestCount %u requestStart %llu requestSize %llu\n",
229		  srByteStart, srByteCount, (uint32_t)srRequestCount, requestStart, requestSize);
230
231	    IOStorage::complete(completion, kIOReturnInternalError, 0);
232	    return;
233	}
234
235	// XXX set storageCompletion to reschedule more i/o;
236	// srBytesScheduled  ??
237
238	IOLog(" lvm write failed #2, srByteStart %llu srByteCount %llu srRequestCount %u requestStart %llu requestSize %llu\n",
239	      srByteStart, srByteCount, (uint32_t)srRequestCount, requestStart, requestSize);
240
241        IOStorage::complete(completion, kIOReturnInternalError, 0);
242	return;
243    }
244
245//	IOLog(" lvm write   extent %p offset %llu byteStart %llu\n", extent, extent->lvExtentGroupOffset, srByteStart);
246
247    assert(srMemberBaseOffset == 0);
248
249    // second pass, kick off the i/o's if device exists
250
251    UInt32 i;
252    for (i=0; i < srRequestCount; i++) {
253
254	memoryDescriptor = srMemoryDescriptors[i];
255	storageCompletion.parameter = memoryDescriptor;
256
257	member = srRAIDSet->arMembers[memoryDescriptor->mdMemberIndex];
258
259	if (member) {
260	    storageCompletion.parameter = memoryDescriptor;
261	    member->write(srRAIDSet, memoryDescriptor->mdMemberByteStart, memoryDescriptor, attributes, &storageCompletion);
262	} else {
263	    srEventSource->completeRequest(memoryDescriptor, kIOReturnSuccess, 0);   // no bytes & no error in completion
264	}
265    }
266}
267