Home | History | Annotate | Line # | Download | only in raidframe
rf_declusterPQ.c revision 1.1
      1  1.1  oster /*	$NetBSD: rf_declusterPQ.c,v 1.1 1998/11/13 04:20:28 oster 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  * Authors: Daniel Stodolsky, Mark Holland, Jim Zelenka
      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  * rf_declusterPQ.c
     31  1.1  oster  *
     32  1.1  oster  * mapping code for declustered P & Q or declustered EvenOdd
     33  1.1  oster  * much code borrowed from rf_decluster.c
     34  1.1  oster  *
     35  1.1  oster  *--------------------------------------------------*/
     36  1.1  oster 
     37  1.1  oster /*
     38  1.1  oster  * $Header: /tank/opengrok/rsync2/NetBSD/src/sys/dev/raidframe/rf_declusterPQ.c,v 1.1 1998/11/13 04:20:28 oster Exp $
     39  1.1  oster  *
     40  1.1  oster  * Log: rf_declusterPQ.c,v
     41  1.1  oster  * Revision 1.34  1996/08/21 19:47:14  jimz
     42  1.1  oster  * fix bogus return values from config
     43  1.1  oster  *
     44  1.1  oster  * Revision 1.33  1996/08/21  15:09:16  jimz
     45  1.1  oster  * cleanup debugging spoo
     46  1.1  oster  *
     47  1.1  oster  * Revision 1.32  1996/08/21  04:13:36  jimz
     48  1.1  oster  * debug with EvenOdd
     49  1.1  oster  *
     50  1.1  oster  * Revision 1.31  1996/08/20  22:41:54  jimz
     51  1.1  oster  * 2 parity disks, not 1
     52  1.1  oster  *
     53  1.1  oster  * Revision 1.30  1996/07/31  16:56:18  jimz
     54  1.1  oster  * dataBytesPerStripe, sectorsPerDisk init arch-indep.
     55  1.1  oster  *
     56  1.1  oster  * Revision 1.29  1996/07/18  22:57:14  jimz
     57  1.1  oster  * port simulator to AIX
     58  1.1  oster  *
     59  1.1  oster  * Revision 1.28  1996/07/13  00:00:59  jimz
     60  1.1  oster  * sanitized generalized reconstruction architecture
     61  1.1  oster  * cleaned up head sep, rbuf problems
     62  1.1  oster  *
     63  1.1  oster  * Revision 1.27  1996/06/11  08:45:12  jimz
     64  1.1  oster  * improved error-checking on array configuration
     65  1.1  oster  *
     66  1.1  oster  * Revision 1.26  1996/06/10  11:55:47  jimz
     67  1.1  oster  * Straightened out some per-array/not-per-array distinctions, fixed
     68  1.1  oster  * a couple bugs related to confusion. Added shutdown lists. Removed
     69  1.1  oster  * layout shutdown function (now subsumed by shutdown lists).
     70  1.1  oster  *
     71  1.1  oster  * Revision 1.25  1996/06/07  21:33:04  jimz
     72  1.1  oster  * begin using consistent types for sector numbers,
     73  1.1  oster  * stripe numbers, row+col numbers, recon unit numbers
     74  1.1  oster  *
     75  1.1  oster  * Revision 1.24  1996/06/02  17:31:48  jimz
     76  1.1  oster  * Moved a lot of global stuff into array structure, where it belongs.
     77  1.1  oster  * Fixed up paritylogging, pss modules in this manner. Some general
     78  1.1  oster  * code cleanup. Removed lots of dead code, some dead files.
     79  1.1  oster  *
     80  1.1  oster  * Revision 1.23  1996/05/30  23:22:16  jimz
     81  1.1  oster  * bugfixes of serialization, timing problems
     82  1.1  oster  * more cleanup
     83  1.1  oster  *
     84  1.1  oster  * Revision 1.22  1996/05/27  18:56:37  jimz
     85  1.1  oster  * more code cleanup
     86  1.1  oster  * better typing
     87  1.1  oster  * compiles in all 3 environments
     88  1.1  oster  *
     89  1.1  oster  * Revision 1.21  1996/05/24  22:17:04  jimz
     90  1.1  oster  * continue code + namespace cleanup
     91  1.1  oster  * typed a bunch of flags
     92  1.1  oster  *
     93  1.1  oster  * Revision 1.20  1996/05/24  01:59:45  jimz
     94  1.1  oster  * another checkpoint in code cleanup for release
     95  1.1  oster  * time to sync kernel tree
     96  1.1  oster  *
     97  1.1  oster  * Revision 1.19  1996/05/23  00:33:23  jimz
     98  1.1  oster  * code cleanup: move all debug decls to rf_options.c, all extern
     99  1.1  oster  * debug decls to rf_options.h, all debug vars preceded by rf_
    100  1.1  oster  *
    101  1.1  oster  * Revision 1.18  1996/05/18  19:51:34  jimz
    102  1.1  oster  * major code cleanup- fix syntax, make some types consistent,
    103  1.1  oster  * add prototypes, clean out dead code, et cetera
    104  1.1  oster  *
    105  1.1  oster  * Revision 1.17  1996/05/17  00:52:56  jimz
    106  1.1  oster  * RepIndex was not being initialized before the computation of
    107  1.1  oster  * RepIndexQ in MapQDeclusteredPQ(). I copied the initialization
    108  1.1  oster  * from MapParityDeclusteredPQ(). Hope that was right.
    109  1.1  oster  *
    110  1.1  oster  * Revision 1.16  1995/12/12  18:10:06  jimz
    111  1.1  oster  * MIN -> RF_MIN, MAX -> RF_MAX, ASSERT -> RF_ASSERT
    112  1.1  oster  * fix 80-column brain damage in comments
    113  1.1  oster  *
    114  1.1  oster  * Revision 1.15  1995/12/01  15:57:46  root
    115  1.1  oster  * added copyright info
    116  1.1  oster  *
    117  1.1  oster  * Revision 1.14  1995/11/17  19:00:13  wvcii
    118  1.1  oster  * added prototyping to MapParity
    119  1.1  oster  * created MapQ
    120  1.1  oster  *
    121  1.1  oster  * Revision 1.13  1995/10/05  22:20:48  jimz
    122  1.1  oster  * free_1d_array() takes two args; provide them both
    123  1.1  oster  *
    124  1.1  oster  * Revision 1.12  1995/09/06  19:26:33  wvcii
    125  1.1  oster  * offset cfgBuf by sparemap length (ConfigureDeclusteredPQ)
    126  1.1  oster  *
    127  1.1  oster  * Revision 1.11  95/06/23  13:41:11  robby
    128  1.1  oster  * updeated to prototypes in rf_layout.h
    129  1.1  oster  *
    130  1.1  oster  * Revision 1.10  1995/05/02  22:46:53  holland
    131  1.1  oster  * minor code cleanups.
    132  1.1  oster  *
    133  1.1  oster  * Revision 1.9  1995/03/15  20:45:23  holland
    134  1.1  oster  * distr sparing changes.
    135  1.1  oster  *
    136  1.1  oster  * Revision 1.8  1995/03/01  20:25:48  holland
    137  1.1  oster  * kernelization changes
    138  1.1  oster  *
    139  1.1  oster  * Revision 1.7  1995/02/17  19:39:56  holland
    140  1.1  oster  * added size param to all calls to Free().
    141  1.1  oster  * this is ignored at user level, but necessary in the kernel.
    142  1.1  oster  *
    143  1.1  oster  * Revision 1.6  1995/02/10  17:34:10  holland
    144  1.1  oster  * kernelization changes
    145  1.1  oster  *
    146  1.1  oster  * Revision 1.5  1995/02/03  22:31:36  holland
    147  1.1  oster  * many changes related to kernelization
    148  1.1  oster  *
    149  1.1  oster  * Revision 1.4  1995/02/01  15:13:05  holland
    150  1.1  oster  * moved #include of general.h out of raid.h and into each file
    151  1.1  oster  *
    152  1.1  oster  * Revision 1.3  1995/02/01  14:25:19  holland
    153  1.1  oster  * began changes for kernelization:
    154  1.1  oster  *      changed all instances of mutex_t and cond_t to DECLARE macros
    155  1.1  oster  *      converted configuration code to use config structure
    156  1.1  oster  *
    157  1.1  oster  * Revision 1.2  1994/11/28  22:13:56  danner
    158  1.1  oster  * corrected some mapping bugs.
    159  1.1  oster  *
    160  1.1  oster  */
    161  1.1  oster 
    162  1.1  oster #include "rf_types.h"
    163  1.1  oster #include "rf_raid.h"
    164  1.1  oster #include "rf_configure.h"
    165  1.1  oster #include "rf_decluster.h"
    166  1.1  oster #include "rf_declusterPQ.h"
    167  1.1  oster #include "rf_debugMem.h"
    168  1.1  oster #include "rf_utils.h"
    169  1.1  oster #include "rf_alloclist.h"
    170  1.1  oster #include "rf_general.h"
    171  1.1  oster 
    172  1.1  oster /* configuration code */
    173  1.1  oster 
    174  1.1  oster int rf_ConfigureDeclusteredPQ(
    175  1.1  oster   RF_ShutdownList_t  **listp,
    176  1.1  oster   RF_Raid_t           *raidPtr,
    177  1.1  oster   RF_Config_t         *cfgPtr)
    178  1.1  oster {
    179  1.1  oster     RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
    180  1.1  oster     int b, v, k, r, lambda;				/* block design params */
    181  1.1  oster     int i, j, l;
    182  1.1  oster     int *first_avail_slot;
    183  1.1  oster     int  complete_FT_count, SUID;
    184  1.1  oster     RF_DeclusteredConfigInfo_t *info;
    185  1.1  oster     int numCompleteFullTablesPerDisk;
    186  1.1  oster     int PUsPerDisk, spareRegionDepthInPUs, numCompleteSpareRegionsPerDisk = 0, extraPUsPerDisk;
    187  1.1  oster     int totSparePUsPerDisk;
    188  1.1  oster     int diskOffsetOfLastFullTableInSUs, SpareSpaceInSUs;
    189  1.1  oster     char *cfgBuf = (char *) (cfgPtr->layoutSpecific);
    190  1.1  oster 
    191  1.1  oster     cfgBuf += RF_SPAREMAP_NAME_LEN;
    192  1.1  oster 
    193  1.1  oster     b        = *( (int *) cfgBuf);   cfgBuf += sizeof(int);
    194  1.1  oster     v        = *( (int *) cfgBuf);   cfgBuf += sizeof(int);
    195  1.1  oster     k        = *( (int *) cfgBuf);   cfgBuf += sizeof(int);
    196  1.1  oster     r        = *( (int *) cfgBuf);   cfgBuf += sizeof(int);
    197  1.1  oster     lambda   = *( (int *) cfgBuf);   cfgBuf += sizeof(int);
    198  1.1  oster     raidPtr->noRotate = *( (int *) cfgBuf);   cfgBuf += sizeof(int);
    199  1.1  oster 
    200  1.1  oster     if (k <= 2) {
    201  1.1  oster       printf("RAIDFRAME: k=%d, minimum value 2\n", k);
    202  1.1  oster       return(EINVAL);
    203  1.1  oster     }
    204  1.1  oster 
    205  1.1  oster     /* 1. create layout specific structure */
    206  1.1  oster     RF_MallocAndAdd(info, sizeof(RF_DeclusteredConfigInfo_t), (RF_DeclusteredConfigInfo_t *), raidPtr->cleanupList);
    207  1.1  oster     if (info == NULL)
    208  1.1  oster       return(ENOMEM);
    209  1.1  oster     layoutPtr->layoutSpecificInfo = (void *) info;
    210  1.1  oster 
    211  1.1  oster     /* the sparemaps are generated assuming that parity is rotated, so we issue
    212  1.1  oster      * a warning if both distributed sparing and no-rotate are on at the same time
    213  1.1  oster      */
    214  1.1  oster     if ((raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE) && raidPtr->noRotate) {
    215  1.1  oster 	RF_ERRORMSG("Warning:  distributed sparing specified without parity rotation.\n");
    216  1.1  oster     }
    217  1.1  oster 
    218  1.1  oster     if (raidPtr->numCol != v) {
    219  1.1  oster         RF_ERRORMSG2("RAID: config error: table element count (%d) not equal to no. of cols (%d)\n", v, raidPtr->numCol);
    220  1.1  oster         return(EINVAL);
    221  1.1  oster     }
    222  1.1  oster 
    223  1.1  oster     /* 3.  set up the values used in devRaidMap */
    224  1.1  oster     info->BlocksPerTable = b;
    225  1.1  oster     info->NumParityReps = info->groupSize = k;
    226  1.1  oster     info->PUsPerBlock = k-2;  /* PQ */
    227  1.1  oster     info->SUsPerTable = b * info->PUsPerBlock * layoutPtr->SUsPerPU;/* b blks, k-1 SUs each */
    228  1.1  oster     info->SUsPerFullTable = k * info->SUsPerTable;	/* rot k times */
    229  1.1  oster     info->SUsPerBlock = info->PUsPerBlock * layoutPtr->SUsPerPU;
    230  1.1  oster     info->TableDepthInPUs = (b*k) / v;
    231  1.1  oster     info->FullTableDepthInPUs = info->TableDepthInPUs * k;		/* k repetitions */
    232  1.1  oster 
    233  1.1  oster     /* used only in distributed sparing case */
    234  1.1  oster     info->FullTablesPerSpareRegion = (v-1) / rf_gcd(r, v-1);		/* (v-1)/gcd fulltables */
    235  1.1  oster     info->TablesPerSpareRegion = k * info->FullTablesPerSpareRegion;
    236  1.1  oster     info->SpareSpaceDepthPerRegionInSUs = (r * info->TablesPerSpareRegion / (v-1)) * layoutPtr->SUsPerPU;
    237  1.1  oster 
    238  1.1  oster     /* check to make sure the block design is sufficiently small */
    239  1.1  oster     if ((raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE)) {
    240  1.1  oster         if (info->FullTableDepthInPUs * layoutPtr->SUsPerPU + info->SpareSpaceDepthPerRegionInSUs > layoutPtr->stripeUnitsPerDisk) {
    241  1.1  oster 	    RF_ERRORMSG3("RAID: config error: Full Table depth (%d) + Spare Space (%d) larger than disk size (%d) (BD too big)\n",
    242  1.1  oster 			 (int)info->FullTableDepthInPUs,
    243  1.1  oster 			 (int)info->SpareSpaceDepthPerRegionInSUs,
    244  1.1  oster 			 (int)layoutPtr->stripeUnitsPerDisk);
    245  1.1  oster 	    return(EINVAL);
    246  1.1  oster 	}
    247  1.1  oster     } else {
    248  1.1  oster 	if (info->TableDepthInPUs * layoutPtr->SUsPerPU > layoutPtr->stripeUnitsPerDisk) {
    249  1.1  oster 	    RF_ERRORMSG2("RAID: config error: Table depth (%d) larger than disk size (%d) (BD too big)\n",
    250  1.1  oster 			 (int)(info->TableDepthInPUs * layoutPtr->SUsPerPU),
    251  1.1  oster 			 (int)layoutPtr->stripeUnitsPerDisk);
    252  1.1  oster 	    return(EINVAL);
    253  1.1  oster 	}
    254  1.1  oster     }
    255  1.1  oster 
    256  1.1  oster 
    257  1.1  oster     /* compute the size of each disk, and the number of tables in the last fulltable (which
    258  1.1  oster      * need not be complete)
    259  1.1  oster      */
    260  1.1  oster     if ((raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE)) {
    261  1.1  oster 
    262  1.1  oster 	PUsPerDisk = layoutPtr->stripeUnitsPerDisk / layoutPtr->SUsPerPU;
    263  1.1  oster 	spareRegionDepthInPUs = (info->TablesPerSpareRegion * info->TableDepthInPUs +
    264  1.1  oster 				 (info->TablesPerSpareRegion * info->TableDepthInPUs) / (v-1));
    265  1.1  oster 	info->SpareRegionDepthInSUs = spareRegionDepthInPUs * layoutPtr->SUsPerPU;
    266  1.1  oster 
    267  1.1  oster 	numCompleteSpareRegionsPerDisk = PUsPerDisk / spareRegionDepthInPUs;
    268  1.1  oster 	info->NumCompleteSRs = numCompleteSpareRegionsPerDisk;
    269  1.1  oster 	extraPUsPerDisk = PUsPerDisk % spareRegionDepthInPUs;
    270  1.1  oster 
    271  1.1  oster 	/* assume conservatively that we need the full amount of spare space in one region in order
    272  1.1  oster 	 * to provide spares for the partial spare region at the end of the array.  We set "i" to
    273  1.1  oster 	 * the number of tables in the partial spare region.  This may actually include some fulltables.
    274  1.1  oster 	 */
    275  1.1  oster 	extraPUsPerDisk -= (info->SpareSpaceDepthPerRegionInSUs / layoutPtr->SUsPerPU);
    276  1.1  oster 	if (extraPUsPerDisk <= 0) i = 0;
    277  1.1  oster 	else i = extraPUsPerDisk/info->TableDepthInPUs;
    278  1.1  oster 
    279  1.1  oster 	complete_FT_count = raidPtr->numRow * (numCompleteSpareRegionsPerDisk * (info->TablesPerSpareRegion/k) + i/k);
    280  1.1  oster         info->FullTableLimitSUID = complete_FT_count * info->SUsPerFullTable;
    281  1.1  oster 	info->ExtraTablesPerDisk = i % k;
    282  1.1  oster 
    283  1.1  oster 	/* note that in the last spare region, the spare space is complete even though data/parity space is not */
    284  1.1  oster 	totSparePUsPerDisk = (numCompleteSpareRegionsPerDisk+1) * (info->SpareSpaceDepthPerRegionInSUs / layoutPtr->SUsPerPU);
    285  1.1  oster 	info->TotSparePUsPerDisk = totSparePUsPerDisk;
    286  1.1  oster 
    287  1.1  oster 	layoutPtr->stripeUnitsPerDisk =
    288  1.1  oster 	    ((complete_FT_count/raidPtr->numRow) * info->FullTableDepthInPUs +	 	/* data & parity space */
    289  1.1  oster 	     info->ExtraTablesPerDisk * info->TableDepthInPUs +
    290  1.1  oster 	     totSparePUsPerDisk								/* spare space */
    291  1.1  oster 	    ) * layoutPtr->SUsPerPU;
    292  1.1  oster 	layoutPtr->dataStripeUnitsPerDisk =
    293  1.1  oster 	    (complete_FT_count * info->FullTableDepthInPUs + info->ExtraTablesPerDisk * info->TableDepthInPUs)
    294  1.1  oster 	    * layoutPtr->SUsPerPU * (k-1) / k;
    295  1.1  oster 
    296  1.1  oster     } else {
    297  1.1  oster         /* non-dist spare case:  force each disk to contain an integral number of tables */
    298  1.1  oster         layoutPtr->stripeUnitsPerDisk /= (info->TableDepthInPUs * layoutPtr->SUsPerPU);
    299  1.1  oster         layoutPtr->stripeUnitsPerDisk *= (info->TableDepthInPUs * layoutPtr->SUsPerPU);
    300  1.1  oster 
    301  1.1  oster 	/* compute the number of tables in the last fulltable, which need not be complete */
    302  1.1  oster         complete_FT_count =
    303  1.1  oster             ((layoutPtr->stripeUnitsPerDisk/layoutPtr->SUsPerPU) / info->FullTableDepthInPUs) * raidPtr->numRow;
    304  1.1  oster 
    305  1.1  oster         info->FullTableLimitSUID = complete_FT_count * info->SUsPerFullTable;
    306  1.1  oster         info->ExtraTablesPerDisk =
    307  1.1  oster 		((layoutPtr->stripeUnitsPerDisk/layoutPtr->SUsPerPU) / info->TableDepthInPUs) % k;
    308  1.1  oster     }
    309  1.1  oster 
    310  1.1  oster     raidPtr->sectorsPerDisk = layoutPtr->stripeUnitsPerDisk * layoutPtr->sectorsPerStripeUnit;
    311  1.1  oster 
    312  1.1  oster     /* find the disk offset of the stripe unit where the last fulltable starts */
    313  1.1  oster     numCompleteFullTablesPerDisk = complete_FT_count / raidPtr->numRow;
    314  1.1  oster     diskOffsetOfLastFullTableInSUs = numCompleteFullTablesPerDisk * info->FullTableDepthInPUs * layoutPtr->SUsPerPU;
    315  1.1  oster     if ((raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE)) {
    316  1.1  oster         SpareSpaceInSUs  = numCompleteSpareRegionsPerDisk * info->SpareSpaceDepthPerRegionInSUs;
    317  1.1  oster         diskOffsetOfLastFullTableInSUs += SpareSpaceInSUs;
    318  1.1  oster         info->DiskOffsetOfLastSpareSpaceChunkInSUs =
    319  1.1  oster 	    diskOffsetOfLastFullTableInSUs + info->ExtraTablesPerDisk * info->TableDepthInPUs * layoutPtr->SUsPerPU;
    320  1.1  oster     }
    321  1.1  oster     info->DiskOffsetOfLastFullTableInSUs = diskOffsetOfLastFullTableInSUs;
    322  1.1  oster     info->numCompleteFullTablesPerDisk = numCompleteFullTablesPerDisk;
    323  1.1  oster 
    324  1.1  oster     /* 4.  create and initialize the lookup tables */
    325  1.1  oster     info->LayoutTable = rf_make_2d_array(b, k, raidPtr->cleanupList);
    326  1.1  oster     if (info->LayoutTable == NULL)
    327  1.1  oster       return(ENOMEM);
    328  1.1  oster     info->OffsetTable = rf_make_2d_array(b, k, raidPtr->cleanupList);
    329  1.1  oster     if (info->OffsetTable == NULL)
    330  1.1  oster       return(ENOMEM);
    331  1.1  oster     info->BlockTable  =	rf_make_2d_array(info->TableDepthInPUs*layoutPtr->SUsPerPU, raidPtr->numCol, raidPtr->cleanupList);
    332  1.1  oster     if (info->BlockTable == NULL)
    333  1.1  oster       return(ENOMEM);
    334  1.1  oster 
    335  1.1  oster     first_avail_slot  = (int *) rf_make_1d_array(v, NULL);
    336  1.1  oster     if (first_avail_slot == NULL)
    337  1.1  oster       return(ENOMEM);
    338  1.1  oster 
    339  1.1  oster     for (i=0; i<b; i++)
    340  1.1  oster       for (j=0; j<k; j++)
    341  1.1  oster         info->LayoutTable[i][j] = *cfgBuf++;
    342  1.1  oster 
    343  1.1  oster     /* initialize offset table */
    344  1.1  oster     for (i=0; i<b; i++) for (j=0; j<k; j++) {
    345  1.1  oster         info->OffsetTable[i][j] = first_avail_slot[ info->LayoutTable[i][j] ];
    346  1.1  oster         first_avail_slot[ info->LayoutTable[i][j] ]++;
    347  1.1  oster     }
    348  1.1  oster 
    349  1.1  oster     /* initialize block table */
    350  1.1  oster     for (SUID=l=0; l<layoutPtr->SUsPerPU; l++) {
    351  1.1  oster         for (i=0; i<b; i++) {
    352  1.1  oster             for (j=0; j<k; j++) {
    353  1.1  oster                 info->BlockTable[ (info->OffsetTable[i][j] * layoutPtr->SUsPerPU) + l ]
    354  1.1  oster 		                [ info->LayoutTable[i][j] ] = SUID;
    355  1.1  oster             }
    356  1.1  oster             SUID++;
    357  1.1  oster         }
    358  1.1  oster     }
    359  1.1  oster 
    360  1.1  oster     rf_free_1d_array(first_avail_slot, v);
    361  1.1  oster 
    362  1.1  oster     /* 5.  set up the remaining redundant-but-useful parameters */
    363  1.1  oster 
    364  1.1  oster     raidPtr->totalSectors = (k*complete_FT_count + raidPtr->numRow*info->ExtraTablesPerDisk) *
    365  1.1  oster     			  info->SUsPerTable * layoutPtr->sectorsPerStripeUnit;
    366  1.1  oster     layoutPtr->numStripe = (raidPtr->totalSectors / layoutPtr->sectorsPerStripeUnit) / (k-2);
    367  1.1  oster 
    368  1.1  oster     /* strange evaluation order below to try and minimize overflow problems */
    369  1.1  oster 
    370  1.1  oster     layoutPtr->dataSectorsPerStripe = (k-2) * layoutPtr->sectorsPerStripeUnit;
    371  1.1  oster     layoutPtr->bytesPerStripeUnit = layoutPtr->sectorsPerStripeUnit << raidPtr->logBytesPerSector;
    372  1.1  oster     layoutPtr->numDataCol = k-2;
    373  1.1  oster     layoutPtr->numParityCol = 2;
    374  1.1  oster 
    375  1.1  oster     return(0);
    376  1.1  oster }
    377  1.1  oster 
    378  1.1  oster int rf_GetDefaultNumFloatingReconBuffersPQ(RF_Raid_t *raidPtr)
    379  1.1  oster {
    380  1.1  oster   int def_decl;
    381  1.1  oster 
    382  1.1  oster   def_decl = rf_GetDefaultNumFloatingReconBuffersDeclustered(raidPtr);
    383  1.1  oster   return(RF_MAX(3 * raidPtr->numCol, def_decl));
    384  1.1  oster }
    385  1.1  oster 
    386  1.1  oster void rf_MapSectorDeclusteredPQ(
    387  1.1  oster   RF_Raid_t         *raidPtr,
    388  1.1  oster   RF_RaidAddr_t      raidSector,
    389  1.1  oster   RF_RowCol_t       *row,
    390  1.1  oster   RF_RowCol_t       *col,
    391  1.1  oster   RF_SectorNum_t    *diskSector,
    392  1.1  oster   int                remap)
    393  1.1  oster {
    394  1.1  oster     RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
    395  1.1  oster     RF_DeclusteredConfigInfo_t *info = (RF_DeclusteredConfigInfo_t *) layoutPtr->layoutSpecificInfo;
    396  1.1  oster     RF_StripeNum_t SUID = raidSector / layoutPtr->sectorsPerStripeUnit;
    397  1.1  oster     RF_StripeNum_t FullTableID, FullTableOffset, TableID, TableOffset;
    398  1.1  oster     RF_StripeNum_t BlockID, BlockOffset, RepIndex;
    399  1.1  oster     RF_StripeCount_t sus_per_fulltable = info->SUsPerFullTable;
    400  1.1  oster     RF_StripeCount_t fulltable_depth  = info->FullTableDepthInPUs * layoutPtr->SUsPerPU;
    401  1.1  oster     RF_StripeNum_t base_suid = 0, outSU, SpareRegion=0, SpareSpace=0;
    402  1.1  oster 
    403  1.1  oster     rf_decluster_adjust_params(layoutPtr, &SUID, &sus_per_fulltable, &fulltable_depth, &base_suid);
    404  1.1  oster 
    405  1.1  oster     FullTableID     = SUID / sus_per_fulltable;		/* fulltable ID within array (across rows) */
    406  1.1  oster     *row            = FullTableID % raidPtr->numRow;
    407  1.1  oster     FullTableID    /= raidPtr->numRow;			/* convert to fulltable ID on this disk */
    408  1.1  oster     if ((raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE)) {
    409  1.1  oster 	SpareRegion = FullTableID / info->FullTablesPerSpareRegion;
    410  1.1  oster         SpareSpace  = SpareRegion * info->SpareSpaceDepthPerRegionInSUs;
    411  1.1  oster     }
    412  1.1  oster     FullTableOffset = SUID % sus_per_fulltable;
    413  1.1  oster     TableID         = FullTableOffset / info->SUsPerTable;
    414  1.1  oster     TableOffset     = FullTableOffset - TableID * info->SUsPerTable;
    415  1.1  oster     BlockID         = TableOffset / info->PUsPerBlock;
    416  1.1  oster     BlockOffset     = TableOffset - BlockID * info->PUsPerBlock;
    417  1.1  oster     BlockID        %= info->BlocksPerTable;
    418  1.1  oster     RF_ASSERT(BlockOffset < info->groupSize-2 );
    419  1.1  oster     /*
    420  1.1  oster        TableIDs go from 0 .. GroupSize-1 inclusive.
    421  1.1  oster        PUsPerBlock is k-2.
    422  1.1  oster        We want the tableIDs to rotate from the
    423  1.1  oster        right, so use GroupSize
    424  1.1  oster        */
    425  1.1  oster     RepIndex        = info->groupSize - 1 - TableID;
    426  1.1  oster     RF_ASSERT(RepIndex >= 0);
    427  1.1  oster     if (!raidPtr->noRotate)
    428  1.1  oster       {
    429  1.1  oster 	if (TableID==0)
    430  1.1  oster 	    BlockOffset++; /* P on last drive, Q on first */
    431  1.1  oster 	else
    432  1.1  oster 	  BlockOffset    += ((BlockOffset >= RepIndex) ? 2 : 0); /* skip over PQ */
    433  1.1  oster 	RF_ASSERT(BlockOffset < info->groupSize);
    434  1.1  oster 	*col            = info->LayoutTable[BlockID][BlockOffset];
    435  1.1  oster       }
    436  1.1  oster 
    437  1.1  oster     /* remap to distributed spare space if indicated */
    438  1.1  oster     if (remap) {
    439  1.1  oster 	rf_remap_to_spare_space(layoutPtr, info, *row, FullTableID, TableID, BlockID, (base_suid) ? 1 : 0, SpareRegion, col, &outSU);
    440  1.1  oster     } else {
    441  1.1  oster 
    442  1.1  oster         outSU	    = base_suid;
    443  1.1  oster         outSU      += FullTableID * fulltable_depth;  				        /* offs to strt of FT */
    444  1.1  oster         outSU	   += SpareSpace;						        /* skip rsvd spare space */
    445  1.1  oster         outSU      += TableID * info->TableDepthInPUs * layoutPtr->SUsPerPU;   	        /* offs to strt of tble */
    446  1.1  oster         outSU      += info->OffsetTable[BlockID][BlockOffset] * layoutPtr->SUsPerPU;	/* offs to the PU */
    447  1.1  oster     }
    448  1.1  oster     outSU          += TableOffset / (info->BlocksPerTable * info->PUsPerBlock);	        /* offs to the SU within a PU */
    449  1.1  oster 
    450  1.1  oster     /* convert SUs to sectors, and, if not aligned to SU boundary, add in offset to sector */
    451  1.1  oster     *diskSector     = outSU*layoutPtr->sectorsPerStripeUnit + (raidSector % layoutPtr->sectorsPerStripeUnit);
    452  1.1  oster }
    453  1.1  oster 
    454  1.1  oster 
    455  1.1  oster void rf_MapParityDeclusteredPQ(
    456  1.1  oster   RF_Raid_t       *raidPtr,
    457  1.1  oster   RF_RaidAddr_t    raidSector,
    458  1.1  oster   RF_RowCol_t     *row,
    459  1.1  oster   RF_RowCol_t     *col,
    460  1.1  oster   RF_SectorNum_t  *diskSector,
    461  1.1  oster   int              remap)
    462  1.1  oster {
    463  1.1  oster   RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
    464  1.1  oster   RF_DeclusteredConfigInfo_t *info = (RF_DeclusteredConfigInfo_t *) layoutPtr->layoutSpecificInfo;
    465  1.1  oster   RF_StripeNum_t SUID = raidSector / layoutPtr->sectorsPerStripeUnit;
    466  1.1  oster   RF_StripeNum_t FullTableID, FullTableOffset, TableID, TableOffset;
    467  1.1  oster   RF_StripeNum_t BlockID, BlockOffset, RepIndex;
    468  1.1  oster   RF_StripeCount_t sus_per_fulltable = info->SUsPerFullTable;
    469  1.1  oster   RF_StripeCount_t fulltable_depth  = info->FullTableDepthInPUs * layoutPtr->SUsPerPU;
    470  1.1  oster   RF_StripeNum_t base_suid = 0, outSU, SpareRegion, SpareSpace=0;
    471  1.1  oster 
    472  1.1  oster   rf_decluster_adjust_params(layoutPtr, &SUID, &sus_per_fulltable, &fulltable_depth, &base_suid);
    473  1.1  oster 
    474  1.1  oster   /* compute row & (possibly) spare space exactly as before */
    475  1.1  oster   FullTableID     = SUID / sus_per_fulltable;
    476  1.1  oster   *row            = FullTableID % raidPtr->numRow;
    477  1.1  oster   FullTableID    /= raidPtr->numRow;			/* convert to fulltable ID on this disk */
    478  1.1  oster   if ((raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE)) {
    479  1.1  oster     SpareRegion = FullTableID / info->FullTablesPerSpareRegion;
    480  1.1  oster     SpareSpace  = SpareRegion * info->SpareSpaceDepthPerRegionInSUs;
    481  1.1  oster   }
    482  1.1  oster 
    483  1.1  oster   /* compute BlockID and RepIndex exactly as before */
    484  1.1  oster   FullTableOffset = SUID % sus_per_fulltable;
    485  1.1  oster   TableID         = FullTableOffset / info->SUsPerTable;
    486  1.1  oster     TableOffset     = FullTableOffset - TableID * info->SUsPerTable;
    487  1.1  oster     BlockID         = TableOffset / info->PUsPerBlock;
    488  1.1  oster     BlockOffset     = TableOffset - BlockID * info->PUsPerBlock;
    489  1.1  oster     BlockID        %= info->BlocksPerTable;
    490  1.1  oster 
    491  1.1  oster   /* the parity block is in the position indicated by RepIndex */
    492  1.1  oster   RepIndex        = (raidPtr->noRotate) ? info->PUsPerBlock : info->groupSize - 1 - TableID;
    493  1.1  oster   *col	    = info->LayoutTable[BlockID][RepIndex];
    494  1.1  oster 
    495  1.1  oster   if (remap)
    496  1.1  oster     RF_PANIC();
    497  1.1  oster 
    498  1.1  oster   /* compute sector as before, except use RepIndex instead of BlockOffset */
    499  1.1  oster   outSU        = base_suid;
    500  1.1  oster   outSU       += FullTableID * fulltable_depth;
    501  1.1  oster   outSU	+= SpareSpace;						/* skip rsvd spare space */
    502  1.1  oster   outSU       += TableID * info->TableDepthInPUs * layoutPtr->SUsPerPU;
    503  1.1  oster   outSU       += info->OffsetTable[BlockID][RepIndex] * layoutPtr->SUsPerPU;
    504  1.1  oster   outSU       += TableOffset / (info->BlocksPerTable * info->PUsPerBlock);
    505  1.1  oster 
    506  1.1  oster   *diskSector  = outSU*layoutPtr->sectorsPerStripeUnit + (raidSector % layoutPtr->sectorsPerStripeUnit);
    507  1.1  oster }
    508  1.1  oster 
    509  1.1  oster void rf_MapQDeclusteredPQ(
    510  1.1  oster   RF_Raid_t       *raidPtr,
    511  1.1  oster   RF_RaidAddr_t    raidSector,
    512  1.1  oster   RF_RowCol_t     *row,
    513  1.1  oster   RF_RowCol_t     *col,
    514  1.1  oster   RF_SectorNum_t  *diskSector,
    515  1.1  oster   int              remap)
    516  1.1  oster {
    517  1.1  oster   RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
    518  1.1  oster   RF_DeclusteredConfigInfo_t *info = (RF_DeclusteredConfigInfo_t *) layoutPtr->layoutSpecificInfo;
    519  1.1  oster   RF_StripeNum_t SUID = raidSector / layoutPtr->sectorsPerStripeUnit;
    520  1.1  oster   RF_StripeNum_t FullTableID, FullTableOffset, TableID, TableOffset;
    521  1.1  oster   RF_StripeNum_t BlockID, BlockOffset, RepIndex, RepIndexQ;
    522  1.1  oster   RF_StripeCount_t sus_per_fulltable = info->SUsPerFullTable;
    523  1.1  oster   RF_StripeCount_t fulltable_depth  = info->FullTableDepthInPUs * layoutPtr->SUsPerPU;
    524  1.1  oster   RF_StripeNum_t base_suid = 0, outSU, SpareRegion, SpareSpace=0;
    525  1.1  oster 
    526  1.1  oster   rf_decluster_adjust_params(layoutPtr, &SUID, &sus_per_fulltable, &fulltable_depth, &base_suid);
    527  1.1  oster 
    528  1.1  oster   /* compute row & (possibly) spare space exactly as before */
    529  1.1  oster   FullTableID     = SUID / sus_per_fulltable;
    530  1.1  oster   *row            = FullTableID % raidPtr->numRow;
    531  1.1  oster   FullTableID    /= raidPtr->numRow;			/* convert to fulltable ID on this disk */
    532  1.1  oster   if ((raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE)) {
    533  1.1  oster     SpareRegion = FullTableID / info->FullTablesPerSpareRegion;
    534  1.1  oster     SpareSpace  = SpareRegion * info->SpareSpaceDepthPerRegionInSUs;
    535  1.1  oster   }
    536  1.1  oster 
    537  1.1  oster   /* compute BlockID and RepIndex exactly as before */
    538  1.1  oster   FullTableOffset = SUID % sus_per_fulltable;
    539  1.1  oster   TableID         = FullTableOffset / info->SUsPerTable;
    540  1.1  oster     TableOffset     = FullTableOffset - TableID * info->SUsPerTable;
    541  1.1  oster     BlockID         = TableOffset / info->PUsPerBlock;
    542  1.1  oster     BlockOffset     = TableOffset - BlockID * info->PUsPerBlock;
    543  1.1  oster     BlockID        %= info->BlocksPerTable;
    544  1.1  oster 
    545  1.1  oster   /* the q block is in the position indicated by RepIndex */
    546  1.1  oster   RepIndex        = (raidPtr->noRotate) ? info->PUsPerBlock : info->groupSize - 1 - TableID;
    547  1.1  oster   RepIndexQ = ((RepIndex == (info->groupSize-1)) ? 0 : RepIndex+1);
    548  1.1  oster   *col = info->LayoutTable[BlockID][RepIndexQ];
    549  1.1  oster 
    550  1.1  oster   if (remap)
    551  1.1  oster     RF_PANIC();
    552  1.1  oster 
    553  1.1  oster   /* compute sector as before, except use RepIndex instead of BlockOffset */
    554  1.1  oster   outSU        = base_suid;
    555  1.1  oster   outSU       += FullTableID * fulltable_depth;
    556  1.1  oster   outSU	+= SpareSpace;						/* skip rsvd spare space */
    557  1.1  oster   outSU       += TableID * info->TableDepthInPUs * layoutPtr->SUsPerPU;
    558  1.1  oster   outSU       += TableOffset / (info->BlocksPerTable * info->PUsPerBlock);
    559  1.1  oster 
    560  1.1  oster   outSU       += info->OffsetTable[BlockID][RepIndexQ] * layoutPtr->SUsPerPU;
    561  1.1  oster   *diskSector = outSU*layoutPtr->sectorsPerStripeUnit + (raidSector % layoutPtr->sectorsPerStripeUnit);
    562  1.1  oster }
    563  1.1  oster 
    564  1.1  oster /* returns an array of ints identifying the disks that comprise the stripe containing the indicated address.
    565  1.1  oster  * the caller must _never_ attempt to modify this array.
    566  1.1  oster  */
    567  1.1  oster void rf_IdentifyStripeDeclusteredPQ(
    568  1.1  oster   RF_Raid_t        *raidPtr,
    569  1.1  oster   RF_RaidAddr_t     addr,
    570  1.1  oster   RF_RowCol_t     **diskids,
    571  1.1  oster   RF_RowCol_t      *outRow)
    572  1.1  oster {
    573  1.1  oster   RF_RaidLayout_t *layoutPtr           = &(raidPtr->Layout);
    574  1.1  oster   RF_DeclusteredConfigInfo_t *info     = (RF_DeclusteredConfigInfo_t *) layoutPtr->layoutSpecificInfo;
    575  1.1  oster   RF_StripeCount_t sus_per_fulltable = info->SUsPerFullTable;
    576  1.1  oster   RF_StripeCount_t fulltable_depth   = info->FullTableDepthInPUs * layoutPtr->SUsPerPU;
    577  1.1  oster   RF_StripeNum_t base_suid         = 0;
    578  1.1  oster   RF_StripeNum_t SUID              = rf_RaidAddressToStripeUnitID(layoutPtr, addr);
    579  1.1  oster   RF_StripeNum_t stripeID, FullTableID;
    580  1.1  oster   int tableOffset;
    581  1.1  oster 
    582  1.1  oster   rf_decluster_adjust_params(layoutPtr, &SUID, &sus_per_fulltable, &fulltable_depth, &base_suid);
    583  1.1  oster   FullTableID     = SUID / sus_per_fulltable;		/* fulltable ID within array (across rows) */
    584  1.1  oster   *outRow         = FullTableID % raidPtr->numRow;
    585  1.1  oster   stripeID = rf_StripeUnitIDToStripeID(layoutPtr, SUID);                     /* find stripe offset into array */
    586  1.1  oster   tableOffset = (stripeID % info->BlocksPerTable);                        /* find offset into block design table */
    587  1.1  oster   *diskids = info->LayoutTable[tableOffset];
    588  1.1  oster }
    589