Improve performance by using dmu_tx_hold_*_by_dnode()

In zfs_write() and dmu_tx_hold_sa(), we can use dmu_tx_hold_*_by_dnode()
instead of dmu_tx_hold_*(), since we already have a dbuf from the target
dnode in hand.  This eliminates some calls to dnode_hold(), which can be
expensive.  This is especially impactful if several threads are
accessing objects that are in the same block of dnodes, because they
will contend for that dbuf's lock.

We are seeing 10-20% performance wins for the sequential_writes tests in
the performance test suite, when doing >=128K writes to files with
recordsize=8K.

This also removes some unnecessary casts that are in the area.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Tony Nguyen <tony.nguyen@delphix.com>
Signed-off-by: Matthew Ahrens <mahrens@delphix.com>
Closes #9081
This commit is contained in:
Matthew Ahrens 2019-07-30 09:18:30 -07:00 committed by Tony Hutter
parent 8c00159411
commit 6c9882d5db
3 changed files with 15 additions and 9 deletions

View File

@ -1338,7 +1338,10 @@ dmu_tx_hold_sa(dmu_tx_t *tx, sa_handle_t *hdl, boolean_t may_grow)
object = sa_handle_object(hdl); object = sa_handle_object(hdl);
dmu_tx_hold_bonus(tx, object); dmu_buf_impl_t *db = (dmu_buf_impl_t *)hdl->sa_bonus;
DB_DNODE_ENTER(db);
dmu_tx_hold_bonus_by_dnode(tx, DB_DNODE(db));
DB_DNODE_EXIT(db);
if (tx->tx_objset->os_sa->sa_master_obj == 0) if (tx->tx_objset->os_sa->sa_master_obj == 0)
return; return;
@ -1360,7 +1363,6 @@ dmu_tx_hold_sa(dmu_tx_t *tx, sa_handle_t *hdl, boolean_t may_grow)
ASSERT(tx->tx_txg == 0); ASSERT(tx->tx_txg == 0);
dmu_tx_hold_spill(tx, object); dmu_tx_hold_spill(tx, object);
} else { } else {
dmu_buf_impl_t *db = (dmu_buf_impl_t *)hdl->sa_bonus;
dnode_t *dn; dnode_t *dn;
DB_DNODE_ENTER(db); DB_DNODE_ENTER(db);

View File

@ -1380,7 +1380,7 @@ sa_handle_destroy(sa_handle_t *hdl)
dmu_buf_rele(hdl->sa_bonus, NULL); dmu_buf_rele(hdl->sa_bonus, NULL);
if (hdl->sa_spill) if (hdl->sa_spill)
dmu_buf_rele((dmu_buf_t *)hdl->sa_spill, NULL); dmu_buf_rele(hdl->sa_spill, NULL);
mutex_exit(&hdl->sa_lock); mutex_exit(&hdl->sa_lock);
kmem_cache_free(sa_cache, hdl); kmem_cache_free(sa_cache, hdl);
@ -2028,7 +2028,7 @@ sa_bulk_update_impl(sa_handle_t *hdl, sa_bulk_attr_t *bulk, int count,
hdl->sa_spill_tab = NULL; hdl->sa_spill_tab = NULL;
} }
dmu_buf_rele((dmu_buf_t *)hdl->sa_spill, NULL); dmu_buf_rele(hdl->sa_spill, NULL);
hdl->sa_spill = NULL; hdl->sa_spill = NULL;
} }
@ -2131,13 +2131,13 @@ sa_remove(sa_handle_t *hdl, sa_attr_type_t attr, dmu_tx_t *tx)
void void
sa_object_info(sa_handle_t *hdl, dmu_object_info_t *doi) sa_object_info(sa_handle_t *hdl, dmu_object_info_t *doi)
{ {
dmu_object_info_from_db((dmu_buf_t *)hdl->sa_bonus, doi); dmu_object_info_from_db(hdl->sa_bonus, doi);
} }
void void
sa_object_size(sa_handle_t *hdl, uint32_t *blksize, u_longlong_t *nblocks) sa_object_size(sa_handle_t *hdl, uint32_t *blksize, u_longlong_t *nblocks)
{ {
dmu_object_size_from_db((dmu_buf_t *)hdl->sa_bonus, dmu_object_size_from_db(hdl->sa_bonus,
blksize, nblocks); blksize, nblocks);
} }
@ -2150,7 +2150,7 @@ sa_set_userp(sa_handle_t *hdl, void *ptr)
dmu_buf_t * dmu_buf_t *
sa_get_db(sa_handle_t *hdl) sa_get_db(sa_handle_t *hdl)
{ {
return ((dmu_buf_t *)hdl->sa_bonus); return (hdl->sa_bonus);
} }
void * void *

View File

@ -775,7 +775,11 @@ zfs_write(struct inode *ip, uio_t *uio, int ioflag, cred_t *cr)
*/ */
dmu_tx_t *tx = dmu_tx_create(zfsvfs->z_os); dmu_tx_t *tx = dmu_tx_create(zfsvfs->z_os);
dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE); dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
dmu_tx_hold_write(tx, zp->z_id, woff, MIN(n, max_blksz)); dmu_buf_impl_t *db = (dmu_buf_impl_t *)sa_get_db(zp->z_sa_hdl);
DB_DNODE_ENTER(db);
dmu_tx_hold_write_by_dnode(tx, DB_DNODE(db), woff,
MIN(n, max_blksz));
DB_DNODE_EXIT(db);
zfs_sa_upgrade_txholds(tx, zp); zfs_sa_upgrade_txholds(tx, zp);
error = dmu_tx_assign(tx, TXG_WAIT); error = dmu_tx_assign(tx, TXG_WAIT);
if (error) { if (error) {
@ -1048,7 +1052,7 @@ zfs_get_data(void *arg, lr_write_t *lr, char *buf, struct lwb *lwb, zio_t *zio)
return (SET_ERROR(ENOENT)); return (SET_ERROR(ENOENT));
} }
zgd = (zgd_t *)kmem_zalloc(sizeof (zgd_t), KM_SLEEP); zgd = kmem_zalloc(sizeof (zgd_t), KM_SLEEP);
zgd->zgd_lwb = lwb; zgd->zgd_lwb = lwb;
zgd->zgd_private = zp; zgd->zgd_private = zp;