summaryrefslogtreecommitdiff
path: root/sys/dev/raidframe
diff options
context:
space:
mode:
authoroster <oster@NetBSD.org>2009-02-11 23:54:10 +0000
committeroster <oster@NetBSD.org>2009-02-11 23:54:10 +0000
commitf17e8d67c466e3bd19bb5533966bb5e5f4a04710 (patch)
tree36c1c55b3cf36559bb46ed12078b05aaa05227f6 /sys/dev/raidframe
parentcfd7bc04514dffe07d131c04dac540c09306ca7b (diff)
If we see a RF_RECON_WRITE_ERROR event we know a write has finished and
we need to account for that. Failure to do so means we can end up waiting forever for writes we think are outstanding, but which have already completed. Addresses the RAIDframe part of PR#40569. Thanks to Matthias Scheler for reporting the issue and verifying the fix.
Diffstat (limited to 'sys/dev/raidframe')
-rw-r--r--sys/dev/raidframe/rf_reconstruct.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/sys/dev/raidframe/rf_reconstruct.c b/sys/dev/raidframe/rf_reconstruct.c
index c89b5d0030e..604472625be 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.106 2008/12/20 17:04:51 oster Exp $ */
+/* $NetBSD: rf_reconstruct.c,v 1.107 2009/02/11 23:54:10 oster Exp $ */
/*
* Copyright (c) 1995 Carnegie-Mellon University.
* All rights reserved.
@@ -33,7 +33,7 @@
************************************************************/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rf_reconstruct.c,v 1.106 2008/12/20 17:04:51 oster Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rf_reconstruct.c,v 1.107 2009/02/11 23:54:10 oster Exp $");
#include <sys/param.h>
#include <sys/time.h>
@@ -676,8 +676,10 @@ rf_ContinueReconstructFailedDisk(RF_RaidReconDesc_t *reconDesc)
done dealing with the reads that are
finished, we don't want to wait for any
writes */
- if (status == RF_RECON_WRITE_ERROR)
+ if (status == RF_RECON_WRITE_ERROR) {
write_error = 1;
+ num_writes++;
+ }
} else if (status == RF_RECON_READ_STOPPED) {
/* count this component as being "done" */
@@ -718,12 +720,13 @@ rf_ContinueReconstructFailedDisk(RF_RaidReconDesc_t *reconDesc)
status = ProcessReconEvent(raidPtr, event);
if (status == RF_RECON_WRITE_ERROR) {
+ num_writes++;
recon_error = 1;
raidPtr->reconControl->error = 1;
/* an error was encountered at the very end... bail */
} else if (status == RF_RECON_WRITE_DONE) {
num_writes++;
- }
+ } /* else it's something else, and we don't care */
}
if (recon_error ||
(raidPtr->reconControl->lastPSID == lastPSID)) {
@@ -1054,6 +1057,12 @@ ProcessReconEvent(RF_Raid_t *raidPtr, RF_ReconEvent_t *event)
case RF_REVENT_WRITE_FAILED:
retcode = RF_RECON_WRITE_ERROR;
+ /* This is an error, but it was a pending write.
+ Account for it. */
+ RF_LOCK_MUTEX(raidPtr->reconControl->rb_mutex);
+ raidPtr->reconControl->pending_writes--;
+ RF_UNLOCK_MUTEX(raidPtr->reconControl->rb_mutex);
+
rbuf = (RF_ReconBuffer_t *) event->arg;
/* cleanup the disk queue data */