git: 112c453ba910 - stable/15 - geom(9): struct bio KBI fix

From: Ka Ho Ng <khng_at_FreeBSD.org>
Date: Mon, 22 Dec 2025 00:38:46 UTC
The branch stable/15 has been updated by khng:

URL: https://cgit.FreeBSD.org/src/commit/?id=112c453ba91012f19ed140c56a3ac8fc929ddabb

commit 112c453ba91012f19ed140c56a3ac8fc929ddabb
Author:     Ka Ho Ng <khng@FreeBSD.org>
AuthorDate: 2025-12-21 22:45:03 +0000
Commit:     Ka Ho Ng <khng@FreeBSD.org>
CommitDate: 2025-12-22 00:37:40 +0000

    geom(9): struct bio KBI fix
    
    The struct bio was changed after cb85c2e2e995 on the branch. To fix
    this, move BIO_ERROR flag to another value, and now BIO_ERROR_COMPAT
    occupies 0x1 instead. Also, introduce b_error_compat field at the place
    where the old bio_error was.
    
    This allows non-CAM(9) disk drivers and software volume manager modules
    compiled against 15.0-RELEASE kernel to work on 15-STABLE kernel again.
    
    Reviewed by:    kib
    Differential Revision:  https://reviews.freebsd.org/D54327
    
    Approved by:    re (cperciva)
---
 sys/geom/geom_io.c |  1 +
 sys/kern/vfs_bio.c | 21 ++++++++++++++++++++-
 sys/sys/bio.h      |  4 +++-
 3 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/sys/geom/geom_io.c b/sys/geom/geom_io.c
index 247a623bf1bf..3a58b3ec9d00 100644
--- a/sys/geom/geom_io.c
+++ b/sys/geom/geom_io.c
@@ -545,6 +545,7 @@ g_io_request(struct bio *bp, struct g_consumer *cp)
 	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),
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index 880cc6b99951..c02aa30fb03a 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -4474,6 +4474,14 @@ biodone(struct bio *bp)
 
 	biotrack(bp, __func__);
 
+	if ((bp->bio_flags & BIO_ERROR_COMPAT) != 0) {
+		/* The caller of this KPI is using the old bio(9) KBI */
+		bp->bio_error = bp->bio_error_compat;
+		bp->bio_flags |= BIO_ERROR;
+		bp->bio_error_compat = 0;
+		bp->bio_flags &= BIO_ERROR_COMPAT;
+	}
+
 	/*
 	 * Avoid completing I/O when dumping after a panic since that may
 	 * result in a deadlock in the filesystem or pager code.  Note that
@@ -4505,8 +4513,19 @@ biodone(struct bio *bp)
 		bp->bio_flags |= BIO_DONE;
 		wakeup(bp);
 		mtx_unlock(mtxp);
-	} else
+	} else {
+		if ((bp->bio_flags & BIO_ERROR) != 0) {
+			/*
+			 * Provide compatibility with the consumers of the old
+			 * bio(9) KBI filled in bio_done callback handler.
+			 */
+			bp->bio_error_compat = bp->bio_error;
+			bp->bio_flags |= BIO_ERROR_COMPAT;
+		}
 		done(bp);
+		bp->bio_error_compat = 0;
+		bp->bio_flags &= BIO_ERROR_COMPAT;
+	}
 }
 
 /*
diff --git a/sys/sys/bio.h b/sys/sys/bio.h
index 5c12c858f3e5..ae59c659e661 100644
--- 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 bio {
 	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. */