The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/raidframe/rf_chaindecluster.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: rf_chaindecluster.c,v 1.11 2003/12/30 21:59:03 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_chaindecluster.c -- implements chained declustering
   32  *
   33  *****************************************************************************/
   34 
   35 #include <sys/cdefs.h>
   36 __KERNEL_RCSID(0, "$NetBSD: rf_chaindecluster.c,v 1.11 2003/12/30 21:59:03 oster Exp $");
   37 
   38 #include "rf_archs.h"
   39 
   40 #if (RF_INCLUDE_CHAINDECLUSTER > 0) 
   41 
   42 #include <dev/raidframe/raidframevar.h>
   43 
   44 #include "rf_raid.h"
   45 #include "rf_chaindecluster.h"
   46 #include "rf_dag.h"
   47 #include "rf_dagutils.h"
   48 #include "rf_dagffrd.h"
   49 #include "rf_dagffwr.h"
   50 #include "rf_dagdegrd.h"
   51 #include "rf_dagfuncs.h"
   52 #include "rf_general.h"
   53 #include "rf_utils.h"
   54 
   55 typedef struct RF_ChaindeclusterConfigInfo_s {
   56         RF_RowCol_t **stripeIdentifier; /* filled in at config time and used
   57                                          * by IdentifyStripe */
   58         RF_StripeCount_t numSparingRegions;
   59         RF_StripeCount_t stripeUnitsPerSparingRegion;
   60         RF_SectorNum_t mirrorStripeOffset;
   61 }       RF_ChaindeclusterConfigInfo_t;
   62 
   63 int 
   64 rf_ConfigureChainDecluster(RF_ShutdownList_t **listp, RF_Raid_t *raidPtr,
   65                            RF_Config_t *cfgPtr)
   66 {
   67         RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
   68         RF_StripeCount_t num_used_stripeUnitsPerDisk;
   69         RF_ChaindeclusterConfigInfo_t *info;
   70         RF_RowCol_t i;
   71 
   72         /* create a Chained Declustering configuration structure */
   73         RF_MallocAndAdd(info, sizeof(RF_ChaindeclusterConfigInfo_t), (RF_ChaindeclusterConfigInfo_t *), raidPtr->cleanupList);
   74         if (info == NULL)
   75                 return (ENOMEM);
   76         layoutPtr->layoutSpecificInfo = (void *) info;
   77 
   78         /* fill in the config structure.  */
   79         info->stripeIdentifier = rf_make_2d_array(raidPtr->numCol, 2, raidPtr->cleanupList);
   80         if (info->stripeIdentifier == NULL)
   81                 return (ENOMEM);
   82         for (i = 0; i < raidPtr->numCol; i++) {
   83                 info->stripeIdentifier[i][0] = i % raidPtr->numCol;
   84                 info->stripeIdentifier[i][1] = (i + 1) % raidPtr->numCol;
   85         }
   86 
   87         /* fill in the remaining layout parameters */
   88         num_used_stripeUnitsPerDisk = layoutPtr->stripeUnitsPerDisk - (layoutPtr->stripeUnitsPerDisk %
   89             (2 * raidPtr->numCol - 2));
   90         info->numSparingRegions = num_used_stripeUnitsPerDisk / (2 * raidPtr->numCol - 2);
   91         info->stripeUnitsPerSparingRegion = raidPtr->numCol * (raidPtr->numCol - 1);
   92         info->mirrorStripeOffset = info->numSparingRegions * (raidPtr->numCol - 1);
   93         layoutPtr->numStripe = info->numSparingRegions * info->stripeUnitsPerSparingRegion;
   94         layoutPtr->numDataCol = 1;
   95         layoutPtr->dataSectorsPerStripe = layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit;
   96         layoutPtr->numParityCol = 1;
   97 
   98         layoutPtr->dataStripeUnitsPerDisk = num_used_stripeUnitsPerDisk;
   99 
  100         raidPtr->sectorsPerDisk =
  101             num_used_stripeUnitsPerDisk * layoutPtr->sectorsPerStripeUnit;
  102 
  103         raidPtr->totalSectors =
  104             (layoutPtr->numStripe) * layoutPtr->sectorsPerStripeUnit;
  105 
  106         layoutPtr->stripeUnitsPerDisk = raidPtr->sectorsPerDisk / layoutPtr->sectorsPerStripeUnit;
  107 
  108         return (0);
  109 }
  110 
  111 RF_ReconUnitCount_t 
  112 rf_GetNumSpareRUsChainDecluster(RF_Raid_t *raidPtr)
  113 {
  114         RF_ChaindeclusterConfigInfo_t *info = (RF_ChaindeclusterConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
  115 
  116         /*
  117          * The layout uses two stripe units per disk as spare within each
  118          * sparing region.
  119          */
  120         return (2 * info->numSparingRegions);
  121 }
  122 
  123 
  124 /* Maps to the primary copy of the data, i.e. the first mirror pair */
  125 void 
  126 rf_MapSectorChainDecluster(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
  127                            RF_RowCol_t *col, RF_SectorNum_t *diskSector,
  128                            int remap)
  129 {
  130         RF_ChaindeclusterConfigInfo_t *info = (RF_ChaindeclusterConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
  131         RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
  132         RF_SectorNum_t index_within_region, index_within_disk;
  133         RF_StripeNum_t sparing_region_id;
  134         int     col_before_remap;
  135 
  136         sparing_region_id = SUID / info->stripeUnitsPerSparingRegion;
  137         index_within_region = SUID % info->stripeUnitsPerSparingRegion;
  138         index_within_disk = index_within_region / raidPtr->numCol;
  139         col_before_remap = SUID % raidPtr->numCol;
  140 
  141         if (!remap) {
  142                 *col = col_before_remap;
  143                 *diskSector = (index_within_disk + ((raidPtr->numCol - 1) * sparing_region_id)) *
  144                     raidPtr->Layout.sectorsPerStripeUnit;
  145                 *diskSector += (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
  146         } else {
  147                 /* remap sector to spare space... */
  148                 *diskSector = sparing_region_id * (raidPtr->numCol + 1) * raidPtr->Layout.sectorsPerStripeUnit;
  149                 *diskSector += (raidPtr->numCol - 1) * raidPtr->Layout.sectorsPerStripeUnit;
  150                 *diskSector += (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
  151                 index_within_disk = index_within_region / raidPtr->numCol;
  152                 if (index_within_disk < col_before_remap)
  153                         *col = index_within_disk;
  154                 else
  155                         if (index_within_disk == raidPtr->numCol - 2) {
  156                                 *col = (col_before_remap + raidPtr->numCol - 1) % raidPtr->numCol;
  157                                 *diskSector += raidPtr->Layout.sectorsPerStripeUnit;
  158                         } else
  159                                 *col = (index_within_disk + 2) % raidPtr->numCol;
  160         }
  161 
  162 }
  163 
  164 
  165 
  166 /* Maps to the second copy of the mirror pair, which is chain declustered. The second copy is contained
  167    in the next disk (mod numCol) after the disk containing the primary copy.
  168    The offset into the disk is one-half disk down */
  169 void 
  170 rf_MapParityChainDecluster(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
  171                            RF_RowCol_t *col, RF_SectorNum_t *diskSector,
  172                            int remap)
  173 {
  174         RF_ChaindeclusterConfigInfo_t *info = (RF_ChaindeclusterConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
  175         RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
  176         RF_SectorNum_t index_within_region, index_within_disk;
  177         RF_StripeNum_t sparing_region_id;
  178         int     col_before_remap;
  179 
  180         if (!remap) {
  181                 *col = SUID % raidPtr->numCol;
  182                 *col = (*col + 1) % raidPtr->numCol;
  183                 *diskSector = info->mirrorStripeOffset * raidPtr->Layout.sectorsPerStripeUnit;
  184                 *diskSector += (SUID / raidPtr->numCol) * raidPtr->Layout.sectorsPerStripeUnit;
  185                 *diskSector += (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
  186         } else {
  187                 /* remap parity to spare space ... */
  188                 sparing_region_id = SUID / info->stripeUnitsPerSparingRegion;
  189                 index_within_region = SUID % info->stripeUnitsPerSparingRegion;
  190                 index_within_disk = index_within_region / raidPtr->numCol;
  191                 *diskSector = sparing_region_id * (raidPtr->numCol + 1) * raidPtr->Layout.sectorsPerStripeUnit;
  192                 *diskSector += (raidPtr->numCol) * raidPtr->Layout.sectorsPerStripeUnit;
  193                 *diskSector += (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
  194                 col_before_remap = SUID % raidPtr->numCol;
  195                 if (index_within_disk < col_before_remap)
  196                         *col = index_within_disk;
  197                 else
  198                         if (index_within_disk == raidPtr->numCol - 2) {
  199                                 *col = (col_before_remap + 2) % raidPtr->numCol;
  200                                 *diskSector -= raidPtr->Layout.sectorsPerStripeUnit;
  201                         } else
  202                                 *col = (index_within_disk + 2) % raidPtr->numCol;
  203         }
  204 
  205 }
  206 
  207 void 
  208 rf_IdentifyStripeChainDecluster(RF_Raid_t *raidPtr, RF_RaidAddr_t addr,
  209                                 RF_RowCol_t **diskids)
  210 {
  211         RF_ChaindeclusterConfigInfo_t *info = (RF_ChaindeclusterConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
  212         RF_StripeNum_t SUID;
  213         RF_RowCol_t col;
  214 
  215         SUID = addr / raidPtr->Layout.sectorsPerStripeUnit;
  216         col = SUID % raidPtr->numCol;
  217         *diskids = info->stripeIdentifier[col];
  218 }
  219 
  220 void 
  221 rf_MapSIDToPSIDChainDecluster(RF_RaidLayout_t *layoutPtr,
  222                               RF_StripeNum_t stripeID,
  223                               RF_StripeNum_t *psID,
  224                               RF_ReconUnitNum_t *which_ru)
  225 {
  226         *which_ru = 0;
  227         *psID = stripeID;
  228 }
  229 /******************************************************************************
  230  * select a graph to perform a single-stripe access
  231  *
  232  * Parameters:  raidPtr    - description of the physical array
  233  *              type       - type of operation (read or write) requested
  234  *              asmap      - logical & physical addresses for this access
  235  *              createFunc - function to use to create the graph (return value)
  236  *****************************************************************************/
  237 
  238 void 
  239 rf_RAIDCDagSelect(RF_Raid_t *raidPtr, RF_IoType_t type,
  240                   RF_AccessStripeMap_t *asmap, RF_VoidFuncPtr *createFunc)
  241 #if 0
  242         void    (**createFunc) (RF_Raid_t *, RF_AccessStripeMap_t *,
  243             RF_DagHeader_t *, void *, RF_RaidAccessFlags_t,
  244             RF_AllocListElem_t *)
  245 #endif
  246 {
  247         RF_ASSERT(RF_IO_IS_R_OR_W(type));
  248 
  249         if (asmap->numDataFailed + asmap->numParityFailed > 1) {
  250                 RF_ERRORMSG("Multiple disks failed in a single group!  Aborting I/O operation.\n");
  251                 *createFunc = NULL;
  252                 return;
  253         }
  254         *createFunc = (type == RF_IO_TYPE_READ) ? (RF_VoidFuncPtr) rf_CreateFaultFreeReadDAG : (RF_VoidFuncPtr) rf_CreateRaidOneWriteDAG;
  255 
  256         if (type == RF_IO_TYPE_READ) {
  257                 if ((raidPtr->status == rf_rs_degraded) || (raidPtr->status == rf_rs_reconstructing))
  258                         *createFunc = (RF_VoidFuncPtr) rf_CreateRaidCDegradedReadDAG;   /* array status is
  259                                                                                          * degraded, implement
  260                                                                                          * workload shifting */
  261                 else
  262                         *createFunc = (RF_VoidFuncPtr) rf_CreateMirrorPartitionReadDAG; /* array status not
  263                                                                                          * degraded, so use
  264                                                                                          * mirror partition dag */
  265         } else
  266                 *createFunc = (RF_VoidFuncPtr) rf_CreateRaidOneWriteDAG;
  267 }
  268 #endif /* (RF_INCLUDE_CHAINDECLUSTER > 0) */

Cache object: c4c2b2b398aa65c600f036d22e55e99a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.