summaryrefslogtreecommitdiffstats
path: root/module/zfs/zvol.c
diff options
context:
space:
mode:
authorSerapheim Dimitropoulos <[email protected]>2018-08-20 09:52:37 -0700
committerBrian Behlendorf <[email protected]>2018-08-20 09:52:37 -0700
commita448a2557ec4938ed6944c7766fe0b8e6e5f6456 (patch)
tree1d622c6c40aeb9c34d233ad562b2920ab2ef651c /module/zfs/zvol.c
parentfa84714abbb9316208bef7188009ee74204d532e (diff)
Introduce read/write kstats per dataset
The following patch introduces a few statistics on reads and writes grouped by dataset. These statistics are implemented as kstats (backed by aggregate sums for performance) and can be retrieved by using the dataset objset ID number. The motivation for this change is to provide some preliminary analytics on dataset usage/performance. Reviewed-by: Richard Elling <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Reviewed by: Matthew Ahrens <[email protected]> Signed-off-by: Serapheim Dimitropoulos <[email protected]> Closes #7705
Diffstat (limited to 'module/zfs/zvol.c')
-rw-r--r--module/zfs/zvol.c49
1 files changed, 33 insertions, 16 deletions
diff --git a/module/zfs/zvol.c b/module/zfs/zvol.c
index ecba516fc..19bc1b18e 100644
--- a/module/zfs/zvol.c
+++ b/module/zfs/zvol.c
@@ -36,7 +36,7 @@
*
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2016 Actifio, Inc. All rights reserved.
- * Copyright (c) 2012, 2017 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2018 by Delphix. All rights reserved.
*/
/*
@@ -74,6 +74,7 @@
* and zvol_release()->zvol_last_close() directly as well.
*/
+#include <sys/dataset_kstats.h>
#include <sys/dbuf.h>
#include <sys/dmu_traverse.h>
#include <sys/dsl_dataset.h>
@@ -88,7 +89,9 @@
#include <sys/zfs_znode.h>
#include <sys/spa_impl.h>
#include <sys/zvol.h>
+
#include <linux/blkdev_compat.h>
+#include <linux/task_io_accounting_ops.h>
unsigned int zvol_inhibit_dev = 0;
unsigned int zvol_major = ZVOL_MAJOR;
@@ -125,6 +128,7 @@ struct zvol_state {
dev_t zv_dev; /* device id */
struct gendisk *zv_disk; /* generic disk */
struct request_queue *zv_queue; /* request queue */
+ dataset_kstats_t zv_kstat; /* zvol kstats */
list_node_t zv_next; /* next zvol_state_t linkage */
uint64_t zv_hash; /* name hash */
struct hlist_node zv_hlink; /* hash link */
@@ -730,25 +734,25 @@ uio_from_bio(uio_t *uio, struct bio *bio)
static void
zvol_write(void *arg)
{
+ int error = 0;
+
zv_request_t *zvr = arg;
struct bio *bio = zvr->bio;
uio_t uio;
- zvol_state_t *zv = zvr->zv;
- uint64_t volsize = zv->zv_volsize;
- boolean_t sync;
- int error = 0;
- unsigned long start_jif;
-
uio_from_bio(&uio, bio);
+ zvol_state_t *zv = zvr->zv;
ASSERT(zv && zv->zv_open_count > 0);
- start_jif = jiffies;
+ ssize_t start_resid = uio.uio_resid;
+ unsigned long start_jif = jiffies;
blk_generic_start_io_acct(zv->zv_queue, WRITE, bio_sectors(bio),
&zv->zv_disk->part0);
- sync = bio_is_fua(bio) || zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS;
+ boolean_t sync =
+ bio_is_fua(bio) || zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS;
+ uint64_t volsize = zv->zv_volsize;
while (uio.uio_resid > 0 && uio.uio_loffset < volsize) {
uint64_t bytes = MIN(uio.uio_resid, DMU_MAX_ACCESS >> 1);
uint64_t off = uio.uio_loffset;
@@ -766,14 +770,20 @@ zvol_write(void *arg)
break;
}
error = dmu_write_uio_dnode(zv->zv_dn, &uio, bytes, tx);
- if (error == 0)
+ if (error == 0) {
zvol_log_write(zv, tx, off, bytes, sync);
+ }
dmu_tx_commit(tx);
if (error)
break;
}
zfs_range_unlock(zvr->rl);
+
+ int64_t nwritten = start_resid - uio.uio_resid;
+ dataset_kstats_update_write_kstats(&zv->zv_kstat, nwritten);
+ task_io_account_write(nwritten);
+
if (sync)
zil_commit(zv->zv_zilog, ZVOL_OBJ);
@@ -876,22 +886,22 @@ unlock:
static void
zvol_read(void *arg)
{
+ int error = 0;
+
zv_request_t *zvr = arg;
struct bio *bio = zvr->bio;
uio_t uio;
- zvol_state_t *zv = zvr->zv;
- uint64_t volsize = zv->zv_volsize;
- int error = 0;
- unsigned long start_jif;
-
uio_from_bio(&uio, bio);
+ zvol_state_t *zv = zvr->zv;
ASSERT(zv && zv->zv_open_count > 0);
- start_jif = jiffies;
+ ssize_t start_resid = uio.uio_resid;
+ unsigned long start_jif = jiffies;
blk_generic_start_io_acct(zv->zv_queue, READ, bio_sectors(bio),
&zv->zv_disk->part0);
+ uint64_t volsize = zv->zv_volsize;
while (uio.uio_resid > 0 && uio.uio_loffset < volsize) {
uint64_t bytes = MIN(uio.uio_resid, DMU_MAX_ACCESS >> 1);
@@ -909,6 +919,10 @@ zvol_read(void *arg)
}
zfs_range_unlock(zvr->rl);
+ int64_t nread = start_resid - uio.uio_resid;
+ dataset_kstats_update_read_kstats(&zv->zv_kstat, nread);
+ task_io_account_read(nread);
+
rw_exit(&zv->zv_suspend_lock);
blk_generic_end_io_acct(zv->zv_queue, READ, &zv->zv_disk->part0,
start_jif);
@@ -1741,6 +1755,7 @@ zvol_free(void *arg)
ida_simple_remove(&zvol_ida, MINOR(zv->zv_dev) >> ZVOL_MINOR_BITS);
mutex_destroy(&zv->zv_state_lock);
+ dataset_kstats_destroy(&zv->zv_kstat);
kmem_free(zv, sizeof (zvol_state_t));
}
@@ -1831,6 +1846,8 @@ zvol_create_minor_impl(const char *name)
else
zil_replay(os, zv, zvol_replay_vector);
}
+ ASSERT3P(zv->zv_kstat.dk_kstats, ==, NULL);
+ dataset_kstats_create(&zv->zv_kstat, zv->zv_objset);
/*
* When udev detects the addition of the device it will immediately