1 /* $NetBSD: rf_raid5_rotatedspare.c,v 1.7 2002/09/23 02:40:09 oster 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.7 2002/09/23 02:40:09 oster 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->numDataCol = raidPtr->numCol - 2; 92 layoutPtr->dataSectorsPerStripe = layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit; 93 layoutPtr->numParityCol = 1; 94 layoutPtr->dataStripeUnitsPerDisk = layoutPtr->stripeUnitsPerDisk; 95 raidPtr->sectorsPerDisk = layoutPtr->stripeUnitsPerDisk * layoutPtr->sectorsPerStripeUnit; 96 97 raidPtr->totalSectors = layoutPtr->stripeUnitsPerDisk * layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit; 98 99 return (0); 100 } 101 102 RF_ReconUnitCount_t 103 rf_GetNumSpareRUsRAID5_RS(raidPtr) 104 RF_Raid_t *raidPtr; 105 { 106 return (raidPtr->Layout.stripeUnitsPerDisk / raidPtr->numCol); 107 } 108 109 void 110 rf_MapSectorRAID5_RS( 111 RF_Raid_t * raidPtr, 112 RF_RaidAddr_t raidSector, 113 RF_RowCol_t * row, 114 RF_RowCol_t * col, 115 RF_SectorNum_t * diskSector, 116 int remap) 117 { 118 RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit; 119 120 *row = 0; 121 if (remap) { 122 *col = raidPtr->numCol - 1 - (1 + SUID / raidPtr->Layout.numDataCol) % raidPtr->numCol; 123 *col = (*col + 1) % raidPtr->numCol; /* spare unit is rotated 124 * with parity; line 125 * above maps to parity */ 126 } else { 127 *col = (SUID + (SUID / raidPtr->Layout.numDataCol)) % raidPtr->numCol; 128 } 129 *diskSector = (SUID / (raidPtr->Layout.numDataCol)) * raidPtr->Layout.sectorsPerStripeUnit + 130 (raidSector % raidPtr->Layout.sectorsPerStripeUnit); 131 } 132 133 void 134 rf_MapParityRAID5_RS( 135 RF_Raid_t * raidPtr, 136 RF_RaidAddr_t raidSector, 137 RF_RowCol_t * row, 138 RF_RowCol_t * col, 139 RF_SectorNum_t * diskSector, 140 int remap) 141 { 142 RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit; 143 144 *row = 0; 145 *col = raidPtr->numCol - 1 - (1 + SUID / raidPtr->Layout.numDataCol) % raidPtr->numCol; 146 *diskSector = (SUID / (raidPtr->Layout.numDataCol)) * raidPtr->Layout.sectorsPerStripeUnit + 147 (raidSector % raidPtr->Layout.sectorsPerStripeUnit); 148 if (remap) 149 *col = (*col + 1) % raidPtr->numCol; 150 } 151 152 void 153 rf_IdentifyStripeRAID5_RS( 154 RF_Raid_t * raidPtr, 155 RF_RaidAddr_t addr, 156 RF_RowCol_t ** diskids, 157 RF_RowCol_t * outRow) 158 { 159 RF_StripeNum_t stripeID = rf_RaidAddressToStripeID(&raidPtr->Layout, addr); 160 RF_Raid5RSConfigInfo_t *info = (RF_Raid5RSConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo; 161 *outRow = 0; 162 *diskids = info->stripeIdentifier[stripeID % raidPtr->numCol]; 163 164 } 165 166 void 167 rf_MapSIDToPSIDRAID5_RS( 168 RF_RaidLayout_t * layoutPtr, 169 RF_StripeNum_t stripeID, 170 RF_StripeNum_t * psID, 171 RF_ReconUnitNum_t * which_ru) 172 { 173 *which_ru = 0; 174 *psID = stripeID; 175 } 176 #endif /* RF_INCLUDE_RAID5_RS > 0 */ 177