Illumos #3537
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> References: http://www.illumos.org/issues/3537 illumos/illumos-gate@c3a6601 Ported by: Cyril Plisko <cyril.plisko@mountall.com> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Porting Notes: 1. The patch was restructured to take advantage of the existing spa statistics infrastructure. To accomplish this the kstat was moved in to spa->io_stats and the init/destroy code moved to spa_stats.c. 2. The I/O kstat was simply named <pool> which conflicted with the pool directory we had already created. Therefore it was renamed to <pool>/io 3. An update handler was added to allow the kstat to be zeroed.
This commit is contained in:
parent
a117a6d66e
commit
330847ff36
|
@ -550,6 +550,7 @@ typedef struct spa_stats {
|
||||||
spa_stats_history_t read_history;
|
spa_stats_history_t read_history;
|
||||||
spa_stats_history_t txg_history;
|
spa_stats_history_t txg_history;
|
||||||
spa_stats_history_t tx_assign_histogram;
|
spa_stats_history_t tx_assign_histogram;
|
||||||
|
spa_stats_history_t io_history;
|
||||||
} spa_stats_t;
|
} spa_stats_t;
|
||||||
|
|
||||||
typedef enum txg_state {
|
typedef enum txg_state {
|
||||||
|
|
|
@ -344,10 +344,16 @@ extern void cv_broadcast(kcondvar_t *cv);
|
||||||
/*
|
/*
|
||||||
* kstat creation, installation and deletion
|
* kstat creation, installation and deletion
|
||||||
*/
|
*/
|
||||||
extern kstat_t *kstat_create(char *, int,
|
extern kstat_t *kstat_create(const char *, int,
|
||||||
char *, char *, uchar_t, ulong_t, uchar_t);
|
const char *, const char *, uchar_t, ulong_t, uchar_t);
|
||||||
extern void kstat_install(kstat_t *);
|
extern void kstat_install(kstat_t *);
|
||||||
extern void kstat_delete(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 *);
|
||||||
extern void kstat_set_raw_ops(kstat_t *ksp,
|
extern void kstat_set_raw_ops(kstat_t *ksp,
|
||||||
int (*headers)(char *buf, size_t size),
|
int (*headers)(char *buf, size_t size),
|
||||||
int (*data)(char *buf, size_t size, void *data),
|
int (*data)(char *buf, size_t size, void *data),
|
||||||
|
|
|
@ -224,8 +224,8 @@ zk_thread_join(kt_did_t tid)
|
||||||
*/
|
*/
|
||||||
/*ARGSUSED*/
|
/*ARGSUSED*/
|
||||||
kstat_t *
|
kstat_t *
|
||||||
kstat_create(char *module, int instance, char *name, char *class,
|
kstat_create(const char *module, int instance, const char *name,
|
||||||
uchar_t type, ulong_t ndata, uchar_t ks_flag)
|
const char *class, uchar_t type, ulong_t ndata, uchar_t ks_flag)
|
||||||
{
|
{
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
@ -241,6 +241,35 @@ kstat_delete(kstat_t *ksp)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/*ARGSUSED*/
|
/*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)
|
||||||
|
{}
|
||||||
|
|
||||||
void
|
void
|
||||||
kstat_set_raw_ops(kstat_t *ksp,
|
kstat_set_raw_ops(kstat_t *ksp,
|
||||||
int (*headers)(char *buf, size_t size),
|
int (*headers)(char *buf, size_t size),
|
||||||
|
|
|
@ -608,12 +608,61 @@ spa_tx_assign_add_nsecs(spa_t *spa, uint64_t nsecs)
|
||||||
atomic_inc_64(&((kstat_named_t *)ssh->private)[idx].value.ui64);
|
atomic_inc_64(&((kstat_named_t *)ssh->private)[idx].value.ui64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ==========================================================================
|
||||||
|
* SPA IO History Routines
|
||||||
|
* ==========================================================================
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
spa_io_history_update(kstat_t *ksp, int rw)
|
||||||
|
{
|
||||||
|
if (rw == KSTAT_WRITE)
|
||||||
|
memset(ksp->ks_data, 0, ksp->ks_data_size);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
spa_io_history_init(spa_t *spa)
|
||||||
|
{
|
||||||
|
spa_stats_history_t *ssh = &spa->spa_stats.io_history;
|
||||||
|
char name[KSTAT_STRLEN];
|
||||||
|
kstat_t *ksp;
|
||||||
|
|
||||||
|
mutex_init(&ssh->lock, NULL, MUTEX_DEFAULT, NULL);
|
||||||
|
|
||||||
|
(void) snprintf(name, KSTAT_STRLEN, "zfs/%s", spa_name(spa));
|
||||||
|
name[KSTAT_STRLEN-1] = '\0';
|
||||||
|
|
||||||
|
ksp = kstat_create(name, 0, "io", "disk", KSTAT_TYPE_IO, 1, 0);
|
||||||
|
ssh->kstat = ksp;
|
||||||
|
|
||||||
|
if (ksp) {
|
||||||
|
ksp->ks_lock = &ssh->lock;
|
||||||
|
ksp->ks_private = spa;
|
||||||
|
ksp->ks_update = spa_io_history_update;
|
||||||
|
kstat_install(ksp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
spa_io_history_destroy(spa_t *spa)
|
||||||
|
{
|
||||||
|
spa_stats_history_t *ssh = &spa->spa_stats.io_history;
|
||||||
|
|
||||||
|
if (ssh->kstat)
|
||||||
|
kstat_delete(ssh->kstat);
|
||||||
|
|
||||||
|
mutex_destroy(&ssh->lock);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
spa_stats_init(spa_t *spa)
|
spa_stats_init(spa_t *spa)
|
||||||
{
|
{
|
||||||
spa_read_history_init(spa);
|
spa_read_history_init(spa);
|
||||||
spa_txg_history_init(spa);
|
spa_txg_history_init(spa);
|
||||||
spa_tx_assign_init(spa);
|
spa_tx_assign_init(spa);
|
||||||
|
spa_io_history_init(spa);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -622,6 +671,7 @@ spa_stats_destroy(spa_t *spa)
|
||||||
spa_tx_assign_destroy(spa);
|
spa_tx_assign_destroy(spa);
|
||||||
spa_txg_history_destroy(spa);
|
spa_txg_history_destroy(spa);
|
||||||
spa_read_history_destroy(spa);
|
spa_read_history_destroy(spa);
|
||||||
|
spa_io_history_destroy(spa);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_KERNEL) && defined(HAVE_SPL)
|
#if defined(_KERNEL) && defined(HAVE_SPL)
|
||||||
|
|
|
@ -29,8 +29,10 @@
|
||||||
|
|
||||||
#include <sys/zfs_context.h>
|
#include <sys/zfs_context.h>
|
||||||
#include <sys/vdev_impl.h>
|
#include <sys/vdev_impl.h>
|
||||||
|
#include <sys/spa_impl.h>
|
||||||
#include <sys/zio.h>
|
#include <sys/zio.h>
|
||||||
#include <sys/avl.h>
|
#include <sys/avl.h>
|
||||||
|
#include <sys/kstat.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These tunables are for performance analysis.
|
* These tunables are for performance analysis.
|
||||||
|
@ -164,15 +166,72 @@ vdev_queue_fini(vdev_t *vd)
|
||||||
static void
|
static void
|
||||||
vdev_queue_io_add(vdev_queue_t *vq, zio_t *zio)
|
vdev_queue_io_add(vdev_queue_t *vq, zio_t *zio)
|
||||||
{
|
{
|
||||||
|
spa_t *spa = zio->io_spa;
|
||||||
|
spa_stats_history_t *ssh = &spa->spa_stats.io_history;
|
||||||
|
|
||||||
avl_add(&vq->vq_deadline_tree, zio);
|
avl_add(&vq->vq_deadline_tree, zio);
|
||||||
avl_add(zio->io_vdev_tree, zio);
|
avl_add(zio->io_vdev_tree, zio);
|
||||||
|
|
||||||
|
if (ssh->kstat != NULL) {
|
||||||
|
mutex_enter(&ssh->lock);
|
||||||
|
kstat_waitq_enter(ssh->kstat->ks_data);
|
||||||
|
mutex_exit(&ssh->lock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vdev_queue_io_remove(vdev_queue_t *vq, zio_t *zio)
|
vdev_queue_io_remove(vdev_queue_t *vq, zio_t *zio)
|
||||||
{
|
{
|
||||||
|
spa_t *spa = zio->io_spa;
|
||||||
|
spa_stats_history_t *ssh = &spa->spa_stats.io_history;
|
||||||
|
|
||||||
avl_remove(&vq->vq_deadline_tree, zio);
|
avl_remove(&vq->vq_deadline_tree, zio);
|
||||||
avl_remove(zio->io_vdev_tree, zio);
|
avl_remove(zio->io_vdev_tree, zio);
|
||||||
|
|
||||||
|
if (ssh->kstat != NULL) {
|
||||||
|
mutex_enter(&ssh->lock);
|
||||||
|
kstat_waitq_exit(ssh->kstat->ks_data);
|
||||||
|
mutex_exit(&ssh->lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vdev_queue_pending_add(vdev_queue_t *vq, zio_t *zio)
|
||||||
|
{
|
||||||
|
spa_t *spa = zio->io_spa;
|
||||||
|
spa_stats_history_t *ssh = &spa->spa_stats.io_history;
|
||||||
|
|
||||||
|
avl_add(&vq->vq_pending_tree, zio);
|
||||||
|
|
||||||
|
if (ssh->kstat != NULL) {
|
||||||
|
mutex_enter(&ssh->lock);
|
||||||
|
kstat_runq_enter(ssh->kstat->ks_data);
|
||||||
|
mutex_exit(&ssh->lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vdev_queue_pending_remove(vdev_queue_t *vq, zio_t *zio)
|
||||||
|
{
|
||||||
|
spa_t *spa = zio->io_spa;
|
||||||
|
spa_stats_history_t *ssh = &spa->spa_stats.io_history;
|
||||||
|
|
||||||
|
avl_remove(&vq->vq_pending_tree, zio);
|
||||||
|
|
||||||
|
if (ssh->kstat != NULL) {
|
||||||
|
kstat_io_t *ksio = ssh->kstat->ks_data;
|
||||||
|
|
||||||
|
mutex_enter(&ssh->lock);
|
||||||
|
kstat_runq_exit(ksio);
|
||||||
|
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(&ssh->lock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -351,7 +410,7 @@ again:
|
||||||
zio_execute(dio);
|
zio_execute(dio);
|
||||||
} while (dio != lio);
|
} while (dio != lio);
|
||||||
|
|
||||||
avl_add(&vq->vq_pending_tree, aio);
|
vdev_queue_pending_add(vq, aio);
|
||||||
list_remove(&vq->vq_io_list, vi);
|
list_remove(&vq->vq_io_list, vi);
|
||||||
|
|
||||||
return (aio);
|
return (aio);
|
||||||
|
@ -374,7 +433,7 @@ again:
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
|
|
||||||
avl_add(&vq->vq_pending_tree, fio);
|
vdev_queue_pending_add(vq, fio);
|
||||||
|
|
||||||
return (fio);
|
return (fio);
|
||||||
}
|
}
|
||||||
|
@ -431,7 +490,7 @@ vdev_queue_io_done(zio_t *zio)
|
||||||
|
|
||||||
mutex_enter(&vq->vq_lock);
|
mutex_enter(&vq->vq_lock);
|
||||||
|
|
||||||
avl_remove(&vq->vq_pending_tree, zio);
|
vdev_queue_pending_remove(vq, zio);
|
||||||
|
|
||||||
zio->io_delta = gethrtime() - zio->io_timestamp;
|
zio->io_delta = gethrtime() - zio->io_timestamp;
|
||||||
vq->vq_io_complete_ts = gethrtime();
|
vq->vq_io_complete_ts = gethrtime();
|
||||||
|
|
Loading…
Reference in New Issue