g_vfs_done: Only report ENXIO once

The contract with the lower layers is that once ENXIO is reported, all
further I/O to the device is not possible. This is reported when the
device departs for good or changes in some material manner out from
underneath the system. Since the lower layers terminate all pending I/O
when this is detected with ENXIO, reporting more than one provides no
extra value. ENXIO suppression done with atomics due to race described
in e8827f4094. It's on the error path and a rare event, so this won't affect
performance.

Sponsored by:		Netflix
Reviewed by:		mckusick, kib
Differential Revision:	https://reviews.freebsd.org/D35034
This commit is contained in:
Warner Losh 2022-04-24 13:54:29 -06:00
parent e8827f4094
commit 347a8e93fe

View File

@ -57,6 +57,7 @@ struct g_vfs_softc {
int sc_active; int sc_active;
bool sc_orphaned; bool sc_orphaned;
int sc_enxio_active; int sc_enxio_active;
int sc_enxio_reported;
}; };
static struct buf_ops __g_vfs_bufops = { static struct buf_ops __g_vfs_bufops = {
@ -150,8 +151,13 @@ g_vfs_done(struct bio *bip)
} }
if (sc->sc_enxio_active) if (sc->sc_enxio_active)
bip->bio_error = ENXIO; bip->bio_error = ENXIO;
g_print_bio("g_vfs_done():", bip, "error = %d", if (bip->bio_error != ENXIO ||
bip->bio_error); atomic_cmpset_int(&sc->sc_enxio_reported, 0, 1)) {
g_print_bio("g_vfs_done():", bip, "error = %d%s",
bip->bio_error,
bip->bio_error != ENXIO ? "" :
" supressing further ENXIO");
}
} }
bp->b_error = bip->bio_error; bp->b_error = bip->bio_error;
bp->b_ioflags = bip->bio_flags; bp->b_ioflags = bip->bio_flags;