1 /* $NetBSD: rf_raid5_rotatedspare.c,v 1.13 2009/03/14 15:36:20 dsl 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.13 2009/03/14 15:36:20 dsl 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(RF_Raid_t *raidPtr) 103 { 104 return (raidPtr->Layout.stripeUnitsPerDisk / raidPtr->numCol); 105 } 106 107 void 108 rf_MapSectorRAID5_RS( 109 RF_Raid_t * raidPtr, 110 RF_RaidAddr_t raidSector, 111 RF_RowCol_t * col, 112 RF_SectorNum_t * diskSector, 113 int remap) 114 { 115 RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit; 116 117 if (remap) { 118 *col = raidPtr->numCol - 1 - (1 + SUID / raidPtr->Layout.numDataCol) % raidPtr->numCol; 119 *col = (*col + 1) % raidPtr->numCol; /* spare unit is rotated 120 * with parity; line 121 * above maps to parity */ 122 } else { 123 *col = (SUID + (SUID / raidPtr->Layout.numDataCol)) % raidPtr->numCol; 124 } 125 *diskSector = (SUID / (raidPtr->Layout.numDataCol)) * raidPtr->Layout.sectorsPerStripeUnit + 126 (raidSector % raidPtr->Layout.sectorsPerStripeUnit); 127 } 128 129 void 130 rf_MapParityRAID5_RS( 131 RF_Raid_t * raidPtr, 132 RF_RaidAddr_t raidSector, 133 RF_RowCol_t * col, 134 RF_SectorNum_t * diskSector, 135 int remap) 136 { 137 RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit; 138 139 *col = raidPtr->numCol - 1 - (1 + SUID / raidPtr->Layout.numDataCol) % raidPtr->numCol; 140 *diskSector = (SUID / (raidPtr->Layout.numDataCol)) * raidPtr->Layout.sectorsPerStripeUnit + 141 (raidSector % raidPtr->Layout.sectorsPerStripeUnit); 142 if (remap) 143 *col = (*col + 1) % raidPtr->numCol; 144 } 145 146 void 147 rf_IdentifyStripeRAID5_RS( 148 RF_Raid_t * raidPtr, 149 RF_RaidAddr_t addr, 150 RF_RowCol_t ** diskids) 151 { 152 RF_StripeNum_t stripeID = rf_RaidAddressToStripeID(&raidPtr->Layout, addr); 153 RF_Raid5RSConfigInfo_t *info = (RF_Raid5RSConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo; 154 *diskids = info->stripeIdentifier[stripeID % raidPtr->numCol]; 155 156 } 157 158 void 159 rf_MapSIDToPSIDRAID5_RS( 160 RF_RaidLayout_t * layoutPtr, 161 RF_StripeNum_t stripeID, 162 RF_StripeNum_t * psID, 163 RF_ReconUnitNum_t * which_ru) 164 { 165 *which_ru = 0; 166 *psID = stripeID; 167 } 168 #endif /* RF_INCLUDE_RAID5_RS > 0 */ 169