Index: lib/libgeom/geom_stats.c
===================================================================
--- lib/libgeom/geom_stats.c
+++ lib/libgeom/geom_stats.c
@@ -32,9 +32,12 @@
  */
 
 #include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/disk.h>
 #include <sys/devicestat.h>
 #include <sys/mman.h>
 #include <sys/time.h>
+#include <err.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <paths.h>
@@ -63,18 +66,18 @@
 geom_stats_resync(void)
 {
 	void *p;
+	off_t mediasize;
+	int error;
 
 	if (statsfd == -1)
 		return;
-	for (;;) {
-		p = mmap(statp, (npages + 1) * pagesize,
-		    PROT_READ, MAP_SHARED, statsfd, 0);
-		if (p == MAP_FAILED)
-			break;
-		else
-			statp = p;
-		npages++;
-	}
+	error = ioctl(statsfd, DIOCGMEDIASIZE, &mediasize);
+	if (error)
+		err(1, "DIOCGMEDIASIZE(" _PATH_DEV DEVSTAT_DEVICE_NAME ")");
+
+	p = mmap(statp, mediasize, PROT_READ, MAP_SHARED, statsfd, 0);
+	if (p == MAP_FAILED)
+		err(1, "mmap:");
 }
 
 int
Index: sbin/mdconfig/mdconfig.c
===================================================================
--- sbin/mdconfig/mdconfig.c
+++ sbin/mdconfig/mdconfig.c
@@ -423,7 +423,7 @@
 /*
  * Lists md(4) disks. Is used also as a query routine, since it handles XML
  * interface. 'units' can be NULL for listing memory disks. It might be
- * coma-separated string containing md(4) disk names. 'opt' distinguished
+ * comma-separated string containing md(4) disk names. 'opt' distinguished
  * between list and query mode.
  */
 static int
Index: sys/kern/subr_devstat.c
===================================================================
--- sys/kern/subr_devstat.c
+++ sys/kern/subr_devstat.c
@@ -32,6 +32,7 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
+#include <sys/disk.h>
 #include <sys/kernel.h>
 #include <sys/systm.h>
 #include <sys/bio.h>
@@ -473,10 +474,12 @@
 
 #define statsperpage (PAGE_SIZE / sizeof(struct devstat))
 
+static d_ioctl_t devstat_ioctl;
 static d_mmap_t devstat_mmap;
 
 static struct cdevsw devstat_cdevsw = {
 	.d_version =	D_VERSION,
+	.d_ioctl =	devstat_ioctl,
 	.d_mmap =	devstat_mmap,
 	.d_name =	"devstat",
 };
@@ -487,9 +490,26 @@
 	u_int			nfree;
 };
 
+static size_t pagelist_pages = 0;
 static TAILQ_HEAD(, statspage)	pagelist = TAILQ_HEAD_INITIALIZER(pagelist);
 static MALLOC_DEFINE(M_DEVSTAT, "devstat", "Device statistics");
 
+static int
+devstat_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
+    struct thread *td)
+{
+	int error = ENOTTY;
+
+	switch (cmd) {
+	case DIOCGMEDIASIZE:
+		error = 0;
+		*(off_t *)data = pagelist_pages * PAGE_SIZE;;
+		break;
+	}
+
+	return (error);
+}
+
 static int
 devstat_mmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr,
     int nprot, vm_memattr_t *memattr)
@@ -556,6 +576,7 @@
 			 * head but the order on the list determine the
 			 * sequence of the mapping so we can't do that.
 			 */
+			pagelist_pages++;
 			TAILQ_INSERT_TAIL(&pagelist, spp, list);
 		} else
 			break;