FreeBSD/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
/*
 * This is our just-in-time copy function.  It makes a copy of
 * buffers, that have been modified in a previous transaction
 * group, before we modify them in the current active group.
 *
 * This function is used in two places: when we are dirtying a
 * buffer for the first time in a txg, and when we are freeing
 * a range in a dnode that includes this buffer.
 *
 * Note that when we are called from dbuf_free_range() we do
 * not put a hold on the buffer, we just traverse the active
 * dbuf list for the dnode.
 */
This is our just-in-time copy function.  It makes a copy of
buffers, that have been modified in a previous transaction
group, before we modify them in the current active group.

This function is used in two places: when we are dirtying a
buffer for the first time in a txg, and when we are freeing
a range in a dnode that includes this buffer.

Note that when we are called from dbuf_free_range() we do
not put a hold on the buffer, we just traverse the active
dbuf list for the dnode.
This is our just - in - time copy function . It makes a copy of buffers that have been modified in a previous transaction group before we modify them in the current active group . This function is used in two places : when we are dirtying a buffer for the first time in a txg and when we are freeing a range in a dnode that includes this buffer . Note that when we are called from dbuf_free_range () we do not put a hold on the buffer we just traverse the active dbuf list for the dnode .
static void
dbuf_fix_old_data(dmu_buf_impl_t *db, uint64_t txg)
{
	dbuf_dirty_record_t *dr = db->db_last_dirty;
	ASSERT(MUTEX_HELD(&db->db_mtx));
	ASSERT(db->db.db_data != NULL);
	ASSERT(db->db_level == 0);
	ASSERT(db->db.db_object != DMU_META_DNODE_OBJECT);
	if (dr == NULL ||
	    (dr->dt.dl.dr_data !=
	    ((db->db_blkid  == DMU_BONUS_BLKID) ? db->db.db_data : db->db_buf)))
		return;
	ASSERT(dr->dr_txg >= txg - 2);
	if (db->db_blkid == DMU_BONUS_BLKID) {
		dr->dt.dl.dr_data = zio_buf_alloc(DN_MAX_BONUSLEN);
		arc_space_consume(DN_MAX_BONUSLEN, ARC_SPACE_OTHER);
		bcopy(db->db.db_data, dr->dt.dl.dr_data, DN_MAX_BONUSLEN);
	} else if (refcount_count(&db->db_holds) > db->db_dirtycnt) {
		int size = db->db.db_size;
		arc_buf_contents_t type = DBUF_GET_BUFC_TYPE(db);
		spa_t *spa = db->db_objset->os_spa;
		dr->dt.dl.dr_data = arc_buf_alloc(spa, size, db, type);
		bcopy(db->db.db_data, dr->dt.dl.dr_data->b_data, size);
	} else {
		dbuf_clear_data(db);
	}
}
static void dbuf_fix_old_data ( dmu_buf_impl_t * db , uint64_t txg ) { dbuf_dirty_record_t * dr = db -> db_last_dirty ; ASSERT ( MUTEX_HELD ( & db -> db_mtx ) ) ; ASSERT ( db -> db . db_data != NULL ) ; ASSERT ( db -> db_level == 0 ) ; ASSERT ( db -> db . db_object != DMU_META_DNODE_OBJECT ) ; if ( dr == NULL || ( dr -> dt . dl . dr_data != ( ( db -> db_blkid == DMU_BONUS_BLKID ) ? db -> db . db_data : db -> db_buf ) ) ) return ; ASSERT ( dr -> dr_txg >= txg - 2 ) ; if ( db -> db_blkid == DMU_BONUS_BLKID ) { dr -> dt . dl . dr_data = zio_buf_alloc ( DN_MAX_BONUSLEN ) ; arc_space_consume ( DN_MAX_BONUSLEN , ARC_SPACE_OTHER ) ; bcopy ( db -> db . db_data , dr -> dt . dl . dr_data , DN_MAX_BONUSLEN ) ; } else if ( refcount_count ( & db -> db_holds ) > db -> db_dirtycnt ) { int size = db -> db . db_size ; arc_buf_contents_t type = DBUF_GET_BUFC_TYPE ( db ) ; spa_t * spa = db -> db_objset -> os_spa ; dr -> dt . dl . dr_data = arc_buf_alloc ( spa , size , db , type ) ; bcopy ( db -> db . db_data , dr -> dt . dl . dr_data -> b_data , size ) ; } else { dbuf_clear_data ( db ) ; } }
This is our just-in-time copy function.
This is our just - in - time copy function .
/*
	 * If the last dirty record for this dbuf has not yet synced
	 * and its referencing the dbuf data, either:
	 *	reset the reference to point to a new copy,
	 * or (if there a no active holders)
	 *	just null out the current db_data pointer.
	 */ /* Note that the data bufs here are zio_bufs */