git: 78376b16a4ba - main - gconcat: Add rotation rate support

From: Alexander Motin <mav_at_FreeBSD.org>
Date: Wed, 26 Aug 2026 00:18:05 UTC
The branch main has been updated by mav:

URL: https://cgit.FreeBSD.org/src/commit/?id=78376b16a4ba1eed0f804c493e2c715ccb57b165

commit 78376b16a4ba1eed0f804c493e2c715ccb57b165
Author:     Alexander Motin <mav@FreeBSD.org>
AuthorDate: 2026-08-26 00:14:11 +0000
Commit:     Alexander Motin <mav@FreeBSD.org>
CommitDate: 2026-08-26 00:14:11 +0000

    gconcat: Add rotation rate support
    
    If all member devices report the same rotation rate, pass it up.
---
 sys/geom/concat/g_concat.c | 41 ++++++++++++++++++++++++++++++++++++++++-
 sys/geom/concat/g_concat.h |  1 +
 2 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/sys/geom/concat/g_concat.c b/sys/geom/concat/g_concat.c
index 5461c6dd73d3..8f39eeff5ce2 100644
--- a/sys/geom/concat/g_concat.c
+++ b/sys/geom/concat/g_concat.c
@@ -39,6 +39,7 @@
 #include <sys/malloc.h>
 #include <geom/geom.h>
 #include <geom/geom_dbg.h>
+#include <geom/geom_disk.h>
 #include <geom/concat/g_concat.h>
 
 FEATURE(geom_concat, "GEOM concatenation support");
@@ -228,6 +229,30 @@ g_concat_candelete(struct bio *bp)
 	g_handleattr(bp, "GEOM::candelete", &val, sizeof(val));
 }
 
+static void
+g_concat_rotation_rate(struct bio *bp)
+{
+	struct g_concat_softc *sc;
+	struct g_concat_disk *disk;
+	uint16_t rr = DISK_RR_UNKNOWN;
+	bool first = true;
+
+	sc = bp->bio_to->geom->softc;
+	sx_assert(&sc->sc_disks_lock, SX_LOCKED);
+	TAILQ_FOREACH(disk, &sc->sc_disks, d_next) {
+		if (disk->d_removed)
+			continue;
+		if (first)
+			rr = disk->d_rotation_rate;
+		else if (rr != disk->d_rotation_rate) {
+			rr = DISK_RR_UNKNOWN;
+			break;
+		}
+		first = false;
+	}
+	g_handleattr(bp, "GEOM::rotation_rate", &rr, sizeof(rr));
+}
+
 static void
 g_concat_kernel_dump(struct bio *bp)
 {
@@ -360,6 +385,10 @@ g_concat_start(struct bio *bp)
 		} else if (strcmp("GEOM::candelete", bp->bio_attribute) == 0) {
 			g_concat_candelete(bp);
 			goto end;
+		} else if (strcmp("GEOM::rotation_rate",
+		    bp->bio_attribute) == 0) {
+			g_concat_rotation_rate(bp);
+			goto end;
 		}
 		/* To which provider it should be delivered? */
 		/* FALLTHROUGH */
@@ -465,6 +494,10 @@ g_concat_check_and_run(struct g_concat_softc *sc)
 			    &disk->d_candelete);
 			if (error != 0)
 				disk->d_candelete = 0;
+			error = g_getattr("GEOM::rotation_rate",
+			    disk->d_consumer, &disk->d_rotation_rate);
+			if (error != 0)
+				disk->d_rotation_rate = DISK_RR_UNKNOWN;
 			(void)g_access(disk->d_consumer, -1, 0, 0);
 		} else
 			G_CONCAT_DEBUG(1, "Failed to access disk %s, error %d.",
@@ -1060,7 +1093,8 @@ g_concat_ctl_append(struct gctl_req *req, struct g_class *mp)
 	struct g_concat_disk *disk;
 	int *nargs, *hardcode;
 	int error;
-	int disk_candelete;
+	int disk_candelete = 0;
+	uint16_t disk_rotation_rate = DISK_RR_UNKNOWN;
 
 	g_topology_assert();
 
@@ -1141,6 +1175,10 @@ g_concat_ctl_append(struct gctl_req *req, struct g_class *mp)
 		error = g_getattr("GEOM::candelete", cp, &disk_candelete);
 		if (error != 0)
 			disk_candelete = 0;
+		error = g_getattr("GEOM::rotation_rate", cp,
+		    &disk_rotation_rate);
+		if (error != 0)
+			disk_rotation_rate = DISK_RR_UNKNOWN;
 		(void)g_access(cp, -1, 0, 0);
 	} else
 		G_CONCAT_DEBUG(1, "Failed to access disk %s, error %d.", name, error);
@@ -1162,6 +1200,7 @@ g_concat_ctl_append(struct gctl_req *req, struct g_class *mp)
 	disk->d_start = TAILQ_LAST(&sc->sc_disks, g_concat_disks)->d_end;
 	disk->d_end = disk->d_start + cp->provider->mediasize;
 	disk->d_candelete = disk_candelete;
+	disk->d_rotation_rate = disk_rotation_rate;
 	disk->d_removed = 0;
 	disk->d_hardcoded = *hardcode;
 	cp->private = disk;
diff --git a/sys/geom/concat/g_concat.h b/sys/geom/concat/g_concat.h
index 68bfe40ee6a1..702a06c054e0 100644
--- a/sys/geom/concat/g_concat.h
+++ b/sys/geom/concat/g_concat.h
@@ -59,6 +59,7 @@ struct g_concat_disk {
 	off_t			 d_start;
 	off_t			 d_end;
 	int			 d_candelete;
+	uint16_t		 d_rotation_rate;
 	int			 d_removed;
 	bool			 d_hardcoded;
 };