Skip to content

Commit

Permalink
Switch synchronous IO on zvols to use _by_dbuf routines
Browse files Browse the repository at this point in the history
This saves a small amount of CPU time and slightly improves latencies on
synchronous operations on zvols.

Signed-off-by: Richard Yao <[email protected]>
  • Loading branch information
Richard Yao authored and ryao committed Apr 26, 2017
1 parent 0091d66 commit 7687327
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 4 deletions.
4 changes: 4 additions & 0 deletions include/sys/dmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,8 @@ int dmu_spill_hold_existing(dmu_buf_t *bonus, void *tag, dmu_buf_t **dbp);
*/
int dmu_buf_hold(objset_t *os, uint64_t object, uint64_t offset,
void *tag, dmu_buf_t **, int flags);
int dmu_buf_hold_by_dbuf(dmu_buf_t *zdb, uint64_t offset,
void *tag, dmu_buf_t **, int flags);
int dmu_buf_hold_by_dnode(dnode_t *dn, uint64_t offset,
void *tag, dmu_buf_t **dbp, int flags);

Expand Down Expand Up @@ -741,6 +743,8 @@ int dmu_read(objset_t *os, uint64_t object, uint64_t offset, uint64_t size,
void *buf, uint32_t flags);
int dmu_read_by_dnode(dnode_t *dn, uint64_t offset, uint64_t size, void *buf,
uint32_t flags);
int dmu_read_by_dbuf(dmu_buf_t *zdb, uint64_t offset, uint64_t size, void *buf,
uint32_t flags);
void dmu_write(objset_t *os, uint64_t object, uint64_t offset, uint64_t size,
const void *buf, dmu_tx_t *tx);
void dmu_write_by_dnode(dnode_t *dn, uint64_t offset, uint64_t size,
Expand Down
44 changes: 44 additions & 0 deletions module/zfs/dmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,23 @@ dmu_buf_hold_by_dnode(dnode_t *dn, uint64_t offset,
return (err);
}

int
dmu_buf_hold_by_dbuf(dmu_buf_t *zdb, uint64_t offset,
void *tag, dmu_buf_t **dbp, int flags)
{
dmu_buf_impl_t *db = (dmu_buf_impl_t *)zdb;
dnode_t *dn;
int err;


DB_DNODE_ENTER(db);
dn = DB_DNODE(db);
err = dmu_buf_hold_by_dnode(dn, offset, tag, dbp, flags);
DB_DNODE_EXIT(db);

return (err);
}

int
dmu_buf_hold(objset_t *os, uint64_t object, uint64_t offset,
void *tag, dmu_buf_t **dbp, int flags)
Expand Down Expand Up @@ -968,6 +985,33 @@ dmu_read_by_dnode(dnode_t *dn, uint64_t offset, uint64_t size, void *buf,
return (dmu_read_impl(dn, offset, size, buf, flags));
}

/*
* Read 'size' bytes into the buffer.
* From object zdb->db_object.
*
* If the caller already has a dbuf in the target object
* (e.g. its bonus buffer), this routine is faster than dmu_read(),
* because we don't have to find the dnode_t for the object.
*/
int
dmu_read_by_dbuf(dmu_buf_t *zdb, uint64_t offset, uint64_t size, void *buf,
uint32_t flags)
{
dmu_buf_impl_t *db = (dmu_buf_impl_t *)zdb;
dnode_t *dn;
int err;

if (size == 0)
return (0);

DB_DNODE_ENTER(db);
dn = DB_DNODE(db);
err = dmu_read_impl(dn, offset, size, buf, flags);
DB_DNODE_EXIT(db);

return (err);
}

static void
dmu_write_impl(dmu_buf_t **dbp, int numbufs, uint64_t offset, uint64_t size,
const void *buf, dmu_tx_t *tx)
Expand Down
8 changes: 4 additions & 4 deletions module/zfs/zvol.c
Original file line number Diff line number Diff line change
Expand Up @@ -609,8 +609,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_dbuf(zv->zv_dbuf,
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;
Expand Down Expand Up @@ -901,12 +901,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_dbuf(zv->zv_dbuf, 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_dbuf(zv->zv_dbuf, offset, zgd, &db,
DMU_READ_NO_PREFETCH);
if (error == 0) {
blkptr_t *obp = dmu_buf_get_blkptr(db);
Expand Down

0 comments on commit 7687327

Please sign in to comment.