changeset 13957:512faafc0eaf

3537 want pool io kstats Reviewed by: George Wilson <george.wilson@delphix.com> Reviewed by: Adam Leventhal <ahl@delphix.com> Reviewed by: Eric Schrock <eric.schrock@delphix.com> Reviewed by: Sa?o Kiselkov <skiselkov.ml@gmail.com> Reviewed by: Garrett D'Amore <garrett@damore.org> Reviewed by: Brendan Gregg <brendan.gregg@joyent.com> Approved by: Gordon Ross <gwr@nexenta.com>
author Matthew Ahrens <mahrens@delphix.com>
date Tue, 12 Feb 2013 12:53:43 -0800
parents ba0ec3e45034
children 1fd91513472c
files usr/src/lib/libzpool/common/kernel.c usr/src/lib/libzpool/common/sys/zfs_context.h usr/src/uts/common/fs/zfs/spa_misc.c usr/src/uts/common/fs/zfs/sys/spa_impl.h usr/src/uts/common/fs/zfs/vdev_queue.c
diffstat 5 files changed, 105 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/lib/libzpool/common/kernel.c	Wed Oct 10 20:07:26 2012 -0400
+++ b/usr/src/lib/libzpool/common/kernel.c	Tue Feb 12 12:53:43 2013 -0800
@@ -80,8 +80,8 @@
  */
 /*ARGSUSED*/
 kstat_t *
-kstat_create(char *module, int instance, char *name, char *class,
-    uchar_t type, ulong_t ndata, uchar_t ks_flag)
+kstat_create(const char *module, int instance, const char *name,
+    const char *class, uchar_t type, ulong_t ndata, uchar_t ks_flag)
 {
 	return (NULL);
 }
@@ -96,6 +96,36 @@
 kstat_delete(kstat_t *ksp)
 {}
 
+/*ARGSUSED*/
+void
+kstat_waitq_enter(kstat_io_t *kiop)
+{}
+
+/*ARGSUSED*/
+void
+kstat_waitq_exit(kstat_io_t *kiop)
+{}
+
+/*ARGSUSED*/
+void
+kstat_runq_enter(kstat_io_t *kiop)
+{}
+
+/*ARGSUSED*/
+void
+kstat_runq_exit(kstat_io_t *kiop)
+{}
+
+/*ARGSUSED*/
+void
+kstat_waitq_to_runq(kstat_io_t *kiop)
+{}
+
+/*ARGSUSED*/
+void
+kstat_runq_back_to_waitq(kstat_io_t *kiop)
+{}
+
 /*
  * =========================================================================
  * mutexes
--- a/usr/src/lib/libzpool/common/sys/zfs_context.h	Wed Oct 10 20:07:26 2012 -0400
+++ b/usr/src/lib/libzpool/common/sys/zfs_context.h	Tue Feb 12 12:53:43 2013 -0800
@@ -255,10 +255,16 @@
 /*
  * kstat creation, installation and deletion
  */
-extern kstat_t *kstat_create(char *, int,
-    char *, char *, uchar_t, ulong_t, uchar_t);
+extern kstat_t *kstat_create(const char *, int,
+    const char *, const char *, uchar_t, ulong_t, uchar_t);
 extern void kstat_install(kstat_t *);
 extern void kstat_delete(kstat_t *);
+extern void kstat_waitq_enter(kstat_io_t *);
+extern void kstat_waitq_exit(kstat_io_t *);
+extern void kstat_runq_enter(kstat_io_t *);
+extern void kstat_runq_exit(kstat_io_t *);
+extern void kstat_waitq_to_runq(kstat_io_t *);
+extern void kstat_runq_back_to_waitq(kstat_io_t *);
 
 /*
  * Kernel memory
--- a/usr/src/uts/common/fs/zfs/spa_misc.c	Wed Oct 10 20:07:26 2012 -0400
+++ b/usr/src/uts/common/fs/zfs/spa_misc.c	Tue Feb 12 12:53:43 2013 -0800
@@ -480,6 +480,7 @@
 	mutex_init(&spa->spa_scrub_lock, NULL, MUTEX_DEFAULT, NULL);
 	mutex_init(&spa->spa_suspend_lock, NULL, MUTEX_DEFAULT, NULL);
 	mutex_init(&spa->spa_vdev_top_lock, NULL, MUTEX_DEFAULT, NULL);
+	mutex_init(&spa->spa_iokstat_lock, NULL, MUTEX_DEFAULT, NULL);
 
 	cv_init(&spa->spa_async_cv, NULL, CV_DEFAULT, NULL);
 	cv_init(&spa->spa_proc_cv, NULL, CV_DEFAULT, NULL);
@@ -559,6 +560,13 @@
 		    KM_SLEEP) == 0);
 	}
 
+	spa->spa_iokstat = kstat_create("zfs", 0, name,
+	    "disk", KSTAT_TYPE_IO, 1, 0);
+	if (spa->spa_iokstat) {
+		spa->spa_iokstat->ks_lock = &spa->spa_iokstat_lock;
+		kstat_install(spa->spa_iokstat);
+	}
+
 	return (spa);
 }
 
@@ -608,6 +616,9 @@
 
 	spa_config_lock_destroy(spa);
 
+	kstat_delete(spa->spa_iokstat);
+	spa->spa_iokstat = NULL;
+
 	for (int t = 0; t < TXG_SIZE; t++)
 		bplist_destroy(&spa->spa_free_bplist[t]);
 
@@ -625,6 +636,7 @@
 	mutex_destroy(&spa->spa_scrub_lock);
 	mutex_destroy(&spa->spa_suspend_lock);
 	mutex_destroy(&spa->spa_vdev_top_lock);
+	mutex_destroy(&spa->spa_iokstat_lock);
 
 	kmem_free(spa, sizeof (spa_t));
 }
--- a/usr/src/uts/common/fs/zfs/sys/spa_impl.h	Wed Oct 10 20:07:26 2012 -0400
+++ b/usr/src/uts/common/fs/zfs/sys/spa_impl.h	Tue Feb 12 12:53:43 2013 -0800
@@ -231,6 +231,8 @@
 	uint64_t	spa_deadman_calls;	/* number of deadman calls */
 	uint64_t	spa_sync_starttime;	/* starting time fo spa_sync */
 	uint64_t	spa_deadman_synctime;	/* deadman expiration timer */
+	kmutex_t	spa_iokstat_lock;	/* protects spa_iokstat_* */
+	struct kstat	*spa_iokstat;		/* kstat of io to this pool */
 	/*
 	 * spa_refcnt & spa_config_lock must be the last elements
 	 * because refcount_t changes size based on compilation options.
--- a/usr/src/uts/common/fs/zfs/vdev_queue.c	Wed Oct 10 20:07:26 2012 -0400
+++ b/usr/src/uts/common/fs/zfs/vdev_queue.c	Tue Feb 12 12:53:43 2013 -0800
@@ -29,6 +29,7 @@
 
 #include <sys/zfs_context.h>
 #include <sys/vdev_impl.h>
+#include <sys/spa_impl.h>
 #include <sys/zio.h>
 #include <sys/avl.h>
 
@@ -142,15 +143,62 @@
 static void
 vdev_queue_io_add(vdev_queue_t *vq, zio_t *zio)
 {
+	spa_t *spa = zio->io_spa;
 	avl_add(&vq->vq_deadline_tree, zio);
 	avl_add(zio->io_vdev_tree, zio);
+
+	if (spa->spa_iokstat != NULL) {
+		mutex_enter(&spa->spa_iokstat_lock);
+		kstat_waitq_enter(spa->spa_iokstat->ks_data);
+		mutex_exit(&spa->spa_iokstat_lock);
+	}
 }
 
 static void
 vdev_queue_io_remove(vdev_queue_t *vq, zio_t *zio)
 {
+	spa_t *spa = zio->io_spa;
 	avl_remove(&vq->vq_deadline_tree, zio);
 	avl_remove(zio->io_vdev_tree, zio);
+
+	if (spa->spa_iokstat != NULL) {
+		mutex_enter(&spa->spa_iokstat_lock);
+		kstat_waitq_exit(spa->spa_iokstat->ks_data);
+		mutex_exit(&spa->spa_iokstat_lock);
+	}
+}
+
+static void
+vdev_queue_pending_add(vdev_queue_t *vq, zio_t *zio)
+{
+	spa_t *spa = zio->io_spa;
+	avl_add(&vq->vq_pending_tree, zio);
+	if (spa->spa_iokstat != NULL) {
+		mutex_enter(&spa->spa_iokstat_lock);
+		kstat_runq_enter(spa->spa_iokstat->ks_data);
+		mutex_exit(&spa->spa_iokstat_lock);
+	}
+}
+
+static void
+vdev_queue_pending_remove(vdev_queue_t *vq, zio_t *zio)
+{
+	spa_t *spa = zio->io_spa;
+	avl_remove(&vq->vq_pending_tree, zio);
+	if (spa->spa_iokstat != NULL) {
+		kstat_io_t *ksio = spa->spa_iokstat->ks_data;
+
+		mutex_enter(&spa->spa_iokstat_lock);
+		kstat_runq_exit(spa->spa_iokstat->ks_data);
+		if (zio->io_type == ZIO_TYPE_READ) {
+			ksio->reads++;
+			ksio->nread += zio->io_size;
+		} else if (zio->io_type == ZIO_TYPE_WRITE) {
+			ksio->writes++;
+			ksio->nwritten += zio->io_size;
+		}
+		mutex_exit(&spa->spa_iokstat_lock);
+	}
 }
 
 static void
@@ -317,7 +365,7 @@
 			zio_execute(dio);
 		} while (dio != lio);
 
-		avl_add(&vq->vq_pending_tree, aio);
+		vdev_queue_pending_add(vq, aio);
 
 		return (aio);
 	}
@@ -339,7 +387,7 @@
 		goto again;
 	}
 
-	avl_add(&vq->vq_pending_tree, fio);
+	vdev_queue_pending_add(vq, fio);
 
 	return (fio);
 }
@@ -395,7 +443,7 @@
 
 	mutex_enter(&vq->vq_lock);
 
-	avl_remove(&vq->vq_pending_tree, zio);
+	vdev_queue_pending_remove(vq, zio);
 
 	vq->vq_io_complete_ts = ddi_get_lbolt64();
 	vq->vq_io_delta_ts = vq->vq_io_complete_ts - zio->io_timestamp;