Skip to content

Commit

Permalink
Illumos 6288 dmu_buf_will_dirty could be faster
Browse files Browse the repository at this point in the history
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>

References:
https://www.illumos.org/issues/6288 dmu_buf_will_dirty could be faster
illumos/illumos-gate@0f2e7d0

Ported-by: kernelOfTruth kerneloftruth@gmail.com
  • Loading branch information
ahrens authored and kernelOfTruth committed Nov 4, 2015
1 parent b23d543 commit 640fead
Showing 1 changed file with 51 additions and 10 deletions.
61 changes: 51 additions & 10 deletions module/zfs/dbuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1162,6 +1162,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)
{
Expand Down Expand Up @@ -1234,16 +1260,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);
}
Expand Down Expand Up @@ -1548,6 +1565,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;
Expand Down

0 comments on commit 640fead

Please sign in to comment.