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()).