Module Name: src
Committed By: oster
Date: Wed Mar 3 14:23:27 UTC 2010
Modified Files:
src/sys/dev/raidframe: rf_paritymap.c
Log Message:
Don't attempt to read or write component label stuff from/to 'dead disks'.
Update used spares with the correct parity map bits too.
Addresses PR#42904 by Louis Guillaume. Fix confirmed by submitter.
Thanks!
To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/sys/dev/raidframe/rf_paritymap.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/raidframe/rf_paritymap.c
diff -u src/sys/dev/raidframe/rf_paritymap.c:1.3 src/sys/dev/raidframe/rf_paritymap.c:1.4
--- src/sys/dev/raidframe/rf_paritymap.c:1.3 Thu Nov 26 07:35:39 2009
+++ src/sys/dev/raidframe/rf_paritymap.c Wed Mar 3 14:23:27 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: rf_paritymap.c,v 1.3 2009/11/26 07:35:39 pooka Exp $ */
+/* $NetBSD: rf_paritymap.c,v 1.4 2010/03/03 14:23:27 oster Exp $ */
/*-
* Copyright (c) 2009 Jed Davis.
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rf_paritymap.c,v 1.3 2009/11/26 07:35:39 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rf_paritymap.c,v 1.4 2010/03/03 14:23:27 oster Exp $");
#include <sys/param.h>
#include <sys/callout.h>
@@ -359,12 +359,31 @@
if (todisk) {
raidPtr = pm->raid;
for (col = 0; col < raidPtr->numCol; col++) {
+ if (RF_DEAD_DISK(raidPtr->Disks[col].status))
+ continue;
+
clabel = raidget_component_label(raidPtr, col);
clabel->parity_map_ntick = cooldown;
clabel->parity_map_tickms = tickms;
clabel->parity_map_regions = regions;
+
+ /* Don't touch the disk if it's been spared */
+ if (clabel->status == rf_ds_spared)
+ continue;
+
raidflush_component_label(raidPtr, col);
}
+
+ /* handle the spares too... */
+ for (col = 0; col < raidPtr->numSpare; col++) {
+ if (raidPtr->Disks[raidPtr->numCol+col].status == rf_ds_used_spare) {
+ clabel = raidget_component_label(raidPtr, raidPtr->numCol+col);
+ clabel->parity_map_ntick = cooldown;
+ clabel->parity_map_tickms = tickms;
+ clabel->parity_map_regions = regions;
+ raidflush_component_label(raidPtr, raidPtr->numCol+col);
+ }
+ }
}
return 0;
}
@@ -603,6 +622,8 @@
*/
if (!force) {
for (col = 0; col < raidPtr->numCol; col++) {
+ if (RF_DEAD_DISK(raidPtr->Disks[col].status))
+ continue;
clabel = raidget_component_label(raidPtr, col);
flags = clabel->parity_map_flags;
/* Check for use by non-parity-map kernel. */
@@ -670,6 +691,8 @@
/* Alter labels in-core to reflect the current view of things. */
for (col = 0; col < raidPtr->numCol; col++) {
+ if (RF_DEAD_DISK(raidPtr->Disks[col].status))
+ continue;
clabel = raidget_component_label(raidPtr, col);
if (pm_use)
@@ -683,12 +706,13 @@
clabel->parity_map_regions = g_regions;
raidflush_component_label(raidPtr, col);
}
+ /* Note that we're just in 'attach' here, and there won't
+ be any spare disks at this point. */
}
/*
* For initializing the parity-map fields of a component label, both on
- * initial creation and on reconstruct/copyback/etc.
- */
+ * initial creation and on reconstruct/copyback/etc. */
void
rf_paritymap_init_label(struct rf_paritymap *pm, RF_ComponentLabel_t *clabel)
{
@@ -724,10 +748,19 @@
dis = 0;
for (col = 0; col < raidPtr->numCol; col++) {
+ if (RF_DEAD_DISK(raidPtr->Disks[col].status))
+ continue;
clabel = raidget_component_label(raidPtr, col);
if (clabel->parity_map_flags & RF_PMLABEL_DISABLE)
dis = 1;
}
+ for (col = 0; col < raidPtr->numSpare; col++) {
+ if (raidPtr->Disks[raidPtr->numCol+col].status != rf_ds_used_spare)
+ continue;
+ clabel = raidget_component_label(raidPtr, raidPtr->numCol+col);
+ if (clabel->parity_map_flags & RF_PMLABEL_DISABLE)
+ dis = 1;
+ }
return dis;
}
@@ -740,6 +773,8 @@
RF_RowCol_t col;
for (col = 0; col < raidPtr->numCol; col++) {
+ if (RF_DEAD_DISK(raidPtr->Disks[col].status))
+ continue;
clabel = raidget_component_label(raidPtr, col);
if (dis)
clabel->parity_map_flags |= RF_PMLABEL_DISABLE;
@@ -747,4 +782,17 @@
clabel->parity_map_flags &= ~RF_PMLABEL_DISABLE;
raidflush_component_label(raidPtr, col);
}
+
+ /* update any used spares as well */
+ for (col = 0; col < raidPtr->numSpare; col++) {
+ if (raidPtr->Disks[raidPtr->numCol+col].status != rf_ds_used_spare)
+ continue;
+
+ clabel = raidget_component_label(raidPtr, raidPtr->numCol+col);
+ if (dis)
+ clabel->parity_map_flags |= RF_PMLABEL_DISABLE;
+ else
+ clabel->parity_map_flags &= ~RF_PMLABEL_DISABLE;
+ raidflush_component_label(raidPtr, raidPtr->numCol+col);
+ }
}