summaryrefslogtreecommitdiff
path: root/sys/dev/raidframe/rf_disks.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/raidframe/rf_disks.c')
-rw-r--r--sys/dev/raidframe/rf_disks.c402
1 files changed, 341 insertions, 61 deletions
diff --git a/sys/dev/raidframe/rf_disks.c b/sys/dev/raidframe/rf_disks.c
index a598a218919..80aaffd87d8 100644
--- a/sys/dev/raidframe/rf_disks.c
+++ b/sys/dev/raidframe/rf_disks.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: rf_disks.c,v 1.5 2000/01/11 18:02:21 peter Exp $ */
-/* $NetBSD: rf_disks.c,v 1.14 2000/01/09 01:29:28 oster Exp $ */
+/* $OpenBSD: rf_disks.c,v 1.6 2000/08/08 16:07:40 peter Exp $ */
+/* $NetBSD: rf_disks.c,v 1.31 2000/06/02 01:17:14 oster Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -75,6 +75,12 @@
#include "rf_options.h"
#include "rf_kintf.h"
+#if defined(__NetBSD__)
+#include "rf_netbsd.h"
+#elif defined(__OpenBSD__)
+#include "rf_openbsd.h"
+#endif
+
#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
@@ -85,9 +91,11 @@
#include <sys/vnode.h>
#endif
-/* XXX these should be in a header file somewhere */
-void rf_UnconfigureVnodes( RF_Raid_t * );
-int rf_CheckLabels( RF_Raid_t *, RF_Config_t *);
+static int rf_AllocDiskStructures(RF_Raid_t *, RF_Config_t *);
+static void rf_print_label_status( RF_Raid_t *, int, int, char *,
+ RF_ComponentLabel_t *);
+static int rf_check_label_vitals( RF_Raid_t *, int, int, char *,
+ RF_ComponentLabel_t *, int, int );
#define DPRINTF6(a,b,c,d,e,f) if (rf_diskDebug) printf(a,b,c,d,e,f)
#define DPRINTF7(a,b,c,d,e,f,g) if (rf_diskDebug) printf(a,b,c,d,e,f,g)
@@ -116,54 +124,23 @@ rf_ConfigureDisks( listp, raidPtr, cfgPtr )
RF_RowCol_t r, c;
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);
- if (disks == NULL) {
- ret = ENOMEM;
+ ret = rf_AllocDiskStructures(raidPtr, cfgPtr);
+ if (ret)
goto fail;
- }
- raidPtr->Disks = disks;
- /* get space for the device-specific stuff... */
- RF_CallocAndAdd(raidPtr->raid_cinfo, raidPtr->numRow,
- sizeof(struct raidcinfo *), (struct raidcinfo **),
- raidPtr->cleanupList);
- if (raidPtr->raid_cinfo == NULL) {
- ret = ENOMEM;
- goto fail;
- }
+ disks = raidPtr->Disks;
+
for (r = 0; r < raidPtr->numRow; r++) {
numFailuresThisRow = 0;
- /* We allocate RF_MAXSPARE on the first row so that we
- have room to do hot-swapping of spares */
- RF_CallocAndAdd(disks[r], raidPtr->numCol
- + ((r == 0) ? RF_MAXSPARE : 0),
- sizeof(RF_RaidDisk_t), (RF_RaidDisk_t *),
- raidPtr->cleanupList);
- if (disks[r] == NULL) {
- ret = ENOMEM;
- goto fail;
- }
- /* get more space for device specific stuff.. */
- RF_CallocAndAdd(raidPtr->raid_cinfo[r],
- raidPtr->numCol + ((r == 0) ? raidPtr->numSpare : 0),
- sizeof(struct raidcinfo), (struct raidcinfo *),
- raidPtr->cleanupList);
- if (raidPtr->raid_cinfo[r] == NULL) {
- ret = ENOMEM;
- goto fail;
- }
for (c = 0; c < raidPtr->numCol; c++) {
ret = rf_ConfigureDisk(raidPtr,
&cfgPtr->devnames[r][c][0],
&disks[r][c], r, c);
+
if (ret)
goto fail;
@@ -186,14 +163,12 @@ rf_ConfigureDisks( listp, raidPtr, cfgPtr )
(long int) disks[r][c].numBlocks *
disks[r][c].blockSize / 1024 / 1024);
}
- num_cols_done++;
}
/* XXX fix for n-fault tolerant */
/* XXX this should probably check to see how many failures
we can handle for this configuration! */
if (numFailuresThisRow > 0)
raidPtr->status[r] = rf_rs_degraded;
- num_rows_done++;
}
/* all disks must be the same size & have the same block size, bs must
* be a power of 2 */
@@ -340,11 +315,289 @@ fail:
*/
rf_UnconfigureVnodes( raidPtr );
-
+
return (ret);
}
+static int
+rf_AllocDiskStructures(raidPtr, cfgPtr)
+ RF_Raid_t *raidPtr;
+ RF_Config_t *cfgPtr;
+{
+ RF_RaidDisk_t **disks;
+ int ret;
+ int r;
+ RF_CallocAndAdd(disks, raidPtr->numRow, sizeof(RF_RaidDisk_t *),
+ (RF_RaidDisk_t **), raidPtr->cleanupList);
+ if (disks == NULL) {
+ ret = ENOMEM;
+ goto fail;
+ }
+ raidPtr->Disks = disks;
+ /* get space for the device-specific stuff... */
+ RF_CallocAndAdd(raidPtr->raid_cinfo, raidPtr->numRow,
+ sizeof(struct raidcinfo *), (struct raidcinfo **),
+ raidPtr->cleanupList);
+ if (raidPtr->raid_cinfo == NULL) {
+ ret = ENOMEM;
+ goto fail;
+ }
+
+ for (r = 0; r < raidPtr->numRow; r++) {
+ /* We allocate RF_MAXSPARE on the first row so that we
+ have room to do hot-swapping of spares */
+ RF_CallocAndAdd(disks[r], raidPtr->numCol
+ + ((r == 0) ? RF_MAXSPARE : 0),
+ sizeof(RF_RaidDisk_t), (RF_RaidDisk_t *),
+ raidPtr->cleanupList);
+ if (disks[r] == NULL) {
+ ret = ENOMEM;
+ goto fail;
+ }
+ /* get more space for device specific stuff.. */
+ RF_CallocAndAdd(raidPtr->raid_cinfo[r],
+ raidPtr->numCol + ((r == 0) ? raidPtr->numSpare : 0),
+ sizeof(struct raidcinfo), (struct raidcinfo *),
+ raidPtr->cleanupList);
+ if (raidPtr->raid_cinfo[r] == NULL) {
+ ret = ENOMEM;
+ goto fail;
+ }
+ }
+ return(0);
+fail:
+ rf_UnconfigureVnodes( raidPtr );
+
+ return(ret);
+}
+
+
+/* configure a single disk during auto-configuration at boot */
+int
+rf_AutoConfigureDisks(raidPtr, cfgPtr, auto_config)
+ RF_Raid_t *raidPtr;
+ RF_Config_t *cfgPtr;
+ RF_AutoConfig_t *auto_config;
+{
+ RF_RaidDisk_t **disks;
+ RF_RaidDisk_t *diskPtr;
+ RF_RowCol_t r, c;
+ RF_SectorCount_t min_numblks = (RF_SectorCount_t) 0x7FFFFFFFFFFFLL;
+ int bs, ret;
+ int numFailuresThisRow;
+ int force;
+ RF_AutoConfig_t *ac;
+ int parity_good;
+ int mod_counter;
+ int mod_counter_found;
+
+#if DEBUG
+ printf("Starting autoconfiguration of RAID set...\n");
+#endif
+ force = cfgPtr->force;
+
+ ret = rf_AllocDiskStructures(raidPtr, cfgPtr);
+ if (ret)
+ goto fail;
+
+ disks = raidPtr->Disks;
+
+ /* assume the parity will be fine.. */
+ parity_good = RF_RAID_CLEAN;
+
+ /* Check for mod_counters that are too low */
+ mod_counter_found = 0;
+ ac = auto_config;
+ while(ac!=NULL) {
+ if (mod_counter_found==0) {
+ mod_counter = ac->clabel->mod_counter;
+ mod_counter_found = 1;
+ } else {
+ if (ac->clabel->mod_counter > mod_counter) {
+ mod_counter = ac->clabel->mod_counter;
+ }
+ }
+ ac->flag = 0; /* clear the general purpose flag */
+ ac = ac->next;
+ }
+
+ for (r = 0; r < raidPtr->numRow; r++) {
+ numFailuresThisRow = 0;
+ for (c = 0; c < raidPtr->numCol; c++) {
+ diskPtr = &disks[r][c];
+
+ /* find this row/col in the autoconfig */
+#if DEBUG
+ printf("Looking for %d,%d in autoconfig\n",r,c);
+#endif
+ ac = auto_config;
+ while(ac!=NULL) {
+ if (ac->clabel==NULL) {
+ /* big-time bad news. */
+ goto fail;
+ }
+ if ((ac->clabel->row == r) &&
+ (ac->clabel->column == c) &&
+ (ac->clabel->mod_counter == mod_counter)) {
+ /* it's this one... */
+ /* flag it as 'used', so we don't
+ free it later. */
+ ac->flag = 1;
+#if DEBUG
+ printf("Found: %s at %d,%d\n",
+ ac->devname,r,c);
+#endif
+
+ break;
+ }
+ ac=ac->next;
+ }
+
+ if (ac==NULL) {
+ /* we didn't find an exact match with a
+ correct mod_counter above... can we
+ find one with an incorrect mod_counter
+ to use instead? (this one, if we find
+ it, will be marked as failed once the
+ set configures)
+ */
+
+ ac = auto_config;
+ while(ac!=NULL) {
+ if (ac->clabel==NULL) {
+ /* big-time bad news. */
+ goto fail;
+ }
+ if ((ac->clabel->row == r) &&
+ (ac->clabel->column == c)) {
+ /* it's this one...
+ flag it as 'used', so we
+ don't free it later. */
+ ac->flag = 1;
+#if DEBUG
+ printf("Found(low mod_counter): %s at %d,%d\n",
+ ac->devname,r,c);
+#endif
+
+ break;
+ }
+ ac=ac->next;
+ }
+ }
+
+
+
+ if (ac!=NULL) {
+ /* Found it. Configure it.. */
+ diskPtr->blockSize = ac->clabel->blockSize;
+ diskPtr->numBlocks = ac->clabel->numBlocks;
+ /* Note: rf_protectedSectors is already
+ factored into numBlocks here */
+ raidPtr->raid_cinfo[r][c].ci_vp = ac->vp;
+ raidPtr->raid_cinfo[r][c].ci_dev = ac->dev;
+
+ memcpy(&raidPtr->raid_cinfo[r][c].ci_label,
+ ac->clabel, sizeof(*ac->clabel));
+ sprintf(diskPtr->devname, "/dev/%s",
+ ac->devname);
+
+ /* note the fact that this component was
+ autoconfigured. You'll need this info
+ later. Trust me :) */
+ diskPtr->auto_configured = 1;
+ diskPtr->dev = ac->dev;
+
+ /*
+ * 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
+ */
+
+ diskPtr->numBlocks = diskPtr->numBlocks *
+ rf_sizePercentage / 100;
+
+ /* XXX these will get set multiple times,
+ but since we're autoconfiguring, they'd
+ better be always the same each time!
+ If not, this is the least of your worries */
+
+ bs = diskPtr->blockSize;
+ min_numblks = diskPtr->numBlocks;
+
+ /* this gets done multiple times, but that's
+ fine -- the serial number will be the same
+ for all components, guaranteed */
+ raidPtr->serial_number =
+ ac->clabel->serial_number;
+ /* check the last time the label
+ was modified */
+ if (ac->clabel->mod_counter !=
+ mod_counter) {
+ /* Even though we've filled in all
+ of the above, we don't trust
+ this component since it's
+ modification counter is not
+ in sync with the rest, and we really
+ consider it to be failed. */
+ disks[r][c].status = rf_ds_failed;
+ numFailuresThisRow++;
+ } else {
+ if (ac->clabel->clean !=
+ RF_RAID_CLEAN) {
+ parity_good = RF_RAID_DIRTY;
+ }
+ }
+ } else {
+ /* Didn't find it at all!!
+ Component must really be dead */
+ disks[r][c].status = rf_ds_failed;
+ sprintf(disks[r][c].devname,"component%d",
+ r * raidPtr->numCol + c);
+ numFailuresThisRow++;
+ }
+ }
+ /* XXX fix for n-fault tolerant */
+ /* XXX this should probably check to see how many failures
+ we can handle for this configuration! */
+ if (numFailuresThisRow > 0)
+ raidPtr->status[r] = rf_rs_degraded;
+ }
+
+ /* close the device for the ones that didn't get used */
+
+ ac = auto_config;
+ while(ac!=NULL) {
+ if (ac->flag == 0) {
+ VOP_CLOSE(ac->vp, FREAD, NOCRED, 0);
+ vput(ac->vp);
+ ac->vp = NULL;
+#if DEBUG
+ printf("Released %s from auto-config set.\n",
+ ac->devname);
+#endif
+ }
+ ac = ac->next;
+ }
+
+ raidPtr->mod_counter = mod_counter;
+
+ /* note the state of the parity, if any */
+ raidPtr->parity_good = parity_good;
+ raidPtr->sectorsPerDisk = min_numblks;
+ raidPtr->logBytesPerSector = ffs(bs) - 1;
+ raidPtr->bytesPerSector = bs;
+ raidPtr->sectorMask = bs - 1;
+ return (0);
+
+fail:
+
+ rf_UnconfigureVnodes( raidPtr );
+
+ return (ret);
+
+}
/* configure a single disk in the array */
int
@@ -407,10 +660,13 @@ rf_ConfigureDisk(raidPtr, buf, diskPtr, row, col)
diskPtr->blockSize = dpart.disklab->d_secsize;
diskPtr->numBlocks = dpart.part->p_size - rf_protectedSectors;
-
+ diskPtr->partitionSize = dpart.part->p_size;
+
raidPtr->raid_cinfo[row][col].ci_vp = vp;
raidPtr->raid_cinfo[row][col].ci_dev = va.va_rdev;
+ /* This component was not automatically configured */
+ diskPtr->auto_configured = 0;
diskPtr->dev = va.va_rdev;
/* we allow the user to specify that only a fraction of the
@@ -422,9 +678,6 @@ 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;
@@ -446,8 +699,6 @@ rf_print_label_status( raidPtr, row, column, dev_name, ci_label )
ci_label->clean ? "Yes" : "No", 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;
@@ -764,13 +1015,6 @@ rf_CheckLabels( raidPtr, cfgPtr )
return(fatal_error);
}
-int config_disk_queue(RF_Raid_t *, RF_DiskQueue_t *, RF_RowCol_t,
- RF_RowCol_t, RF_DiskQueueSW_t *,
- RF_SectorCount_t, dev_t, int,
- RF_ShutdownList_t **,
- RF_AllocListElem_t *);
-
-int rf_add_hot_spare(RF_Raid_t *, RF_SingleComponent_t *);
int
rf_add_hot_spare(raidPtr, sparePtr)
RF_Raid_t *raidPtr;
@@ -782,8 +1026,10 @@ rf_add_hot_spare(raidPtr, sparePtr)
unsigned int bs;
int spare_number;
+#if 0
printf("Just in rf_add_hot_spare: %d\n",raidPtr->numSpare);
printf("Num col: %d\n",raidPtr->numCol);
+#endif
if (raidPtr->numSpare >= RF_MAXSPARE) {
RF_ERRORMSG1("Too many spares: %d\n", raidPtr->numSpare);
return(EINVAL);
@@ -843,12 +1089,13 @@ rf_add_hot_spare(raidPtr, sparePtr)
}
spareQueues = &raidPtr->Queues[0][raidPtr->numCol];
- ret = config_disk_queue( raidPtr, &spareQueues[spare_number],
+ ret = rf_ConfigureDiskQueue( raidPtr, &spareQueues[spare_number],
0, raidPtr->numCol + spare_number,
- raidPtr->Queues[0][0].qPtr, /* XXX */
+ raidPtr->qType,
raidPtr->sectorsPerDisk,
- raidPtr->Disks[0][raidPtr->numCol + spare_number].dev,
- raidPtr->Queues[0][0].maxOutstanding, /* XXX */
+ raidPtr->Disks[0][raidPtr->numCol +
+ spare_number].dev,
+ raidPtr->maxOutstanding,
&raidPtr->shutdownList,
raidPtr->cleanupList);
@@ -892,3 +1139,36 @@ rf_remove_hot_spare(raidPtr,sparePtr)
return (0);
#endif
}
+
+int
+rf_delete_component(raidPtr,component)
+ RF_Raid_t *raidPtr;
+ RF_SingleComponent_t *component;
+{
+ RF_RaidDisk_t *disks;
+
+ if ((component->row < 0) ||
+ (component->row >= raidPtr->numRow) ||
+ (component->column < 0) ||
+ (component->column >= raidPtr->numCol)) {
+ return(EINVAL);
+ }
+
+ disks = &raidPtr->Disks[component->row][component->column];
+
+ /* 1. This component must be marked as 'failed' */
+
+ return(EINVAL); /* Not implemented yet. */
+}
+
+int
+rf_incorporate_hot_spare(raidPtr,component)
+ RF_Raid_t *raidPtr;
+ RF_SingleComponent_t *component;
+{
+
+ /* Issues here include how to 'move' this in if there is IO
+ taking place (e.g. component queues and such) */
+
+ return(EINVAL); /* Not implemented yet. */
+}