MFV r289296: 6288 dmu_buf_will_dirty could be faster
Reviewed by: George Wilson <george.wilson@delphix.com> Reviewed by: Paul Dagnelie <pcd@delphix.com> Reviewed by: Justin Gibbs <gibbs@scsiguy.com> Reviewed by: Richard Elling <Richard.Elling@RichardElling.com> Approved by: Robert Mustacchi <rm@joyent.com> Author: Matthew Ahrens <mahrens@delphix.com> illumos/illumos-gate@0f2e7d03b8
This commit is contained in:
commit
a4256278bf
@ -1115,6 +1115,32 @@ dbuf_release_bp(dmu_buf_impl_t *db)
|
||||
(void) arc_release(db->db_buf, db);
|
||||
}
|
||||
|
||||
/*
|
||||
* We already have a dirty record for this TXG, and we are being
|
||||
* dirtied again.
|
||||
*/
|
||||
static void
|
||||
dbuf_redirty(dbuf_dirty_record_t *dr)
|
||||
{
|
||||
dmu_buf_impl_t *db = dr->dr_dbuf;
|
||||
|
||||
ASSERT(MUTEX_HELD(&db->db_mtx));
|
||||
|
||||
if (db->db_level == 0 && db->db_blkid != DMU_BONUS_BLKID) {
|
||||
/*
|
||||
* If this buffer has already been written out,
|
||||
* we now need to reset its state.
|
||||
*/
|
||||
dbuf_unoverride(dr);
|
||||
if (db->db.db_object != DMU_META_DNODE_OBJECT &&
|
||||
db->db_state != DB_NOFILL) {
|
||||
/* Already released on initial dirty, so just thaw. */
|
||||
ASSERT(arc_released(db->db_buf));
|
||||
arc_buf_thaw(db->db_buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dbuf_dirty_record_t *
|
||||
dbuf_dirty(dmu_buf_impl_t *db, dmu_tx_t *tx)
|
||||
{
|
||||
@ -1187,16 +1213,7 @@ dbuf_dirty(dmu_buf_impl_t *db, dmu_tx_t *tx)
|
||||
if (dr && dr->dr_txg == tx->tx_txg) {
|
||||
DB_DNODE_EXIT(db);
|
||||
|
||||
if (db->db_level == 0 && db->db_blkid != DMU_BONUS_BLKID) {
|
||||
/*
|
||||
* If this buffer has already been written out,
|
||||
* we now need to reset its state.
|
||||
*/
|
||||
dbuf_unoverride(dr);
|
||||
if (db->db.db_object != DMU_META_DNODE_OBJECT &&
|
||||
db->db_state != DB_NOFILL)
|
||||
arc_buf_thaw(db->db_buf);
|
||||
}
|
||||
dbuf_redirty(dr);
|
||||
mutex_exit(&db->db_mtx);
|
||||
return (dr);
|
||||
}
|
||||
@ -1500,6 +1517,30 @@ dmu_buf_will_dirty(dmu_buf_t *db_fake, dmu_tx_t *tx)
|
||||
ASSERT(tx->tx_txg != 0);
|
||||
ASSERT(!refcount_is_zero(&db->db_holds));
|
||||
|
||||
/*
|
||||
* Quick check for dirtyness. For already dirty blocks, this
|
||||
* reduces runtime of this function by >90%, and overall performance
|
||||
* by 50% for some workloads (e.g. file deletion with indirect blocks
|
||||
* cached).
|
||||
*/
|
||||
mutex_enter(&db->db_mtx);
|
||||
dbuf_dirty_record_t *dr;
|
||||
for (dr = db->db_last_dirty;
|
||||
dr != NULL && dr->dr_txg >= tx->tx_txg; dr = dr->dr_next) {
|
||||
/*
|
||||
* It's possible that it is already dirty but not cached,
|
||||
* because there are some calls to dbuf_dirty() that don't
|
||||
* go through dmu_buf_will_dirty().
|
||||
*/
|
||||
if (dr->dr_txg == tx->tx_txg && db->db_state == DB_CACHED) {
|
||||
/* This dbuf is already dirty and cached. */
|
||||
dbuf_redirty(dr);
|
||||
mutex_exit(&db->db_mtx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
mutex_exit(&db->db_mtx);
|
||||
|
||||
DB_DNODE_ENTER(db);
|
||||
if (RW_WRITE_HELD(&DB_DNODE(db)->dn_struct_rwlock))
|
||||
rf |= DB_RF_HAVESTRUCT;
|
||||
|
Loading…
Reference in New Issue
Block a user