Home | History | Annotate | Line # | Download | only in raidframe
rf_chaindecluster.c revision 1.6.2.3
      1  1.6.2.2  nathanw /*	$NetBSD: rf_chaindecluster.c,v 1.6.2.3 2002/10/18 02:43:42 nathanw Exp $	*/
      2      1.1    oster /*
      3      1.1    oster  * Copyright (c) 1995 Carnegie-Mellon University.
      4      1.1    oster  * All rights reserved.
      5      1.1    oster  *
      6      1.1    oster  * Author: Khalil Amiri
      7      1.1    oster  *
      8      1.1    oster  * Permission to use, copy, modify and distribute this software and
      9      1.1    oster  * its documentation is hereby granted, provided that both the copyright
     10      1.1    oster  * notice and this permission notice appear in all copies of the
     11      1.1    oster  * software, derivative works or modified versions, and any portions
     12      1.1    oster  * thereof, and that both notices appear in supporting documentation.
     13      1.1    oster  *
     14      1.1    oster  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
     15      1.1    oster  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
     16      1.1    oster  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
     17      1.1    oster  *
     18      1.1    oster  * Carnegie Mellon requests users of this software to return to
     19      1.1    oster  *
     20      1.1    oster  *  Software Distribution Coordinator  or  Software.Distribution (at) CS.CMU.EDU
     21      1.1    oster  *  School of Computer Science
     22      1.1    oster  *  Carnegie Mellon University
     23      1.1    oster  *  Pittsburgh PA 15213-3890
     24      1.1    oster  *
     25      1.1    oster  * any improvements or extensions that they make and grant Carnegie the
     26      1.1    oster  * rights to redistribute these changes.
     27      1.1    oster  */
     28      1.1    oster 
     29      1.1    oster /******************************************************************************
     30      1.1    oster  *
     31      1.1    oster  * rf_chaindecluster.c -- implements chained declustering
     32      1.1    oster  *
     33      1.1    oster  *****************************************************************************/
     34  1.6.2.2  nathanw 
     35  1.6.2.2  nathanw #include <sys/cdefs.h>
     36  1.6.2.2  nathanw __KERNEL_RCSID(0, "$NetBSD: rf_chaindecluster.c,v 1.6.2.3 2002/10/18 02:43:42 nathanw Exp $");
     37      1.1    oster 
     38      1.1    oster #include "rf_archs.h"
     39      1.6    oster 
     40      1.6    oster #if (RF_INCLUDE_CHAINDECLUSTER > 0)
     41      1.6    oster 
     42  1.6.2.1  nathanw #include <dev/raidframe/raidframevar.h>
     43  1.6.2.1  nathanw 
     44      1.1    oster #include "rf_raid.h"
     45      1.1    oster #include "rf_chaindecluster.h"
     46      1.1    oster #include "rf_dag.h"
     47      1.1    oster #include "rf_dagutils.h"
     48      1.1    oster #include "rf_dagffrd.h"
     49      1.1    oster #include "rf_dagffwr.h"
     50      1.1    oster #include "rf_dagdegrd.h"
     51      1.1    oster #include "rf_dagfuncs.h"
     52      1.1    oster #include "rf_general.h"
     53      1.1    oster #include "rf_utils.h"
     54      1.1    oster 
     55      1.1    oster typedef struct RF_ChaindeclusterConfigInfo_s {
     56      1.3    oster 	RF_RowCol_t **stripeIdentifier;	/* filled in at config time and used
     57      1.3    oster 					 * by IdentifyStripe */
     58      1.3    oster 	RF_StripeCount_t numSparingRegions;
     59      1.3    oster 	RF_StripeCount_t stripeUnitsPerSparingRegion;
     60      1.3    oster 	RF_SectorNum_t mirrorStripeOffset;
     61      1.3    oster }       RF_ChaindeclusterConfigInfo_t;
     62      1.3    oster 
     63      1.3    oster int
     64      1.3    oster rf_ConfigureChainDecluster(
     65      1.3    oster     RF_ShutdownList_t ** listp,
     66      1.3    oster     RF_Raid_t * raidPtr,
     67      1.3    oster     RF_Config_t * cfgPtr)
     68      1.1    oster {
     69      1.3    oster 	RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
     70      1.3    oster 	RF_StripeCount_t num_used_stripeUnitsPerDisk;
     71      1.3    oster 	RF_ChaindeclusterConfigInfo_t *info;
     72      1.3    oster 	RF_RowCol_t i;
     73      1.3    oster 
     74      1.3    oster 	/* create a Chained Declustering configuration structure */
     75      1.3    oster 	RF_MallocAndAdd(info, sizeof(RF_ChaindeclusterConfigInfo_t), (RF_ChaindeclusterConfigInfo_t *), raidPtr->cleanupList);
     76      1.3    oster 	if (info == NULL)
     77      1.3    oster 		return (ENOMEM);
     78      1.3    oster 	layoutPtr->layoutSpecificInfo = (void *) info;
     79      1.3    oster 
     80      1.3    oster 	/* fill in the config structure.  */
     81      1.3    oster 	info->stripeIdentifier = rf_make_2d_array(raidPtr->numCol, 2, raidPtr->cleanupList);
     82      1.3    oster 	if (info->stripeIdentifier == NULL)
     83      1.3    oster 		return (ENOMEM);
     84      1.3    oster 	for (i = 0; i < raidPtr->numCol; i++) {
     85      1.3    oster 		info->stripeIdentifier[i][0] = i % raidPtr->numCol;
     86      1.3    oster 		info->stripeIdentifier[i][1] = (i + 1) % raidPtr->numCol;
     87      1.3    oster 	}
     88      1.3    oster 
     89      1.3    oster 	RF_ASSERT(raidPtr->numRow == 1);
     90      1.3    oster 
     91      1.3    oster 	/* fill in the remaining layout parameters */
     92      1.3    oster 	num_used_stripeUnitsPerDisk = layoutPtr->stripeUnitsPerDisk - (layoutPtr->stripeUnitsPerDisk %
     93      1.3    oster 	    (2 * raidPtr->numCol - 2));
     94      1.3    oster 	info->numSparingRegions = num_used_stripeUnitsPerDisk / (2 * raidPtr->numCol - 2);
     95      1.3    oster 	info->stripeUnitsPerSparingRegion = raidPtr->numCol * (raidPtr->numCol - 1);
     96      1.3    oster 	info->mirrorStripeOffset = info->numSparingRegions * (raidPtr->numCol - 1);
     97      1.3    oster 	layoutPtr->numStripe = info->numSparingRegions * info->stripeUnitsPerSparingRegion;
     98      1.3    oster 	layoutPtr->numDataCol = 1;
     99      1.3    oster 	layoutPtr->dataSectorsPerStripe = layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit;
    100      1.3    oster 	layoutPtr->numParityCol = 1;
    101      1.3    oster 
    102      1.3    oster 	layoutPtr->dataStripeUnitsPerDisk = num_used_stripeUnitsPerDisk;
    103      1.3    oster 
    104      1.3    oster 	raidPtr->sectorsPerDisk =
    105      1.3    oster 	    num_used_stripeUnitsPerDisk * layoutPtr->sectorsPerStripeUnit;
    106      1.1    oster 
    107      1.3    oster 	raidPtr->totalSectors =
    108      1.3    oster 	    (layoutPtr->numStripe) * layoutPtr->sectorsPerStripeUnit;
    109      1.1    oster 
    110      1.3    oster 	layoutPtr->stripeUnitsPerDisk = raidPtr->sectorsPerDisk / layoutPtr->sectorsPerStripeUnit;
    111      1.1    oster 
    112      1.3    oster 	return (0);
    113      1.1    oster }
    114      1.1    oster 
    115      1.3    oster RF_ReconUnitCount_t
    116      1.3    oster rf_GetNumSpareRUsChainDecluster(raidPtr)
    117      1.3    oster 	RF_Raid_t *raidPtr;
    118      1.1    oster {
    119      1.3    oster 	RF_ChaindeclusterConfigInfo_t *info = (RF_ChaindeclusterConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
    120      1.1    oster 
    121      1.3    oster 	/*
    122      1.3    oster          * The layout uses two stripe units per disk as spare within each
    123      1.3    oster          * sparing region.
    124      1.3    oster          */
    125      1.3    oster 	return (2 * info->numSparingRegions);
    126      1.1    oster }
    127      1.1    oster 
    128      1.1    oster 
    129      1.1    oster /* Maps to the primary copy of the data, i.e. the first mirror pair */
    130      1.3    oster void
    131      1.3    oster rf_MapSectorChainDecluster(
    132      1.3    oster     RF_Raid_t * raidPtr,
    133      1.3    oster     RF_RaidAddr_t raidSector,
    134      1.3    oster     RF_RowCol_t * row,
    135      1.3    oster     RF_RowCol_t * col,
    136      1.3    oster     RF_SectorNum_t * diskSector,
    137      1.3    oster     int remap)
    138      1.1    oster {
    139      1.3    oster 	RF_ChaindeclusterConfigInfo_t *info = (RF_ChaindeclusterConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
    140      1.3    oster 	RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
    141      1.3    oster 	RF_SectorNum_t index_within_region, index_within_disk;
    142      1.3    oster 	RF_StripeNum_t sparing_region_id;
    143      1.3    oster 	int     col_before_remap;
    144      1.3    oster 
    145      1.3    oster 	*row = 0;
    146      1.3    oster 	sparing_region_id = SUID / info->stripeUnitsPerSparingRegion;
    147      1.3    oster 	index_within_region = SUID % info->stripeUnitsPerSparingRegion;
    148      1.3    oster 	index_within_disk = index_within_region / raidPtr->numCol;
    149      1.3    oster 	col_before_remap = SUID % raidPtr->numCol;
    150      1.3    oster 
    151      1.3    oster 	if (!remap) {
    152      1.3    oster 		*col = col_before_remap;
    153      1.3    oster 		*diskSector = (index_within_disk + ((raidPtr->numCol - 1) * sparing_region_id)) *
    154      1.3    oster 		    raidPtr->Layout.sectorsPerStripeUnit;
    155      1.3    oster 		*diskSector += (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
    156      1.3    oster 	} else {
    157      1.3    oster 		/* remap sector to spare space... */
    158      1.3    oster 		*diskSector = sparing_region_id * (raidPtr->numCol + 1) * raidPtr->Layout.sectorsPerStripeUnit;
    159      1.3    oster 		*diskSector += (raidPtr->numCol - 1) * raidPtr->Layout.sectorsPerStripeUnit;
    160      1.3    oster 		*diskSector += (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
    161      1.3    oster 		index_within_disk = index_within_region / raidPtr->numCol;
    162      1.3    oster 		if (index_within_disk < col_before_remap)
    163      1.3    oster 			*col = index_within_disk;
    164      1.3    oster 		else
    165      1.3    oster 			if (index_within_disk == raidPtr->numCol - 2) {
    166      1.3    oster 				*col = (col_before_remap + raidPtr->numCol - 1) % raidPtr->numCol;
    167      1.3    oster 				*diskSector += raidPtr->Layout.sectorsPerStripeUnit;
    168      1.3    oster 			} else
    169      1.3    oster 				*col = (index_within_disk + 2) % raidPtr->numCol;
    170      1.3    oster 	}
    171      1.1    oster 
    172      1.1    oster }
    173      1.1    oster 
    174      1.1    oster 
    175      1.1    oster 
    176      1.1    oster /* Maps to the second copy of the mirror pair, which is chain declustered. The second copy is contained
    177      1.3    oster    in the next disk (mod numCol) after the disk containing the primary copy.
    178      1.1    oster    The offset into the disk is one-half disk down */
    179      1.3    oster void
    180      1.3    oster rf_MapParityChainDecluster(
    181      1.3    oster     RF_Raid_t * raidPtr,
    182      1.3    oster     RF_RaidAddr_t raidSector,
    183      1.3    oster     RF_RowCol_t * row,
    184      1.3    oster     RF_RowCol_t * col,
    185      1.3    oster     RF_SectorNum_t * diskSector,
    186      1.3    oster     int remap)
    187      1.1    oster {
    188      1.3    oster 	RF_ChaindeclusterConfigInfo_t *info = (RF_ChaindeclusterConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
    189      1.3    oster 	RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
    190      1.3    oster 	RF_SectorNum_t index_within_region, index_within_disk;
    191      1.3    oster 	RF_StripeNum_t sparing_region_id;
    192      1.3    oster 	int     col_before_remap;
    193      1.3    oster 
    194      1.3    oster 	*row = 0;
    195      1.3    oster 	if (!remap) {
    196      1.3    oster 		*col = SUID % raidPtr->numCol;
    197      1.3    oster 		*col = (*col + 1) % raidPtr->numCol;
    198      1.3    oster 		*diskSector = info->mirrorStripeOffset * raidPtr->Layout.sectorsPerStripeUnit;
    199      1.3    oster 		*diskSector += (SUID / raidPtr->numCol) * raidPtr->Layout.sectorsPerStripeUnit;
    200      1.3    oster 		*diskSector += (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
    201      1.3    oster 	} else {
    202      1.3    oster 		/* remap parity to spare space ... */
    203      1.3    oster 		sparing_region_id = SUID / info->stripeUnitsPerSparingRegion;
    204      1.3    oster 		index_within_region = SUID % info->stripeUnitsPerSparingRegion;
    205      1.3    oster 		index_within_disk = index_within_region / raidPtr->numCol;
    206      1.3    oster 		*diskSector = sparing_region_id * (raidPtr->numCol + 1) * raidPtr->Layout.sectorsPerStripeUnit;
    207      1.3    oster 		*diskSector += (raidPtr->numCol) * raidPtr->Layout.sectorsPerStripeUnit;
    208      1.3    oster 		*diskSector += (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
    209      1.3    oster 		col_before_remap = SUID % raidPtr->numCol;
    210      1.3    oster 		if (index_within_disk < col_before_remap)
    211      1.3    oster 			*col = index_within_disk;
    212      1.3    oster 		else
    213      1.3    oster 			if (index_within_disk == raidPtr->numCol - 2) {
    214      1.3    oster 				*col = (col_before_remap + 2) % raidPtr->numCol;
    215      1.3    oster 				*diskSector -= raidPtr->Layout.sectorsPerStripeUnit;
    216      1.3    oster 			} else
    217      1.3    oster 				*col = (index_within_disk + 2) % raidPtr->numCol;
    218      1.3    oster 	}
    219      1.1    oster 
    220      1.1    oster }
    221      1.1    oster 
    222      1.3    oster void
    223      1.3    oster rf_IdentifyStripeChainDecluster(
    224      1.3    oster     RF_Raid_t * raidPtr,
    225      1.3    oster     RF_RaidAddr_t addr,
    226      1.3    oster     RF_RowCol_t ** diskids,
    227      1.3    oster     RF_RowCol_t * outRow)
    228      1.1    oster {
    229      1.3    oster 	RF_ChaindeclusterConfigInfo_t *info = (RF_ChaindeclusterConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
    230      1.3    oster 	RF_StripeNum_t SUID;
    231      1.3    oster 	RF_RowCol_t col;
    232      1.3    oster 
    233      1.3    oster 	SUID = addr / raidPtr->Layout.sectorsPerStripeUnit;
    234      1.3    oster 	col = SUID % raidPtr->numCol;
    235      1.3    oster 	*outRow = 0;
    236      1.3    oster 	*diskids = info->stripeIdentifier[col];
    237      1.1    oster }
    238      1.1    oster 
    239      1.3    oster void
    240      1.3    oster rf_MapSIDToPSIDChainDecluster(
    241      1.3    oster     RF_RaidLayout_t * layoutPtr,
    242      1.3    oster     RF_StripeNum_t stripeID,
    243      1.3    oster     RF_StripeNum_t * psID,
    244      1.3    oster     RF_ReconUnitNum_t * which_ru)
    245      1.1    oster {
    246      1.3    oster 	*which_ru = 0;
    247      1.3    oster 	*psID = stripeID;
    248      1.1    oster }
    249      1.1    oster /******************************************************************************
    250      1.1    oster  * select a graph to perform a single-stripe access
    251      1.1    oster  *
    252      1.1    oster  * Parameters:  raidPtr    - description of the physical array
    253      1.1    oster  *              type       - type of operation (read or write) requested
    254      1.1    oster  *              asmap      - logical & physical addresses for this access
    255      1.1    oster  *              createFunc - function to use to create the graph (return value)
    256      1.1    oster  *****************************************************************************/
    257      1.1    oster 
    258      1.3    oster void
    259      1.3    oster rf_RAIDCDagSelect(
    260      1.3    oster     RF_Raid_t * raidPtr,
    261      1.3    oster     RF_IoType_t type,
    262      1.3    oster     RF_AccessStripeMap_t * asmap,
    263      1.3    oster     RF_VoidFuncPtr * createFunc)
    264      1.1    oster #if 0
    265      1.3    oster 	void    (**createFunc) (RF_Raid_t *, RF_AccessStripeMap_t *,
    266      1.3    oster             RF_DagHeader_t *, void *, RF_RaidAccessFlags_t,
    267      1.5    oster             RF_AllocListElem_t *)
    268      1.1    oster #endif
    269      1.1    oster {
    270      1.3    oster 	RF_ASSERT(RF_IO_IS_R_OR_W(type));
    271      1.3    oster 	RF_ASSERT(raidPtr->numRow == 1);
    272      1.1    oster 
    273      1.3    oster 	if (asmap->numDataFailed + asmap->numParityFailed > 1) {
    274      1.3    oster 		RF_ERRORMSG("Multiple disks failed in a single group!  Aborting I/O operation.\n");
    275      1.3    oster 		*createFunc = NULL;
    276      1.3    oster 		return;
    277      1.3    oster 	}
    278      1.3    oster 	*createFunc = (type == RF_IO_TYPE_READ) ? (RF_VoidFuncPtr) rf_CreateFaultFreeReadDAG : (RF_VoidFuncPtr) rf_CreateRaidOneWriteDAG;
    279      1.3    oster 
    280      1.3    oster 	if (type == RF_IO_TYPE_READ) {
    281      1.3    oster 		if ((raidPtr->status[0] == rf_rs_degraded) || (raidPtr->status[0] == rf_rs_reconstructing))
    282      1.3    oster 			*createFunc = (RF_VoidFuncPtr) rf_CreateRaidCDegradedReadDAG;	/* array status is
    283      1.3    oster 											 * degraded, implement
    284      1.3    oster 											 * workload shifting */
    285      1.3    oster 		else
    286      1.3    oster 			*createFunc = (RF_VoidFuncPtr) rf_CreateMirrorPartitionReadDAG;	/* array status not
    287      1.3    oster 											 * degraded, so use
    288      1.3    oster 											 * mirror partition dag */
    289      1.3    oster 	} else
    290      1.3    oster 		*createFunc = (RF_VoidFuncPtr) rf_CreateRaidOneWriteDAG;
    291      1.1    oster }
    292      1.6    oster #endif /* (RF_INCLUDE_CHAINDECLUSTER > 0) */
    293