1 /* $NetBSD: rf_raid5_rotatedspare.c,v 1.10 2005/12/11 12:23:37 christos 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.10 2005/12/11 12:23:37 christos 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->numCol >= 3); 73 74 /* the stripe identifier must identify the disks in each stripe, IN 75 * THE ORDER THAT THEY APPEAR IN THE STRIPE. */ 76 info->stripeIdentifier = rf_make_2d_array(raidPtr->numCol, raidPtr->numCol, raidPtr->cleanupList); 77 if (info->stripeIdentifier == NULL) 78 return (ENOMEM); 79 startdisk = 0; 80 for (i = 0; i < raidPtr->numCol; i++) { 81 for (j = 0; j < raidPtr->numCol; j++) { 82 info->stripeIdentifier[i][j] = (startdisk + j) % raidPtr->numCol; 83 } 84 if ((--startdisk) < 0) 85 startdisk = raidPtr->numCol - 1; 86 } 87 88 /* fill in the remaining layout parameters */ 89 layoutPtr->numStripe = layoutPtr->stripeUnitsPerDisk; 90 layoutPtr->numDataCol = raidPtr->numCol - 2; 91 layoutPtr->dataSectorsPerStripe = layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit; 92 layoutPtr->numParityCol = 1; 93 layoutPtr->dataStripeUnitsPerDisk = layoutPtr->stripeUnitsPerDisk; 94 raidPtr->sectorsPerDisk = layoutPtr->stripeUnitsPerDisk * layoutPtr->sectorsPerStripeUnit; 95 96 raidPtr->totalSectors = layoutPtr->stripeUnitsPerDisk * layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit; 97 98 return (0); 99 } 100 101 RF_ReconUnitCount_t 102 rf_GetNumSpareRUsRAID5_RS(raidPtr) 103 RF_Raid_t *raidPtr; 104 { 105 return (raidPtr->Layout.stripeUnitsPerDisk / raidPtr->numCol); 106 } 107 108 void 109 rf_MapSectorRAID5_RS( 110 RF_Raid_t * raidPtr, 111 RF_RaidAddr_t raidSector, 112 RF_RowCol_t * col, 113 RF_SectorNum_t * diskSector, 114 int remap) 115 { 116 RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit; 117 118 if (remap) { 119 *col = raidPtr->numCol - 1 - (1 + SUID / raidPtr->Layout.numDataCol) % raidPtr->numCol; 120 *col = (*col + 1) % raidPtr->numCol; /* spare unit is rotated 121 * with parity; line 122 * above maps to parity */ 123 } else { 124 *col = (SUID + (SUID / raidPtr->Layout.numDataCol)) % raidPtr->numCol; 125 } 126 *diskSector = (SUID / (raidPtr->Layout.numDataCol)) * raidPtr->Layout.sectorsPerStripeUnit + 127 (raidSector % raidPtr->Layout.sectorsPerStripeUnit); 128 } 129 130 void 131 rf_MapParityRAID5_RS( 132 RF_Raid_t * raidPtr, 133 RF_RaidAddr_t raidSector, 134 RF_RowCol_t * col, 135 RF_SectorNum_t * diskSector, 136 int remap) 137 { 138 RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit; 139 140 *col = raidPtr->numCol - 1 - (1 + SUID / raidPtr->Layout.numDataCol) % raidPtr->numCol; 141 *diskSector = (SUID / (raidPtr->Layout.numDataCol)) * raidPtr->Layout.sectorsPerStripeUnit + 142 (raidSector % raidPtr->Layout.sectorsPerStripeUnit); 143 if (remap) 144 *col = (*col + 1) % raidPtr->numCol; 145 } 146 147 void 148 rf_IdentifyStripeRAID5_RS( 149 RF_Raid_t * raidPtr, 150 RF_RaidAddr_t addr, 151 RF_RowCol_t ** diskids) 152 { 153 RF_StripeNum_t stripeID = rf_RaidAddressToStripeID(&raidPtr->Layout, addr); 154 RF_Raid5RSConfigInfo_t *info = (RF_Raid5RSConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo; 155 *diskids = info->stripeIdentifier[stripeID % raidPtr->numCol]; 156 157 } 158 159 void 160 rf_MapSIDToPSIDRAID5_RS( 161 RF_RaidLayout_t * layoutPtr, 162 RF_StripeNum_t stripeID, 163 RF_StripeNum_t * psID, 164 RF_ReconUnitNum_t * which_ru) 165 { 166 *which_ru = 0; 167 *psID = stripeID; 168 } 169 #endif /* RF_INCLUDE_RAID5_RS > 0 */ 170