rf_pqdeg.c revision 1.4.2.1 1 /* $NetBSD: rf_pqdeg.c,v 1.4.2.1 2000/11/20 11:42:57 bouyer Exp $ */
2 /*
3 * Copyright (c) 1995 Carnegie-Mellon University.
4 * All rights reserved.
5 *
6 * Author: Daniel Stodolsky
7 *
8 * Permission to use, copy, modify and distribute this software and
9 * its documentation is hereby granted, provided that both the copyright
10 * notice and this permission notice appear in all copies of the
11 * software, derivative works or modified versions, and any portions
12 * thereof, and that both notices appear in supporting documentation.
13 *
14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
16 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17 *
18 * Carnegie Mellon requests users of this software to return to
19 *
20 * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
24 *
25 * any improvements or extensions that they make and grant Carnegie the
26 * rights to redistribute these changes.
27 */
28
29 #include "rf_archs.h"
30
31 #if (RF_INCLUDE_DECL_PQ > 0) || (RF_INCLUDE_RAID6 > 0)
32
33 #include "rf_types.h"
34 #include "rf_raid.h"
35 #include "rf_dag.h"
36 #include "rf_dagutils.h"
37 #include "rf_dagfuncs.h"
38 #include "rf_dagffrd.h"
39 #include "rf_dagffwr.h"
40 #include "rf_dagdegrd.h"
41 #include "rf_dagdegwr.h"
42 #include "rf_etimer.h"
43 #include "rf_pqdeg.h"
44 #include "rf_general.h"
45 #include "rf_pqdegdags.h"
46 #include "rf_pq.h"
47
48 /*
49 Degraded mode dag functions for P+Q calculations.
50
51 The following nomenclature is used.
52
53 PQ_<D><P><Q>_Create{Large,Small}<Write|Read>DAG
54
55 where <D><P><Q> are single digits representing the number of failed
56 data units <D> (0,1,2), parity units <P> (0,1), and Q units <Q>, effecting
57 the I/O. The reads have only PQ_<D><P><Q>_CreateReadDAG variants, while
58 the single fault writes have both large and small write versions. (Single fault
59 PQ is equivalent to normal mode raid 5 in many aspects.
60
61 Some versions degenerate into the same case, and are grouped together below.
62 */
63
64 /* Reads, single failure
65
66 we have parity, so we can do a raid 5
67 reconstruct read.
68 */
69
70 RF_CREATE_DAG_FUNC_DECL(rf_PQ_100_CreateReadDAG)
71 {
72 rf_CreateDegradedReadDAG(raidPtr, asmap, dag_h, bp, flags, allocList, &rf_pRecoveryFuncs);
73 }
74 /* Reads double failure */
75
76 /*
77 Q is lost, but not parity
78 so we can a raid 5 reconstruct read.
79 */
80
81 RF_CREATE_DAG_FUNC_DECL(rf_PQ_101_CreateReadDAG)
82 {
83 rf_CreateDegradedReadDAG(raidPtr, asmap, dag_h, bp, flags, allocList, &rf_pRecoveryFuncs);
84 }
85 /*
86 parity is lost, so we need to
87 do a reconstruct read and recompute
88 the data with Q.
89 */
90
91 RF_CREATE_DAG_FUNC_DECL(rf_PQ_110_CreateReadDAG)
92 {
93 RF_PhysDiskAddr_t *temp;
94 /* swap P and Q pointers to fake out the DegradedReadDAG code */
95 temp = asmap->parityInfo;
96 asmap->parityInfo = asmap->qInfo;
97 asmap->qInfo = temp;
98 rf_CreateDegradedReadDAG(raidPtr, asmap, dag_h, bp, flags, allocList, &rf_qRecoveryFuncs);
99 }
100 /*
101 Two data units are dead in this stripe, so we will need read
102 both P and Q to reconstruct the data. Note that only
103 one data unit we are reading may actually be missing.
104 */
105 RF_CREATE_DAG_FUNC_DECL(rf_CreateDoubleDegradedReadDAG);
106 RF_CREATE_DAG_FUNC_DECL(rf_CreateDoubleDegradedReadDAG)
107 {
108 rf_PQ_DoubleDegRead(raidPtr, asmap, dag_h, bp, flags, allocList);
109 }
110 RF_CREATE_DAG_FUNC_DECL(rf_PQ_200_CreateReadDAG);
111 RF_CREATE_DAG_FUNC_DECL(rf_PQ_200_CreateReadDAG)
112 {
113 rf_CreateDoubleDegradedReadDAG(raidPtr, asmap, dag_h, bp, flags, allocList);
114 }
115 /* Writes, single failure */
116
117 RF_CREATE_DAG_FUNC_DECL(rf_PQ_100_CreateWriteDAG);
118 RF_CREATE_DAG_FUNC_DECL(rf_PQ_100_CreateWriteDAG)
119 {
120 if (asmap->numStripeUnitsAccessed != 1 &&
121 asmap->failedPDAs[0]->numSector !=
122 raidPtr->Layout.sectorsPerStripeUnit)
123 RF_PANIC();
124 rf_CommonCreateSimpleDegradedWriteDAG(raidPtr, asmap, dag_h, bp,
125 flags, allocList, 2,
126 (int (*) (RF_DagNode_t *)) rf_Degraded_100_PQFunc,
127 RF_FALSE);
128 }
129 /* Dead P - act like a RAID 5 small write with parity = Q */
130 RF_CREATE_DAG_FUNC_DECL(rf_PQ_010_CreateSmallWriteDAG)
131 {
132 RF_PhysDiskAddr_t *temp;
133 /* swap P and Q pointers to fake out the DegradedReadDAG code */
134 temp = asmap->parityInfo;
135 asmap->parityInfo = asmap->qInfo;
136 asmap->qInfo = temp;
137 rf_CommonCreateSmallWriteDAG(raidPtr, asmap, dag_h, bp, flags,
138 allocList, &rf_qFuncs, NULL);
139 }
140 /* Dead Q - act like a RAID 5 small write */
141 RF_CREATE_DAG_FUNC_DECL(rf_PQ_001_CreateSmallWriteDAG)
142 {
143 rf_CommonCreateSmallWriteDAG(raidPtr, asmap, dag_h, bp, flags,
144 allocList, &rf_pFuncs, NULL);
145 }
146 /* Dead P - act like a RAID 5 large write but for Q */
147 RF_CREATE_DAG_FUNC_DECL(rf_PQ_010_CreateLargeWriteDAG)
148 {
149 RF_PhysDiskAddr_t *temp;
150 /* swap P and Q pointers to fake out the code */
151 temp = asmap->parityInfo;
152 asmap->parityInfo = asmap->qInfo;
153 asmap->qInfo = temp;
154 rf_CommonCreateLargeWriteDAG(raidPtr, asmap, dag_h, bp, flags,
155 allocList, 1, rf_RegularQFunc, RF_FALSE);
156 }
157 /* Dead Q - act like a RAID 5 large write */
158 RF_CREATE_DAG_FUNC_DECL(rf_PQ_001_CreateLargeWriteDAG)
159 {
160 rf_CommonCreateLargeWriteDAG(raidPtr, asmap, dag_h, bp, flags,
161 allocList, 1, rf_RegularPFunc, RF_FALSE);
162 }
163
164
165 /*
166 * writes, double failure
167 */
168
169 /*
170 * Lost P & Q - do a nonredundant write
171 */
172 RF_CREATE_DAG_FUNC_DECL(rf_PQ_011_CreateWriteDAG)
173 {
174 rf_CreateNonRedundantWriteDAG(raidPtr, asmap, dag_h, bp, flags, allocList,
175 RF_IO_TYPE_WRITE);
176 }
177 /*
178 In the two cases below,
179 A nasty case arises when the write a (strict) portion of a failed stripe unit
180 and parts of another su. For now, we do not support this.
181 */
182
183 /*
184 Lost Data and P - do a Q write.
185 */
186 RF_CREATE_DAG_FUNC_DECL(rf_PQ_110_CreateWriteDAG)
187 {
188 RF_PhysDiskAddr_t *temp;
189
190 if (asmap->numStripeUnitsAccessed != 1 &&
191 asmap->failedPDAs[0]->numSector != raidPtr->Layout.sectorsPerStripeUnit) {
192 RF_PANIC();
193 }
194 /* swap P and Q to fake out parity code */
195 temp = asmap->parityInfo;
196 asmap->parityInfo = asmap->qInfo;
197 asmap->qInfo = temp;
198 rf_CommonCreateSimpleDegradedWriteDAG(raidPtr, asmap, dag_h, bp, flags,
199 allocList, 1,
200 (int (*) (RF_DagNode_t *)) rf_PQ_DegradedWriteQFunc,
201 RF_FALSE);
202 /* is the regular Q func the right one to call? */
203 }
204 /*
205 Lost Data and Q - do degraded mode P write
206 */
207 RF_CREATE_DAG_FUNC_DECL(rf_PQ_101_CreateWriteDAG)
208 {
209 if (asmap->numStripeUnitsAccessed != 1 &&
210 asmap->failedPDAs[0]->numSector != raidPtr->Layout.sectorsPerStripeUnit)
211 RF_PANIC();
212 rf_CommonCreateSimpleDegradedWriteDAG(raidPtr, asmap, dag_h, bp, flags,
213 allocList, 1, rf_RecoveryXorFunc, RF_FALSE);
214 }
215 #endif /* (RF_INCLUDE_DECL_PQ > 0) ||
216 * (RF_INCLUDE_RAID6 > 0) */
217