1 /* $NetBSD: rf_raid5_rotatedspare.c,v 1.6 2001/11/13 07:11:16 lukem Exp $ */ 2 /* 3 * Copyright (c) 1995 Carnegie-Mellon University. 4 * All rights reserved. 5 * 6 * Author: Khalil Amiri 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 /************************************************************************** 30 * 31 * rf_raid5_rotated_spare.c -- implements RAID Level 5 with rotated sparing 32 * 33 **************************************************************************/ 34 35 #include <sys/cdefs.h> 36 __KERNEL_RCSID(0, "$NetBSD: rf_raid5_rotatedspare.c,v 1.6 2001/11/13 07:11:16 lukem Exp $"); 37 38 #include "rf_archs.h" 39 40 #if RF_INCLUDE_RAID5_RS > 0 41 42 #include "rf_raid.h" 43 #include "rf_raid5.h" 44 #include "rf_dag.h" 45 #include "rf_dagutils.h" 46 #include "rf_dagfuncs.h" 47 #include "rf_general.h" 48 #include "rf_utils.h" 49 #include "rf_raid5_rotatedspare.h" 50 51 typedef struct RF_Raid5RSConfigInfo_s { 52 RF_RowCol_t **stripeIdentifier; /* filled in at config time & used by 53 * IdentifyStripe */ 54 } RF_Raid5RSConfigInfo_t; 55 56 int 57 rf_ConfigureRAID5_RS( 58 RF_ShutdownList_t ** listp, 59 RF_Raid_t * raidPtr, 60 RF_Config_t * cfgPtr) 61 { 62 RF_RaidLayout_t *layoutPtr = &raidPtr->Layout; 63 RF_Raid5RSConfigInfo_t *info; 64 RF_RowCol_t i, j, startdisk; 65 66 /* create a RAID level 5 configuration structure */ 67 RF_MallocAndAdd(info, sizeof(RF_Raid5RSConfigInfo_t), (RF_Raid5RSConfigInfo_t *), raidPtr->cleanupList); 68 if (info == NULL) 69 return (ENOMEM); 70 layoutPtr->layoutSpecificInfo = (void *) info; 71 72 RF_ASSERT(raidPtr->numRow == 1); 73 RF_ASSERT(raidPtr->numCol >= 3); 74 75 /* the stripe identifier must identify the disks in each stripe, IN 76 * THE ORDER THAT THEY APPEAR IN THE STRIPE. */ 77 info->stripeIdentifier = rf_make_2d_array(raidPtr->numCol, raidPtr->numCol, raidPtr->cleanupList); 78 if (info->stripeIdentifier == NULL) 79 return (ENOMEM); 80 startdisk = 0; 81 for (i = 0; i < raidPtr->numCol; i++) { 82 for (j = 0; j < raidPtr->numCol; j++) { 83 info->stripeIdentifier[i][j] = (startdisk + j) % raidPtr->numCol; 84 } 85 if ((--startdisk) < 0) 86 startdisk = raidPtr->numCol - 1; 87 } 88 89 /* fill in the remaining layout parameters */ 90 layoutPtr->numStripe = layoutPtr->stripeUnitsPerDisk; 91 layoutPtr->bytesPerStripeUnit = layoutPtr->sectorsPerStripeUnit << raidPtr->logBytesPerSector; 92 layoutPtr->numDataCol = raidPtr->numCol - 2; 93 layoutPtr->dataSectorsPerStripe = layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit; 94 layoutPtr->numParityCol = 1; 95 layoutPtr->dataStripeUnitsPerDisk = layoutPtr->stripeUnitsPerDisk; 96 raidPtr->sectorsPerDisk = layoutPtr->stripeUnitsPerDisk * layoutPtr->sectorsPerStripeUnit; 97 98 raidPtr->totalSectors = layoutPtr->stripeUnitsPerDisk * layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit; 99 100 return (0); 101 } 102 103 RF_ReconUnitCount_t 104 rf_GetNumSpareRUsRAID5_RS(raidPtr) 105 RF_Raid_t *raidPtr; 106 { 107 return (raidPtr->Layout.stripeUnitsPerDisk / raidPtr->numCol); 108 } 109 110 void 111 rf_MapSectorRAID5_RS( 112 RF_Raid_t * raidPtr, 113 RF_RaidAddr_t raidSector, 114 RF_RowCol_t * row, 115 RF_RowCol_t * col, 116 RF_SectorNum_t * diskSector, 117 int remap) 118 { 119 RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit; 120 121 *row = 0; 122 if (remap) { 123 *col = raidPtr->numCol - 1 - (1 + SUID / raidPtr->Layout.numDataCol) % raidPtr->numCol; 124 *col = (*col + 1) % raidPtr->numCol; /* spare unit is rotated 125 * with parity; line 126 * above maps to parity */ 127 } else { 128 *col = (SUID + (SUID / raidPtr->Layout.numDataCol)) % raidPtr->numCol; 129 } 130 *diskSector = (SUID / (raidPtr->Layout.numDataCol)) * raidPtr->Layout.sectorsPerStripeUnit + 131 (raidSector % raidPtr->Layout.sectorsPerStripeUnit); 132 } 133 134 void 135 rf_MapParityRAID5_RS( 136 RF_Raid_t * raidPtr, 137 RF_RaidAddr_t raidSector, 138 RF_RowCol_t * row, 139 RF_RowCol_t * col, 140 RF_SectorNum_t * diskSector, 141 int remap) 142 { 143 RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit; 144 145 *row = 0; 146 *col = raidPtr->numCol - 1 - (1 + SUID / raidPtr->Layout.numDataCol) % raidPtr->numCol; 147 *diskSector = (SUID / (raidPtr->Layout.numDataCol)) * raidPtr->Layout.sectorsPerStripeUnit + 148 (raidSector % raidPtr->Layout.sectorsPerStripeUnit); 149 if (remap) 150 *col = (*col + 1) % raidPtr->numCol; 151 } 152 153 void 154 rf_IdentifyStripeRAID5_RS( 155 RF_Raid_t * raidPtr, 156 RF_RaidAddr_t addr, 157 RF_RowCol_t ** diskids, 158 RF_RowCol_t * outRow) 159 { 160 RF_StripeNum_t stripeID = rf_RaidAddressToStripeID(&raidPtr->Layout, addr); 161 RF_Raid5RSConfigInfo_t *info = (RF_Raid5RSConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo; 162 *outRow = 0; 163 *diskids = info->stripeIdentifier[stripeID % raidPtr->numCol]; 164 165 } 166 167 void 168 rf_MapSIDToPSIDRAID5_RS( 169 RF_RaidLayout_t * layoutPtr, 170 RF_StripeNum_t stripeID, 171 RF_StripeNum_t * psID, 172 RF_ReconUnitNum_t * which_ru) 173 { 174 *which_ru = 0; 175 *psID = stripeID; 176 } 177 #endif /* RF_INCLUDE_RAID5_RS > 0 */ 178