Index: sys/dev/md/md.c =================================================================== --- sys/dev/md/md.c +++ sys/dev/md/md.c @@ -92,7 +92,7 @@ #include #include #include -#include +#include #include #include @@ -1230,6 +1230,10 @@ error = -1; else if (g_handleattr_int(bp, "MNT::verified", isv)) error = -1; + else if (strcmp("GEOM::media", bp->bio_attribute) + == 0) + atomic_set_long((long *)bp->bio_data, + _PC_MEDIA_MEMORY); else error = EOPNOTSUPP; } else { Index: sys/geom/geom_disk.c =================================================================== --- sys/geom/geom_disk.c +++ sys/geom/geom_disk.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -225,6 +226,33 @@ } static void +g_disk_media(struct bio *bp, struct disk *dp) +{ + long mediaword = 0; + + if (dp->d_rotation_rate > DISK_RR_NON_ROTATING) + mediaword |= _PC_MEDIA_SPINNING; + else if (dp->d_rotation_rate == DISK_RR_NON_ROTATING) + mediaword |= _PC_MEDIA_SOLID; + + /* + * XXXGL: This is ugly. + */ + if (strncmp(dp->d_name, "nvd", 3) == 0) + mediaword |= _PC_MEDIA_NVME; + else if (strncmp(dp->d_name, "ada", 3) == 0) + mediaword |= _PC_MEDIA_ATA; + else if (strncmp(dp->d_name, "da", 2) == 0) + mediaword |= _PC_MEDIA_SCSI; + else if (strncmp(dp->d_name, "vtbd", 4) == 0) + mediaword |= _PC_MEDIA_VIRTUAL; + + atomic_set_long((long *)bp->bio_data, mediaword); + + g_io_deliver(bp, 0); +} + +static void g_disk_done(struct bio *bp) { struct bintime now; @@ -525,6 +553,8 @@ g_disk_kerneldump(bp, dp); else if (!strcmp(bp->bio_attribute, "GEOM::setstate")) g_disk_setstate(bp, sc); + else if (!strcmp(bp->bio_attribute, "GEOM::media")) + g_disk_media(bp, dp); else if (g_handleattr_uint16_t(bp, "GEOM::rotation_rate", dp->d_rotation_rate)) break; Index: sys/geom/mirror/g_mirror.c =================================================================== --- sys/geom/mirror/g_mirror.c +++ sys/geom/mirror/g_mirror.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -1119,6 +1120,27 @@ } static void +g_mirror_media(struct bio *bp) +{ + struct g_mirror_softc *sc; + struct g_mirror_disk *disk; + struct bio *cbp; + + atomic_set_long((long *)bp->bio_data, _PC_MEDIA_MIRROR); + + sc = bp->bio_to->private; + LIST_FOREACH(disk, &sc->sc_disks, d_next) { + cbp = g_clone_bio(bp); + if (cbp == NULL) { + g_io_deliver(bp, ENOMEM); + return; + } + cbp->bio_done = g_std_done; + g_io_request(cbp, disk->d_consumer); + } +} + +static void g_mirror_start(struct bio *bp) { struct g_mirror_softc *sc; @@ -1145,6 +1167,9 @@ return; } else if (strcmp("GEOM::kerneldump", bp->bio_attribute) == 0) { g_mirror_kernel_dump(bp); + return; + } else if (strcmp("GEOM::media", bp->bio_attribute) == 0) { + g_mirror_media(bp); return; } /* FALLTHROUGH */ Index: sys/geom/stripe/g_stripe.c =================================================================== --- sys/geom/stripe/g_stripe.c +++ sys/geom/stripe/g_stripe.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -569,6 +570,27 @@ } static void +g_stripe_media(struct bio *bp) +{ + struct g_stripe_softc *sc; + struct bio *cbp; + u_int no; + + atomic_set_long((long *)bp->bio_data, _PC_MEDIA_STRIPE); + + sc = bp->bio_to->geom->softc; + for (no = 0; no < sc->sc_ndisks; no++) { + cbp = g_clone_bio(bp); + if (cbp == NULL) { + g_io_deliver(bp, ENOMEM); + return; + } + cbp->bio_done = g_std_done; + g_io_request(cbp, sc->sc_disks[no]); + } +} + +static void g_stripe_start(struct bio *bp) { off_t offset, start, length, nstripe; @@ -596,6 +618,10 @@ g_stripe_flush(sc, bp); return; case BIO_GETATTR: + if (strcmp("GEOM::media", bp->bio_attribute) == 0) { + g_stripe_media(bp); + return; + } /* To which provider it should be delivered? */ default: g_io_deliver(bp, EOPNOTSUPP); Index: sys/sys/unistd.h =================================================================== --- sys/sys/unistd.h +++ sys/sys/unistd.h @@ -156,6 +156,19 @@ #define _PC_INF_PRESENT 62 #define _PC_MAC_PRESENT 63 #define _PC_ACL_NFS4 64 +#define _PC_MEDIA 65 + +/* Value bits for _PC_MEDIA */ +#define _PC_MEDIA_SPINNING 0x00000001 +#define _PC_MEDIA_SOLID 0x00000002 +#define _PC_MEDIA_VIRTUAL 0x00000004 +#define _PC_MEDIA_MEMORY 0x00000008 +#define _PC_MEDIA_ATA 0x00001000 +#define _PC_MEDIA_SCSI 0x00002000 +#define _PC_MEDIA_NVME 0x00004000 +#define _PC_MEDIA_MIRROR 0x00010000 +#define _PC_MEDIA_STRIPE 0x00020000 +#define _PC_MEDIA_RAID 0x00040000 #endif /* From OpenSolaris, used by SEEK_DATA/SEEK_HOLE. */ Index: sys/ufs/ufs/ufs_vnops.c =================================================================== --- sys/ufs/ufs/ufs_vnops.c +++ sys/ufs/ufs/ufs_vnops.c @@ -71,6 +71,8 @@ #include #include +#include + #include #include #include @@ -2416,10 +2418,11 @@ struct vop_pathconf_args /* { struct vnode *a_vp; int a_name; - int *a_retval; + long *a_retval; } */ *ap; { - int error; + struct ufsmount *ump; + int len, error; error = 0; switch (ap->a_name) { @@ -2512,6 +2515,12 @@ break; case _PC_SYMLINK_MAX: *ap->a_retval = MAXPATHLEN; + break; + case _PC_MEDIA: + ump = VFSTOUFS(ap->a_vp->v_mount); + len = sizeof(long); + *ap->a_retval = 0; + error = g_io_getattr("GEOM::media", ump->um_cp, &len, ap->a_retval); break; default: