FreeBSD/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
/*
 * "Clear" the contents of this dbuf.  This will mark the dbuf
 * EVICTING and clear *most* of its references.  Unfortunately,
 * when we are not holding the dn_dbufs_mtx, we can't clear the
 * entry in the dn_dbufs list.  We have to wait until dbuf_destroy()
 * in this case.  For callers from the DMU we will usually see:
 *	dbuf_clear()->arc_clear_callback()->dbuf_do_evict()->dbuf_destroy()
 * For the arc callback, we will usually see:
 *	dbuf_do_evict()->dbuf_clear();dbuf_destroy()
 * Sometimes, though, we will get a mix of these two:
 *	DMU: dbuf_clear()->arc_clear_callback()
 *	ARC: dbuf_do_evict()->dbuf_destroy()
 *
 * This routine will dissociate the dbuf from the arc, by calling
 * arc_clear_callback(), but will not evict the data from the ARC.
 */
"Clear" the contents of this dbuf.  This will mark the dbuf
EVICTING and clear *most* of its references.  Unfortunately,
when we are not holding the dn_dbufs_mtx, we can't clear the
entry in the dn_dbufs list.  We have to wait until dbuf_destroy()
in this case.

This routine will dissociate the dbuf from the arc, by calling
arc_clear_callback(), but will not evict the data from the ARC.
" Clear " the contents of this dbuf . This will mark the dbuf EVICTING and clear * most * of its references . Unfortunately when we are not holding the dn_dbufs_mtx we can ' t clear the entry in the dn_dbufs list . We have to wait until dbuf_destroy () in this case . This routine will dissociate the dbuf from the arc by calling arc_clear_callback () but will not evict the data from the ARC .
void
dbuf_clear(dmu_buf_impl_t *db)
{
	dnode_t *dn;
	dmu_buf_impl_t *parent = db->db_parent;
	dmu_buf_impl_t *dndb;
	boolean_t dbuf_gone = B_FALSE;
	ASSERT(MUTEX_HELD(&db->db_mtx));
	ASSERT(refcount_is_zero(&db->db_holds));
	dbuf_evict_user(db);
	if (db->db_state == DB_CACHED) {
		ASSERT(db->db.db_data != NULL);
		if (db->db_blkid == DMU_BONUS_BLKID) {
			zio_buf_free(db->db.db_data, DN_MAX_BONUSLEN);
			arc_space_return(DN_MAX_BONUSLEN, ARC_SPACE_OTHER);
		}
		db->db.db_data = NULL;
		db->db_state = DB_UNCACHED;
	}
	ASSERT(db->db_state == DB_UNCACHED || db->db_state == DB_NOFILL);
	ASSERT(db->db_data_pending == NULL);
	db->db_state = DB_EVICTING;
	db->db_blkptr = NULL;
	DB_DNODE_ENTER(db);
	dn = DB_DNODE(db);
	dndb = dn->dn_dbuf;
	if (db->db_blkid != DMU_BONUS_BLKID && MUTEX_HELD(&dn->dn_dbufs_mtx)) {
		avl_remove(&dn->dn_dbufs, db);
		atomic_dec_32(&dn->dn_dbufs_count);
		membar_producer();
		DB_DNODE_EXIT(db);
		dnode_rele(dn, db);
		db->db_dnode_handle = NULL;
	} else {
		DB_DNODE_EXIT(db);
	}
	if (db->db_buf)
		dbuf_gone = arc_clear_callback(db->db_buf);
	if (!dbuf_gone)
		mutex_exit(&db->db_mtx);
	if (parent && parent != dndb)
		dbuf_rele(parent, db);
}
void dbuf_clear ( dmu_buf_impl_t * db ) { dnode_t * dn ; dmu_buf_impl_t * parent = db -> db_parent ; dmu_buf_impl_t * dndb ; boolean_t dbuf_gone = B_FALSE ; ASSERT ( MUTEX_HELD ( & db -> db_mtx ) ) ; ASSERT ( refcount_is_zero ( & db -> db_holds ) ) ; dbuf_evict_user ( db ) ; if ( db -> db_state == DB_CACHED ) { ASSERT ( db -> db . db_data != NULL ) ; if ( db -> db_blkid == DMU_BONUS_BLKID ) { zio_buf_free ( db -> db . db_data , DN_MAX_BONUSLEN ) ; arc_space_return ( DN_MAX_BONUSLEN , ARC_SPACE_OTHER ) ; } db -> db . db_data = NULL ; db -> db_state = DB_UNCACHED ; } ASSERT ( db -> db_state == DB_UNCACHED || db -> db_state == DB_NOFILL ) ; ASSERT ( db -> db_data_pending == NULL ) ; db -> db_state = DB_EVICTING ; db -> db_blkptr = NULL ; DB_DNODE_ENTER ( db ) ; dn = DB_DNODE ( db ) ; dndb = dn -> dn_dbuf ; if ( db -> db_blkid != DMU_BONUS_BLKID && MUTEX_HELD ( & dn -> dn_dbufs_mtx ) ) { avl_remove ( & dn -> dn_dbufs , db ) ; atomic_dec_32 ( & dn -> dn_dbufs_count ) ; membar_producer ( ) ; DB_DNODE_EXIT ( db ) ; dnode_rele ( dn , db ) ; db -> db_dnode_handle = NULL ; } else { DB_DNODE_EXIT ( db ) ; } if ( db -> db_buf ) dbuf_gone = arc_clear_callback ( db -> db_buf ) ; if ( ! dbuf_gone ) mutex_exit ( & db -> db_mtx ) ; if ( parent && parent != dndb ) dbuf_rele ( parent , db ) ; }
"Clear" the contents of this dbuf.
" Clear " the contents of this dbuf .
/*
		 * Decrementing the dbuf count means that the hold corresponding
		 * to the removed dbuf is no longer discounted in dnode_move(),
		 * so the dnode cannot be moved until after we release the hold.
		 * The membar_producer() ensures visibility of the decremented
		 * value in dnode_move(), since DB_DNODE_EXIT doesn't actually
		 * release any lock.
		 */ /*
	 * If this dbuf is referenced from an indirect dbuf,
	 * decrement the ref count on the indirect dbuf.
	 */