Print this page
Possibility to physically reserve space without writing leaf blocks

*** 1019,1029 **** (void) arc_release(db->db_buf, db); } dbuf_dirty_record_t * ! dbuf_dirty(dmu_buf_impl_t *db, dmu_tx_t *tx) { dnode_t *dn; objset_t *os; dbuf_dirty_record_t **drp, *dr; int drop_struct_lock = FALSE; --- 1019,1037 ---- (void) arc_release(db->db_buf, db); } dbuf_dirty_record_t * ! dbuf_zero_dirty(dmu_buf_impl_t *db, dmu_tx_t *tx) ! { ! ASSERT(db->db_objset != NULL); ! ! return (dbuf_dirty(db, tx, B_TRUE)); ! } ! ! dbuf_dirty_record_t * ! dbuf_dirty(dmu_buf_impl_t *db, dmu_tx_t *tx, boolean_t zero_write) { dnode_t *dn; objset_t *os; dbuf_dirty_record_t **drp, *dr; int drop_struct_lock = FALSE;
*** 1150,1159 **** --- 1158,1168 ---- * If this buffer is dirty in an old transaction group we need * to make a copy of it so that the changes we make in this * transaction group won't leak out when we sync the older txg. */ dr = kmem_zalloc(sizeof (dbuf_dirty_record_t), KM_SLEEP); + dr->dr_zero_write = zero_write; if (db->db_level == 0) { void *data_old = db->db_buf; if (db->db_state != DB_NOFILL) { if (db->db_blkid == DMU_BONUS_BLKID) {
*** 1263,1273 **** parent_held = TRUE; } if (drop_struct_lock) rw_exit(&dn->dn_struct_rwlock); ASSERT3U(db->db_level+1, ==, parent->db_level); ! di = dbuf_dirty(parent, tx); if (parent_held) dbuf_rele(parent, FTAG); mutex_enter(&db->db_mtx); /* --- 1272,1282 ---- parent_held = TRUE; } if (drop_struct_lock) rw_exit(&dn->dn_struct_rwlock); ASSERT3U(db->db_level+1, ==, parent->db_level); ! di = dbuf_dirty(parent, tx, B_FALSE); if (parent_held) dbuf_rele(parent, FTAG); mutex_enter(&db->db_mtx); /*
*** 1406,1416 **** DB_DNODE_ENTER(db); if (RW_WRITE_HELD(&DB_DNODE(db)->dn_struct_rwlock)) rf |= DB_RF_HAVESTRUCT; DB_DNODE_EXIT(db); (void) dbuf_read(db, NULL, rf); ! (void) dbuf_dirty(db, tx); } void dmu_buf_will_not_fill(dmu_buf_t *db_fake, dmu_tx_t *tx) { --- 1415,1425 ---- DB_DNODE_ENTER(db); if (RW_WRITE_HELD(&DB_DNODE(db)->dn_struct_rwlock)) rf |= DB_RF_HAVESTRUCT; DB_DNODE_EXIT(db); (void) dbuf_read(db, NULL, rf); ! (void) dbuf_dirty(db, tx, B_FALSE); } void dmu_buf_will_not_fill(dmu_buf_t *db_fake, dmu_tx_t *tx) {
*** 1433,1443 **** ASSERT(db->db.db_object != DMU_META_DNODE_OBJECT || dmu_tx_private_ok(tx)); dbuf_noread(db); ! (void) dbuf_dirty(db, tx); } #pragma weak dmu_buf_fill_done = dbuf_fill_done /* ARGSUSED */ void --- 1442,1470 ---- ASSERT(db->db.db_object != DMU_META_DNODE_OBJECT || dmu_tx_private_ok(tx)); dbuf_noread(db); ! (void) dbuf_dirty(db, tx, B_FALSE); ! } ! ! ! void ! dmu_buf_will_zero_fill(dmu_buf_t *db_fake, dmu_tx_t *tx) ! { ! dmu_buf_impl_t *db = (dmu_buf_impl_t *)db_fake; ! ! ASSERT(db->db_blkid != DMU_BONUS_BLKID); ! ASSERT(tx->tx_txg != 0); ! ASSERT(db->db_level == 0); ! ASSERT(!refcount_is_zero(&db->db_holds)); ! ! ASSERT(db->db.db_object != DMU_META_DNODE_OBJECT || ! dmu_tx_private_ok(tx)); ! ! dbuf_noread(db); ! (void) dbuf_zero_dirty(db, tx); } #pragma weak dmu_buf_fill_done = dbuf_fill_done /* ARGSUSED */ void
*** 1518,1528 **** ASSERT(db->db_state == DB_CACHED || db->db_state == DB_UNCACHED); if (db->db_state == DB_CACHED && refcount_count(&db->db_holds) - 1 > db->db_dirtycnt) { mutex_exit(&db->db_mtx); ! (void) dbuf_dirty(db, tx); bcopy(buf->b_data, db->db.db_data, db->db.db_size); VERIFY(arc_buf_remove_ref(buf, db)); xuio_stat_wbuf_copied(); return; } --- 1545,1555 ---- ASSERT(db->db_state == DB_CACHED || db->db_state == DB_UNCACHED); if (db->db_state == DB_CACHED && refcount_count(&db->db_holds) - 1 > db->db_dirtycnt) { mutex_exit(&db->db_mtx); ! (void) dbuf_dirty(db, tx, B_FALSE); bcopy(buf->b_data, db->db.db_data, db->db.db_size); VERIFY(arc_buf_remove_ref(buf, db)); xuio_stat_wbuf_copied(); return; }
*** 1549,1559 **** } ASSERT(db->db_buf == NULL); dbuf_set_data(db, buf); db->db_state = DB_FILL; mutex_exit(&db->db_mtx); ! (void) dbuf_dirty(db, tx); dmu_buf_fill_done(&db->db, tx); } /* * "Clear" the contents of this dbuf. This will mark the dbuf --- 1576,1586 ---- } ASSERT(db->db_buf == NULL); dbuf_set_data(db, buf); db->db_state = DB_FILL; mutex_exit(&db->db_mtx); ! (void) dbuf_dirty(db, tx, B_FALSE); dmu_buf_fill_done(&db->db, tx); } /* * "Clear" the contents of this dbuf. This will mark the dbuf
*** 2818,2827 **** --- 2845,2864 ---- wp_flag |= (db->db_state == DB_NOFILL) ? WP_NOFILL : 0; dmu_write_policy(os, dn, db->db_level, wp_flag, &zp); DB_DNODE_EXIT(db); + if (dr->dr_zero_write) { + zp.zp_zero_write = B_TRUE; + + if (!spa_feature_is_active(os->os_spa, SPA_FEATURE_SPACE_RESERVATION)) + { + spa_feature_incr(os->os_spa, + SPA_FEATURE_SPACE_RESERVATION, tx); + } + } + if (db->db_level == 0 && dr->dt.dl.dr_override_state == DR_OVERRIDDEN) { /* * The BP for this block has been provided by open context * (by dmu_sync() or dmu_buf_write_embedded()).