Avoid completing I/O when dumping core after a panic.

Filesystem or pager completion callbacks are generally non-functional
after a panic and may trigger deadlocks if invoked in this context
(e.g., by attempting to destroying a buffer mapping).  To avoid this
situation, short-circuit I/O completion in biodone().

Reviewed by:	imp
Discussed with:	mav
MFC after:	2 weeks
Differential Revision:	https://reviews.freebsd.org/D15592
This commit is contained in:
Mark Johnston 2018-06-01 23:49:32 +00:00
parent 2e7680c6bf
commit 3fb14f61e1

View File

@ -4310,6 +4310,8 @@ allocbuf(struct buf *bp, int size)
extern int inflight_transient_maps; extern int inflight_transient_maps;
static struct bio_queue nondump_bios;
void void
biodone(struct bio *bp) biodone(struct bio *bp)
{ {
@ -4318,6 +4320,17 @@ biodone(struct bio *bp)
vm_offset_t start, end; vm_offset_t start, end;
biotrack(bp, __func__); biotrack(bp, __func__);
/*
* Avoid completing I/O when dumping after a panic since that may
* result in a deadlock in the filesystem or pager code. Note that
* this doesn't affect dumps that were started manually since we aim
* to keep the system usable after it has been resumed.
*/
if (__predict_false(dumping && SCHEDULER_STOPPED())) {
TAILQ_INSERT_HEAD(&nondump_bios, bp, bio_queue);
return;
}
if ((bp->bio_flags & BIO_TRANSIENT_MAPPING) != 0) { if ((bp->bio_flags & BIO_TRANSIENT_MAPPING) != 0) {
bp->bio_flags &= ~BIO_TRANSIENT_MAPPING; bp->bio_flags &= ~BIO_TRANSIENT_MAPPING;
bp->bio_flags |= BIO_UNMAPPED; bp->bio_flags |= BIO_UNMAPPED;