--- a/usr/src/uts/common/fs/zfs/dnode_sync.c Tue Mar 16 06:44:44 2010 -0700
+++ b/usr/src/uts/common/fs/zfs/dnode_sync.c Tue Mar 16 09:43:38 2010 -0600
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -434,7 +434,7 @@
db->db_last_dirty = NULL;
db->db_dirtycnt -= 1;
if (db->db_level == 0) {
- ASSERT(db->db_blkid == DB_BONUS_BLKID ||
+ ASSERT(db->db_blkid == DMU_BONUS_BLKID ||
dr->dt.dl.dr_data == db->db_buf);
dbuf_unoverride(dr);
}
@@ -490,6 +490,7 @@
dn->dn_maxblkid = 0;
dn->dn_allocated_txg = 0;
dn->dn_free_txg = 0;
+ dn->dn_have_spill = B_FALSE;
mutex_exit(&dn->dn_mtx);
ASSERT(dn->dn_object != DMU_META_DNODE_OBJECT);
@@ -512,6 +513,7 @@
int txgoff = tx->tx_txg & TXG_MASK;
list_t *list = &dn->dn_dirty_records[txgoff];
static const dnode_phys_t zerodn = { 0 };
+ boolean_t kill_spill = B_FALSE;
ASSERT(dmu_tx_is_syncing(tx));
ASSERT(dnp->dn_type != DMU_OT_NONE || dn->dn_allocated_txg);
@@ -523,10 +525,13 @@
if (dmu_objset_userused_enabled(dn->dn_objset) &&
!DMU_OBJECT_IS_SPECIAL(dn->dn_object)) {
- ASSERT(dn->dn_oldphys == NULL);
- dn->dn_oldphys = zio_buf_alloc(sizeof (dnode_phys_t));
- *dn->dn_oldphys = *dn->dn_phys; /* struct assignment */
+ mutex_enter(&dn->dn_mtx);
+ dn->dn_oldused = DN_USED_BYTES(dn->dn_phys);
+ dn->dn_oldflags = dn->dn_phys->dn_flags;
+ dn->dn_id_flags |= DN_ID_SYNC;
dn->dn_phys->dn_flags |= DNODE_FLAG_USERUSED_ACCOUNTED;
+ mutex_exit(&dn->dn_mtx);
+ dmu_objset_userquota_get_ids(dn, B_FALSE);
} else {
/* Once we account for it, we should always account for it. */
ASSERT(!(dn->dn_phys->dn_flags &
@@ -573,6 +578,24 @@
dn->dn_next_bonuslen[txgoff] = 0;
}
+ if (dn->dn_next_bonustype[txgoff]) {
+ ASSERT(dn->dn_next_bonustype[txgoff] < DMU_OT_NUMTYPES);
+ dnp->dn_bonustype = dn->dn_next_bonustype[txgoff];
+ dn->dn_next_bonustype[txgoff] = 0;
+ }
+
+ /*
+ * We will either remove a spill block when a file is being removed
+ * or we have been asked to remove it.
+ */
+ if (dn->dn_rm_spillblk[txgoff] ||
+ ((dnp->dn_flags & DNODE_FLAG_SPILL_BLKPTR) &&
+ dn->dn_free_txg > 0 && dn->dn_free_txg <= tx->tx_txg)) {
+ if ((dnp->dn_flags & DNODE_FLAG_SPILL_BLKPTR))
+ kill_spill = B_TRUE;
+ dn->dn_rm_spillblk[txgoff] = 0;
+ }
+
if (dn->dn_next_indblkshift[txgoff]) {
ASSERT(dnp->dn_nlevels == 1);
dnp->dn_indblkshift = dn->dn_next_indblkshift[txgoff];
@@ -589,6 +612,21 @@
mutex_exit(&dn->dn_mtx);
+ if (kill_spill) {
+ dmu_buf_impl_t *spilldb;
+ (void) free_blocks(dn, &dn->dn_phys->dn_spill, 1, tx);
+ mutex_enter(&dn->dn_mtx);
+ dnp->dn_flags &= ~DNODE_FLAG_SPILL_BLKPTR;
+ mutex_exit(&dn->dn_mtx);
+ rw_enter(&dn->dn_struct_rwlock, RW_READER);
+ spilldb = dbuf_find(dn, 0, DMU_SPILL_BLKID);
+ if (spilldb) {
+ spilldb->db_blkptr = NULL;
+ mutex_exit(&spilldb->db_mtx);
+ }
+ rw_exit(&dn->dn_struct_rwlock);
+ }
+
/* process all the "freed" ranges in the file */
while (rp = avl_last(&dn->dn_ranges[txgoff])) {
dnode_sync_free_range(dn, rp->fr_blkid, rp->fr_nblks, tx);