Update for recent changes including component label support, clean
bits, rebuilding components in-place, adding hot spares, shutdownhooks, etc.
This commit is contained in:
parent
d17a319fc8
commit
98d8c12355
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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_ */
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue