From 0efd61c1f2043cb89cc0593a872630911c7b1f30 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Sat, 22 Apr 2017 13:33:36 -0400 Subject: [PATCH] Make ZIL operations on zvols use _by_dnode routines This continues what was started in 0eef1bde31d67091d3deed23fe2394f5a8bf2276 by fully converting zvols to avoid unnecessary dnode_hold() calls. This saves a small amount of CPU time and slightly improves latencies on synchronous operations on zvols. Signed-off-by: Richard Yao --- include/sys/dmu.h | 3 +++ module/zfs/dmu.c | 10 ++++++++-- module/zfs/zvol.c | 22 ++++++++++------------ 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/include/sys/dmu.h b/include/sys/dmu.h index ea1b116bed2e..d24615262737 100644 --- a/include/sys/dmu.h +++ b/include/sys/dmu.h @@ -751,10 +751,13 @@ void dmu_prealloc(objset_t *os, uint64_t object, uint64_t offset, uint64_t size, #include int dmu_read_uio(objset_t *os, uint64_t object, struct uio *uio, uint64_t size); int dmu_read_uio_dbuf(dmu_buf_t *zdb, struct uio *uio, uint64_t size); +int dmu_read_uio_dnode(dnode_t *dn, struct uio *uio, uint64_t size); int dmu_write_uio(objset_t *os, uint64_t object, struct uio *uio, uint64_t size, dmu_tx_t *tx); int dmu_write_uio_dbuf(dmu_buf_t *zdb, struct uio *uio, uint64_t size, dmu_tx_t *tx); +int dmu_write_uio_dnode(dnode_t *dn, struct uio *uio, uint64_t size, + dmu_tx_t *tx); #endif struct arc_buf *dmu_request_arcbuf(dmu_buf_t *handle, int size); void dmu_return_arcbuf(struct arc_buf *buf); diff --git a/module/zfs/dmu.c b/module/zfs/dmu.c index 5cf09412f753..8f99c148d1cf 100644 --- a/module/zfs/dmu.c +++ b/module/zfs/dmu.c @@ -965,6 +965,9 @@ int dmu_read_by_dnode(dnode_t *dn, uint64_t offset, uint64_t size, void *buf, uint32_t flags) { + if (size == 0) + return (0); + return (dmu_read_impl(dn, offset, size, buf, flags)); } @@ -1225,7 +1228,7 @@ xuio_stat_wbuf_nocopy(void) } #ifdef _KERNEL -static int +int dmu_read_uio_dnode(dnode_t *dn, uio_t *uio, uint64_t size) { dmu_buf_t **dbp; @@ -1334,7 +1337,7 @@ dmu_read_uio(objset_t *os, uint64_t object, uio_t *uio, uint64_t size) return (err); } -static int +int dmu_write_uio_dnode(dnode_t *dn, uio_t *uio, uint64_t size, dmu_tx_t *tx) { dmu_buf_t **dbp; @@ -1342,6 +1345,9 @@ dmu_write_uio_dnode(dnode_t *dn, uio_t *uio, uint64_t size, dmu_tx_t *tx) int err = 0; int i; + if (size == 0) + return (0); + err = dmu_buf_hold_array_by_dnode(dn, uio->uio_loffset, size, FALSE, FTAG, &numbufs, &dbp, DMU_READ_PREFETCH); if (err) diff --git a/module/zfs/zvol.c b/module/zfs/zvol.c index 1a86cd3cdc0c..f883eb39871a 100644 --- a/module/zfs/zvol.c +++ b/module/zfs/zvol.c @@ -111,7 +111,7 @@ struct zvol_state { uint32_t zv_changed; /* disk changed */ zilog_t *zv_zilog; /* ZIL handle */ zfs_rlock_t zv_range_lock; /* range lock */ - dmu_buf_t *zv_dbuf; /* bonus handle */ + dnode_t *zv_dn; /* dnode hold */ dev_t zv_dev; /* device id */ struct gendisk *zv_disk; /* generic disk */ struct request_queue *zv_queue; /* request queue */ @@ -647,8 +647,8 @@ zvol_log_write(zvol_state_t *zv, dmu_tx_t *tx, uint64_t offset, itx = zil_itx_create(TX_WRITE, sizeof (*lr) + (write_state == WR_COPIED ? len : 0)); lr = (lr_write_t *)&itx->itx_lr; - if (write_state == WR_COPIED && dmu_read(zv->zv_objset, - ZVOL_OBJ, offset, len, lr+1, DMU_READ_NO_PREFETCH) != 0) { + if (write_state == WR_COPIED && dmu_read_by_dnode(zv->zv_dn, + offset, len, lr+1, DMU_READ_NO_PREFETCH) != 0) { zil_itx_destroy(itx); itx = zil_itx_create(TX_WRITE, sizeof (*lr)); lr = (lr_write_t *)&itx->itx_lr; @@ -729,7 +729,7 @@ zvol_write(void *arg) dmu_tx_abort(tx); break; } - error = dmu_write_uio_dbuf(zv->zv_dbuf, &uio, bytes, tx); + error = dmu_write_uio_dnode(zv->zv_dn, &uio, bytes, tx); if (error == 0) zvol_log_write(zv, tx, off, bytes, sync); dmu_tx_commit(tx); @@ -854,7 +854,7 @@ zvol_read(void *arg) if (bytes > volsize - uio.uio_loffset) bytes = volsize - uio.uio_loffset; - error = dmu_read_uio_dbuf(zv->zv_dbuf, &uio, bytes); + error = dmu_read_uio_dnode(zv->zv_dn, &uio, bytes); if (error) { /* convert checksum errors into IO errors */ if (error == ECKSUM) @@ -978,8 +978,6 @@ static int zvol_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio) { zvol_state_t *zv = arg; - objset_t *os = zv->zv_objset; - uint64_t object = ZVOL_OBJ; uint64_t offset = lr->lr_offset; uint64_t size = lr->lr_length; blkptr_t *bp = &lr->lr_blkptr; @@ -1003,12 +1001,12 @@ zvol_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio) * we don't have to write the data twice. */ if (buf != NULL) { /* immediate write */ - error = dmu_read(os, object, offset, size, buf, + error = dmu_read_by_dnode(zv->zv_dn, offset, size, buf, DMU_READ_NO_PREFETCH); } else { size = zv->zv_volblocksize; offset = P2ALIGN_TYPED(offset, size, uint64_t); - error = dmu_buf_hold(os, object, offset, zgd, &db, + error = dmu_buf_hold_by_dnode(zv->zv_dn, offset, zgd, &db, DMU_READ_NO_PREFETCH); if (error == 0) { blkptr_t *obp = dmu_buf_get_blkptr(db); @@ -1079,7 +1077,7 @@ zvol_setup_zv(zvol_state_t *zv) if (error) return (SET_ERROR(error)); - error = dmu_bonus_hold(os, ZVOL_OBJ, zv, &zv->zv_dbuf); + error = dnode_hold(os, ZVOL_OBJ, FTAG, &zv->zv_dn); if (error) return (SET_ERROR(error)); @@ -1108,8 +1106,8 @@ zvol_shutdown_zv(zvol_state_t *zv) zil_close(zv->zv_zilog); zv->zv_zilog = NULL; - dmu_buf_rele(zv->zv_dbuf, zv); - zv->zv_dbuf = NULL; + dnode_rele(zv->zv_dn, FTAG); + zv->zv_dn = NULL; /* * Evict cached data