diff --git a/sys/geom/geom_io.c b/sys/geom/geom_io.c --- a/sys/geom/geom_io.c +++ b/sys/geom/geom_io.c @@ -545,6 +545,7 @@ bp->bio_from = cp; bp->bio_to = pp; bp->bio_error = 0; + bp->bio_error_compat = 0; bp->bio_completed = 0; KASSERT(!(bp->bio_flags & BIO_ONQUEUE), @@ -617,6 +618,7 @@ cp = bp->bio_from; if (cp == NULL) { bp->bio_error = error; + bp->bio_error_compat = error; bp->bio_done(bp); return; } diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -4471,9 +4471,22 @@ struct mtx *mtxp; void (*done)(struct bio *); vm_offset_t start, end; + bool has_error, has_error_compat; biotrack(bp, __func__); + has_error = (bp->bio_flags & BIO_ERROR) != 0; + has_error_compat = (bp->bio_flags & BIO_ERROR_COMPAT) != 0; + if (has_error != has_error_compat) { + if (has_error) { + bp->bio_error_compat = bp->bio_error; + bp->bio_flags |= BIO_ERROR_COMPAT; + } else { + bp->bio_error = bp->bio_error_compat; + bp->bio_flags |= BIO_ERROR; + } + } + /* * Avoid completing I/O when dumping after a panic since that may * result in a deadlock in the filesystem or pager code. Note that diff --git a/sys/sys/bio.h b/sys/sys/bio.h --- a/sys/sys/bio.h +++ b/sys/sys/bio.h @@ -54,7 +54,7 @@ #define BIO_SPEEDUP 0x0a /* Upper layers face shortage */ /* bio_flags */ -#define BIO_ERROR 0x01 /* An error occurred processing this bio. */ +#define BIO_ERROR_COMPAT 0x01 /* KBI compat on stable/15. */ #define BIO_DONE 0x02 /* This bio is finished. */ #define BIO_ONQUEUE 0x04 /* This bio is in a queue & not yet taken. */ /* @@ -66,6 +66,7 @@ #define BIO_TRANSIENT_MAPPING 0x20 #define BIO_VLIST 0x40 #define BIO_SWAP 0x200 /* Swap-related I/O */ +#define BIO_ERROR 0x1000 /* An error occurred processing this bio. */ #define BIO_EXTERR 0x2000 #define BIO_SPEEDUP_WRITE 0x4000 /* Resource shortage at upper layers */ #define BIO_SPEEDUP_TRIM 0x8000 /* Resource shortage at upper layers */ @@ -97,6 +98,7 @@ struct vm_page **bio_ma; /* Or unmapped. */ int bio_ma_offset; /* Offset in the first page of bio_ma. */ int bio_ma_n; /* Number of pages in bio_ma. */ + int bio_error_compat; /* Error for KBI compat on stable/15 */ long bio_resid; /* Remaining I/O in bytes. */ void (*bio_done)(struct bio *); void *bio_driver1; /* Private use by the provider. */