aboutsummaryrefslogtreecommitdiffstats
path: root/module/zfs/zvol.c
diff options
context:
space:
mode:
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