dnode.c revision 3b83abdd1d7e7b52c4baa3de2742ab154fa69902
0N/A * The contents of this file are subject to the terms of the 0N/A * Common Development and Distribution License, Version 1.0 only 0N/A * (the "License"). You may not use this file except in compliance 0N/A * See the License for the specific language governing permissions 0N/A * and limitations under the License. 0N/A * When distributing Covered Code, include this CDDL HEADER in each 0N/A * If applicable, add the following below this CDDL HEADER, with the 0N/A * fields enclosed by brackets "[]" replaced with your own identifying 0N/A * information: Portions Copyright [yyyy] [name of copyright owner] 0N/A * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 0N/A * Use is subject to license terms. 1879N/A#
pragma ident "%Z%%M% %I% %E% SMI" 0N/A * dn_nblkptr is only one byte, so it's OK to read it in either 0N/A * byte order. We can't read dn_bouslen. 0N/A * OK to check dn_bonuslen for zero, because it won't matter if 0N/A * we have the wrong byte order. This is necessary because the 0N/A * dnode dnode is smaller than a regular dnode. 0N/A * Note that the bonus length calculated here may be 0N/A * longer than the actual bonus buffer. This is because 0N/A * we always put the bonus buffer after the last block 2062N/A * pointer (instead of packing it against the end of the * XXX I should really have a generation number to tell if we /* don't need dd_dirty_mtx, dnode is already dirty */ /* change bonus size and type */ for (i = 0; i <
epb; i++) {
* If there are holds on this dnode, then there should * be holds on the dnode's containing dbuf as well; thus * it wouldn't be eligable for eviction and this function * would not have been called. * Returns held dnode if the object number is valid, NULL if not. * Note that this will succeed even for free dnodes. * Return held dnode if the object is allocated, NULL if not. /* NOTE: the DNODE_DNODE does not have a dn_dbuf */ /* ASSERT(dn->dn_free_txg == 0 || dn->dn_free_txg >= txg); */ * If we are already marked dirty, we're done. * The dnode maintains a hold on its containing dbuf as * long as there are holds on it. Each instantiated child * dbuf maintaines a hold on the dnode. When the last child * drops its hold, the dnode will drop its hold on the * containing dbuf. We add a "dirty hold" here so that the * dnode will hang around after we finish processing its /* we should be the only holder... hopefully */ /* ASSERT3U(refcount_count(&dn->dn_holds), ==, 1); */ * If the dnode is already dirty, it needs to be moved from * the dirty list to the free list. * Try to change the block size for the indicated dnode. This can only * succeed if there are no blocks allocated or dirty beyond first block /* Check for any allocated blocks beyond the first */ * Any buffers allocated for blocks beyond the first * Since we have the dn_dbufs_mtx, nothing can be * removed from dn_dbufs. Since we have dn_struct_rwlock/w, * nothing can be added to dn_dbufs. /* Fast-track if there is no data in the file */ /* don't need dd_dirty_mtx, dnode is already dirty */ /* obtain the old block */ /* Not allowed to decrease the size if there is data present */ /* don't need dd_dirty_mtx, dnode is already dirty */ * Compute the number of levels necessary to support the dprintf(
"dn %p increasing nlevels from %u to %u\n",
* Dirty the left indirects. * Note: the caller should have just dnode_use_space()'d one * data block's worth, so we could subtract that out of * dn_inflight_data to determine if there is any dirty data * We don't strictly need to dirty them unless there's * *something* in the object (eg. on disk or dirty)... dprintf(
"dn %p dirtying left indirects\n",
dn);
/* clear this entire range */ /* clear the beginning of this range */ /* clear the end of this range */ /* clear a chunk out of this range */ /* there may be no overlap */ /* If the range is past the end of the file, this is a no-op */ * First, block align the region to free: /* zero out any partial block data at the start of the range */ /* don't dirty if it isn't on disk and isn't dirty */ /* If the range was less than one block, we are done */ /* If the remaining range is past the end of the file, we are done */ /* zero out any partial block data at the end of the range */ /* don't dirty if it isn't on disk and isn't dirty */ /* If the range did not include a full block, we are done */ /* dirty the left indirects */ /* dirty the right indirects */ * Finally, add this range to the dnode range list, we * will finish up this free operation in the syncing phase. /* Add new range to dn_ranges */ /* return TRUE if this blkid was freed in a recent txg, or FALSE if it wasn't */ * If we're in the process of opening the pool, dp will not be * set yet, but there shouldn't be anything dirty. * If dn_datablkshift is not set, then there's only a single * block, in which case there will never be a free range so it /* call from syncing context when we actually write/free space for this dnode */ * Call when we think we're going to write/free space in open context. * Be conservative (ie. OK to write less than this or free more than * this, but don't write more or free less). dprintf(
"probing object %llu offset %llx level %d of %u\n",
* Find the next hole, data, or sparse region at or after *offset. * The value 'blkfill' tells us how many items we expect to find * in an L0 data block; this value is 1 for normal objects, * DNODES_PER_BLOCK for the meta dnode, and some fraction of * DNODES_PER_BLOCK when searching for sparse regions thereof. * dnode_next_offset(dn, hole, offset, 1, 1); * Used in dmu_offset_next(). * dnode_next_offset(mdn, hole, offset, 0, DNODES_PER_BLOCK); * Used in dmu_object_next(). * dnode_next_offset(mdn, TRUE, offset, 2, DNODES_PER_BLOCK >> 2); * Finds the next L2 meta-dnode bp that's at most 1/4 full. * Used in dmu_object_alloc().