usr/src/uts/common/fs/zfs/dmu_tx.c
author ahrens
Mon, 31 Oct 2005 11:33:35 -0800
changeset 789 b348f31ed315
child 873 adefbfa5f42d
permissions -rw-r--r--
PSARC 2002/240 ZFS 6338653 Integrate ZFS PSARC 2004/652 - DKIOCFLUSH 5096886 Write caching disks need mechanism to flush cache to physical media
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
789
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     1
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     2
 * CDDL HEADER START
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     3
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     5
 * Common Development and Distribution License, Version 1.0 only
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     6
 * (the "License").  You may not use this file except in compliance
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     7
 * with the License.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     8
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
     9
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    10
 * or http://www.opensolaris.org/os/licensing.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    11
 * See the License for the specific language governing permissions
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    12
 * and limitations under the License.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    13
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    14
 * When distributing Covered Code, include this CDDL HEADER in each
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    15
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    16
 * If applicable, add the following below this CDDL HEADER, with the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    17
 * fields enclosed by brackets "[]" replaced with your own identifying
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    18
 * information: Portions Copyright [yyyy] [name of copyright owner]
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    19
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    20
 * CDDL HEADER END
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    21
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    22
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    23
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    24
 * Use is subject to license terms.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    25
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    26
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    27
#pragma ident	"%Z%%M%	%I%	%E% SMI"
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    28
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    29
#include <sys/dmu.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    30
#include <sys/dmu_impl.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    31
#include <sys/dbuf.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    32
#include <sys/dmu_tx.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    33
#include <sys/dmu_objset.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    34
#include <sys/dsl_dataset.h> /* for dsl_dataset_block_freeable() */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    35
#include <sys/dsl_dir.h> /* for dsl_dir_tempreserve_*() */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    36
#include <sys/dsl_pool.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    37
#include <sys/zap_impl.h>	/* for ZAP_BLOCK_SHIFT */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    38
#include <sys/spa.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    39
#include <sys/zfs_context.h>
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    40
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    41
#ifdef ZFS_DEBUG
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    42
int dmu_use_tx_debug_bufs = 1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    43
#endif
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    44
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    45
dmu_tx_t *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    46
dmu_tx_create_ds(dsl_dir_t *dd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    47
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    48
	dmu_tx_t *tx = kmem_zalloc(sizeof (dmu_tx_t), KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    49
	tx->tx_dir = dd;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    50
	if (dd)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    51
		tx->tx_pool = dd->dd_pool;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    52
	list_create(&tx->tx_holds, sizeof (dmu_tx_hold_t),
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    53
	    offsetof(dmu_tx_hold_t, dth_node));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    54
	refcount_create(&tx->tx_space_written);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    55
	refcount_create(&tx->tx_space_freed);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    56
	return (tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    57
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    58
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    59
dmu_tx_t *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    60
dmu_tx_create(objset_t *os)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    61
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    62
	dmu_tx_t *tx = dmu_tx_create_ds(os->os->os_dsl_dataset->ds_dir);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    63
	tx->tx_objset = os;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    64
	return (tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    65
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    66
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    67
dmu_tx_t *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    68
dmu_tx_create_assigned(struct dsl_pool *dp, uint64_t txg)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    69
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    70
	dmu_tx_t *tx = dmu_tx_create_ds(NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    71
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    72
	ASSERT3U(txg, <=, dp->dp_tx.tx_open_txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    73
	tx->tx_pool = dp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    74
	tx->tx_txg = txg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    75
	tx->tx_anyobj = TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    76
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    77
	return (tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    78
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    79
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    80
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    81
dmu_tx_is_syncing(dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    82
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    83
	return (tx->tx_anyobj);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    84
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    85
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    86
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    87
dmu_tx_private_ok(dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    88
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    89
	return (tx->tx_anyobj || tx->tx_privateobj);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    90
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    91
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    92
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    93
dmu_tx_hold_object_impl(dmu_tx_t *tx, objset_t *os, uint64_t object,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    94
    enum dmu_tx_hold_type type, dmu_tx_hold_func_t func,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    95
    uint64_t arg1, uint64_t arg2)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    96
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    97
	dmu_tx_hold_t *dth;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    98
	dnode_t *dn = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
    99
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   100
	if (object != DMU_NEW_OBJECT) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   101
		dn = dnode_hold(os->os, object, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   102
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   103
		if (tx->tx_txg != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   104
			mutex_enter(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   105
			/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   106
			 * dn->dn_assigned_txg == tx->tx_txg doesn't pose a
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   107
			 * problem, but there's no way for it to happen (for
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   108
			 * now, at least).
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   109
			 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   110
			ASSERT(dn->dn_assigned_txg == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   111
			ASSERT(dn->dn_assigned_tx == NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   112
			dn->dn_assigned_txg = tx->tx_txg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   113
			dn->dn_assigned_tx = tx;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   114
			(void) refcount_add(&dn->dn_tx_holds, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   115
			mutex_exit(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   116
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   117
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   118
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   119
	dth = kmem_zalloc(sizeof (dmu_tx_hold_t), KM_SLEEP);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   120
	dth->dth_dnode = dn;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   121
	dth->dth_type = type;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   122
	dth->dth_func = func;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   123
	dth->dth_arg1 = arg1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   124
	dth->dth_arg2 = arg2;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   125
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   126
	 * XXX Investigate using a different data structure to keep
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   127
	 * track of dnodes in a tx.  Maybe array, since there will
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   128
	 * generally not be many entries?
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   129
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   130
	list_insert_tail(&tx->tx_holds, dth);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   131
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   132
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   133
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   134
dmu_tx_add_new_object(dmu_tx_t *tx, objset_t *os, uint64_t object)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   135
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   136
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   137
	 * If we're syncing, they can manipulate any object anyhow, and
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   138
	 * the hold on the dnode_t can cause problems.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   139
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   140
	if (!dmu_tx_is_syncing(tx)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   141
		dmu_tx_hold_object_impl(tx, os, object, THT_NEWOBJECT,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   142
		    NULL, 0, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   143
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   144
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   145
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   146
/* ARGSUSED */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   147
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   148
dmu_tx_count_write(dmu_tx_t *tx, dnode_t *dn, uint64_t off, uint64_t len)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   149
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   150
	uint64_t start, end, space;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   151
	int min_bs, max_bs, min_ibs, max_ibs, epbs, bits;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   152
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   153
	if (len == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   154
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   155
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   156
	min_bs = SPA_MINBLOCKSHIFT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   157
	max_bs = SPA_MAXBLOCKSHIFT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   158
	min_ibs = DN_MIN_INDBLKSHIFT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   159
	max_ibs = DN_MAX_INDBLKSHIFT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   160
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   161
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   162
	 * If there's more than one block, the blocksize can't change,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   163
	 * so we can make a more precise estimate.  Alternatively,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   164
	 * if the dnode's ibs is larger than max_ibs, always use that.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   165
	 * This ensures that if we reduce DN_MAX_INDBLKSHIFT,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   166
	 * the code will still work correctly on existing pools.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   167
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   168
	if (dn && (dn->dn_maxblkid != 0 || dn->dn_indblkshift > max_ibs)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   169
		min_ibs = max_ibs = dn->dn_indblkshift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   170
		if (dn->dn_datablkshift != 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   171
			min_bs = max_bs = dn->dn_datablkshift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   172
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   173
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   174
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   175
	 * 'end' is the last thing we will access, not one past.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   176
	 * This way we won't overflow when accessing the last byte.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   177
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   178
	start = P2ALIGN(off, 1ULL << max_bs);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   179
	end = P2ROUNDUP(off + len, 1ULL << max_bs) - 1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   180
	space = end - start + 1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   181
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   182
	start >>= min_bs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   183
	end >>= min_bs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   184
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   185
	epbs = min_ibs - SPA_BLKPTRSHIFT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   186
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   187
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   188
	 * The object contains at most 2^(64 - min_bs) blocks,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   189
	 * and each indirect level maps 2^epbs.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   190
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   191
	for (bits = 64 - min_bs; bits >= 0; bits -= epbs) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   192
		start >>= epbs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   193
		end >>= epbs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   194
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   195
		 * If we increase the number of levels of indirection,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   196
		 * we'll need new blkid=0 indirect blocks.  If start == 0,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   197
		 * we're already accounting for that blocks; and if end == 0,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   198
		 * we can't increase the number of levels beyond that.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   199
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   200
		if (start != 0 && end != 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   201
			space += 1ULL << max_ibs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   202
		space += (end - start + 1) << max_ibs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   203
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   204
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   205
	ASSERT(space < 2 * DMU_MAX_ACCESS);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   206
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   207
	tx->tx_space_towrite += space;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   208
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   209
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   210
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   211
dmu_tx_count_dnode(dmu_tx_t *tx, dnode_t *dn)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   212
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   213
	dnode_t *mdn = tx->tx_objset->os->os_meta_dnode;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   214
	uint64_t object = dn ? dn->dn_object : DN_MAX_OBJECT - 1;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   215
	uint64_t pre_write_space;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   216
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   217
	ASSERT(object < DN_MAX_OBJECT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   218
	pre_write_space = tx->tx_space_towrite;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   219
	dmu_tx_count_write(tx, mdn, object << DNODE_SHIFT, 1 << DNODE_SHIFT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   220
	if (dn && dn->dn_dbuf->db_blkptr &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   221
	    dsl_dataset_block_freeable(dn->dn_objset->os_dsl_dataset,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   222
	    dn->dn_dbuf->db_blkptr->blk_birth, tx)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   223
		tx->tx_space_tooverwrite +=
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   224
			tx->tx_space_towrite - pre_write_space;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   225
		tx->tx_space_towrite = pre_write_space;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   226
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   227
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   228
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   229
/* ARGSUSED */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   230
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   231
dmu_tx_hold_write_impl(dmu_tx_t *tx, dnode_t *dn, uint64_t off, uint64_t len)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   232
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   233
	dmu_tx_count_write(tx, dn, off, len);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   234
	dmu_tx_count_dnode(tx, dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   235
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   236
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   237
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   238
dmu_tx_hold_write(dmu_tx_t *tx, uint64_t object, uint64_t off, int len)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   239
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   240
	ASSERT(tx->tx_txg == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   241
	ASSERT(len > 0 && len < DMU_MAX_ACCESS);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   242
	ASSERT(UINT64_MAX - off >= len - 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   243
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   244
	dmu_tx_hold_object_impl(tx, tx->tx_objset, object, THT_WRITE,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   245
	    dmu_tx_hold_write_impl, off, len);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   246
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   247
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   248
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   249
dmu_tx_count_free(dmu_tx_t *tx, dnode_t *dn, uint64_t off, uint64_t len)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   250
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   251
	uint64_t blkid, nblks;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   252
	uint64_t space = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   253
	dsl_dataset_t *ds = dn->dn_objset->os_dsl_dataset;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   254
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   255
	ASSERT(dn->dn_assigned_tx == tx || dn->dn_assigned_tx == NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   256
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   257
	if (dn->dn_datablkshift == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   258
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   259
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   260
	 * not that the dnode can change, since it isn't dirty, but
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   261
	 * dbuf_hold_impl() wants us to have the struct_rwlock.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   262
	 * also need it to protect dn_maxblkid.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   263
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   264
	rw_enter(&dn->dn_struct_rwlock, RW_READER);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   265
	blkid = off >> dn->dn_datablkshift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   266
	nblks = (off + len) >> dn->dn_datablkshift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   267
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   268
	if (blkid >= dn->dn_maxblkid)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   269
		goto out;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   270
	if (blkid + nblks > dn->dn_maxblkid)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   271
		nblks = dn->dn_maxblkid - blkid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   272
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   273
	/* don't bother after the 100,000 blocks */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   274
	nblks = MIN(nblks, 128*1024);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   275
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   276
	if (dn->dn_phys->dn_nlevels == 1) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   277
		int i;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   278
		for (i = 0; i < nblks; i++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   279
			blkptr_t *bp = dn->dn_phys->dn_blkptr;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   280
			ASSERT3U(blkid + i, <, dn->dn_phys->dn_nblkptr);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   281
			bp += blkid + i;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   282
			if (dsl_dataset_block_freeable(ds, bp->blk_birth, tx)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   283
				dprintf_bp(bp, "can free old%s", "");
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   284
				space += BP_GET_ASIZE(bp);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   285
			}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   286
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   287
		goto out;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   288
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   289
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   290
	while (nblks) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   291
		dmu_buf_impl_t *dbuf;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   292
		int err, epbs, blkoff, tochk;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   293
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   294
		epbs = dn->dn_indblkshift - SPA_BLKPTRSHIFT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   295
		blkoff = P2PHASE(blkid, 1<<epbs);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   296
		tochk = MIN((1<<epbs) - blkoff, nblks);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   297
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   298
		err = dbuf_hold_impl(dn, 1, blkid >> epbs, TRUE, FTAG, &dbuf);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   299
		if (err == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   300
			int i;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   301
			blkptr_t *bp;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   302
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   303
			dbuf_read_havestruct(dbuf);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   304
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   305
			bp = dbuf->db.db_data;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   306
			bp += blkoff;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   307
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   308
			for (i = 0; i < tochk; i++) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   309
				if (dsl_dataset_block_freeable(ds,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   310
				    bp[i].blk_birth, tx)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   311
					dprintf_bp(&bp[i],
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   312
					    "can free old%s", "");
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   313
					space += BP_GET_ASIZE(&bp[i]);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   314
				}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   315
			}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   316
			dbuf_remove_ref(dbuf, FTAG);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   317
		} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   318
			/* the indirect block is sparse */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   319
			ASSERT(err == ENOENT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   320
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   321
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   322
		blkid += tochk;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   323
		nblks -= tochk;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   324
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   325
out:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   326
	rw_exit(&dn->dn_struct_rwlock);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   327
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   328
	tx->tx_space_tofree += space;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   329
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   330
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   331
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   332
dmu_tx_hold_free_impl(dmu_tx_t *tx, dnode_t *dn, uint64_t off, uint64_t len)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   333
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   334
	int dirty;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   335
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   336
	/* first block */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   337
	if (off != 0 /* || dn->dn_maxblkid == 0 */)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   338
		dmu_tx_count_write(tx, dn, off, 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   339
	/* last block */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   340
	if (len != DMU_OBJECT_END)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   341
		dmu_tx_count_write(tx, dn, off+len, 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   342
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   343
	dmu_tx_count_dnode(tx, dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   344
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   345
	if (off >= (dn->dn_maxblkid+1) * dn->dn_datablksz)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   346
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   347
	if (len == DMU_OBJECT_END)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   348
		len = (dn->dn_maxblkid+1) * dn->dn_datablksz - off;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   349
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   350
	/* XXX locking */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   351
	dirty = dn->dn_dirtyblksz[0] | dn->dn_dirtyblksz[1] |
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   352
	    dn->dn_dirtyblksz[2] | dn->dn_dirtyblksz[3];
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   353
	if (dn->dn_assigned_tx != NULL && !dirty)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   354
		dmu_tx_count_free(tx, dn, off, len);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   355
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   356
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   357
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   358
dmu_tx_hold_free(dmu_tx_t *tx, uint64_t object, uint64_t off, uint64_t len)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   359
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   360
	ASSERT(tx->tx_txg == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   361
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   362
	dmu_tx_hold_object_impl(tx, tx->tx_objset, object, THT_FREE,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   363
	    dmu_tx_hold_free_impl, off, len);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   364
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   365
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   366
/* ARGSUSED */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   367
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   368
dmu_tx_hold_zap_impl(dmu_tx_t *tx, dnode_t *dn, uint64_t nops, uint64_t cops)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   369
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   370
	uint64_t nblocks;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   371
	int epbs;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   372
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   373
	dmu_tx_count_dnode(tx, dn);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   374
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   375
	if (dn == NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   376
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   377
		 * Assuming that nops+cops is not super huge, we will be
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   378
		 * able to fit a new object's entries into one leaf
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   379
		 * block.  So there will be at most 2 blocks total,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   380
		 * including the header block.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   381
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   382
		dmu_tx_count_write(tx, dn, 0, 2 << ZAP_BLOCK_SHIFT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   383
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   384
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   385
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   386
	ASSERT3P(dmu_ot[dn->dn_type].ot_byteswap, ==, zap_byteswap);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   387
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   388
	if (dn->dn_maxblkid == 0 && nops == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   389
		/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   390
		 * If there is only one block  (i.e. this is a micro-zap)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   391
		 * and we are only doing updates, the accounting is simple.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   392
		 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   393
		if (dsl_dataset_block_freeable(dn->dn_objset->os_dsl_dataset,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   394
		    dn->dn_phys->dn_blkptr[0].blk_birth, tx))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   395
			tx->tx_space_tooverwrite += dn->dn_datablksz;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   396
		else
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   397
			tx->tx_space_towrite += dn->dn_datablksz;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   398
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   399
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   400
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   401
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   402
	 * 3 blocks overwritten per op: target leaf, ptrtbl block, header block
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   403
	 * 3 new blocks written per op: new split leaf, 2 grown ptrtbl blocks
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   404
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   405
	dmu_tx_count_write(tx, dn, dn->dn_maxblkid * dn->dn_datablksz,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   406
	    (nops * 6ULL + cops * 3ULL) << ZAP_BLOCK_SHIFT);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   407
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   408
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   409
	 * If the modified blocks are scattered to the four winds,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   410
	 * we'll have to modify an indirect twig for each.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   411
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   412
	epbs = dn->dn_indblkshift - SPA_BLKPTRSHIFT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   413
	for (nblocks = dn->dn_maxblkid >> epbs; nblocks != 0; nblocks >>= epbs)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   414
		tx->tx_space_towrite +=
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   415
		    ((nops + cops) * 3ULL) << dn->dn_indblkshift;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   416
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   417
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   418
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   419
dmu_tx_hold_zap(dmu_tx_t *tx, uint64_t object, int ops)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   420
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   421
	ASSERT(tx->tx_txg == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   422
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   423
	dmu_tx_hold_object_impl(tx, tx->tx_objset, object, THT_ZAP,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   424
	    dmu_tx_hold_zap_impl, (ops > 0?ops:0), (ops < 0?-ops:0));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   425
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   426
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   427
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   428
dmu_tx_hold_bonus(dmu_tx_t *tx, uint64_t object)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   429
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   430
	ASSERT(tx->tx_txg == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   431
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   432
	dmu_tx_hold_object_impl(tx, tx->tx_objset, object, THT_BONUS,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   433
	    dmu_tx_hold_write_impl, 0, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   434
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   435
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   436
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   437
/* ARGSUSED */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   438
static void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   439
dmu_tx_hold_space_impl(dmu_tx_t *tx, dnode_t *dn,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   440
    uint64_t space, uint64_t unused)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   441
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   442
	tx->tx_space_towrite += space;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   443
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   444
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   445
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   446
dmu_tx_hold_space(dmu_tx_t *tx, uint64_t space)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   447
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   448
	ASSERT(tx->tx_txg == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   449
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   450
	dmu_tx_hold_object_impl(tx, tx->tx_objset, DMU_NEW_OBJECT, THT_SPACE,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   451
	    dmu_tx_hold_space_impl, space, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   452
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   453
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   454
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   455
dmu_tx_holds(dmu_tx_t *tx, uint64_t object)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   456
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   457
	dmu_tx_hold_t *dth;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   458
	int holds = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   459
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   460
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   461
	 * By asserting that the tx is assigned, we're counting the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   462
	 * number of dn_tx_holds, which is the same as the number of
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   463
	 * dn_holds.  Otherwise, we'd be counting dn_holds, but
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   464
	 * dn_tx_holds could be 0.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   465
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   466
	ASSERT(tx->tx_txg != 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   467
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   468
	/* if (tx->tx_anyobj == TRUE) */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   469
		/* return (0); */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   470
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   471
	for (dth = list_head(&tx->tx_holds); dth;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   472
	    dth = list_next(&tx->tx_holds, dth)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   473
		if (dth->dth_dnode && dth->dth_dnode->dn_object == object)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   474
			holds++;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   475
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   476
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   477
	return (holds);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   478
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   479
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   480
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   481
dmu_tx_dirty_buf(dmu_tx_t *tx, dmu_buf_impl_t *db)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   482
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   483
#ifdef ZFS_DEBUG
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   484
	dmu_tx_hold_t *dth;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   485
	int match_object = FALSE, match_offset = FALSE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   486
	dnode_t *dn = db->db_dnode;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   487
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   488
	ASSERT(tx->tx_txg != 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   489
	ASSERT(tx->tx_objset == NULL || dn->dn_objset == tx->tx_objset->os);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   490
	ASSERT3U(dn->dn_object, ==, db->db.db_object);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   491
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   492
	if (tx->tx_anyobj)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   493
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   494
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   495
	/* XXX No checking on the meta dnode for now */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   496
	if (db->db.db_object & DMU_PRIVATE_OBJECT)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   497
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   498
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   499
	for (dth = list_head(&tx->tx_holds); dth;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   500
	    dth = list_next(&tx->tx_holds, dth)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   501
		ASSERT(dn == NULL || dn->dn_assigned_txg == tx->tx_txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   502
		if (dth->dth_dnode == dn && dth->dth_type != THT_NEWOBJECT)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   503
			match_object = TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   504
		if (dth->dth_dnode == NULL || dth->dth_dnode == dn) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   505
			int datablkshift = dn->dn_datablkshift ?
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   506
			    dn->dn_datablkshift : SPA_MAXBLOCKSHIFT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   507
			int epbs = dn->dn_indblkshift - SPA_BLKPTRSHIFT;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   508
			int shift = datablkshift + epbs * db->db_level;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   509
			uint64_t beginblk = shift >= 64 ? 0 :
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   510
			    (dth->dth_arg1 >> shift);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   511
			uint64_t endblk = shift >= 64 ? 0 :
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   512
			    ((dth->dth_arg1 + dth->dth_arg2 - 1) >> shift);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   513
			uint64_t blkid = db->db_blkid;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   514
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   515
			/* XXX dth_arg2 better not be zero... */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   516
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   517
			dprintf("found dth type %x beginblk=%llx endblk=%llx\n",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   518
			    dth->dth_type, beginblk, endblk);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   519
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   520
			switch (dth->dth_type) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   521
			case THT_WRITE:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   522
				if (blkid >= beginblk && blkid <= endblk)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   523
					match_offset = TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   524
				/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   525
				 * We will let this hold work for the bonus
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   526
				 * buffer so that we don't need to hold it
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   527
				 * when creating a new object.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   528
				 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   529
				if (blkid == DB_BONUS_BLKID)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   530
					match_offset = TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   531
				/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   532
				 * They might have to increase nlevels,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   533
				 * thus dirtying the new TLIBs.  Or the
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   534
				 * might have to change the block size,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   535
				 * thus dirying the new lvl=0 blk=0.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   536
				 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   537
				if (blkid == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   538
					match_offset = TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   539
				break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   540
			case THT_FREE:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   541
				if (blkid == beginblk &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   542
				    (dth->dth_arg1 != 0 ||
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   543
				    dn->dn_maxblkid == 0))
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   544
					match_offset = TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   545
				if (blkid == endblk &&
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   546
				    dth->dth_arg2 != DMU_OBJECT_END)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   547
					match_offset = TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   548
				break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   549
			case THT_BONUS:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   550
				if (blkid == DB_BONUS_BLKID)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   551
					match_offset = TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   552
				break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   553
			case THT_ZAP:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   554
				match_offset = TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   555
				break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   556
			case THT_NEWOBJECT:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   557
				match_object = TRUE;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   558
				break;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   559
			default:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   560
				ASSERT(!"bad dth_type");
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   561
			}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   562
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   563
		if (match_object && match_offset)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   564
			return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   565
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   566
	panic("dirtying dbuf obj=%llx lvl=%u blkid=%llx but not tx_held\n",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   567
	    (u_longlong_t)db->db.db_object, db->db_level,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   568
	    (u_longlong_t)db->db_blkid);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   569
#endif
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   570
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   571
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   572
static int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   573
dmu_tx_try_assign(dmu_tx_t *tx, uint64_t txg_how, dmu_tx_hold_t **last_dth)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   574
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   575
	dmu_tx_hold_t *dth;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   576
	uint64_t lsize, asize, fsize;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   577
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   578
	*last_dth = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   579
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   580
	tx->tx_space_towrite = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   581
	tx->tx_space_tofree = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   582
	tx->tx_space_tooverwrite = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   583
	tx->tx_txg = txg_hold_open(tx->tx_pool, &tx->tx_txgh);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   584
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   585
	if (txg_how >= TXG_INITIAL && txg_how != tx->tx_txg)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   586
		return (ERESTART);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   587
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   588
	for (dth = list_head(&tx->tx_holds); dth;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   589
	    *last_dth = dth, dth = list_next(&tx->tx_holds, dth)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   590
		dnode_t *dn = dth->dth_dnode;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   591
		if (dn != NULL) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   592
			mutex_enter(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   593
			while (dn->dn_assigned_txg == tx->tx_txg - 1) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   594
				if (txg_how != TXG_WAIT) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   595
					mutex_exit(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   596
					return (ERESTART);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   597
				}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   598
				cv_wait(&dn->dn_notxholds, &dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   599
			}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   600
			if (dn->dn_assigned_txg == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   601
				ASSERT(dn->dn_assigned_tx == NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   602
				dn->dn_assigned_txg = tx->tx_txg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   603
				dn->dn_assigned_tx = tx;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   604
			} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   605
				ASSERT(dn->dn_assigned_txg == tx->tx_txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   606
				if (dn->dn_assigned_tx != tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   607
					dn->dn_assigned_tx = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   608
			}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   609
			(void) refcount_add(&dn->dn_tx_holds, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   610
			mutex_exit(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   611
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   612
		if (dth->dth_func)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   613
			dth->dth_func(tx, dn, dth->dth_arg1, dth->dth_arg2);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   614
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   615
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   616
	/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   617
	 * Convert logical size to worst-case allocated size.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   618
	 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   619
	fsize = spa_get_asize(tx->tx_pool->dp_spa, tx->tx_space_tooverwrite) +
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   620
	    tx->tx_space_tofree;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   621
	lsize = tx->tx_space_towrite + tx->tx_space_tooverwrite;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   622
	asize = spa_get_asize(tx->tx_pool->dp_spa, lsize);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   623
	tx->tx_space_towrite = asize;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   624
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   625
	if (tx->tx_dir && asize != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   626
		int err = dsl_dir_tempreserve_space(tx->tx_dir,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   627
		    lsize, asize, fsize, &tx->tx_tempreserve_cookie, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   628
		if (err)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   629
			return (err);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   630
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   631
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   632
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   633
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   634
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   635
static uint64_t
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   636
dmu_tx_unassign(dmu_tx_t *tx, dmu_tx_hold_t *last_dth)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   637
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   638
	uint64_t txg = tx->tx_txg;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   639
	dmu_tx_hold_t *dth;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   640
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   641
	ASSERT(txg != 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   642
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   643
	txg_rele_to_quiesce(&tx->tx_txgh);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   644
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   645
	for (dth = last_dth; dth; dth = list_prev(&tx->tx_holds, dth)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   646
		dnode_t *dn = dth->dth_dnode;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   647
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   648
		if (dn == NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   649
			continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   650
		mutex_enter(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   651
		ASSERT3U(dn->dn_assigned_txg, ==, txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   652
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   653
		if (refcount_remove(&dn->dn_tx_holds, tx) == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   654
			dn->dn_assigned_txg = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   655
			dn->dn_assigned_tx = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   656
			cv_broadcast(&dn->dn_notxholds);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   657
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   658
		mutex_exit(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   659
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   660
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   661
	txg_rele_to_sync(&tx->tx_txgh);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   662
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   663
	tx->tx_txg = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   664
	return (txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   665
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   666
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   667
/*
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   668
 * Assign tx to a transaction group.  txg_how can be one of:
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   669
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   670
 * (1)	TXG_WAIT.  If the current open txg is full, waits until there's
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   671
 *	a new one.  This should be used when you're not holding locks.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   672
 *	If will only fail if we're truly out of space (or over quota).
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   673
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   674
 * (2)	TXG_NOWAIT.  If we can't assign into the current open txg without
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   675
 *	blocking, returns immediately with ERESTART.  This should be used
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   676
 *	whenever you're holding locks.  On an ERESTART error, the caller
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   677
 *	should drop locks, do a txg_wait_open(dp, 0), and try again.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   678
 *
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   679
 * (3)	A specific txg.  Use this if you need to ensure that multiple
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   680
 *	transactions all sync in the same txg.  Like TXG_NOWAIT, it
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   681
 *	returns ERESTART if it can't assign you into the requested txg.
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   682
 */
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   683
int
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   684
dmu_tx_assign(dmu_tx_t *tx, uint64_t txg_how)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   685
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   686
	dmu_tx_hold_t *last_dth;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   687
	int err;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   688
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   689
	ASSERT(tx->tx_txg == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   690
	ASSERT(txg_how != 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   691
	ASSERT(!dsl_pool_sync_context(tx->tx_pool));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   692
	ASSERT3U(tx->tx_space_towrite, ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   693
	ASSERT3U(tx->tx_space_tofree, ==, 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   694
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   695
	while ((err = dmu_tx_try_assign(tx, txg_how, &last_dth)) != 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   696
		uint64_t txg = dmu_tx_unassign(tx, last_dth);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   697
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   698
		if (err != ERESTART || txg_how != TXG_WAIT)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   699
			return (err);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   700
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   701
		txg_wait_open(tx->tx_pool, txg + 1);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   702
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   703
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   704
	txg_rele_to_quiesce(&tx->tx_txgh);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   705
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   706
	return (0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   707
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   708
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   709
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   710
dmu_tx_willuse_space(dmu_tx_t *tx, int64_t delta)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   711
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   712
	if (tx->tx_dir == NULL || delta == 0)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   713
		return;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   714
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   715
	if (delta > 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   716
		ASSERT3U(refcount_count(&tx->tx_space_written) + delta, <=,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   717
		    tx->tx_space_towrite);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   718
		(void) refcount_add_many(&tx->tx_space_written, delta, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   719
	} else {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   720
		(void) refcount_add_many(&tx->tx_space_freed, -delta, NULL);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   721
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   722
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   723
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   724
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   725
dmu_tx_commit(dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   726
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   727
	dmu_tx_hold_t *dth;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   728
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   729
	ASSERT(tx->tx_txg != 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   730
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   731
	while (dth = list_head(&tx->tx_holds)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   732
		dnode_t *dn = dth->dth_dnode;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   733
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   734
		list_remove(&tx->tx_holds, dth);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   735
		kmem_free(dth, sizeof (dmu_tx_hold_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   736
		if (dn == NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   737
			continue;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   738
		mutex_enter(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   739
		ASSERT3U(dn->dn_assigned_txg, ==, tx->tx_txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   740
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   741
		if (refcount_remove(&dn->dn_tx_holds, tx) == 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   742
			dn->dn_assigned_txg = 0;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   743
			dn->dn_assigned_tx = NULL;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   744
			cv_broadcast(&dn->dn_notxholds);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   745
		}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   746
		mutex_exit(&dn->dn_mtx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   747
		dnode_rele(dn, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   748
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   749
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   750
	if (tx->tx_dir && tx->tx_space_towrite > 0) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   751
		dsl_dir_tempreserve_clear(tx->tx_tempreserve_cookie, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   752
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   753
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   754
	if (tx->tx_anyobj == FALSE)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   755
		txg_rele_to_sync(&tx->tx_txgh);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   756
	dprintf("towrite=%llu written=%llu tofree=%llu freed=%llu\n",
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   757
	    tx->tx_space_towrite, refcount_count(&tx->tx_space_written),
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   758
	    tx->tx_space_tofree, refcount_count(&tx->tx_space_freed));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   759
	refcount_destroy_many(&tx->tx_space_written,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   760
	    refcount_count(&tx->tx_space_written));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   761
	refcount_destroy_many(&tx->tx_space_freed,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   762
	    refcount_count(&tx->tx_space_freed));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   763
#ifdef ZFS_DEBUG
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   764
	if (tx->tx_debug_buf)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   765
		kmem_free(tx->tx_debug_buf, 4096);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   766
#endif
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   767
	kmem_free(tx, sizeof (dmu_tx_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   768
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   769
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   770
void
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   771
dmu_tx_abort(dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   772
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   773
	dmu_tx_hold_t *dth;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   774
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   775
	ASSERT(tx->tx_txg == 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   776
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   777
	while (dth = list_head(&tx->tx_holds)) {
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   778
		dnode_t *dn = dth->dth_dnode;
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   779
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   780
		list_remove(&tx->tx_holds, dth);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   781
		kmem_free(dth, sizeof (dmu_tx_hold_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   782
		if (dn != NULL)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   783
			dnode_rele(dn, tx);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   784
	}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   785
	refcount_destroy_many(&tx->tx_space_written,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   786
	    refcount_count(&tx->tx_space_written));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   787
	refcount_destroy_many(&tx->tx_space_freed,
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   788
	    refcount_count(&tx->tx_space_freed));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   789
#ifdef ZFS_DEBUG
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   790
	if (tx->tx_debug_buf)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   791
		kmem_free(tx->tx_debug_buf, 4096);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   792
#endif
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   793
	kmem_free(tx, sizeof (dmu_tx_t));
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   794
}
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   795
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   796
uint64_t
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   797
dmu_tx_get_txg(dmu_tx_t *tx)
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   798
{
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   799
	ASSERT(tx->tx_txg != 0);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   800
	return (tx->tx_txg);
b348f31ed315 PSARC 2002/240 ZFS
ahrens
parents:
diff changeset
   801
}