summaryrefslogtreecommitdiff
path: root/sys/dev/raidframe
diff options
context:
space:
mode:
authoroster <oster@NetBSD.org>1999-03-02 03:18:48 +0000
committeroster <oster@NetBSD.org>1999-03-02 03:18:48 +0000
commit98d8c12355f52f3ed7bb6937988cd6edfe5bf052 (patch)
tree604cc4b606cc49d12d9a70328bade5ff863955eb /sys/dev/raidframe
parentd17a319fc82e1f9937c07a376714ed64bf4eb61d (diff)
Update for recent changes including component label support, clean
bits, rebuilding components in-place, adding hot spares, shutdownhooks, etc.
Diffstat (limited to 'sys/dev/raidframe')
-rw-r--r--sys/dev/raidframe/rf_configure.h9
-rw-r--r--sys/dev/raidframe/rf_copyback.c26
-rw-r--r--sys/dev/raidframe/rf_disks.c370
-rw-r--r--sys/dev/raidframe/rf_driver.c174
-rw-r--r--sys/dev/raidframe/rf_netbsd.h15
-rw-r--r--sys/dev/raidframe/rf_netbsdkintf.c229
-rw-r--r--sys/dev/raidframe/rf_raid.h7
-rw-r--r--sys/dev/raidframe/rf_raidframe.h7
-rw-r--r--sys/dev/raidframe/rf_reconstruct.c267
-rw-r--r--sys/dev/raidframe/rf_reconstruct.h5
10 files changed, 997 insertions, 112 deletions
diff --git a/sys/dev/raidframe/rf_configure.h b/sys/dev/raidframe/rf_configure.h
index 4baa9cc3756..2577d4eaf88 100644
--- a/sys/dev/raidframe/rf_configure.h
+++ b/sys/dev/raidframe/rf_configure.h
@@ -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.
* All rights reserved.
@@ -75,6 +75,13 @@ struct RF_Config_s {
* layout-specific info */
void *layoutSpecific; /* a pointer to a layout-specific structure to
* 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
int rf_MakeConfig(char *configname, RF_Config_t * cfgPtr);
diff --git a/sys/dev/raidframe/rf_copyback.c b/sys/dev/raidframe/rf_copyback.c
index 7a4b269405d..42e52122be6 100644
--- a/sys/dev/raidframe/rf_copyback.c
+++ b/sys/dev/raidframe/rf_copyback.c
@@ -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.
* All rights reserved.
@@ -82,13 +82,17 @@ rf_ConfigureCopyback(listp)
#include <sys/fcntl.h>
#include <sys/vnode.h>
+/* 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 *);
/* do a complete copyback */
void
rf_CopybackReconstructedData(raidPtr)
RF_Raid_t *raidPtr;
{
+ RF_ComponentLabel_t c_label;
int done, retcode;
RF_CopybackDesc_t *desc;
RF_RowCol_t frow, fcol;
@@ -227,6 +231,26 @@ rf_CopybackReconstructedData(raidPtr)
printf("COPYBACK: Beginning\n");
RF_GETTIME(desc->starttime);
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);
}
diff --git a/sys/dev/raidframe/rf_disks.c b/sys/dev/raidframe/rf_disks.c
index 914b35f01e2..af717290dbd 100644
--- a/sys/dev/raidframe/rf_disks.c
+++ b/sys/dev/raidframe/rf_disks.c
@@ -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.
* All rights reserved.
@@ -119,9 +119,11 @@ rf_ConfigureDisks( listp, raidPtr, cfgPtr )
int bs, ret;
unsigned i, count, foundone = 0, numFailuresThisRow;
int num_rows_done, num_cols_done;
+ int force;
num_rows_done = 0;
num_cols_done = 0;
+ force = cfgPtr->force;
RF_CallocAndAdd(disks, raidPtr->numRow, sizeof(RF_RaidDisk_t *),
(RF_RaidDisk_t **), raidPtr->cleanupList);
@@ -166,14 +168,14 @@ rf_ConfigureDisks( listp, raidPtr, cfgPtr )
&disks[r][c], r, c);
if (ret)
goto fail;
-#ifdef NOT_YET_BOYS_AND_GIRLS
+
if (disks[r][c].status == rf_ds_optimal) {
raidread_component_label(
raidPtr->raid_cinfo[r][c].ci_dev,
raidPtr->raid_cinfo[r][c].ci_vp,
&raidPtr->raid_cinfo[r][c].ci_label);
}
-#endif
+
if (disks[r][c].status != rf_ds_optimal) {
numFailuresThisRow++;
} else {
@@ -221,11 +223,17 @@ rf_ConfigureDisks( listp, raidPtr, cfgPtr )
goto fail;
}
-#if NOT_YET_BOYS_AND_GIRLS
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 (c = 0; c < raidPtr->numCol; c++) {
if (disks[r][c].status == rf_ds_optimal) {
@@ -417,6 +425,78 @@ rf_ConfigureDisk(raidPtr, buf, diskPtr, row, col)
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.
@@ -432,80 +512,252 @@ rf_CheckLabels( raidPtr, cfgPtr )
int r,c;
char *dev_name;
RF_ComponentLabel_t *ci_label;
- int version = 0;
int serial_number = 0;
- int mod_counter = 0;
+ int mod_number = 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".
- for (r = 0; r < raidPtr->numRow; r++) {
+ */
+
+ num_ser = 0;
+ num_mod = 0;
+ for (r = 0; r < raidPtr->numRow && !fatal_error ; r++) {
for (c = 0; c < raidPtr->numCol; c++) {
- dev_name = &cfgPtr->devnames[r][c][0];
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 );
- 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 Clean: %d Status: %d\n", ci_label->version, ci_label->serial_number,
- ci_label->clean, ci_label->status );
-
- if ( r !=0 && c != 0) {
- if (serial_number != ci_label->serial_number) {
- printf("%s has a different %s\n",
- dev_name, "serial number!");
- fatal_error = 1;
+ found=0;
+ for(i=0;i<num_ser;i++) {
+ if (ser_values[i] == ci_label->serial_number) {
+ ser_count[i]++;
+ found=1;
+ break;
}
- if (version != ci_label->version) {
- printf("%s has a different %s\n",
- dev_name, "version!");
+ }
+ 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;
}
- if (mod_counter != ci_label->mod_counter) {
- printf("%s has a different modfication count!\n",dev_name);
+ }
+ found=0;
+ for(i=0;i<num_mod;i++) {
+ if (mod_values[i] == ci_label->mod_counter) {
+ mod_count[i]++;
+ found=1;
+ break;
}
- } 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 (!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 (c != ci_label->column) {
- printf("Column out of alignment for: %s\n",
- dev_name);
- fatal_error = 1;
+ }
+ }
+#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;
+ }
+ }
}
- if (raidPtr->numRow != ci_label->num_rows) {
- printf("Number of rows do not match for: %s\n",
- dev_name);
- fatal_error = 1;
+ 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;
}
- if (raidPtr->numCol != ci_label->num_columns) {
- printf("Number of columns do not match for: %s\n",
- dev_name);
- fatal_error = 1;
+ } 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;
+ }
+ }
+ }
+ }
}
- if (ci_label->clean == 0) {
- /* it's not clean, but it's not fatal */
- printf("%s is not clean!\n", dev_name);
+ 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;
}
- disk_num++;
+ } 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 (c = 0; c < raidPtr->numCol; c++) {
+ dev_name = &cfgPtr->devnames[r][c][0];
+ ci_label = &raidPtr->raid_cinfo[r][c].ci_label;
+
+ if ((r == hosed_row) && (c == hosed_column)) {
+ printf("raid%d: Ignoring %s\n",
+ raidPtr->raidid, dev_name);
+ } else {
+ rf_print_label_status( raidPtr, r, c,
+ dev_name, ci_label );
+ if (rf_check_label_vitals( raidPtr, r, c,
+ dev_name, ci_label,
+ serial_number,
+ mod_number )) {
+ fatal_error = 1;
+ }
+ if (ci_label->clean != RF_RAID_CLEAN) {
+ parity_good = RF_RAID_DIRTY;
+ }
+ }
+ }
+ }
+ if (fatal_error) {
+ parity_good = RF_RAID_DIRTY;
+ }
+
+ /* we note the state of the parity */
+ raidPtr->parity_good = parity_good;
+
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
rf_add_hot_spare(raidPtr, sparePtr)
RF_Raid_t *raidPtr;
- RF_HotSpare_t *sparePtr;
+ RF_SingleComponent_t *sparePtr;
{
RF_RaidDisk_t *disks;
int ret;
@@ -524,7 +776,7 @@ rf_add_hot_spare(raidPtr, sparePtr)
spare_number = raidPtr->numSpare;
- ret = rf_ConfigureDisk(raidPtr, sparePtr->spare_name,
+ ret = rf_ConfigureDisk(raidPtr, sparePtr->component_name,
&disks[spare_number], 0,
raidPtr->numCol + spare_number);
@@ -532,7 +784,7 @@ rf_add_hot_spare(raidPtr, sparePtr)
goto fail;
if (disks[spare_number].status != rf_ds_optimal) {
RF_ERRORMSG1("Warning: spare disk %s failed TUR\n",
- sparePtr->spare_name);
+ sparePtr->component_name);
ret=EINVAL;
goto fail;
} else {
@@ -581,7 +833,7 @@ fail:
int
rf_remove_hot_spare(raidPtr,sparePtr)
RF_Raid_t *raidPtr;
- RF_HotSpare_t *sparePtr;
+ RF_SingleComponent_t *sparePtr;
{
int spare_number;
@@ -591,7 +843,7 @@ rf_remove_hot_spare(raidPtr,sparePtr)
return(EINVAL);
}
- spare_number = sparePtr->spare_number;
+ spare_number = sparePtr->column;
return(EINVAL); /* XXX not implemented yet */
#if 0
diff --git a/sys/dev/raidframe/rf_driver.c b/sys/dev/raidframe/rf_driver.c
index 37db07c8798..b836c9f1f71 100644
--- a/sys/dev/raidframe/rf_driver.c
+++ b/sys/dev/raidframe/rf_driver.c
@@ -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.
* All rights reserved.
@@ -113,6 +149,10 @@ static void rf_ShutdownRDFreeList(void *);
static int rf_ConfigureRDFreeList(RF_ShutdownList_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
* printfs by different stripes */
@@ -141,15 +181,15 @@ RF_DECLARE_GLOBAL_THREADID /* declarations for threadid.h */
}
#endif /* DKUSAGE > 0 */
- static int configureCount = 0; /* number of active configurations */
- static int isconfigged = 0; /* is basic raidframe (non per-array)
- * stuff configged */
+static int configureCount = 0; /* number of active configurations */
+static int isconfigged = 0; /* is basic raidframe (non per-array)
+ * stuff configged */
RF_DECLARE_STATIC_MUTEX(configureMutex) /* used to lock the configuration
* stuff */
- static RF_ShutdownList_t *globalShutdown; /* non array-specific
- * stuff */
+static RF_ShutdownList_t *globalShutdown; /* non array-specific
+ * stuff */
- static int rf_ConfigureRDFreeList(RF_ShutdownList_t ** listp);
+static int rf_ConfigureRDFreeList(RF_ShutdownList_t ** listp);
/* called at system boot time */
int
@@ -236,6 +276,125 @@ rf_UnconfigureArray()
}
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.
*/
@@ -269,6 +428,7 @@ rf_Shutdown(raidPtr)
raidPtr->valid = 0;
+ rf_update_component_labels(raidPtr);
rf_UnconfigureVnodes(raidPtr);
diff --git a/sys/dev/raidframe/rf_netbsd.h b/sys/dev/raidframe/rf_netbsd.h
index a5b0ed86d26..b6d2b512d62 100644
--- a/sys/dev/raidframe/rf_netbsd.h
+++ b/sys/dev/raidframe/rf_netbsd.h
@@ -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.
* All rights reserved.
@@ -106,16 +106,17 @@ typedef struct RF_ComponentLabel_s {
int status; /* rf_ds_optimal, rf_ds_dist_spared, whatever. */
} RF_ComponentLabel_t;
-typedef struct RF_HotSpare_s {
- int spare_number;
- char spare_name[50]; /* name of the spare disk */
-} RF_HotSpare_t;
+typedef struct RF_SingleComponent_s {
+ int row;
+ int column;
+ char component_name[50]; /* name of the component */
+} RF_SingleComponent_t;
#ifdef _KERNEL
/* XXX this is *not* the place for these... */
-int rf_add_hot_spare(RF_Raid_t *raidPtr, RF_HotSpare_t *sparePtr);
-int rf_remove_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_SingleComponent_t *sparePtr);
struct raidcinfo {
diff --git a/sys/dev/raidframe/rf_netbsdkintf.c b/sys/dev/raidframe/rf_netbsdkintf.c
index d41ec9f5320..be2aaddfdbc 100644
--- a/sys/dev/raidframe/rf_netbsdkintf.c
+++ b/sys/dev/raidframe/rf_netbsdkintf.c
@@ -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.
* 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) \
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));
int raidsize __P((dev_t));
@@ -254,6 +256,7 @@ struct raid_softc {
int sc_cflags; /* configuration flags */
size_t sc_size; /* size of the raid device */
dev_t sc_dev; /* our device.. */
+ void * sc_sdhook; /* our shutdown hook */
char sc_xname[20]; /* XXX external name */
struct disk sc_dkdev; /* generic disk device info */
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 *));
int raidlookup __P((char *, struct proc * p, struct vnode **));
+static void rf_markalldirty __P((RF_Raid_t *));
void
raidattach(num)
@@ -655,8 +659,9 @@ raidioctl(dev, cmd, data, flag, p)
RF_ComponentLabel_t *component_label;
RF_ComponentLabel_t ci_label;
RF_ComponentLabel_t **c_label_ptr;
- RF_HotSpare_t *sparePtr;
- RF_HotSpare_t hot_spare;
+ RF_SingleComponent_t *sparePtr,*componentPtr;
+ RF_SingleComponent_t hot_spare;
+ RF_SingleComponent_t component;
if (unit >= numraid)
return (ENXIO);
@@ -697,6 +702,7 @@ raidioctl(dev, cmd, data, flag, p)
case RAIDFRAME_ADD_HOT_SPARE:
case RAIDFRAME_REMOVE_HOT_SPARE:
case RAIDFRAME_INIT_LABELS:
+ case RAIDFRAME_REBUILD_IN_PLACE:
if ((rs->sc_flags & RAIDF_INITED) == 0)
return (ENXIO);
}
@@ -771,6 +777,15 @@ raidioctl(dev, cmd, data, flag, p)
if (retcode == 0) {
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. */
if (k_cfg->layoutSpecificSize) {
@@ -808,9 +823,6 @@ raidioctl(dev, cmd, data, flag, p)
}
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]);
db1_printf(("Done main shutdown\n"));
@@ -820,6 +832,9 @@ raidioctl(dev, cmd, data, flag, p)
/* It's no longer initialized... */
rs->sc_flags &= ~RAIDF_INITED;
+
+ shutdownhook_disestablish( rs->sc_sdhook );
+ rs->sc_sdhook = NULL;
/* Detach the disk. */
disk_detach(&rs->sc_dkdev);
@@ -893,21 +908,21 @@ raidioctl(dev, cmd, data, flag, p)
printf("Status: %d\n", component_label->status);
row = component_label->row;
- printf("Row: %d\n",row);
- if (row > raidPtrs[unit]->numRow) {
- row = 0; /* XXX */
- }
column = component_label->column;
- printf("Column: %d\n",column);
- if (column > raidPtrs[unit]->numCol) {
- column = 0; /* XXX */
+
+ if ((row < 0) || (row > raidPtrs[unit]->numRow) ||
+ (column < 0) || (column > raidPtrs[unit]->numCol)) {
+ return(EINVAL);
}
+
+ /* XXX this isn't allowed to do anything for now :-) */
+#if 0
raidwrite_component_label(
raidPtrs[unit]->Disks[row][column].dev,
raidPtrs[unit]->raid_cinfo[row][column].ci_vp,
component_label );
-
- return (retcode);
+#endif
+ return (0);
case RAIDFRAME_INIT_LABELS:
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
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.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_columns = raidPtrs[unit]->numCol;
ci_label.clean = RF_RAID_DIRTY; /* not clean */
@@ -951,26 +969,40 @@ raidioctl(dev, cmd, data, flag, p)
if (retcode) {
retcode = EIO;
} 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);
case RAIDFRAME_ADD_HOT_SPARE:
- sparePtr = (RF_HotSpare_t *) data;
-#if 0
- retcode = copyin( sparePtr, &hot_spare, sizeof(RF_HotSpare_t));
-#endif
- memcpy( &hot_spare, sparePtr, sizeof(RF_HotSpare_t));
- if (!retcode) {
- printf("Adding spare\n");
- retcode = rf_add_hot_spare(raidPtrs[unit], &hot_spare);
- }
+ sparePtr = (RF_SingleComponent_t *) data;
+ memcpy( &hot_spare, sparePtr, sizeof(RF_SingleComponent_t));
+ printf("Adding spare\n");
+ retcode = rf_add_hot_spare(raidPtrs[unit], &hot_spare);
return(retcode);
case RAIDFRAME_REMOVE_HOT_SPARE:
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
* device */
#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)
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
* the user's buffer */
@@ -1277,6 +1310,28 @@ raidinit(dev, raidPtr, unit)
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 */
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);
}
@@ -2003,7 +2075,7 @@ raidread_component_label(dev, b_vp, component_label)
if (!error) {
memcpy(component_label, bp->b_un.b_addr,
sizeof(RF_ComponentLabel_t));
-#if 1
+#if 0
printf("raidread_component_label: got component label:\n");
printf("Version: %d\n",component_label->version);
printf("Serial Number: %d\n",component_label->serial_number);
@@ -2057,3 +2129,98 @@ raidwrite_component_label(dev, b_vp, component_label)
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
+}
+
diff --git a/sys/dev/raidframe/rf_raid.h b/sys/dev/raidframe/rf_raid.h
index 1af6083ff6c..489d028e5d5 100644
--- a/sys/dev/raidframe/rf_raid.h
+++ b/sys/dev/raidframe/rf_raid.h
@@ -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.
* All rights reserved.
@@ -59,6 +59,7 @@
#define RF_MAX_DISKS 128 /* max disks per array */
#define RF_DEV2RAIDID(_dev) (DISKUNIT(_dev))
+#define RF_COMPONENT_LABEL_VERSION 1
#define RF_RAID_DIRTY 0
#define RF_RAID_CLEAN 1
@@ -130,6 +131,10 @@ struct RF_Raid_s {
RF_LockTableEntry_t *lockTable; /* stripe-lock table */
RF_LockTableEntry_t *quiesceLock; /* quiesnce table */
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. */
/*
* Cleanup stuff
diff --git a/sys/dev/raidframe/rf_raidframe.h b/sys/dev/raidframe/rf_raidframe.h
index 826862f8c7e..8cc0b13fbd3 100644
--- a/sys/dev/raidframe/rf_raidframe.h
+++ b/sys/dev/raidframe/rf_raidframe.h
@@ -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.
* 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_INIT_LABELS _IOW ('r', 21, RF_ComponentLabel_t)
-#define RAIDFRAME_ADD_HOT_SPARE _IOW ('r', 22, RF_HotSpare_t)
-#define RAIDFRAME_REMOVE_HOT_SPARE _IOW ('r', 23, RF_HotSpare_t)
+#define RAIDFRAME_ADD_HOT_SPARE _IOW ('r', 22, RF_SingleComponent_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_ */
diff --git a/sys/dev/raidframe/rf_reconstruct.c b/sys/dev/raidframe/rf_reconstruct.c
index 3a778deee93..e56f2ffe55a 100644
--- a/sys/dev/raidframe/rf_reconstruct.c
+++ b/sys/dev/raidframe/rf_reconstruct.c
@@ -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.
* All rights reserved.
@@ -36,6 +36,16 @@
#include <sys/time.h>
#include <sys/buf.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_reconutil.h"
#include "rf_revent.h"
@@ -120,6 +130,10 @@ static void ForceReconReadDoneProc(void *arg, int status);
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 {
void (*proc) (RF_Raid_t *, void *);
@@ -305,6 +319,7 @@ rf_ReconstructFailedDiskBasic(raidPtr, row, col)
RF_RowCol_t row;
RF_RowCol_t col;
{
+ RF_ComponentLabel_t c_label;
RF_RaidDisk_t *spareDiskPtr = NULL;
RF_RaidReconDesc_t *reconDesc;
RF_RowCol_t srow, scol;
@@ -354,6 +369,256 @@ rf_ReconstructFailedDiskBasic(raidPtr, row, col)
reconDesc->reconExecTicks = 0;
reconDesc->maxReconExecTicks = 0;
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);
}
diff --git a/sys/dev/raidframe/rf_reconstruct.h b/sys/dev/raidframe/rf_reconstruct.h
index ae97c39f3a5..b7514326c47 100644
--- a/sys/dev/raidframe/rf_reconstruct.h
+++ b/sys/dev/raidframe/rf_reconstruct.h
@@ -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.
* All rights reserved.
@@ -182,6 +182,9 @@ int
rf_ReconstructFailedDiskBasic(RF_Raid_t * raidPtr, RF_RowCol_t row,
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