Update for recent changes including component label support, clean

bits, rebuilding components in-place, adding hot spares, shutdownhooks, etc.
This commit is contained in:
oster 1999-03-02 03:18:48 +00:00
parent d17a319fc8
commit 98d8c12355
10 changed files with 1001 additions and 116 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: rf_configure.h,v 1.3 1999/02/05 00:06:06 oster Exp $ */ /* $NetBSD: rf_configure.h,v 1.4 1999/03/02 03:18:49 oster Exp $ */
/* /*
* Copyright (c) 1995 Carnegie-Mellon University. * Copyright (c) 1995 Carnegie-Mellon University.
* All rights reserved. * All rights reserved.
@ -75,6 +75,13 @@ struct RF_Config_s {
* layout-specific info */ * layout-specific info */
void *layoutSpecific; /* a pointer to a layout-specific structure to void *layoutSpecific; /* a pointer to a layout-specific structure to
* be copied in */ * be copied in */
int force; /* if !0, ignore many fatal
configuration conditions */
/*
"force" is used to override cases where the component labels would
indicate that configuration should not proceed without user
intervention
*/
}; };
#ifndef _KERNEL #ifndef _KERNEL
int rf_MakeConfig(char *configname, RF_Config_t * cfgPtr); int rf_MakeConfig(char *configname, RF_Config_t * cfgPtr);

View File

@ -1,4 +1,4 @@
/* $NetBSD: rf_copyback.c,v 1.6 1999/02/27 03:43:20 oster Exp $ */ /* $NetBSD: rf_copyback.c,v 1.7 1999/03/02 03:18:49 oster Exp $ */
/* /*
* Copyright (c) 1995 Carnegie-Mellon University. * Copyright (c) 1995 Carnegie-Mellon University.
* All rights reserved. * All rights reserved.
@ -82,13 +82,17 @@ rf_ConfigureCopyback(listp)
#include <sys/fcntl.h> #include <sys/fcntl.h>
#include <sys/vnode.h> #include <sys/vnode.h>
/* XXX these should be in a .h file somewhere */
int raidlookup __P((char *, struct proc *, struct vnode **)); int raidlookup __P((char *, struct proc *, struct vnode **));
int raidwrite_component_label(dev_t, struct vnode *, RF_ComponentLabel_t *);
int raidread_component_label(dev_t, struct vnode *, RF_ComponentLabel_t *);
/* do a complete copyback */ /* do a complete copyback */
void void
rf_CopybackReconstructedData(raidPtr) rf_CopybackReconstructedData(raidPtr)
RF_Raid_t *raidPtr; RF_Raid_t *raidPtr;
{ {
RF_ComponentLabel_t c_label;
int done, retcode; int done, retcode;
RF_CopybackDesc_t *desc; RF_CopybackDesc_t *desc;
RF_RowCol_t frow, fcol; RF_RowCol_t frow, fcol;
@ -227,6 +231,26 @@ rf_CopybackReconstructedData(raidPtr)
printf("COPYBACK: Beginning\n"); printf("COPYBACK: Beginning\n");
RF_GETTIME(desc->starttime); RF_GETTIME(desc->starttime);
rf_ContinueCopyback(desc); rf_ContinueCopyback(desc);
/* Data has been restored. Fix up the component label. */
/* Don't actually need the read here.. */
raidread_component_label( raidPtr->raid_cinfo[frow][fcol].ci_dev,
raidPtr->raid_cinfo[frow][fcol].ci_vp,
&c_label);
c_label.version = RF_COMPONENT_LABEL_VERSION;
c_label.mod_counter = raidPtr->mod_counter;
c_label.serial_number = raidPtr->serial_number;
c_label.row = frow;
c_label.column = fcol;
c_label.num_rows = raidPtr->numRow;
c_label.num_columns = raidPtr->numCol;
c_label.clean = RF_RAID_DIRTY;
c_label.status = rf_ds_optimal;
raidwrite_component_label( raidPtr->raid_cinfo[frow][fcol].ci_dev,
raidPtr->raid_cinfo[frow][fcol].ci_vp,
&c_label);
} }

View File

@ -1,4 +1,4 @@
/* $NetBSD: rf_disks.c,v 1.6 1999/02/24 00:00:03 oster Exp $ */ /* $NetBSD: rf_disks.c,v 1.7 1999/03/02 03:18:49 oster Exp $ */
/*- /*-
* Copyright (c) 1999 The NetBSD Foundation, Inc. * Copyright (c) 1999 The NetBSD Foundation, Inc.
* All rights reserved. * All rights reserved.
@ -119,9 +119,11 @@ rf_ConfigureDisks( listp, raidPtr, cfgPtr )
int bs, ret; int bs, ret;
unsigned i, count, foundone = 0, numFailuresThisRow; unsigned i, count, foundone = 0, numFailuresThisRow;
int num_rows_done, num_cols_done; int num_rows_done, num_cols_done;
int force;
num_rows_done = 0; num_rows_done = 0;
num_cols_done = 0; num_cols_done = 0;
force = cfgPtr->force;
RF_CallocAndAdd(disks, raidPtr->numRow, sizeof(RF_RaidDisk_t *), RF_CallocAndAdd(disks, raidPtr->numRow, sizeof(RF_RaidDisk_t *),
(RF_RaidDisk_t **), raidPtr->cleanupList); (RF_RaidDisk_t **), raidPtr->cleanupList);
@ -166,14 +168,14 @@ rf_ConfigureDisks( listp, raidPtr, cfgPtr )
&disks[r][c], r, c); &disks[r][c], r, c);
if (ret) if (ret)
goto fail; goto fail;
#ifdef NOT_YET_BOYS_AND_GIRLS
if (disks[r][c].status == rf_ds_optimal) { if (disks[r][c].status == rf_ds_optimal) {
raidread_component_label( raidread_component_label(
raidPtr->raid_cinfo[r][c].ci_dev, raidPtr->raid_cinfo[r][c].ci_dev,
raidPtr->raid_cinfo[r][c].ci_vp, raidPtr->raid_cinfo[r][c].ci_vp,
&raidPtr->raid_cinfo[r][c].ci_label); &raidPtr->raid_cinfo[r][c].ci_label);
} }
#endif
if (disks[r][c].status != rf_ds_optimal) { if (disks[r][c].status != rf_ds_optimal) {
numFailuresThisRow++; numFailuresThisRow++;
} else { } else {
@ -221,11 +223,17 @@ rf_ConfigureDisks( listp, raidPtr, cfgPtr )
goto fail; goto fail;
} }
#if NOT_YET_BOYS_AND_GIRLS
if (rf_CheckLabels( raidPtr, cfgPtr )) { if (rf_CheckLabels( raidPtr, cfgPtr )) {
printf("There were fatal errors (ignored for now)\n"); printf("raid%d: There were fatal errors\n", raidPtr->raidid);
if (force != 0) {
printf("raid%d: Fatal errors being ignored.\n",
raidPtr->raidid);
} else {
ret = EINVAL;
goto fail;
}
} }
#endif
for (r = 0; r < raidPtr->numRow; r++) { for (r = 0; r < raidPtr->numRow; r++) {
for (c = 0; c < raidPtr->numCol; c++) { for (c = 0; c < raidPtr->numCol; c++) {
if (disks[r][c].status == rf_ds_optimal) { if (disks[r][c].status == rf_ds_optimal) {
@ -417,6 +425,78 @@ rf_ConfigureDisk(raidPtr, buf, diskPtr, row, col)
return (0); return (0);
} }
static void rf_print_label_status( RF_Raid_t *, int, int, char *,
RF_ComponentLabel_t *);
static void
rf_print_label_status( raidPtr, row, column, dev_name, ci_label )
RF_Raid_t *raidPtr;
int row;
int column;
char *dev_name;
RF_ComponentLabel_t *ci_label;
{
printf("raid%d: Component %s being configured at row: %d col: %d\n",
raidPtr->raidid, dev_name, row, column );
printf(" Row: %d Column: %d Num Rows: %d Num Columns: %d\n",
ci_label->row, ci_label->column,
ci_label->num_rows, ci_label->num_columns);
printf(" Version: %d Serial Number: %d Mod Counter: %d\n",
ci_label->version, ci_label->serial_number,
ci_label->mod_counter);
printf(" Clean: %d Status: %d\n",
ci_label->clean, ci_label->status );
}
static int rf_check_label_vitals( RF_Raid_t *, int, int, char *,
RF_ComponentLabel_t *, int, int );
static int rf_check_label_vitals( raidPtr, row, column, dev_name, ci_label,
serial_number, mod_counter )
RF_Raid_t *raidPtr;
int row;
int column;
char *dev_name;
RF_ComponentLabel_t *ci_label;
int serial_number;
int mod_counter;
{
int fatal_error = 0;
if (serial_number != ci_label->serial_number) {
printf("%s has a different serial number: %d %d\n",
dev_name, serial_number, ci_label->serial_number);
fatal_error = 1;
}
if (mod_counter != ci_label->mod_counter) {
printf("%s has a different modfication count: %d %d\n",
dev_name, mod_counter, ci_label->mod_counter);
}
if (row != ci_label->row) {
printf("Row out of alignment for: %s\n", dev_name);
fatal_error = 1;
}
if (column != ci_label->column) {
printf("Column out of alignment for: %s\n", dev_name);
fatal_error = 1;
}
if (raidPtr->numRow != ci_label->num_rows) {
printf("Number of rows do not match for: %s\n", dev_name);
fatal_error = 1;
}
if (raidPtr->numCol != ci_label->num_columns) {
printf("Number of columns do not match for: %s\n", dev_name);
fatal_error = 1;
}
if (ci_label->clean == 0) {
/* it's not clean, but that's not fatal */
printf("%s is not clean!\n", dev_name);
}
return(fatal_error);
}
/* /*
rf_CheckLabels() - check all the component labels for consistency. rf_CheckLabels() - check all the component labels for consistency.
@ -432,80 +512,252 @@ rf_CheckLabels( raidPtr, cfgPtr )
int r,c; int r,c;
char *dev_name; char *dev_name;
RF_ComponentLabel_t *ci_label; RF_ComponentLabel_t *ci_label;
int version = 0;
int serial_number = 0; int serial_number = 0;
int mod_counter = 0; int mod_number = 0;
int fatal_error = 0; int fatal_error = 0;
int disk_num = 0; int mod_values[4];
int mod_count[4];
int ser_values[4];
int ser_count[4];
int num_ser;
int num_mod;
int i;
int found;
int hosed_row;
int hosed_column;
int too_fatal;
int parity_good;
int force;
hosed_row = -1;
hosed_column = -1;
too_fatal = 0;
force = cfgPtr->force;
/*
We're going to try to be a little intelligent here. If one
component's label is bogus, and we can identify that it's the
*only* one that's gone, we'll mark it as "failed" and allow
the configuration to proceed. This will be the *only* case
that we'll proceed if there would be (otherwise) fatal errors.
Basically we simply keep a count of how many components had
what serial number. If all but one agree, we simply mark
the disagreeing component as being failed, and allow
things to come up "normally".
We do this first for serial numbers, and then for "mod_counter".
*/
num_ser = 0;
num_mod = 0;
for (r = 0; r < raidPtr->numRow && !fatal_error ; r++) {
for (c = 0; c < raidPtr->numCol; c++) {
ci_label = &raidPtr->raid_cinfo[r][c].ci_label;
found=0;
for(i=0;i<num_ser;i++) {
if (ser_values[i] == ci_label->serial_number) {
ser_count[i]++;
found=1;
break;
}
}
if (!found) {
ser_values[num_ser] = ci_label->serial_number;
ser_count[num_ser] = 1;
num_ser++;
if (num_ser>2) {
fatal_error = 1;
break;
}
}
found=0;
for(i=0;i<num_mod;i++) {
if (mod_values[i] == ci_label->mod_counter) {
mod_count[i]++;
found=1;
break;
}
}
if (!found) {
mod_values[num_mod] = ci_label->mod_counter;
mod_count[num_mod] = 1;
num_mod++;
if (num_mod>2) {
fatal_error = 1;
break;
}
}
}
}
#if DEBUG
printf("raid%d: Summary of serial numbers:\n", raidPtr->raidid);
for(i=0;i<num_ser;i++) {
printf("%d %d\n", ser_values[i], ser_count[i]);
}
printf("raid%d: Summary of mod counters:\n", raidPtr->raidid);
for(i=0;i<num_mod;i++) {
printf("%d %d\n", mod_values[i], mod_count[i]);
}
#endif
serial_number = ser_values[0];
if (num_ser == 2) {
if ((ser_count[0] == 1) || (ser_count[1] == 1)) {
/* Locate the maverick component */
if (ser_count[1] > ser_count[0]) {
serial_number = ser_values[1];
}
for (r = 0; r < raidPtr->numRow; r++) {
for (c = 0; c < raidPtr->numCol; c++) {
ci_label = &raidPtr->raid_cinfo[r][c].ci_label;
if (serial_number !=
ci_label->serial_number) {
hosed_row = r;
hosed_column = c;
break;
}
}
}
printf("Hosed component: %s\n",
&cfgPtr->devnames[hosed_row][hosed_column][0]);
if (!force) {
/* we'll fail this component, as if there are
other major errors, we arn't forcing things
and we'll abort the config anyways */
raidPtr->Disks[hosed_row][hosed_column].status
= rf_ds_failed;
raidPtr->numFailures++;
raidPtr->status[hosed_row] = rf_rs_degraded;
}
} else {
too_fatal = 1;
}
if (cfgPtr->parityConfig == '0') {
/* We've identified two different serial numbers.
RAID 0 can't cope with that, so we'll punt */
too_fatal = 1;
}
}
/* record the serial number for later. If we bail later, setting
this doesn't matter, otherwise we've got the best guess at the
correct serial number */
raidPtr->serial_number = serial_number;
mod_number = mod_values[0];
if (num_mod == 2) {
if ((mod_count[0] == 1) || (mod_count[1] == 1)) {
/* Locate the maverick component */
if (mod_count[1] > mod_count[0]) {
mod_number = mod_values[1];
}
for (r = 0; r < raidPtr->numRow && !too_fatal ; r++) {
for (c = 0; c < raidPtr->numCol; c++) {
ci_label = &raidPtr->raid_cinfo[r][c].ci_label;
if (mod_number !=
ci_label->mod_counter) {
if ( ( hosed_row == r ) &&
( hosed_column == c )) {
/* same one. Can
deal with it. */
} else {
hosed_row = r;
hosed_column = c;
if (num_ser != 1) {
too_fatal = 1;
break;
}
}
}
}
}
printf("Hosed component: %s\n",
&cfgPtr->devnames[hosed_row][hosed_column][0]);
if (!force) {
/* we'll fail this component, as if there are
other major errors, we arn't forcing things
and we'll abort the config anyways */
raidPtr->Disks[hosed_row][hosed_column].status
= rf_ds_failed;
raidPtr->numFailures++;
raidPtr->status[hosed_row] = rf_rs_degraded;
}
} else {
too_fatal = 1;
}
if (cfgPtr->parityConfig == '0') {
/* We've identified two different mod counters.
RAID 0 can't cope with that, so we'll punt */
too_fatal = 1;
}
}
raidPtr->mod_counter = mod_number;
if (too_fatal) {
/* we've had both a serial number mismatch, and a mod_counter
mismatch -- and they involved two different components!!
Bail -- make things fail so that the user must force
the issue... */
hosed_row = -1;
hosed_column = -1;
}
if (num_ser > 2) {
printf("raid%d: Too many different serial numbers!\n",
raidPtr->raidid);
}
if (num_mod > 2) {
printf("raid%d: Too many different mod counters!\n",
raidPtr->raidid);
}
/* we start by assuming the parity will be good, and flee from
that notion at the slightest sign of trouble */
parity_good = RF_RAID_CLEAN;
for (r = 0; r < raidPtr->numRow; r++) { for (r = 0; r < raidPtr->numRow; r++) {
for (c = 0; c < raidPtr->numCol; c++) { for (c = 0; c < raidPtr->numCol; c++) {
dev_name = &cfgPtr->devnames[r][c][0]; dev_name = &cfgPtr->devnames[r][c][0];
ci_label = &raidPtr->raid_cinfo[r][c].ci_label; ci_label = &raidPtr->raid_cinfo[r][c].ci_label;
printf("Component label for %s being configured at row: %d col: %d\n", dev_name, r, c ); if ((r == hosed_row) && (c == hosed_column)) {
printf(" Row: %d Column: %d Num Rows: %d Num Columns: %d\n", ci_label->row, ci_label->column, printf("raid%d: Ignoring %s\n",
ci_label->num_rows, ci_label->num_columns); raidPtr->raidid, dev_name);
printf(" Version: %d Serial Number: %d Clean: %d Status: %d\n", ci_label->version, ci_label->serial_number, } else {
ci_label->clean, ci_label->status ); rf_print_label_status( raidPtr, r, c,
dev_name, ci_label );
if ( r !=0 && c != 0) { if (rf_check_label_vitals( raidPtr, r, c,
if (serial_number != ci_label->serial_number) { dev_name, ci_label,
printf("%s has a different %s\n", serial_number,
dev_name, "serial number!"); mod_number )) {
fatal_error = 1; fatal_error = 1;
} }
if (version != ci_label->version) { if (ci_label->clean != RF_RAID_CLEAN) {
printf("%s has a different %s\n", parity_good = RF_RAID_DIRTY;
dev_name, "version!");
fatal_error = 1;
} }
if (mod_counter != ci_label->mod_counter) {
printf("%s has a different modfication count!\n",dev_name);
}
} else {
serial_number = ci_label->serial_number;
version = ci_label->version;
mod_counter = ci_label->mod_counter;
} }
if (r != ci_label->row) {
printf("Row out of alignment for: %s\n",
dev_name);
fatal_error = 1;
}
if (c != ci_label->column) {
printf("Column out of alignment for: %s\n",
dev_name);
fatal_error = 1;
}
if (raidPtr->numRow != ci_label->num_rows) {
printf("Number of rows do not match for: %s\n",
dev_name);
fatal_error = 1;
}
if (raidPtr->numCol != ci_label->num_columns) {
printf("Number of columns do not match for: %s\n",
dev_name);
fatal_error = 1;
}
if (ci_label->clean == 0) {
/* it's not clean, but it's not fatal */
printf("%s is not clean!\n", dev_name);
}
disk_num++;
} }
} }
if (fatal_error) {
parity_good = RF_RAID_DIRTY;
}
/* we note the state of the parity */
raidPtr->parity_good = parity_good;
return(fatal_error); return(fatal_error);
} }
int rf_add_hot_spare(RF_Raid_t *, RF_HotSpare_t *); int rf_add_hot_spare(RF_Raid_t *, RF_SingleComponent_t *);
int int
rf_add_hot_spare(raidPtr, sparePtr) rf_add_hot_spare(raidPtr, sparePtr)
RF_Raid_t *raidPtr; RF_Raid_t *raidPtr;
RF_HotSpare_t *sparePtr; RF_SingleComponent_t *sparePtr;
{ {
RF_RaidDisk_t *disks; RF_RaidDisk_t *disks;
int ret; int ret;
@ -524,7 +776,7 @@ rf_add_hot_spare(raidPtr, sparePtr)
spare_number = raidPtr->numSpare; spare_number = raidPtr->numSpare;
ret = rf_ConfigureDisk(raidPtr, sparePtr->spare_name, ret = rf_ConfigureDisk(raidPtr, sparePtr->component_name,
&disks[spare_number], 0, &disks[spare_number], 0,
raidPtr->numCol + spare_number); raidPtr->numCol + spare_number);
@ -532,7 +784,7 @@ rf_add_hot_spare(raidPtr, sparePtr)
goto fail; goto fail;
if (disks[spare_number].status != rf_ds_optimal) { if (disks[spare_number].status != rf_ds_optimal) {
RF_ERRORMSG1("Warning: spare disk %s failed TUR\n", RF_ERRORMSG1("Warning: spare disk %s failed TUR\n",
sparePtr->spare_name); sparePtr->component_name);
ret=EINVAL; ret=EINVAL;
goto fail; goto fail;
} else { } else {
@ -581,7 +833,7 @@ fail:
int int
rf_remove_hot_spare(raidPtr,sparePtr) rf_remove_hot_spare(raidPtr,sparePtr)
RF_Raid_t *raidPtr; RF_Raid_t *raidPtr;
RF_HotSpare_t *sparePtr; RF_SingleComponent_t *sparePtr;
{ {
int spare_number; int spare_number;
@ -591,7 +843,7 @@ rf_remove_hot_spare(raidPtr,sparePtr)
return(EINVAL); return(EINVAL);
} }
spare_number = sparePtr->spare_number; spare_number = sparePtr->column;
return(EINVAL); /* XXX not implemented yet */ return(EINVAL); /* XXX not implemented yet */
#if 0 #if 0

View File

@ -1,4 +1,40 @@
/* $NetBSD: rf_driver.c,v 1.8 1999/02/27 03:43:20 oster Exp $ */ /* $NetBSD: rf_driver.c,v 1.9 1999/03/02 03:18:49 oster Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Greg Oster
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* /*
* Copyright (c) 1995 Carnegie-Mellon University. * Copyright (c) 1995 Carnegie-Mellon University.
* All rights reserved. * All rights reserved.
@ -113,6 +149,10 @@ static void rf_ShutdownRDFreeList(void *);
static int rf_ConfigureRDFreeList(RF_ShutdownList_t **); static int rf_ConfigureRDFreeList(RF_ShutdownList_t **);
void rf_UnconfigureVnodes( RF_Raid_t * ); void rf_UnconfigureVnodes( RF_Raid_t * );
/* XXX move these to their own .h file! */
int raidwrite_component_label(dev_t, struct vnode *, RF_ComponentLabel_t *);
int raidread_component_label(dev_t, struct vnode *, RF_ComponentLabel_t *);
int raidmarkclean(dev_t dev, struct vnode *b_vp,int);
RF_DECLARE_MUTEX(rf_printf_mutex) /* debug only: avoids interleaved RF_DECLARE_MUTEX(rf_printf_mutex) /* debug only: avoids interleaved
* printfs by different stripes */ * printfs by different stripes */
@ -141,15 +181,15 @@ RF_DECLARE_GLOBAL_THREADID /* declarations for threadid.h */
} }
#endif /* DKUSAGE > 0 */ #endif /* DKUSAGE > 0 */
static int configureCount = 0; /* number of active configurations */ static int configureCount = 0; /* number of active configurations */
static int isconfigged = 0; /* is basic raidframe (non per-array) static int isconfigged = 0; /* is basic raidframe (non per-array)
* stuff configged */ * stuff configged */
RF_DECLARE_STATIC_MUTEX(configureMutex) /* used to lock the configuration RF_DECLARE_STATIC_MUTEX(configureMutex) /* used to lock the configuration
* stuff */ * stuff */
static RF_ShutdownList_t *globalShutdown; /* non array-specific static RF_ShutdownList_t *globalShutdown; /* non array-specific
* stuff */ * stuff */
static int rf_ConfigureRDFreeList(RF_ShutdownList_t ** listp); static int rf_ConfigureRDFreeList(RF_ShutdownList_t ** listp);
/* called at system boot time */ /* called at system boot time */
int int
@ -236,6 +276,125 @@ rf_UnconfigureArray()
} }
RF_UNLOCK_MUTEX(configureMutex); RF_UNLOCK_MUTEX(configureMutex);
} }
static void rf_update_component_labels( RF_Raid_t *);
static void
rf_update_component_labels( raidPtr )
RF_Raid_t *raidPtr;
{
RF_ComponentLabel_t c_label;
int sparecol;
int r,c;
int i,j;
int srow, scol;
srow = -1;
scol = -1;
/* XXX should do extra checks to make sure things really are clean,
rather than blindly setting the clean bit... */
raidPtr->mod_counter++;
for (r = 0; r < raidPtr->numRow; r++) {
for (c = 0; c < raidPtr->numCol; c++) {
if (raidPtr->Disks[r][c].status == rf_ds_optimal) {
raidread_component_label(
raidPtr->Disks[r][c].dev,
raidPtr->raid_cinfo[r][c].ci_vp,
&c_label);
/* make sure status is noted */
c_label.status = rf_ds_optimal;
raidwrite_component_label(
raidPtr->Disks[r][c].dev,
raidPtr->raid_cinfo[r][c].ci_vp,
&c_label);
if (raidPtr->parity_good == RF_RAID_CLEAN) {
raidmarkclean(
raidPtr->Disks[r][c].dev,
raidPtr->raid_cinfo[r][c].ci_vp,
raidPtr->mod_counter);
}
}
/* else we don't touch it.. */
#if 0
else if (raidPtr->Disks[r][c].status !=
rf_ds_failed) {
raidread_component_label(
raidPtr->Disks[r][c].dev,
raidPtr->raid_cinfo[r][c].ci_vp,
&c_label);
/* make sure status is noted */
c_label.status =
raidPtr->Disks[r][c].status;
raidwrite_component_label(
raidPtr->Disks[r][c].dev,
raidPtr->raid_cinfo[r][c].ci_vp,
&c_label);
if (raidPtr->parity_good == RF_RAID_CLEAN) {
raidmarkclean(
raidPtr->Disks[r][c].dev,
raidPtr->raid_cinfo[r][c].ci_vp,
raidPtr->mod_counter);
}
}
#endif
}
}
for( c = 0; c < raidPtr->numSpare ; c++) {
sparecol = raidPtr->numCol + c;
if (raidPtr->Disks[0][sparecol].status == rf_ds_used_spare) {
/*
we claim this disk is "optimal" if it's
rf_ds_used_spare, as that means it should be
directly substitutable for the disk it replaced.
We note that too...
*/
for(i=0;i<raidPtr->numRow;i++) {
for(j=0;j<raidPtr->numCol;j++) {
if ((raidPtr->Disks[i][j].spareRow ==
0) &&
(raidPtr->Disks[i][j].spareCol ==
sparecol)) {
srow = i;
scol = j;
break;
}
}
}
raidread_component_label(
raidPtr->Disks[0][sparecol].dev,
raidPtr->raid_cinfo[0][sparecol].ci_vp,
&c_label);
/* make sure status is noted */
c_label.version = RF_COMPONENT_LABEL_VERSION;
c_label.mod_counter = raidPtr->mod_counter;
c_label.serial_number = raidPtr->serial_number;
c_label.row = srow;
c_label.column = scol;
c_label.num_rows = raidPtr->numRow;
c_label.num_columns = raidPtr->numCol;
c_label.clean = RF_RAID_DIRTY; /* changed in a bit*/
c_label.status = rf_ds_optimal;
raidwrite_component_label(
raidPtr->Disks[0][sparecol].dev,
raidPtr->raid_cinfo[0][sparecol].ci_vp,
&c_label);
if (raidPtr->parity_good == RF_RAID_CLEAN) {
raidmarkclean( raidPtr->Disks[0][sparecol].dev,
raidPtr->raid_cinfo[0][sparecol].ci_vp,
raidPtr->mod_counter);
}
}
}
}
/* /*
* Called to shut down an array. * Called to shut down an array.
*/ */
@ -269,6 +428,7 @@ rf_Shutdown(raidPtr)
raidPtr->valid = 0; raidPtr->valid = 0;
rf_update_component_labels(raidPtr);
rf_UnconfigureVnodes(raidPtr); rf_UnconfigureVnodes(raidPtr);

View File

@ -1,4 +1,4 @@
/* $NetBSD: rf_netbsd.h,v 1.4 1999/02/23 23:57:54 oster Exp $ */ /* $NetBSD: rf_netbsd.h,v 1.5 1999/03/02 03:18:48 oster Exp $ */
/*- /*-
* Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
* All rights reserved. * All rights reserved.
@ -106,16 +106,17 @@ typedef struct RF_ComponentLabel_s {
int status; /* rf_ds_optimal, rf_ds_dist_spared, whatever. */ int status; /* rf_ds_optimal, rf_ds_dist_spared, whatever. */
} RF_ComponentLabel_t; } RF_ComponentLabel_t;
typedef struct RF_HotSpare_s { typedef struct RF_SingleComponent_s {
int spare_number; int row;
char spare_name[50]; /* name of the spare disk */ int column;
} RF_HotSpare_t; char component_name[50]; /* name of the component */
} RF_SingleComponent_t;
#ifdef _KERNEL #ifdef _KERNEL
/* XXX this is *not* the place for these... */ /* XXX this is *not* the place for these... */
int rf_add_hot_spare(RF_Raid_t *raidPtr, RF_HotSpare_t *sparePtr); int rf_add_hot_spare(RF_Raid_t *raidPtr, RF_SingleComponent_t *sparePtr);
int rf_remove_hot_spare(RF_Raid_t *raidPtr, RF_HotSpare_t *sparePtr); int rf_remove_hot_spare(RF_Raid_t *raidPtr, RF_SingleComponent_t *sparePtr);
struct raidcinfo { struct raidcinfo {

View File

@ -1,4 +1,4 @@
/* $NetBSD: rf_netbsdkintf.c,v 1.11 1999/02/23 23:57:53 oster Exp $ */ /* $NetBSD: rf_netbsdkintf.c,v 1.12 1999/03/02 03:18:49 oster Exp $ */
/*- /*-
* Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
* All rights reserved. * All rights reserved.
@ -210,8 +210,10 @@ static void InitBP(struct buf * bp, struct vnode *, unsigned rw_flag,
#define Dprintf3(s,a,b,c) if (rf_queueDebug) \ #define Dprintf3(s,a,b,c) if (rf_queueDebug) \
rf_debug_printf(s,a,b,c,NULL,NULL,NULL,NULL,NULL) rf_debug_printf(s,a,b,c,NULL,NULL,NULL,NULL,NULL)
static int raidmarkclean(dev_t dev, struct vnode *b_vp); int raidmarkclean(dev_t dev, struct vnode *b_vp, int);
int raidmarkdirty(dev_t dev, struct vnode *b_vp, int);
void raid_shutdown(void *);
void raidattach __P((int)); void raidattach __P((int));
int raidsize __P((dev_t)); int raidsize __P((dev_t));
@ -254,6 +256,7 @@ struct raid_softc {
int sc_cflags; /* configuration flags */ int sc_cflags; /* configuration flags */
size_t sc_size; /* size of the raid device */ size_t sc_size; /* size of the raid device */
dev_t sc_dev; /* our device.. */ dev_t sc_dev; /* our device.. */
void * sc_sdhook; /* our shutdown hook */
char sc_xname[20]; /* XXX external name */ char sc_xname[20]; /* XXX external name */
struct disk sc_dkdev; /* generic disk device info */ struct disk sc_dkdev; /* generic disk device info */
struct pool sc_cbufpool; /* component buffer pool */ struct pool sc_cbufpool; /* component buffer pool */
@ -283,6 +286,7 @@ static int raidlock __P((struct raid_softc *));
static void raidunlock __P((struct raid_softc *)); static void raidunlock __P((struct raid_softc *));
int raidlookup __P((char *, struct proc * p, struct vnode **)); int raidlookup __P((char *, struct proc * p, struct vnode **));
static void rf_markalldirty __P((RF_Raid_t *));
void void
raidattach(num) raidattach(num)
@ -655,8 +659,9 @@ raidioctl(dev, cmd, data, flag, p)
RF_ComponentLabel_t *component_label; RF_ComponentLabel_t *component_label;
RF_ComponentLabel_t ci_label; RF_ComponentLabel_t ci_label;
RF_ComponentLabel_t **c_label_ptr; RF_ComponentLabel_t **c_label_ptr;
RF_HotSpare_t *sparePtr; RF_SingleComponent_t *sparePtr,*componentPtr;
RF_HotSpare_t hot_spare; RF_SingleComponent_t hot_spare;
RF_SingleComponent_t component;
if (unit >= numraid) if (unit >= numraid)
return (ENXIO); return (ENXIO);
@ -697,6 +702,7 @@ raidioctl(dev, cmd, data, flag, p)
case RAIDFRAME_ADD_HOT_SPARE: case RAIDFRAME_ADD_HOT_SPARE:
case RAIDFRAME_REMOVE_HOT_SPARE: case RAIDFRAME_REMOVE_HOT_SPARE:
case RAIDFRAME_INIT_LABELS: case RAIDFRAME_INIT_LABELS:
case RAIDFRAME_REBUILD_IN_PLACE:
if ((rs->sc_flags & RAIDF_INITED) == 0) if ((rs->sc_flags & RAIDF_INITED) == 0)
return (ENXIO); return (ENXIO);
} }
@ -771,6 +777,15 @@ raidioctl(dev, cmd, data, flag, p)
if (retcode == 0) { if (retcode == 0) {
retcode = raidinit(dev, raidPtrs[unit], unit); retcode = raidinit(dev, raidPtrs[unit], unit);
rf_markalldirty( raidPtrs[unit] );
/* register our shutdown hook */
if ((rs->sc_sdhook =
shutdownhook_establish(raid_shutdown,
raidPtrs[unit])) == NULL) {
printf("raid%d: WARNING: unable to establish shutdown hook\n",raidPtrs[unit]->raidid);
}
} }
/* free the buffers. No return code here. */ /* free the buffers. No return code here. */
if (k_cfg->layoutSpecificSize) { if (k_cfg->layoutSpecificSize) {
@ -808,9 +823,6 @@ raidioctl(dev, cmd, data, flag, p)
} }
raidPtrs[unit]->proc = p; /* XXX necessary evil */ raidPtrs[unit]->proc = p; /* XXX necessary evil */
#if 1
raidmarkclean( raidPtrs[unit]->Disks[0][0].dev, raidPtrs[unit]->raid_cinfo[0][0].ci_vp);
#endif
retcode = rf_Shutdown(raidPtrs[unit]); retcode = rf_Shutdown(raidPtrs[unit]);
db1_printf(("Done main shutdown\n")); db1_printf(("Done main shutdown\n"));
@ -820,6 +832,9 @@ raidioctl(dev, cmd, data, flag, p)
/* It's no longer initialized... */ /* It's no longer initialized... */
rs->sc_flags &= ~RAIDF_INITED; rs->sc_flags &= ~RAIDF_INITED;
shutdownhook_disestablish( rs->sc_sdhook );
rs->sc_sdhook = NULL;
/* Detach the disk. */ /* Detach the disk. */
disk_detach(&rs->sc_dkdev); disk_detach(&rs->sc_dkdev);
@ -893,21 +908,21 @@ raidioctl(dev, cmd, data, flag, p)
printf("Status: %d\n", component_label->status); printf("Status: %d\n", component_label->status);
row = component_label->row; row = component_label->row;
printf("Row: %d\n",row);
if (row > raidPtrs[unit]->numRow) {
row = 0; /* XXX */
}
column = component_label->column; column = component_label->column;
printf("Column: %d\n",column);
if (column > raidPtrs[unit]->numCol) { if ((row < 0) || (row > raidPtrs[unit]->numRow) ||
column = 0; /* XXX */ (column < 0) || (column > raidPtrs[unit]->numCol)) {
return(EINVAL);
} }
/* XXX this isn't allowed to do anything for now :-) */
#if 0
raidwrite_component_label( raidwrite_component_label(
raidPtrs[unit]->Disks[row][column].dev, raidPtrs[unit]->Disks[row][column].dev,
raidPtrs[unit]->raid_cinfo[row][column].ci_vp, raidPtrs[unit]->raid_cinfo[row][column].ci_vp,
component_label ); component_label );
#endif
return (retcode); return (0);
case RAIDFRAME_INIT_LABELS: case RAIDFRAME_INIT_LABELS:
component_label = (RF_ComponentLabel_t *) data; component_label = (RF_ComponentLabel_t *) data;
@ -917,9 +932,12 @@ raidioctl(dev, cmd, data, flag, p)
from the config that was used to create this RAID from the config that was used to create this RAID
set. set.
*/ */
ci_label.version = 1; /* current version number */
raidPtrs[unit]->serial_number = component_label->serial_number;
/* current version number */
ci_label.version = RF_COMPONENT_LABEL_VERSION;
ci_label.serial_number = component_label->serial_number; ci_label.serial_number = component_label->serial_number;
ci_label.mod_counter = 0; /* XXX this should be non-zero.. */ ci_label.mod_counter = raidPtrs[unit]->mod_counter;
ci_label.num_rows = raidPtrs[unit]->numRow; ci_label.num_rows = raidPtrs[unit]->numRow;
ci_label.num_columns = raidPtrs[unit]->numCol; ci_label.num_columns = raidPtrs[unit]->numCol;
ci_label.clean = RF_RAID_DIRTY; /* not clean */ ci_label.clean = RF_RAID_DIRTY; /* not clean */
@ -951,26 +969,40 @@ raidioctl(dev, cmd, data, flag, p)
if (retcode) { if (retcode) {
retcode = EIO; retcode = EIO;
} else { } else {
/* XXX set the clean bit! */ /* set the clean bit! If we shutdown correctly,
the clean bit on each component label will get
set */
raidPtrs[unit]->parity_good = RF_RAID_CLEAN;
} }
return (retcode); return (retcode);
case RAIDFRAME_ADD_HOT_SPARE: case RAIDFRAME_ADD_HOT_SPARE:
sparePtr = (RF_HotSpare_t *) data; sparePtr = (RF_SingleComponent_t *) data;
#if 0 memcpy( &hot_spare, sparePtr, sizeof(RF_SingleComponent_t));
retcode = copyin( sparePtr, &hot_spare, sizeof(RF_HotSpare_t)); printf("Adding spare\n");
#endif retcode = rf_add_hot_spare(raidPtrs[unit], &hot_spare);
memcpy( &hot_spare, sparePtr, sizeof(RF_HotSpare_t));
if (!retcode) {
printf("Adding spare\n");
retcode = rf_add_hot_spare(raidPtrs[unit], &hot_spare);
}
return(retcode); return(retcode);
case RAIDFRAME_REMOVE_HOT_SPARE: case RAIDFRAME_REMOVE_HOT_SPARE:
return(retcode); return(retcode);
case RAIDFRAME_REBUILD_IN_PLACE:
componentPtr = (RF_SingleComponent_t *) data;
memcpy( &component, componentPtr,
sizeof(RF_SingleComponent_t));
row = component.row;
column = component.column;
printf("Rebuild: %d %d\n",row, column);
if ((row < 0) || (row > raidPtrs[unit]->numRow) ||
(column < 0) || (column > raidPtrs[unit]->numCol)) {
return(EINVAL);
}
printf("Attempting a rebuild in place\n");
raidPtrs[unit]->proc = p; /* Blah... :-p GO */
retcode = rf_ReconstructInPlace(raidPtrs[unit], row, column);
return(retcode);
/* issue a test-unit-ready through raidframe to the indicated /* issue a test-unit-ready through raidframe to the indicated
* device */ * device */
#if 0 /* XXX not supported yet (ever?) */ #if 0 /* XXX not supported yet (ever?) */
@ -1069,7 +1101,8 @@ raidioctl(dev, cmd, data, flag, p)
|| rr->col < 0 || rr->col >= raidPtrs[unit]->numCol) || rr->col < 0 || rr->col >= raidPtrs[unit]->numCol)
return (EINVAL); return (EINVAL);
printf("Failing the disk: row: %d col: %d\n", rr->row, rr->col); printf("raid%d: Failing the disk: row: %d col: %d\n",
unit, rr->row, rr->col);
/* make a copy of the recon request so that we don't rely on /* make a copy of the recon request so that we don't rely on
* the user's buffer */ * the user's buffer */
@ -1277,6 +1310,28 @@ raidinit(dev, raidPtr, unit)
return (retcode); return (retcode);
} }
void
raid_shutdown(arg)
void *arg;
{
RF_Raid_t *raidPtr = arg;
struct raid_softc *rs;
/* This is called by out shutdown hook.
The lights are being turned out, so lets shutdown as
gracefully as possible */
rs = &raid_softc[raidPtr->raidid];
printf("raid%d: shutdown hooks called\n",raidPtr->raidid);
rf_Shutdown(raidPtr);
/* It's no longer initialized... */
rs->sc_flags &= ~RAIDF_INITED;
}
/********************************************************* /*********************************************************
* *
@ -1968,8 +2023,25 @@ raidunlock(rs)
#define RF_COMPONENT_INFO_SIZE 1024 /* bytes */ #define RF_COMPONENT_INFO_SIZE 1024 /* bytes */
int int
raidmarkclean(dev_t dev, struct vnode *b_vp) raidmarkclean(dev_t dev, struct vnode *b_vp, int mod_counter)
{ {
RF_ComponentLabel_t component_label;
raidread_component_label(dev, b_vp, &component_label);
component_label.mod_counter = mod_counter;
component_label.clean = RF_RAID_CLEAN;
raidwrite_component_label(dev, b_vp, &component_label);
return(0);
}
int
raidmarkdirty(dev_t dev, struct vnode *b_vp, int mod_counter)
{
RF_ComponentLabel_t component_label;
raidread_component_label(dev, b_vp, &component_label);
component_label.mod_counter = mod_counter;
component_label.clean = RF_RAID_DIRTY;
raidwrite_component_label(dev, b_vp, &component_label);
return(0); return(0);
} }
@ -2003,7 +2075,7 @@ raidread_component_label(dev, b_vp, component_label)
if (!error) { if (!error) {
memcpy(component_label, bp->b_un.b_addr, memcpy(component_label, bp->b_un.b_addr,
sizeof(RF_ComponentLabel_t)); sizeof(RF_ComponentLabel_t));
#if 1 #if 0
printf("raidread_component_label: got component label:\n"); printf("raidread_component_label: got component label:\n");
printf("Version: %d\n",component_label->version); printf("Version: %d\n",component_label->version);
printf("Serial Number: %d\n",component_label->serial_number); printf("Serial Number: %d\n",component_label->serial_number);
@ -2057,3 +2129,98 @@ raidwrite_component_label(dev, b_vp, component_label)
return(error); return(error);
} }
void
rf_markalldirty( raidPtr )
RF_Raid_t *raidPtr;
{
RF_ComponentLabel_t c_label;
int r,c;
raidPtr->mod_counter++;
for (r = 0; r < raidPtr->numRow; r++) {
for (c = 0; c < raidPtr->numCol; c++) {
if (raidPtr->Disks[r][c].status != rf_ds_failed) {
raidread_component_label(
raidPtr->Disks[r][c].dev,
raidPtr->raid_cinfo[r][c].ci_vp,
&c_label);
if (c_label.status == rf_ds_spared) {
/* XXX do something special...
but whatever you do, don't
try to access it!! */
} else {
#if 0
c_label.status =
raidPtr->Disks[r][c].status;
raidwrite_component_label(
raidPtr->Disks[r][c].dev,
raidPtr->raid_cinfo[r][c].ci_vp,
&c_label);
#endif
raidmarkdirty(
raidPtr->Disks[r][c].dev,
raidPtr->raid_cinfo[r][c].ci_vp,
raidPtr->mod_counter);
}
}
}
}
#if 0
for( c = 0; c < raidPtr->numSpare ; c++) {
sparecol = raidPtr->numCol + c;
if (raidPtr->Disks[r][sparecol].status == rf_ds_used_spare) {
/*
XXX this is where we get fancy and map this spare
into it's correct spot in the array.
*/
/*
we claim this disk is "optimal" if it's
rf_ds_used_spare, as that means it should be
directly substitutable for the disk it replaced.
We note that too...
*/
for(i=0;i<raidPtr->numRow;i++) {
for(j=0;j<raidPtr->numCol;j++) {
if ((raidPtr->Disks[i][j].spareRow ==
r) &&
(raidPtr->Disks[i][j].spareCol ==
sparecol)) {
srow = r;
scol = sparecol;
break;
}
}
}
raidread_component_label(
raidPtr->Disks[r][sparecol].dev,
raidPtr->raid_cinfo[r][sparecol].ci_vp,
&c_label);
/* make sure status is noted */
c_label.version = RF_COMPONENT_LABEL_VERSION;
c_label.mod_counter = raidPtr->mod_counter;
c_label.serial_number = raidPtr->serial_number;
c_label.row = srow;
c_label.column = scol;
c_label.num_rows = raidPtr->numRow;
c_label.num_columns = raidPtr->numCol;
c_label.clean = RF_RAID_DIRTY; /* changed in a bit*/
c_label.status = rf_ds_optimal;
raidwrite_component_label(
raidPtr->Disks[r][sparecol].dev,
raidPtr->raid_cinfo[r][sparecol].ci_vp,
&c_label);
raidmarkclean( raidPtr->Disks[r][sparecol].dev,
raidPtr->raid_cinfo[r][sparecol].ci_vp);
}
}
#endif
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: rf_raid.h,v 1.4 1999/02/23 23:57:53 oster Exp $ */ /* $NetBSD: rf_raid.h,v 1.5 1999/03/02 03:18:49 oster Exp $ */
/* /*
* Copyright (c) 1995 Carnegie-Mellon University. * Copyright (c) 1995 Carnegie-Mellon University.
* All rights reserved. * All rights reserved.
@ -59,6 +59,7 @@
#define RF_MAX_DISKS 128 /* max disks per array */ #define RF_MAX_DISKS 128 /* max disks per array */
#define RF_DEV2RAIDID(_dev) (DISKUNIT(_dev)) #define RF_DEV2RAIDID(_dev) (DISKUNIT(_dev))
#define RF_COMPONENT_LABEL_VERSION 1
#define RF_RAID_DIRTY 0 #define RF_RAID_DIRTY 0
#define RF_RAID_CLEAN 1 #define RF_RAID_CLEAN 1
@ -130,6 +131,10 @@ struct RF_Raid_s {
RF_LockTableEntry_t *lockTable; /* stripe-lock table */ RF_LockTableEntry_t *lockTable; /* stripe-lock table */
RF_LockTableEntry_t *quiesceLock; /* quiesnce table */ RF_LockTableEntry_t *quiesceLock; /* quiesnce table */
int numFailures; /* total number of failures in the array */ int numFailures; /* total number of failures in the array */
int parity_good; /* !0 if parity is known to be correct */
int serial_number; /* a "serial number" for this set */
int mod_counter; /* modification counter for component labels */
int clean; /* the clean bit for this array. */ int clean; /* the clean bit for this array. */
/* /*
* Cleanup stuff * Cleanup stuff

View File

@ -1,4 +1,4 @@
/* $NetBSD: rf_raidframe.h,v 1.4 1999/02/23 23:57:54 oster Exp $ */ /* $NetBSD: rf_raidframe.h,v 1.5 1999/03/02 03:18:48 oster Exp $ */
/* /*
* Copyright (c) 1995 Carnegie-Mellon University. * Copyright (c) 1995 Carnegie-Mellon University.
* All rights reserved. * All rights reserved.
@ -136,7 +136,8 @@ typedef struct RF_DeviceConfig_s {
#define RAIDFRAME_SET_COMPONENT_LABEL _IOW ('r', 20, RF_ComponentLabel_t) #define RAIDFRAME_SET_COMPONENT_LABEL _IOW ('r', 20, RF_ComponentLabel_t)
#define RAIDFRAME_INIT_LABELS _IOW ('r', 21, RF_ComponentLabel_t) #define RAIDFRAME_INIT_LABELS _IOW ('r', 21, RF_ComponentLabel_t)
#define RAIDFRAME_ADD_HOT_SPARE _IOW ('r', 22, RF_HotSpare_t) #define RAIDFRAME_ADD_HOT_SPARE _IOW ('r', 22, RF_SingleComponent_t)
#define RAIDFRAME_REMOVE_HOT_SPARE _IOW ('r', 23, RF_HotSpare_t) #define RAIDFRAME_REMOVE_HOT_SPARE _IOW ('r', 23, RF_SingleComponent_t)
#define RAIDFRAME_REBUILD_IN_PLACE _IOW ('r', 24, RF_SingleComponent_t)
#endif /* !_RF__RF_RAIDFRAME_H_ */ #endif /* !_RF__RF_RAIDFRAME_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: rf_reconstruct.c,v 1.4 1999/02/05 00:06:16 oster Exp $ */ /* $NetBSD: rf_reconstruct.c,v 1.5 1999/03/02 03:18:49 oster Exp $ */
/* /*
* Copyright (c) 1995 Carnegie-Mellon University. * Copyright (c) 1995 Carnegie-Mellon University.
* All rights reserved. * All rights reserved.
@ -36,6 +36,16 @@
#include <sys/time.h> #include <sys/time.h>
#include <sys/buf.h> #include <sys/buf.h>
#include <sys/errno.h> #include <sys/errno.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/ioctl.h>
#include <sys/fcntl.h>
#include <sys/vnode.h>
#include "rf_raid.h" #include "rf_raid.h"
#include "rf_reconutil.h" #include "rf_reconutil.h"
#include "rf_revent.h" #include "rf_revent.h"
@ -120,6 +130,10 @@ static void ForceReconReadDoneProc(void *arg, int status);
static void rf_ShutdownReconstruction(void *); static void rf_ShutdownReconstruction(void *);
/* XXX these should be in a .h file somewhere */
int raidlookup __P((char *, struct proc *, struct vnode **));
int raidwrite_component_label(dev_t, struct vnode *, RF_ComponentLabel_t *);
int raidread_component_label(dev_t, struct vnode *, RF_ComponentLabel_t *);
struct RF_ReconDoneProc_s { struct RF_ReconDoneProc_s {
void (*proc) (RF_Raid_t *, void *); void (*proc) (RF_Raid_t *, void *);
@ -305,6 +319,7 @@ rf_ReconstructFailedDiskBasic(raidPtr, row, col)
RF_RowCol_t row; RF_RowCol_t row;
RF_RowCol_t col; RF_RowCol_t col;
{ {
RF_ComponentLabel_t c_label;
RF_RaidDisk_t *spareDiskPtr = NULL; RF_RaidDisk_t *spareDiskPtr = NULL;
RF_RaidReconDesc_t *reconDesc; RF_RaidReconDesc_t *reconDesc;
RF_RowCol_t srow, scol; RF_RowCol_t srow, scol;
@ -354,6 +369,256 @@ rf_ReconstructFailedDiskBasic(raidPtr, row, col)
reconDesc->reconExecTicks = 0; reconDesc->reconExecTicks = 0;
reconDesc->maxReconExecTicks = 0; reconDesc->maxReconExecTicks = 0;
rc = rf_ContinueReconstructFailedDisk(reconDesc); rc = rf_ContinueReconstructFailedDisk(reconDesc);
if (!rc) {
/* fix up the component label */
/* Don't actually need the read here.. */
raidread_component_label(
raidPtr->raid_cinfo[srow][scol].ci_dev,
raidPtr->raid_cinfo[srow][scol].ci_vp,
&c_label);
c_label.version = RF_COMPONENT_LABEL_VERSION;
c_label.mod_counter = raidPtr->mod_counter;
c_label.serial_number = raidPtr->serial_number;
c_label.row = row;
c_label.column = col;
c_label.num_rows = raidPtr->numRow;
c_label.num_columns = raidPtr->numCol;
c_label.clean = RF_RAID_DIRTY;
c_label.status = rf_ds_optimal;
raidwrite_component_label(
raidPtr->raid_cinfo[srow][scol].ci_dev,
raidPtr->raid_cinfo[srow][scol].ci_vp,
&c_label);
}
return (rc);
}
/*
Allow reconstructing a disk in-place -- i.e. component /dev/sd2e goes AWOL,
and you don't get a spare until the next Monday. With this function
(and hot-swappable drives) you can now put your new disk containing
/dev/sd2e on the bus, scsictl it alive, and then use raidctl(8) to
rebuild the data "on the spot".
*/
int
rf_ReconstructInPlace(raidPtr, row, col)
RF_Raid_t *raidPtr;
RF_RowCol_t row;
RF_RowCol_t col;
{
RF_RaidDisk_t *spareDiskPtr = NULL;
RF_RaidReconDesc_t *reconDesc;
RF_LayoutSW_t *lp;
RF_RaidDisk_t *badDisk;
RF_ComponentLabel_t c_label;
int numDisksDone = 0, rc;
struct partinfo dpart;
struct vnode *vp;
struct vattr va;
struct proc *proc;
int retcode;
lp = raidPtr->Layout.map;
if (lp->SubmitReconBuffer) {
/*
* The current infrastructure only supports reconstructing one
* disk at a time for each array.
*/
RF_LOCK_MUTEX(raidPtr->mutex);
if ((raidPtr->Disks[row][col].status == rf_ds_optimal) &&
(raidPtr->numFailures > 0)) {
/* XXX 0 above shouldn't be constant!!! */
/* some component other than this has failed.
Let's not make things worse than they already
are... */
printf("RAIDFRAME: Unable to reconstruct to disk at:\n");
printf(" Row: %d Col: %d Too many failures.\n",
row, col);
RF_UNLOCK_MUTEX(raidPtr->mutex);
return (EINVAL);
}
if (raidPtr->Disks[row][col].status == rf_ds_reconstructing) {
printf("RAIDFRAME: Unable to reconstruct to disk at:\n");
printf(" Row: %d Col: %d Reconstruction already occuring!\n", row, col);
RF_UNLOCK_MUTEX(raidPtr->mutex);
return (EINVAL);
}
if (raidPtr->Disks[row][col].status != rf_ds_failed) {
/* "It's gone..." */
raidPtr->numFailures++;
raidPtr->Disks[row][col].status = rf_ds_failed;
raidPtr->status[row] = rf_rs_degraded;
}
while (raidPtr->reconInProgress) {
RF_WAIT_COND(raidPtr->waitForReconCond, raidPtr->mutex);
}
/* first look for a spare drive onto which to reconstruct
the data. spare disk descriptors are stored in row 0.
This may have to change eventually */
/* Actually, we don't care if it's failed or not...
On a RAID set with correct parity, this function
should be callable on any component without ill affects. */
/* RF_ASSERT(raidPtr->Disks[row][col].status == rf_ds_failed);
*/
if (raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE) {
RF_ERRORMSG2("Unable to reconstruct to disk at row %d col %d: operation not supported for RF_DISTRIBUTE_SPARE\n", row, col);
RF_UNLOCK_MUTEX(raidPtr->mutex);
return (EINVAL);
}
/* XXX need goop here to see if the disk is alive,
and, if not, make it so... */
badDisk = &raidPtr->Disks[row][col];
proc = raidPtr->proc; /* XXX Yes, this is not nice.. */
/* This device may have been opened successfully the
first time. Close it before trying to open it again.. */
if (raidPtr->raid_cinfo[row][col].ci_vp != NULL) {
printf("Closed the open device: %s\n",
raidPtr->Disks[row][col].devname);
VOP_UNLOCK(raidPtr->raid_cinfo[row][col].ci_vp, 0);
(void) vn_close(raidPtr->raid_cinfo[row][col].ci_vp,
FREAD | FWRITE, proc->p_ucred, proc);
raidPtr->raid_cinfo[row][col].ci_vp = NULL;
}
printf("About to (re-)open the device for rebuilding: %s\n",
raidPtr->Disks[row][col].devname);
retcode = raidlookup(raidPtr->Disks[row][col].devname,
proc, &vp);
if (retcode) {
printf("raid%d: rebuilding: raidlookup on device: %s failed: %d!\n",raidPtr->raidid,
raidPtr->Disks[row][col].devname, retcode);
/* XXX the component isn't responding properly...
must be
* still dead :-( */
RF_UNLOCK_MUTEX(raidPtr->mutex);
return(retcode);
} else {
/* Ok, so we can at least do a lookup...
How about actually getting a vp for it? */
if ((retcode = VOP_GETATTR(vp, &va, proc->p_ucred,
proc)) != 0) {
RF_UNLOCK_MUTEX(raidPtr->mutex);
return(retcode);
}
retcode = VOP_IOCTL(vp, DIOCGPART, (caddr_t) & dpart,
FREAD, proc->p_ucred, proc);
if (retcode) {
RF_UNLOCK_MUTEX(raidPtr->mutex);
return(retcode);
}
raidPtr->Disks[row][col].blockSize =
dpart.disklab->d_secsize;
raidPtr->Disks[row][col].numBlocks =
dpart.part->p_size - rf_protectedSectors;
raidPtr->raid_cinfo[row][col].ci_vp = vp;
raidPtr->raid_cinfo[row][col].ci_dev = va.va_rdev;
raidPtr->Disks[row][col].dev = va.va_rdev;
/* we allow the user to specify that only a
fraction of the disks should be used this is
just for debug: it speeds up
* the parity scan */
raidPtr->Disks[row][col].numBlocks =
raidPtr->Disks[row][col].numBlocks *
rf_sizePercentage / 100;
}
spareDiskPtr = &raidPtr->Disks[row][col];
spareDiskPtr->status = rf_ds_used_spare;
printf("RECON: initiating in-place reconstruction on\n");
printf(" row %d col %d -> spare at row %d col %d\n",
row, col, row, col);
raidPtr->reconInProgress++;
RF_UNLOCK_MUTEX(raidPtr->mutex);
reconDesc = AllocRaidReconDesc((void *) raidPtr, row, col,
spareDiskPtr, numDisksDone,
row, col);
raidPtr->reconDesc = (void *) reconDesc;
#if RF_RECON_STATS > 0
reconDesc->hsStallCount = 0;
reconDesc->numReconExecDelays = 0;
reconDesc->numReconEventWaits = 0;
#endif /* RF_RECON_STATS > 0 */
reconDesc->reconExecTimerRunning = 0;
reconDesc->reconExecTicks = 0;
reconDesc->maxReconExecTicks = 0;
rc = rf_ContinueReconstructFailedDisk(reconDesc);
} else {
RF_ERRORMSG1("RECON: no way to reconstruct failed disk for arch %c\n",
lp->parityConfig);
rc = EIO;
}
RF_LOCK_MUTEX(raidPtr->mutex);
raidPtr->reconInProgress--;
if (!rc) {
/* Need to set these here, as at this point it'll be claiming
that the disk is in rf_ds_spared! But we know better :-) */
raidPtr->Disks[row][col].status = rf_ds_optimal;
raidPtr->status[row] = rf_rs_optimal;
/* fix up the component label */
/* Don't actually need the read here.. */
raidread_component_label(raidPtr->raid_cinfo[row][col].ci_dev,
raidPtr->raid_cinfo[row][col].ci_vp,
&c_label);
c_label.version = RF_COMPONENT_LABEL_VERSION;
c_label.mod_counter = raidPtr->mod_counter;
c_label.serial_number = raidPtr->serial_number;
c_label.row = row;
c_label.column = col;
c_label.num_rows = raidPtr->numRow;
c_label.num_columns = raidPtr->numCol;
c_label.clean = RF_RAID_DIRTY;
c_label.status = rf_ds_optimal;
raidwrite_component_label(raidPtr->raid_cinfo[row][col].ci_dev,
raidPtr->raid_cinfo[row][col].ci_vp,
&c_label);
}
RF_UNLOCK_MUTEX(raidPtr->mutex);
RF_SIGNAL_COND(raidPtr->waitForReconCond);
wakeup(&raidPtr->waitForReconCond);
return (rc); return (rc);
} }

View File

@ -1,4 +1,4 @@
/* $NetBSD: rf_reconstruct.h,v 1.3 1999/02/05 00:06:16 oster Exp $ */ /* $NetBSD: rf_reconstruct.h,v 1.4 1999/03/02 03:18:48 oster Exp $ */
/* /*
* Copyright (c) 1995 Carnegie-Mellon University. * Copyright (c) 1995 Carnegie-Mellon University.
* All rights reserved. * All rights reserved.
@ -182,6 +182,9 @@ int
rf_ReconstructFailedDiskBasic(RF_Raid_t * raidPtr, RF_RowCol_t row, rf_ReconstructFailedDiskBasic(RF_Raid_t * raidPtr, RF_RowCol_t row,
RF_RowCol_t col); RF_RowCol_t col);
int
rf_ReconstructInPlace(RF_Raid_t * raidPtr, RF_RowCol_t row, RF_RowCol_t col);
int rf_ContinueReconstructFailedDisk(RF_RaidReconDesc_t * reconDesc); int rf_ContinueReconstructFailedDisk(RF_RaidReconDesc_t * reconDesc);
int int