1 /* $NetBSD: rf_raid5_rotatedspare.c,v 1.12 2006/11/16 01:33:23 christos Exp $ */
3 * Copyright (c) 1995 Carnegie-Mellon University.
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.
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.
18 * Carnegie Mellon requests users of this software to return to
20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
25 * any improvements or extensions that they make and grant Carnegie the
26 * rights to redistribute these changes.
29 /**************************************************************************
31 * rf_raid5_rotated_spare.c -- implements RAID Level 5 with rotated sparing
33 **************************************************************************/
35 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: rf_raid5_rotatedspare.c,v 1.12 2006/11/16 01:33:23 christos Exp $");
40 #if RF_INCLUDE_RAID5_RS > 0
45 #include "rf_dagutils.h"
46 #include "rf_dagfuncs.h"
47 #include "rf_general.h"
49 #include "rf_raid5_rotatedspare.h"
51 typedef struct RF_Raid5RSConfigInfo_s
{
52 RF_RowCol_t
**stripeIdentifier
; /* filled in at config time & used by
54 } RF_Raid5RSConfigInfo_t
;
58 RF_ShutdownList_t
** listp
,
62 RF_RaidLayout_t
*layoutPtr
= &raidPtr
->Layout
;
63 RF_Raid5RSConfigInfo_t
*info
;
64 RF_RowCol_t i
, j
, startdisk
;
66 /* create a RAID level 5 configuration structure */
67 RF_MallocAndAdd(info
, sizeof(RF_Raid5RSConfigInfo_t
), (RF_Raid5RSConfigInfo_t
*), raidPtr
->cleanupList
);
70 layoutPtr
->layoutSpecificInfo
= (void *) info
;
72 RF_ASSERT(raidPtr
->numCol
>= 3);
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
)
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
;
84 if ((--startdisk
) < 0)
85 startdisk
= raidPtr
->numCol
- 1;
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
;
96 raidPtr
->totalSectors
= layoutPtr
->stripeUnitsPerDisk
* layoutPtr
->numDataCol
* layoutPtr
->sectorsPerStripeUnit
;
102 rf_GetNumSpareRUsRAID5_RS(RF_Raid_t
*raidPtr
)
104 return (raidPtr
->Layout
.stripeUnitsPerDisk
/ raidPtr
->numCol
);
108 rf_MapSectorRAID5_RS(
110 RF_RaidAddr_t raidSector
,
112 RF_SectorNum_t
* diskSector
,
115 RF_StripeNum_t SUID
= raidSector
/ raidPtr
->Layout
.sectorsPerStripeUnit
;
118 *col
= raidPtr
->numCol
- 1 - (1 + SUID
/ raidPtr
->Layout
.numDataCol
) % raidPtr
->numCol
;
119 *col
= (*col
+ 1) % raidPtr
->numCol
; /* spare unit is rotated
121 * above maps to parity */
123 *col
= (SUID
+ (SUID
/ raidPtr
->Layout
.numDataCol
)) % raidPtr
->numCol
;
125 *diskSector
= (SUID
/ (raidPtr
->Layout
.numDataCol
)) * raidPtr
->Layout
.sectorsPerStripeUnit
+
126 (raidSector
% raidPtr
->Layout
.sectorsPerStripeUnit
);
130 rf_MapParityRAID5_RS(
132 RF_RaidAddr_t raidSector
,
134 RF_SectorNum_t
* diskSector
,
137 RF_StripeNum_t SUID
= raidSector
/ raidPtr
->Layout
.sectorsPerStripeUnit
;
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
);
143 *col
= (*col
+ 1) % raidPtr
->numCol
;
147 rf_IdentifyStripeRAID5_RS(
150 RF_RowCol_t
** diskids
)
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
];
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
)
168 #endif /* RF_INCLUDE_RAID5_RS > 0 */