summaryrefslogtreecommitdiffstats
path: root/sys/geom/raid3
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2005-10-28 20:25:02 +0000
committerpjd <pjd@FreeBSD.org>2005-10-28 20:25:02 +0000
commit38ae497c6a8e6bd976ae5ade45c3c5a7501098fb (patch)
tree0fb226f99070f460ec90954610c9878e2fb24067 /sys/geom/raid3
parentae56261d97de2cb2895863dca60fc73e5a52ae48 (diff)
downloadFreeBSD-src-38ae497c6a8e6bd976ae5ade45c3c5a7501098fb.zip
FreeBSD-src-38ae497c6a8e6bd976ae5ade45c3c5a7501098fb.tar.gz
Fix possible live-lock under heavy load where we can't allocate more
memory for request. I was sure graid3 should handle such situations well, but green@ reported it is not and we want to fix it before 6.0. Submitted by: green
Diffstat (limited to 'sys/geom/raid3')
-rw-r--r--sys/geom/raid3/g_raid3.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/sys/geom/raid3/g_raid3.c b/sys/geom/raid3/g_raid3.c
index e60bf9b..65f4c0f 100644
--- a/sys/geom/raid3/g_raid3.c
+++ b/sys/geom/raid3/g_raid3.c
@@ -966,7 +966,7 @@ g_raid3_clone_bio(struct g_raid3_softc *sc, struct bio *pbp)
if (cbp->bio_data == NULL) {
if (size > 16384)
g_raid3_64k_failed++;
- if (size > 4096)
+ else if (size > 4096)
g_raid3_16k_failed++;
else
g_raid3_4k_failed++;
@@ -1560,6 +1560,17 @@ g_raid3_register_request(struct bio *pbp)
if (cbp == NULL) {
while ((cbp = G_RAID3_HEAD_BIO(pbp)) != NULL)
g_raid3_destroy_bio(sc, cbp);
+ /*
+ * To prevent deadlock, we must run back up
+ * with the ENOMEM for failed requests of any
+ * of our consumers. Our own sync requests
+ * can stick around, as they are finite.
+ */
+ if ((pbp->bio_cflags &
+ G_RAID3_BIO_CFLAG_REGULAR) != 0) {
+ g_io_deliver(pbp, ENOMEM);
+ return (0);
+ }
return (ENOMEM);
}
cbp->bio_offset = offset;
OpenPOWER on IntegriCloud