usr/src/uts/common/fs/zfs/dbuf.c
changeset 13298 c234f438c0d3
parent 13026 8a1c615ca92b
child 13700 2889e2596bd6
equal deleted inserted replaced
13297:4b9dc4ca8e9f 13298:c234f438c0d3
    18  *
    18  *
    19  * CDDL HEADER END
    19  * CDDL HEADER END
    20  */
    20  */
    21 /*
    21 /*
    22  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
    22  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
       
    23  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
    23  */
    24  */
    24 
    25 
    25 #include <sys/zfs_context.h>
    26 #include <sys/zfs_context.h>
    26 #include <sys/dmu.h>
    27 #include <sys/dmu.h>
    27 #include <sys/dmu_impl.h>
    28 #include <sys/dmu_impl.h>
  1298 	/*
  1299 	/*
  1299 	 * If this buffer is currently held, we cannot undirty
  1300 	 * If this buffer is currently held, we cannot undirty
  1300 	 * it, since one of the current holders may be in the
  1301 	 * it, since one of the current holders may be in the
  1301 	 * middle of an update.  Note that users of dbuf_undirty()
  1302 	 * middle of an update.  Note that users of dbuf_undirty()
  1302 	 * should not place a hold on the dbuf before the call.
  1303 	 * should not place a hold on the dbuf before the call.
       
  1304 	 * Also note: we can get here with a spill block, so
       
  1305 	 * test for that similar to how dbuf_dirty does.
  1303 	 */
  1306 	 */
  1304 	if (refcount_count(&db->db_holds) > db->db_dirtycnt) {
  1307 	if (refcount_count(&db->db_holds) > db->db_dirtycnt) {
  1305 		mutex_exit(&db->db_mtx);
  1308 		mutex_exit(&db->db_mtx);
  1306 		/* Make sure we don't toss this buffer at sync phase */
  1309 		/* Make sure we don't toss this buffer at sync phase */
  1307 		mutex_enter(&dn->dn_mtx);
  1310 		if (db->db_blkid != DMU_SPILL_BLKID) {
  1308 		dnode_clear_range(dn, db->db_blkid, 1, tx);
  1311 			mutex_enter(&dn->dn_mtx);
  1309 		mutex_exit(&dn->dn_mtx);
  1312 			dnode_clear_range(dn, db->db_blkid, 1, tx);
       
  1313 			mutex_exit(&dn->dn_mtx);
       
  1314 		}
  1310 		DB_DNODE_EXIT(db);
  1315 		DB_DNODE_EXIT(db);
  1311 		return (0);
  1316 		return (0);
  1312 	}
  1317 	}
  1313 
  1318 
  1314 	dprintf_dbuf(db, "size=%llx\n", (u_longlong_t)db->db.db_size);
  1319 	dprintf_dbuf(db, "size=%llx\n", (u_longlong_t)db->db.db_size);
  1317 
  1322 
  1318 	/* XXX would be nice to fix up dn_towrite_space[] */
  1323 	/* XXX would be nice to fix up dn_towrite_space[] */
  1319 
  1324 
  1320 	*drp = dr->dr_next;
  1325 	*drp = dr->dr_next;
  1321 
  1326 
       
  1327 	/*
       
  1328 	 * Note that there are three places in dbuf_dirty()
       
  1329 	 * where this dirty record may be put on a list.
       
  1330 	 * Make sure to do a list_remove corresponding to
       
  1331 	 * every one of those list_insert calls.
       
  1332 	 */
  1322 	if (dr->dr_parent) {
  1333 	if (dr->dr_parent) {
  1323 		mutex_enter(&dr->dr_parent->dt.di.dr_mtx);
  1334 		mutex_enter(&dr->dr_parent->dt.di.dr_mtx);
  1324 		list_remove(&dr->dr_parent->dt.di.dr_children, dr);
  1335 		list_remove(&dr->dr_parent->dt.di.dr_children, dr);
  1325 		mutex_exit(&dr->dr_parent->dt.di.dr_mtx);
  1336 		mutex_exit(&dr->dr_parent->dt.di.dr_mtx);
  1326 	} else if (db->db_level+1 == dn->dn_nlevels) {
  1337 	} else if (db->db_blkid == DMU_SPILL_BLKID ||
       
  1338 	    db->db_level+1 == dn->dn_nlevels) {
  1327 		ASSERT(db->db_blkptr == NULL || db->db_parent == dn->dn_dbuf);
  1339 		ASSERT(db->db_blkptr == NULL || db->db_parent == dn->dn_dbuf);
  1328 		mutex_enter(&dn->dn_mtx);
  1340 		mutex_enter(&dn->dn_mtx);
  1329 		list_remove(&dn->dn_dirty_records[txg & TXG_MASK], dr);
  1341 		list_remove(&dn->dn_dirty_records[txg & TXG_MASK], dr);
  1330 		mutex_exit(&dn->dn_mtx);
  1342 		mutex_exit(&dn->dn_mtx);
  1331 	}
  1343 	}