1 /* $NetBSD: rf_pqdeg.c,v 1.5 2000/01/07 03:41:04 oster 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@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