diff options
author | pjd <pjd@FreeBSD.org> | 2005-10-28 20:25:02 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2005-10-28 20:25:02 +0000 |
commit | 38ae497c6a8e6bd976ae5ade45c3c5a7501098fb (patch) | |
tree | 0fb226f99070f460ec90954610c9878e2fb24067 /sys | |
parent | ae56261d97de2cb2895863dca60fc73e5a52ae48 (diff) | |
download | FreeBSD-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')
-rw-r--r-- | sys/geom/raid3/g_raid3.c | 13 |
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; |